diff --git a/web/src/pages/MyKbs.tsx b/web/src/pages/MyKbs.tsx index e767ffb16..7e57bd7c8 100644 --- a/web/src/pages/MyKbs.tsx +++ b/web/src/pages/MyKbs.tsx @@ -25,17 +25,16 @@ import { Td, Th, Tr, + localDate, } from "../ui"; import { fetchMe } from "../authSession"; -const ymd = (iso: string) => iso.slice(0, 10); - function joinInfo(row: MyKb): string { if (row.my_role === "owner") return S.account.deploymentAdmin; if (row.joined_at) { return row.added_by_name - ? S.account.addedBy(row.added_by_name, ymd(row.joined_at)) - : S.account.joinedOn(ymd(row.joined_at)); + ? S.account.addedBy(row.added_by_name, localDate(row.joined_at)) + : S.account.joinedOn(localDate(row.joined_at)); } return S.account.openToEveryone; } diff --git a/web/src/pages/Review.tsx b/web/src/pages/Review.tsx index 86ade8975..88e3a1eb7 100644 --- a/web/src/pages/Review.tsx +++ b/web/src/pages/Review.tsx @@ -48,6 +48,7 @@ import { SearchSelect, Status, cn, + localDate, type ChipTone, } from "../ui"; @@ -478,7 +479,7 @@ function MergeRow({ ? S.review.mergedBy(merge.merged_by_name) : S.review.mergedByAi} {" · "} - {merge.created_at.slice(0, 10)} + {localDate(merge.created_at)} {merge.reason ? ` · ${escalationText(merge.reason)}` : ""} @@ -523,7 +524,7 @@ function precedentText(p: AgentPrecedent): string { : p.action === "review.keep" ? S.review.agentPrecedentKept : S.review.agentPrecedentMerged; - const line = `${p.left} ≟ ${p.right} · ${verb} · ${p.at.slice(0, 10)}`; + const line = `${p.left} ≟ ${p.right} · ${verb} · ${localDate(p.at)}`; // 人写的那一句(0026)跟在后面:先例不只是结果 return p.why ? `${line} · “${p.why}”` : line; } @@ -596,8 +597,8 @@ function AgentRow({
{d.decided_by_name - ? S.review.agentAnsweredBy(d.decided_by_name, (d.decided_at ?? d.created_at).slice(0, 10)) - : d.created_at.slice(0, 10)} + ? S.review.agentAnsweredBy(d.decided_by_name, localDate(d.decided_at ?? d.created_at)) + : localDate(d.created_at)}
{/* 回答 agent 也能带一句理由(0026)——它走的正是人的裁决路径 */} @@ -691,7 +692,7 @@ function DecisionRow({ e }: { e: ReviewHistoryEvent }) { {e.actor_name ?? S.review.aiActor} {" · "} - {e.created_at.slice(0, 10)} + {localDate(e.created_at)}
); diff --git a/web/src/pages/RulesPanel.tsx b/web/src/pages/RulesPanel.tsx index ff3077b97..12fc5b267 100644 --- a/web/src/pages/RulesPanel.tsx +++ b/web/src/pages/RulesPanel.tsx @@ -37,6 +37,7 @@ import { Th, THead, Tr, + localDate, } from "../ui"; import { toast } from "../toast"; import { expressionText, metadataOnly, metadataPatch } from "./ruleExpressions"; @@ -307,7 +308,7 @@ function History({ kbId, ruleId, attributes }: { kbId: string; ruleId: string; a {S.ontology.ruleVersion(v.seq)} {!v.superseded_at && {S.ontology.ruleVersionCurrent}} - {S.ontology.ruleVersionSince(v.recorded_at.slice(0, 10), v.superseded_at ? v.superseded_at.slice(0, 10) : null)} + {S.ontology.ruleVersionSince(localDate(v.recorded_at), v.superseded_at ? localDate(v.superseded_at) : null)} {S.ontology.ruleVersionStanding(v.derived_count)}
diff --git a/web/src/pages/Tokens.tsx b/web/src/pages/Tokens.tsx index c1224628c..72eec8528 100644 --- a/web/src/pages/Tokens.tsx +++ b/web/src/pages/Tokens.tsx @@ -27,11 +27,12 @@ import { Th, THead, Tr, - buttonLike,} from "../ui"; + buttonLike, + localDate, +} from "../ui"; import { toast } from "../toast"; import { copyAndSay } from "../clipboard"; -const ymd = (iso: string) => iso.slice(0, 10); const EXPIRY_CHOICES = [30, 90, 365, 0] as const; /** Claude Code / Claude Desktop 一族的 Streamable HTTP 写法。每个库一个端点(0014: @@ -164,15 +165,15 @@ function TokenRow({ {t.kb_ids?.length ? S.account.nBases(t.kb_ids.length) : S.account.allBases} - {t.last_used_at ? ymd(t.last_used_at) : S.account.neverUsed} + {t.last_used_at ? localDate(t.last_used_at) : S.account.neverUsed} - {t.expires_at ? ymd(t.expires_at) : S.account.noExpiry} + {t.expires_at ? localDate(t.expires_at) : S.account.noExpiry} - {ymd(t.created_at)} + {localDate(t.created_at)} {revoked ? ( - {S.account.revokedOn(ymd(t.revoked_at!))} + {S.account.revokedOn(localDate(t.revoked_at!))} ) : arm ? (