fix(web): stale-closure + focus trap + 去边界强转 + a11y/性能打磨 + 类型化客户端

P1-6 useStyleLearn/useKimiOauth 修 stale-closure 依赖。
P1-7 CommandPalette/Drawer 加 focus trap(新 lib/a11y/focusTrap)。
P1-8 SSE 解析与 server.ts 去 as 强转改类型守卫/运行时校验。
P2 删冗余强转、开 noUncheckedIndexedAccess、Toast 清理+稳定 key、列表 key 稳定化、
  rel=noopener、useMemo 大文本、ConflictCard role=group、useInjection 加锁、
  client.test 真断言。
codegen 重生成 schema.d.ts + 消费 DimensionEntry/ReviewConflictView 强类型。
This commit is contained in:
Yaojia Wang
2026-06-21 19:32:49 +02:00
parent 016509c5c6
commit c6651b74b9
36 changed files with 792 additions and 140 deletions

View File

@@ -163,7 +163,7 @@ describe("mergeCharacterCards", () => {
const session = [card({ name: "甲", role: "对手" })];
const out = mergeCharacterCards(persisted, session);
expect(out).toHaveLength(1);
expect(out[0].role).toBe("主角"); // persisted version kept
expect(out[0]?.role).toBe("主角"); // persisted version kept
});
it("returns persisted list when no session cards", () => {

View File

@@ -4,10 +4,7 @@ import { useCallback, useState } from "react";
import { api } from "@/lib/api/client";
import { useToast } from "@/components/Toast";
import type {
CharacterCardView,
CharacterIngestResponse,
} from "@/lib/api/types";
import type { CharacterCardView } from "@/lib/api/types";
import {
buildCharacterGenerateRequest,
buildCharacterIngestRequest,
@@ -108,16 +105,12 @@ export function useCharacterGen(): UseCharacterGen {
toast(generationErrorMessage(error), "error");
return false;
}
const result = data as CharacterIngestResponse;
setCreated(result.created ?? []);
setCreated(data.created ?? []);
setConflicts(null);
setIngestStatus("done");
toast(`已入库 ${result.created?.length ?? 0} 个角色`, "success");
if (result.rejected_tables && result.rejected_tables.length > 0) {
toast(
`越权写表被丢弃:${result.rejected_tables.join("、")}`,
"info",
);
toast(`已入库 ${data.created?.length ?? 0} 个角色`, "success");
if (data.rejected_tables && data.rejected_tables.length > 0) {
toast(`越权写表被丢弃:${data.rejected_tables.join("、")}`, "info");
}
return true;
} catch {