From 83c2d201261cbee630e447f87ce4a02f4b001c79 Mon Sep 17 00:00:00 2001 From: hanyuqing <1106611654@qq.com> Date: Wed, 31 Dec 2025 15:55:26 +0800 Subject: [PATCH] all --- controller/QAController.py | 9 ++- vue/src/system/GraphBuilder.vue | 13 +++- vue/src/system/GraphQA.vue | 128 +++++++++++++++++++++++++++++++++------- 3 files changed, 125 insertions(+), 25 deletions(-) diff --git a/controller/QAController.py b/controller/QAController.py index 0613334..48fe2dd 100644 --- a/controller/QAController.py +++ b/controller/QAController.py @@ -25,7 +25,10 @@ def convert_to_g6_format(data): nodes.append({ "id": node_id, "label": name, - "type": ent["t"] # 可用于 G6 的节点样式区分 + "data":{ + "type": ent["t"] # 可用于 G6 的节点样式区分 + } + }) # 构建边 @@ -42,7 +45,9 @@ def convert_to_g6_format(data): edges.append({ "source": source_id, "target": target_id, - "label": r + "data": { + "label": r + } }) else: print(f"Warning: Entity not found for relation: {rel}") diff --git a/vue/src/system/GraphBuilder.vue b/vue/src/system/GraphBuilder.vue index 1cd39e4..7640e46 100644 --- a/vue/src/system/GraphBuilder.vue +++ b/vue/src/system/GraphBuilder.vue @@ -28,7 +28,7 @@
-
+
{{ msg.content }}
@@ -51,7 +51,7 @@ :id="'entity-' + i" :value="ent" v-model="ent.selected" - @click="handleEntitySelectionChange(msg,ent)" + @change="handleEntitySelectionChange(msg,ent)" />
@@ -103,13 +104,96 @@ export default { }; }, + // =============== 👇【新增】组件内路由守卫:离开当前路由时触发 =============== + beforeRouteLeave(to, from, next) { + this.saveDataToLocalStorage(); + next(); // 允许导航 + }, + // ======================================================================= + + mounted() { + // =============== 👇【新增】页面加载时从 localStorage 恢复数据 =============== + this.restoreDataFromLocalStorage(); + // ======================================================================= + + // 如果有初始数据,可以初始化图谱(可选) + if (this.answers.length > 0) { + this.initGraph(this.answers[0].result); + } + }, + + beforeUnmount() { + // =============== 👇【新增】组件销毁前也保存一次(兼容非路由跳转场景)============== + this.saveDataToLocalStorage(); + // 移除页面卸载监听(如果用了 beforeunload) + window.removeEventListener('beforeunload', this.handleBeforeUnload); + // ======================================================================= + }, + + created() { + // =============== 👇【新增】监听页面刷新/关闭事件 =============== + window.addEventListener('beforeunload', this.handleBeforeUnload); + // ======================================================================= + }, methods: { + buildNodeLabelMap(nodes) { + this._nodeLabelMap = new Map(); + nodes.forEach(node => { + this._nodeLabelMap.set(node.id, node.data?.type || 'default'); + }); + }, +// =============== 👇【新增】统一的数据保存方法 =============== + saveDataToLocalStorage() { + try { + localStorage.setItem('graphQA_queryRecord', this.queryRecord); + localStorage.setItem('graphQA_answers', JSON.stringify(this.answers)); + console.log('✅ 数据已保存到 localStorage'); + } catch (e) { + console.warn('⚠️ 无法保存到 localStorage:', e); + } + }, + // ======================================================================= + + // =============== 👇【新增】统一的数据恢复方法 =============== + restoreDataFromLocalStorage() { + try { + const savedQuery = localStorage.getItem('graphQA_queryRecord'); + const savedAnswers = localStorage.getItem('graphQA_answers'); + + if (savedQuery !== null) { + this.queryRecord = savedQuery; + } + if (savedAnswers !== null) { + this.answers = JSON.parse(savedAnswers); + // 确保 selected 不越界 + if (this.answers.length > 0) { + this.selected = Math.min(this.selected, this.answers.length - 1); + } + } + console.log('✅ 数据已从 localStorage 恢复'); + } catch (e) { + console.warn('⚠️ 无法从 localStorage 恢复数据:', e); + // 出错时清空(避免脏数据) + localStorage.removeItem('graphQA_queryRecord'); + localStorage.removeItem('graphQA_answers'); + } + }, + // ======================================================================= + + // =============== 👇【新增】处理页面关闭/刷新的兜底保存 =============== + handleBeforeUnload(event) { + this.saveDataToLocalStorage(); + // 注意:现代浏览器通常不显示自定义消息 + event.preventDefault(); + event.returnValue = ''; // 必须设置才能触发提示(但实际可能不显示) + }, selectGraph(index){ this.selected=index this.formatData(this.answers[index].result) }, handleSearch(){ this.answers=[] + this.formatData([]) let data={ text:this.query } @@ -127,8 +211,8 @@ export default { }) }, formatData(data){ - this._graph.stopLayout(); - this.clearGraphState(); + // this._graph.stopLayout(); + // this.clearGraphState(); const updatedEdges = data.edges.map(edge => ({ ...edge, type: this.edgeType, @@ -204,6 +288,7 @@ export default { nodes: updatedNodes, edges: updatedEdges } + this.buildNodeLabelMap(updatedNodes); const container = this.$refs.graphContainer; console.log(container) if (container!=null){ @@ -241,19 +326,20 @@ export default { node: { style: { fill: (d) => { - const label = d?.type; - if (label === 'Disease') return '#EF4444'; // 红 - if (label === 'Drug') return '#91cc75'; // 绿 - if (label === 'Symptom') return '#fac858'; // 橙 - if (label === 'Check') return '#336eee'; // 橙 + + const label = d.data?.type; + if (label === '疾病') return '#EF4444'; // 红 + if (label === '药品'||label === '药物') return '#91cc75'; // 绿 + if (label === '症状') return '#fac858'; // 橙 + if (label === '检查') return '#336eee'; // 橙 return '#59d1d4'; // 默认灰蓝 }, stroke: (d) => { - const label = d?.type; - if (label === 'Disease') return '#B91C1C'; - if (label === 'Drug') return '#047857'; - if (label === 'Check') return '#1D4ED8'; // 橙 - if (label === 'Symptom') return '#B45309'; + const label = d.data?.type; + if (label === '疾病') return '#B91C1C'; + if (label === '药品'||label === '药物') return '#047857'; + if (label === '检查') return '#1D4ED8'; // 橙 + if (label === '症状') return '#B45309'; return '#40999b'; }, labelText: (d) => d.label, @@ -282,17 +368,18 @@ export default { }, }, + edge: { style: { - labelText: (d) => d.label, + labelText: (d) => { + console.log(d) + return d.data.label}, stroke: (d) => { - // 获取 target 节点的 label - // const targetLabel = this._nodeLabelMap.get(d.source); // d.target 是目标节点 ID - // // 根据 target 节点类型返回对应浅色 - // if (targetLabel === 'Disease') return 'rgba(239,68,68,0.5)'; - // if (targetLabel === 'Drug') return 'rgba(145,204,117,0.5)'; - // if (targetLabel === 'Symptom') return 'rgba(250,200,88,0.5)'; - // if (targetLabel === 'Check') return 'rgba(51,110,238,0.5)'; // 橙 + const targetLabel = this._nodeLabelMap.get(d.source); // d.target 是目标节点 ID + if (targetLabel === '疾病') return 'rgba(239,68,68,0.5)'; + if (targetLabel === '药品'||targetLabel === '药物') return 'rgba(145,204,117,0.5)'; + if (targetLabel === '症状') return 'rgba(250,200,88,0.5)'; + if (targetLabel === '检查') return 'rgba(51,110,238,0.5)'; // 橙 return 'rgba(89,209,212,0.5)'; // default }, // labelFill: (d) => { @@ -342,6 +429,7 @@ export default { }, + }, };