feat(web): read-only identity pool, decisions happen in 待处理
Pool detail keeps 重新识别 only; rows with an open identity decision show 已进待处理 and link to /console/inbox?kind=identity_ambiguous. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
ddb15145d8
commit
f38758bd26
2 files changed
+72
-160
No files matched your search
@@ -5,16 +5,16 @@ import type {
|
||||
IdentityPoolItem,
|
||||
IdentityStatus,
|
||||
} from "@umt/contracts";
|
||||
import { Fingerprint, Lock, SearchX } from "lucide-react";
|
||||
import { ArrowRight, Fingerprint, Inbox, Lock, SearchX } from "lucide-react";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useSearchParams } from "react-router";
|
||||
import { Link, useSearchParams } from "react-router";
|
||||
import { useExternalIdentities, useIdentityPool } from "~/api/identity.ts";
|
||||
import { type DataColumn, DataTable } from "~/components/console/data-table.tsx";
|
||||
import { FilterBar, FilterSelect } from "~/components/console/filter-bar.tsx";
|
||||
import { PageHeader } from "~/components/console/page-header.tsx";
|
||||
import { AliasesPanel } from "~/components/library/identity-aliases.tsx";
|
||||
import { ExternalIdentitySheet, identityRef } from "~/components/library/identity-external-sheet.tsx";
|
||||
import { PoolSheet, querySummary } from "~/components/library/identity-pool-sheet.tsx";
|
||||
import { INBOX_IDENTITY, inInbox, PoolSheet, querySummary } from "~/components/library/identity-pool-sheet.tsx";
|
||||
import {
|
||||
EVIDENCE_LEVEL,
|
||||
IDENTITY_STATUS,
|
||||
@@ -24,9 +24,13 @@ import {
|
||||
VERIFY_STATUS,
|
||||
} from "~/components/library/labels.ts";
|
||||
import { relTime, Tone } from "~/components/library/parts.tsx";
|
||||
import { Button } from "~/components/ui/button.tsx";
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "~/components/ui/tabs.tsx";
|
||||
|
||||
// 身份与元数据(REQ §7.2、§7.5):待识别池、外部身份映射与修订、别名。
|
||||
// 身份与元数据(REQ §7.2、§7.5):待识别资源、外部身份映射与修订、别名。
|
||||
// 待识别资源只读;选候选、忽略在待处理里做(docs/design/console-ia.md §3.1 判定只在待处理)。
|
||||
|
||||
export const meta = () => [{ title: "身份与元数据 · UHD 媒体自动化控制台" }];
|
||||
|
||||
function useDebounced(v: string, ms = 250) {
|
||||
const [d, setD] = useState(v);
|
||||
@@ -65,7 +69,25 @@ function PoolTab() {
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{ key: "reason", header: "原因", cell: (r) => <Tone v={POOL_REASON[r.reason]} /> },
|
||||
{
|
||||
key: "reason",
|
||||
header: "原因",
|
||||
cell: (r) => (
|
||||
<div className="flex flex-col items-start gap-1">
|
||||
<Tone v={POOL_REASON[r.reason]} />
|
||||
{inInbox(r) ? (
|
||||
<Link
|
||||
to={INBOX_IDENTITY}
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
className="inline-flex items-center gap-0.5 text-meta whitespace-nowrap text-muted-foreground underline-offset-4 hover:text-foreground hover:underline"
|
||||
>
|
||||
已进待处理
|
||||
<ArrowRight className="h-3 w-3" />
|
||||
</Link>
|
||||
) : null}
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: "cands",
|
||||
header: "候选",
|
||||
@@ -251,7 +273,18 @@ export default function IdentityPage() {
|
||||
const tab = (TABS as readonly string[]).includes(params.get("tab") ?? "") ? params.get("tab")! : "pool";
|
||||
return (
|
||||
<>
|
||||
<PageHeader title="身份与元数据" description="以本地 ID 为准。自动匹配不覆盖人工锁定的外部身份。" />
|
||||
<PageHeader
|
||||
title="身份与元数据"
|
||||
description="以本地 ID 为准。自动匹配不覆盖人工锁定的外部身份。"
|
||||
actions={
|
||||
<Button asChild variant="outline" size="sm">
|
||||
<Link to={INBOX_IDENTITY}>
|
||||
<Inbox />
|
||||
待确认身份
|
||||
</Link>
|
||||
</Button>
|
||||
}
|
||||
/>
|
||||
<Tabs
|
||||
value={tab}
|
||||
onValueChange={(v) =>
|
||||
@@ -265,7 +298,7 @@ export default function IdentityPage() {
|
||||
}
|
||||
>
|
||||
<TabsList>
|
||||
<TabsTrigger value="pool">待识别池</TabsTrigger>
|
||||
<TabsTrigger value="pool">待识别</TabsTrigger>
|
||||
<TabsTrigger value="external">外部身份</TabsTrigger>
|
||||
<TabsTrigger value="aliases">别名</TabsTrigger>
|
||||
</TabsList>
|
||||
|
||||
Reference in new issue
Block a user