Skip to content

Commit 553e95a

Browse files
committed
fix(kb): 模型轻建契约/Enter与IME/代际守卫(2026-09-05 审查批D)
1 parent 7569871 commit 553e95a

2 files changed

Lines changed: 27 additions & 6 deletions

File tree

‎app/src/components/LinkEntityPicker.tsx‎

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,19 @@ export default function LinkEntityPicker({
8686
value={query}
8787
onChange={(e) => { setQuery(e.target.value); setErr(""); }}
8888
onKeyDown={(e) => {
89-
if (e.key === "Enter") void doCreate();
90-
else if (e.key === "Escape") {
89+
// 审查 D3:IME 中文组词回车(isComposing)不触发动作
90+
if (e.nativeEvent.isComposing) return;
91+
if (e.key === "Enter") {
92+
const name = query.trim();
93+
if (!name || busy) return;
94+
// 审查 D2:Enter=有命中选首项(spec §2.5),零命中才新建
95+
if (visible.length > 0) {
96+
onPick(visible[0].id);
97+
setQuery("");
98+
} else {
99+
void doCreate();
100+
}
101+
} else if (e.key === "Escape") {
91102
if (query) setQuery("");
92103
else onClose?.();
93104
}
@@ -107,7 +118,6 @@ export default function LinkEntityPicker({
107118
data-testid={`note-link-row-${r.id}`}
108119
onClick={() => onPick(r.id)}
109120
style={rowBtn(selectedId === r.id)}
110-
title={r.depth > 0 ? undefined : undefined}
111121
>
112122
<span style={{ display: "inline-block", width: r.depth * 12 }} />
113123
{selectedId === r.id ? "✓ " : ""}

‎app/src/components/NoteLinkToSystem.tsx‎

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
* @ai-context: 反查已挂(list_links_by_target)、切换目标先撤旧链(幂等防堆
1313
* 积)、REQ-276 右缘钳制浮层均保持既有语义。
1414
*/
15-
import { useCallback, useEffect, useMemo, useState } from "react";
15+
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
1616
import { invoke } from "@tauri-apps/api/core";
1717
import type {
1818
KnowledgeConcept, KnowledgeLink, KnowledgeModel, KnowledgeNode, KnowledgeSystem,
@@ -108,7 +108,12 @@ export default function NoteLinkToSystem({ noteId, onChanged }: Props) {
108108
setNodes(ns); setConcepts(cs); setModels(ms);
109109
}, []);
110110

111+
// 审查 D4:体系切换代际守卫——轻建在途(await 列表重载)期间若用户切换
112+
// 体系,旧代结果不得覆盖新体系选择/列表
113+
const entityGenRef = useRef(0);
114+
111115
useEffect(() => {
116+
entityGenRef.current += 1;
112117
setEntityId(null);
113118
void loadEntities(effectiveSystemId);
114119
}, [effectiveSystemId, loadEntities]);
@@ -164,6 +169,7 @@ export default function NoteLinkToSystem({ noteId, onChanged }: Props) {
164169
// 留空,详情回体系页既有对话框补全;模型学科占位「未分类」可后改)
165170
const createEntity = useCallback(async (name: string, anchorId: number | null) => {
166171
if (effectiveSystemId == null) throw new Error("请先选择体系");
172+
const gen = entityGenRef.current;
167173
let id: number;
168174
if (entityType === "node") {
169175
const n = await invoke<KnowledgeNode>("add_knowledge_node", {
@@ -176,14 +182,19 @@ export default function NoteLinkToSystem({ noteId, onChanged }: Props) {
176182
});
177183
id = c.id;
178184
} else {
185+
// 审查 D1:Rust 契约 disciplines:String=JSON 数组字符串(normalize_disciplines
186+
// 只认 JSON 数组)——裸串必拒;同 KnowledgeSampleView JSON.stringify 范式
179187
const m = await invoke<KnowledgeModel>("add_knowledge_model", {
180-
systemId: effectiveSystemId, name, disciplines: "未分类",
188+
systemId: effectiveSystemId, name, disciplines: JSON.stringify(["未分类"]),
181189
claim: null, validWhen: null, invalidWhen: null,
182190
});
183191
id = m.id;
184192
}
185193
await loadEntities(effectiveSystemId); // 列表重载(新增即见)
186-
setEntityId(id); // 即建即选——确认挂接一步收尾
194+
// 审查 D4:代际一致才回填选择(期间切体系则丢弃本次回填)
195+
if (entityGenRef.current === gen) {
196+
setEntityId(id); // 即建即选——确认挂接一步收尾
197+
}
187198
}, [effectiveSystemId, entityType, loadEntities]);
188199

189200
const nodeRows = useMemo(() => flattenNodeRows(nodes), [nodes]);

0 commit comments

Comments
 (0)