import { Card, Descriptions, Flex, Tag, Typography } from "antd"; import type { EntityConfirmation, ProcessingResult } from "../../../../shared/api"; import type { Material, MaterialType } from "../types"; import { formatRelativeTime } from "../../../shared/utils/time"; import { STATUS_MAP } from "./constants"; import { EntityCandidatePanel } from "./EntityCandidatePanel"; interface MaterialContentProps { material: Material; projectId?: string; onConfirmationsChange?: (confirmations: EntityConfirmation[]) => void; } const MATERIAL_TYPE_LABELS: Record = { general: "通用", meeting: "会议", }; function parseProcessingResult(raw: null | string): ProcessingResult | null { if (!raw) return null; try { const parsed = JSON.parse(raw) as Partial; if (parsed && typeof parsed === "object") { return { candidateEntities: Array.isArray(parsed.candidateEntities) ? parsed.candidateEntities : [], normalizedContent: typeof parsed.normalizedContent === "string" ? parsed.normalizedContent : "", summary: typeof parsed.summary === "string" ? parsed.summary : "", }; } return null; } catch { return null; } } export function MaterialContent({ material, projectId, onConfirmationsChange }: MaterialContentProps) { const statusInfo = STATUS_MAP[material.status] ?? { color: "default", label: material.status }; const typeLabel = MATERIAL_TYPE_LABELS[material.materialType] ?? material.materialType; const processingResult = parseProcessingResult(material.processedContent); return ( {material.description} {processingResult && ( <> {processingResult.summary} {processingResult.normalizedContent} {material.status === "review" && projectId && onConfirmationsChange && ( )} {material.status !== "review" && processingResult.candidateEntities.length > 0 && ( {processingResult.candidateEntities.map((ce: { name: string }, i: number) => ( {ce.name} ))} )} )} {!processingResult && material.processedContent && ( {material.processedContent} )} {statusInfo.label} {typeLabel} {material.associatedDate} {formatRelativeTime(material.createdAt)} ); }