新增 PlatformUiKit 通用弹窗、按钮、状态、空态、媒体、表单和标签等公共组件 迁移结果页、创作工作台、认证入口、RPG 暗色面板和运行态弹窗的重复 UI chrome 补充组件测试、页面回归测试、技术文档和 Hermes 共享决策记录
127 lines
3.5 KiB
TypeScript
127 lines
3.5 KiB
TypeScript
import { FileText } from 'lucide-react';
|
||
|
||
import type { PlatformTheme } from '../../../packages/shared/src/contracts/runtime';
|
||
import type {
|
||
LegalDocument,
|
||
LegalDocumentBlock,
|
||
} from './legalDocuments';
|
||
import { PlatformActionButton } from './PlatformActionButton';
|
||
import { UnifiedModal } from './UnifiedModal';
|
||
|
||
type LegalDocumentModalProps = {
|
||
document: LegalDocument | null;
|
||
open: boolean;
|
||
platformTheme?: PlatformTheme;
|
||
zIndexClassName?: string;
|
||
onClose: () => void;
|
||
};
|
||
|
||
function LegalRichText({ text }: { text: string }) {
|
||
const parts = text.split(/(\*\*[^*]+\*\*)/gu);
|
||
|
||
return (
|
||
<>
|
||
{parts.map((part, index) => {
|
||
const boldMatch = /^\*\*([^*]+)\*\*$/u.exec(part);
|
||
if (boldMatch) {
|
||
return (
|
||
<strong
|
||
key={`${index}:${part}`}
|
||
className="font-black text-[var(--platform-text-strong)]"
|
||
>
|
||
{boldMatch[1]}
|
||
</strong>
|
||
);
|
||
}
|
||
|
||
return part;
|
||
})}
|
||
</>
|
||
);
|
||
}
|
||
|
||
function LegalDocumentBodyBlock({
|
||
block,
|
||
}: {
|
||
block: LegalDocumentBlock;
|
||
}) {
|
||
if (block.type === 'heading') {
|
||
const className =
|
||
block.level === 2
|
||
? 'mt-5 text-base font-black leading-7 text-[var(--platform-text-strong)] first:mt-0'
|
||
: 'mt-4 text-sm font-black leading-6 text-[var(--platform-text-strong)] first:mt-0';
|
||
|
||
return <div className={className}>{block.text}</div>;
|
||
}
|
||
|
||
if (block.type === 'list') {
|
||
return (
|
||
<ul className="mt-3 list-disc space-y-2 pl-5 text-sm leading-7 text-[var(--platform-text-base)]">
|
||
{block.items.map((item, index) => (
|
||
<li key={`${index}:${item}`}>
|
||
<LegalRichText text={item} />
|
||
</li>
|
||
))}
|
||
</ul>
|
||
);
|
||
}
|
||
|
||
return (
|
||
<p className="mt-3 whitespace-pre-line text-sm leading-7 text-[var(--platform-text-base)]">
|
||
<LegalRichText text={block.text} />
|
||
</p>
|
||
);
|
||
}
|
||
|
||
export function LegalDocumentModal({
|
||
document,
|
||
open,
|
||
platformTheme,
|
||
zIndexClassName,
|
||
onClose,
|
||
}: LegalDocumentModalProps) {
|
||
return (
|
||
<UnifiedModal
|
||
open={open && Boolean(document)}
|
||
title={document?.title ?? '法律信息'}
|
||
onClose={onClose}
|
||
size="md"
|
||
closeLabel="关闭法律信息"
|
||
zIndexClassName={zIndexClassName ?? 'z-[150]'}
|
||
overlayClassName={`platform-theme ${
|
||
platformTheme ? `platform-theme--${platformTheme}` : ''
|
||
}`}
|
||
panelClassName="platform-remap-surface rounded-t-[1.4rem] sm:rounded-[1.4rem]"
|
||
headerClassName="items-center"
|
||
bodyClassName="px-4 py-0 sm:px-5"
|
||
footerClassName="justify-stretch sm:justify-end"
|
||
footer={
|
||
<PlatformActionButton
|
||
onClick={onClose}
|
||
tone="secondary"
|
||
fullWidth
|
||
className="min-h-0 rounded-[0.9rem] sm:w-auto"
|
||
>
|
||
我知道了
|
||
</PlatformActionButton>
|
||
}
|
||
>
|
||
<div className="max-h-[min(64vh,34rem)] overflow-y-auto py-4 pr-1">
|
||
<div className="mb-4 flex items-center gap-2 text-[var(--platform-cool-text)]">
|
||
<FileText className="h-4 w-4" />
|
||
<span className="text-xs font-black tracking-[0.2em]">
|
||
LEGAL
|
||
</span>
|
||
</div>
|
||
{document?.blocks.map((block, index) => (
|
||
<LegalDocumentBodyBlock
|
||
// 中文注释:法律文本没有稳定段落 id,用序号只限定在静态文档渲染列表内。
|
||
key={`${block.type}:${index}`}
|
||
block={block}
|
||
/>
|
||
))}
|
||
</div>
|
||
</UnifiedModal>
|
||
);
|
||
}
|