071faa482c
纳入 AGC Cargo workspace 的统一 rustfmt 检查与格式化入口 完成项目 TypeScript/Prettier 与 Rust 全量格式化 修复 Pingora expected executable 门禁的空白敏感误报 同步开发运维文档与 AGC skill pack 格式化忽略规则
116 lines
3.4 KiB
TypeScript
116 lines
3.4 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]'}
|
|
portalTheme={platformTheme ?? 'auto'}
|
|
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>
|
|
);
|
|
}
|