Files
Genarrative/src/components/platform-entry/PlatformErrorDialog.tsx
T
kdletters 1ad25e30f8 收口前端平台组件库能力
新增 PlatformUiKit 通用弹窗、按钮、状态、空态、媒体、表单和标签等公共组件
迁移结果页、创作工作台、认证入口、RPG 暗色面板和运行态弹窗的重复 UI chrome
补充组件测试、页面回归测试、技术文档和 Hermes 共享决策记录
2026-06-10 10:24:18 +08:00

89 lines
2.5 KiB
TypeScript

import { useEffect, useMemo } from 'react';
import { CopyFeedbackButton } from '../common/CopyFeedbackButton';
import { PlatformInfoBlock } from '../common/PlatformInfoBlock';
import { UnifiedModal } from '../common/UnifiedModal';
import { useCopyFeedback } from '../common/useCopyFeedback';
export type PlatformErrorDialogPayload = {
source: string;
message: string;
};
type PlatformErrorDialogProps = {
error: PlatformErrorDialogPayload | null;
onClose: () => void;
overlayClassName?: string;
panelClassName?: string;
};
function buildPlatformErrorReport(error: PlatformErrorDialogPayload) {
return [`来源:${error.source}`, `错误:${error.message}`].join('\n');
}
function isBlacklistedPlatformError(error: PlatformErrorDialogPayload | null) {
// 中文注释:入口关闭是平台开关状态,不作为全局错误弹窗打扰用户。
return Boolean(error?.message.includes('creation_entry_disabled'));
}
export function PlatformErrorDialog({
error,
onClose,
overlayClassName = 'platform-theme platform-theme--light !items-center',
panelClassName = 'platform-remap-surface rounded-[1.5rem]',
}: PlatformErrorDialogProps) {
const { copyState, copyText, resetCopyState } = useCopyFeedback();
const dialogError = isBlacklistedPlatformError(error) ? null : error;
const reportText = useMemo(
() => (dialogError ? buildPlatformErrorReport(dialogError) : ''),
[dialogError],
);
useEffect(() => {
resetCopyState();
}, [dialogError?.source, dialogError?.message, resetCopyState]);
const copyError = () => {
if (!reportText) {
return;
}
void copyText(reportText);
};
return (
<UnifiedModal
open={Boolean(dialogError)}
title="发生错误"
onClose={onClose}
size="sm"
overlayClassName={overlayClassName}
panelClassName={panelClassName}
bodyClassName="space-y-3 px-4 py-4 sm:px-5 sm:py-5"
footerClassName="justify-end px-4 py-4 sm:px-5"
footer={
<CopyFeedbackButton
state={copyState}
onClick={copyError}
disabled={!reportText}
idleLabel="复制报错"
actionSurface="platform"
actionFullWidth
className="sm:w-auto"
/>
}
>
{dialogError ? (
<>
<PlatformInfoBlock label="来源">
{dialogError.source}
</PlatformInfoBlock>
<PlatformInfoBlock label="错误" multiline>
{dialogError.message}
</PlatformInfoBlock>
</>
) : null}
</UnifiedModal>
);
}