import type { ExternalIdentity, IdentityRevision } from "@umt/contracts"; import { ExternalLink, Lock, LockOpen } from "lucide-react"; import { Link } from "react-router"; import { toast } from "sonner"; import { useIdentityRevisions, useUpdateIdentity } from "~/api/identity.ts"; import { DetailSection, DetailSheet } from "~/components/console/detail-sheet.tsx"; import { EmptyState, ErrorState, LoadingState } from "~/components/console/empty-state.tsx"; import { JsonView } from "~/components/console/json-view.tsx"; import { KvList } from "~/components/console/kv-list.tsx"; import { consolePath } from "~/components/console/nav.ts"; import { Timeline } from "~/components/console/timeline.tsx"; import { Button } from "~/components/ui/button.tsx"; import { errorMessage } from "~/lib/api.ts"; import { formatDateTime } from "~/lib/utils.ts"; import { EVIDENCE_LEVEL, IDENTITY_STATUS, VERIFY_STATUS } from "./labels.ts"; import { Tone } from "./parts.tsx"; const ACTION: Record = { created: "创建", status_changed: "状态变更", relinked: "重新关联", evidence_updated: "证据更新", locked: "加人工锁", unlocked: "解除人工锁", }; const ACTOR: Record = { user: "用户", agent: "Agent", system: "系统", api_key: "API Key" }; export const identityRef = (i: Pick) => `${i.provider}:${i.entityType}:${i.externalId}`; function Revisions({ id }: { id: string }) { const q = useIdentityRevisions(id); if (q.isPending) return ; if (q.isError) return q.refetch()} />; if (q.data.length === 0) return ; const items = [...q.data].sort((a, b) => b.revision - a.revision); return ( ({ id: r.id, at: r.createdAt, tone: r.toStatus ? IDENTITY_STATUS[r.toStatus].tone : "neutral", title: `r${r.revision} · ${ACTION[r.action]}${ r.fromStatus || r.toStatus ? `:${r.fromStatus ? IDENTITY_STATUS[r.fromStatus].label : "无"} → ${r.toStatus ? IDENTITY_STATUS[r.toStatus].label : "无"}` : "" }`, meta: `${ACTOR[r.actorType] ?? r.actorType}${r.actorId ? ` ${r.actorId}` : ""}`, description: r.reason ?? undefined, children: (
), }))} /> ); } export function ExternalIdentitySheet({ item, onClose }: { item: ExternalIdentity | null; onClose: () => void }) { const update = useUpdateIdentity(); if (!item) return null; const toggleLock = async () => { try { await update.mutateAsync({ id: item.id, expectedRevision: item.revision, locked: !item.locked, reason: item.locked ? "控制台解除人工锁" : "控制台加人工锁", }); toast.success(item.locked ? "已解除人工锁" : "已加人工锁"); onClose(); } catch (err) { toast.error(errorMessage(err)); } }; const target = item.mediaEntityId; return ( !o && onClose()} title={identityRef(item)} footer={ } > }, { label: "证据等级", value: EVIDENCE_LEVEL[item.evidenceLevel] ?? item.evidenceLevel }, { label: "人工锁", value: item.locked ? "已锁定" : "未锁定" }, { label: "外部校验", value: }, { label: "校验时间", value: formatDateTime(item.verifiedAt) }, { label: "修订号", value: `r${item.revision}` }, { label: "关联", value: target ? ( 查看作品 ) : ( `内容单元 ${item.contentUnitId ?? "—"}` ), }, { label: "有效期", value: item.validUntil ? `至 ${formatDateTime(item.validUntil)}` : "长期" }, ]} /> ); }