fix: 修复节点点击无响应 + 支持对比后返回完整导图重新选择复习范围
- MindMapViewer: mind-elixir v5 的 selectNode(el) 不传第二参数导致 selectNewNode 永不触发,改为 monkey-patch selectNode 捕获节点点击 - MindMapViewer: 根节点加入 nodePathMap,子节点路径补全根标题前缀 - ReviewRecall: 新增 resetComparison(),对比完成后可点击「返回完整导图」清空结果,重新选择节点开始新一轮复习 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -99,11 +99,26 @@ const toElixirNode = (node: MindMapTreeNode, ancestors: string[] = []): any => {
|
||||
|
||||
const toElixirData = (tree: MindMapTreeNode): MindElixirData => {
|
||||
nodeCounter = 0;
|
||||
const rootTitle = tree.title || "思维导图";
|
||||
// register root node in path map so clicking it also works
|
||||
if (props.selectable) {
|
||||
nodePathMap["root"] = {
|
||||
title: rootTitle,
|
||||
path: rootTitle,
|
||||
childCount: (tree.children || []).reduce(
|
||||
(sum, c) => sum + 1 + countAllDescendants(c),
|
||||
0,
|
||||
),
|
||||
};
|
||||
}
|
||||
return {
|
||||
nodeData: {
|
||||
id: "root",
|
||||
topic: tree.title || "思维导图",
|
||||
children: (tree.children || []).map(c => toElixirNode(c)),
|
||||
topic: rootTitle,
|
||||
// pass root title as ancestor so child paths include it (e.g. "根 / 子节点")
|
||||
children: (tree.children || []).map((c) =>
|
||||
toElixirNode(c, [rootTitle]),
|
||||
),
|
||||
},
|
||||
} as MindElixirData;
|
||||
};
|
||||
@@ -147,18 +162,31 @@ const render = () => {
|
||||
});
|
||||
}
|
||||
|
||||
instance.bus.addListener("selectNewNode", (node: any) => {
|
||||
if (props.selectable && node?.id) {
|
||||
const info = nodePathMap[node.id];
|
||||
// mind-elixir v5: selectNode(el) is called on every node click, but the
|
||||
// selectNewNode event is never fired (it requires selectNode(el, true),
|
||||
// which the default click handler never passes). Monkey-patch selectNode
|
||||
// to hook into node clicks for both selectable and source-navigation modes.
|
||||
const origSelectNode = instance.selectNode.bind(instance);
|
||||
instance.selectNode = function (el: any, fireEvent?: boolean) {
|
||||
origSelectNode(el, fireEvent);
|
||||
if (!el?.nodeObj) return;
|
||||
const nodeData = el.nodeObj;
|
||||
// selectable mode → emit node-select with title/path/childCount
|
||||
if (props.selectable && nodeData?.id) {
|
||||
const info = nodePathMap[nodeData.id];
|
||||
if (info) {
|
||||
emit("node-select", info);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (node?.sourceType && node?.sourceId != null) {
|
||||
emit("node-click", { sourceType: String(node.sourceType), sourceId: Number(node.sourceId) });
|
||||
// source navigation → emit node-click with sourceType/sourceId
|
||||
if (nodeData?.sourceType && nodeData?.sourceId != null) {
|
||||
emit("node-click", {
|
||||
sourceType: String(nodeData.sourceType),
|
||||
sourceId: Number(nodeData.sourceId),
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
watch(
|
||||
|
||||
@@ -223,6 +223,14 @@ const resetRecall = () => {
|
||||
recallTree.value = buildEmptyRecallTree();
|
||||
};
|
||||
|
||||
// 返回完整标准导图,重新选择复习范围
|
||||
const resetComparison = () => {
|
||||
lastResult.value = null;
|
||||
hasCompared.value = false;
|
||||
focusPath.value = "";
|
||||
recallTree.value = buildEmptyRecallTree();
|
||||
};
|
||||
|
||||
// 编辑标准导图
|
||||
const startEditStandard = () => {
|
||||
editOutline.value = standard.value?.outline || "";
|
||||
@@ -438,8 +446,18 @@ onMounted(() => {
|
||||
<!-- 标准导图(含对比着色) -->
|
||||
<article class="surface-card standard-panel">
|
||||
<div class="panel-header">
|
||||
<h3>📖 标准思维导图</h3>
|
||||
<h3>
|
||||
{{ hasCompared ? '📖 标准思维导图(对比结果)' : '📖 标准思维导图' }}
|
||||
</h3>
|
||||
<div class="panel-actions">
|
||||
<el-button
|
||||
v-if="hasCompared"
|
||||
size="small"
|
||||
type="success"
|
||||
@click="resetComparison"
|
||||
>
|
||||
返回完整导图
|
||||
</el-button>
|
||||
<el-button size="small" @click="standardExpanded = !standardExpanded">
|
||||
{{ standardExpanded ? "折叠" : "展开" }}
|
||||
</el-button>
|
||||
|
||||
Reference in New Issue
Block a user