diff --git a/vue/src/components/GraphToolbar.vue b/vue/src/components/GraphToolbar.vue
index b83a14d..437bd58 100644
--- a/vue/src/components/GraphToolbar.vue
+++ b/vue/src/components/GraphToolbar.vue
@@ -270,12 +270,12 @@ export default {
const url = URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = url;
- link.download = `医疗图谱导出_${Date.now()}.svg`;
+ link.download = `医疗图谱_${Date.now()}.svg`;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
URL.revokeObjectURL(url);
- this.$message.success('高精度矢量图导出成功');
+ this.$message.success('图谱导出成功');
} catch (err) {
this.$message.error('导出失败');
}
diff --git a/vue/src/system/GraphDemo.vue b/vue/src/system/GraphDemo.vue
index 1439871..294cc22 100644
--- a/vue/src/system/GraphDemo.vue
+++ b/vue/src/system/GraphDemo.vue
@@ -134,6 +134,12 @@
@@ -154,15 +160,18 @@ import {
} from "@/api/graph"
import {Graph, Tooltip} from '@antv/g6';
import Menu from "@/components/Menu.vue";
+import GraphToolbar from "@/components/GraphToolbar.vue";
+import { markRaw } from 'vue';
import {a} from "vue-router/dist/devtools-EWN81iOl.mjs";
import Fuse from 'fuse.js';
import {getGraphStyleActive} from "@/api/style";
export default {
name: 'Display',
- components: {Menu},
+ components: {Menu,GraphToolbar},
data() {
return {
+ _graph: null,
G6: null, // 添加这个
// 节点样式
nodeShowLabel: true,
@@ -1174,7 +1183,7 @@ export default {
graph.fitCenter({ padding: 40, duration: 1000 });
}
});
- this._graph = graph
+ this._graph = markRaw(graph)
this._graph.setPlugins([ {
type: 'tooltip',
// 只对节点启用,边不显示tooltip
@@ -1201,12 +1210,26 @@ export default {
${sourceName} — ${rel} —> ${targetName}
`;
},
- },])
+ },
+ {
+ type: 'toolbar',
+ onClick: (id) => {
+ if (this.$refs.toolbarRef) {
+ this.$refs.toolbarRef.handleToolbarAction(id);
+ }
+ },
+ getItems: () => {
+ return [
+ {id: 'zoom-in', value: 'zoom-in', title: '放大'},
+ {id: 'zoom-out', value: 'zoom-out', title: '缩小'},
+ {id: 'auto-fit', value: 'auto-fit', title: '聚焦'},
+ {id: 'export', value: 'export', title: '导出图谱'},
+ ];
+ },
+ },
+ ])
}
-
-
},
-
updateGraph(data) {
if (!this._graph) return
this._graph.setData(data)
@@ -1236,7 +1259,6 @@ export default {
this.defaultData = updatedData
this.updateGraph(updatedData)
},
-
updateAllEdges() {
if (!this._graph) return
const updatedEdges = this.defaultData.edges.map(edge => ({
@@ -1407,7 +1429,6 @@ button:hover {
}
.graph-container {
- flex: 1;
background: #fff;
width: 100%;
height: 100%;
@@ -1546,10 +1567,14 @@ button:hover {
flex: 1;
border: 1px dashed #e2e8f0;
border-radius: 12px;
+ position: relative !important; /* 必须:作为工具栏参照物 */
+ overflow: hidden;
display: flex;
align-items: center;
justify-content: center;
color: #ccc;
+ background: #fff;
+ padding: 0 !important;
}
@@ -1691,4 +1716,16 @@ button:hover {
background-color: #f5f7fa;
}
+:deep(.custom-graph-toolbar) {
+ position: absolute !important; /* 脱离文档流,解决占位问题 */
+ top: 0 !important;
+ right: 0 !important;
+ z-index: 1000 !important;
+
+ background: rgba(255, 255, 255, 0.9) !important;
+ padding: 4px 8px !important;
+ border-radius: 8px !important;
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1) !important;
+ border: 1px solid #ebeef5 !important
+}
\ No newline at end of file
diff --git a/vue/src/system/GraphQA.vue b/vue/src/system/GraphQA.vue
index badd374..82c90f4 100644
--- a/vue/src/system/GraphQA.vue
+++ b/vue/src/system/GraphQA.vue
@@ -63,6 +63,12 @@
@@ -77,11 +83,12 @@ import {qaAnalyze} from "@/api/qa";
import {Graph} from "@antv/g6";
import {getGraph} from "@/api/graph";
import {getGraphStyleActive} from "@/api/style";
+import GraphToolbar from '@/components/GraphToolbar.vue';
export default {
name: 'GraghQA',
- components: {Menu},
+ components: {Menu,GraphToolbar},
data() {
return {
query:"",
@@ -244,47 +251,85 @@ export default {
}
},
- handleSearch(){
- this.isSending=true
- this.answers=[]
- if (this._graph){
+ handleSearch() {
+ this.isSending = true
+ this.answers = []
+ if (this._graph) {
this._graph.clear()
}
- let data={
- text:this.query
+ let data = {
+ text: this.query
}
- this.queryRecord=this.query
- this.query=""
+ this.queryRecord = this.query
+ this.query = ""
// this.answers=[{"answer":"糖尿病患者应避免高糖食物,如糖果、甜点、含糖饮料等,以防止血糖波动。",
// "result":{"nodes":[{"id":"e0a8410b-c5ee-47d4-acbe-b7ae5f111fd4","label":"糖尿病","type":"疾病"},{"id":"89f9498b-7a83-4361-889b-f96dfdfb802c","label":"血糖波动","type":"症状"},{"id":"03201620-ba9f-4957-b7d3-f89c5a115e37","label":"高糖食物","type":"其他类型"},{"id":"b0bace0a-eedc-485c-90d3-0a5378dc5556","label":"糖果","type":"其他类型"},{"id":"ffc12d7b-60e5-4ffa-a945-a0769f6e1047","label":"甜点","type":"其他类型"},{"id":"a7e94ee7-072b-456f-bc0c-354545851c38","label":"含糖饮料","type":"其他类型"}],"edges":[{"source":"e0a8410b-c5ee-47d4-acbe-b7ae5f111fd4","target":"03201620-ba9f-4957-b7d3-f89c5a115e37","label":"关联"},{"source":"e0a8410b-c5ee-47d4-acbe-b7ae5f111fd4","target":"b0bace0a-eedc-485c-90d3-0a5378dc5556","label":"关联"},{"source":"e0a8410b-c5ee-47d4-acbe-b7ae5f111fd4","target":"ffc12d7b-60e5-4ffa-a945-a0769f6e1047","label":"关联"},{"source":"e0a8410b-c5ee-47d4-acbe-b7ae5f111fd4","target":"a7e94ee7-072b-456f-bc0c-354545851c38","label":"关联"},{"source":"e0a8410b-c5ee-47d4-acbe-b7ae5f111fd4","target":"89f9498b-7a83-4361-889b-f96dfdfb802c","label":"导致"}]}}]
// this.initGraph(this.answers[0].result)
// this.formatData(this.answers[0].result)
- qaAnalyze(data).then(res=>{
- this.answers=res
- if(this.answers.length>0){
+ qaAnalyze(data).then(res => {
+ this.answers = res
+ if (this.answers.length > 0) {
this.initGraph(this.answers[0].result)
}
- this.isSending=false
- })
+ this.isSending = false
+ }).catch(err => {
+ console.error('接口失败,启动保底方案', err);
+ const mockData = {
+ nodes: [
+ {id: "node1", label: "霍乱", data: {type: "疾病"}},
+ {id: "node2", label: "腹泻", data: {type: "症状"}},
+ {id: "node3", label: "脱水", data: {type: "疾病"}},
+ {id: "node4", label: "呕吐", data: {type: "疾病"}},
+ {id: "node5", label: "霍乱弧菌", data: {type: "病因"}},
+ {id: "node6", label: "复方磺胺", data: {type: "药品"}},
+ ],
+ edges: [
+ {id: "e1", source: "node1", target: "node2", data: {label: "典型症状"}},
+ {id: "e2", source: "node1", target: "node3", data: {label: "并发症"}},
+ {id: "e3", source: "node1", target: "node4", data: {label: "并发症"}},
+ {id: "e4", source: "node1", target: "node5", data: {label: "致病菌"}},
+ {id: "e5", source: "node1", target: "node6", data: {label: "推荐用药"}},
+ ]
+ };
+ this.answers = [{answer: "连接失败,显示预览版。", result: mockData}];
+ this.initGraph(this.answers[0].result);
+ this.isSending = false;
+ });
},
formatData(data){
// this._graph.stopLayout();
// this.clearGraphState();
- // === 1. 构建 nodeId → label 映射 ===
- const nodeIdToEnLabel = {};
+ const typeMap = { '疾病': 'Disease', '药品': 'Drug', '药物': 'Drug', '症状': 'Symptom', '检查': 'Check', '病因': 'Cause' };
+ const getStandardLabel = (rawType) => typeMap[rawType] || rawType;
+
+ const nodeIdToData = {};
data.nodes.forEach(node => {
- nodeIdToEnLabel[node.id] = node.data.type; // e.g. "Disease"
+ nodeIdToData[node.id] = {
+ enLabel: getStandardLabel(node.data.type),
+ rawType: node.data.type
+ };
});
// === 2. 处理节点:根据自身 label 设置样式 ===
const updatedNodes = data.nodes.map(node => {
- const enLabel = node.data.type;
+ const enLabel = getStandardLabel(node.data.type);
const styleConf = this.parsedStyles[enLabel] || {};
+ // 💡 颜色映射逻辑:如果 styleConf 没给颜色,则按类型分配
+ let fColor = styleConf.nodeFill;
+ if (!fColor) {
+ if (node.data.type === '疾病') fColor = '#EF4444';
+ else if (node.data.type === '药品' || node.data.type === '药物') fColor = '#91cc75';
+ else if (node.data.type === '症状') fColor = '#fac858';
+ else if (node.data.type === '检查') fColor = '#336eee';
+ else fColor = this.nodeFill;
+ }
return {
...node,
type: styleConf.nodeShape || this.nodeShape,
+ data: { ...node.data, label: enLabel, name: node.label },
style: {
+ ...node.style,
size: styleConf.nodeSize || this.nodeSize,
- fill: styleConf.nodeFill || this.nodeFill,
+ fill: fColor,
stroke: styleConf.nodeStroke || this.nodeStroke,
lineWidth: styleConf.nodeLineWidth || this.nodeLineWidth,
label: styleConf.nodeShowLabel !== undefined ? styleConf.nodeShowLabel : true,
@@ -297,15 +342,25 @@ export default {
// === 3. 处理边:根据 source 节点的 label 设置样式 ===
const updatedEdges = data.edges.map(edge => {
- console.log(edge)
- const sourceEnLabel = nodeIdToEnLabel[edge.source]; // e.g. "Disease"
- const styleConf = this.parsedStyles[sourceEnLabel] || {};
+ const sourceInfo = nodeIdToData[edge.source];
+ const styleConf = this.parsedStyles[sourceInfo.enLabel] || {};
+
+ // 💡 边颜色逻辑:跟随源节点类型
+ let eStroke = styleConf.edgeStroke;
+ if (!eStroke) {
+ if (sourceInfo.rawType === '疾病') eStroke = 'rgba(239, 68, 68, 0.4)';
+ else if (sourceInfo.rawType === '药品' || sourceInfo.rawType === '药物') eStroke = 'rgba(145, 204, 117, 0.4)';
+ else if (sourceInfo.rawType === '症状') eStroke = 'rgba(250, 200, 88, 0.4)';
+ else eStroke = this.edgeStroke;
+ }
return {
...edge,
id: edge.data?.relationship?.id || edge.id,
type: styleConf.edgeType ||this.edgeType,
+ data: { ...edge.data, label: edge.data?.label || "" },
style: {
+ ...edge.style,
endArrow: styleConf.edgeEndArrow !== undefined ? styleConf.edgeEndArrow : true,
stroke: styleConf.edgeStroke || this.edgeStroke,
lineWidth: styleConf.edgeLineWidth || this.edgeLineWidth,
@@ -318,41 +373,49 @@ export default {
});
// === 4. 更新图数据 ===
- let updatedData = {
- nodes: updatedNodes,
- edges: updatedEdges
- };
-
- this.updateGraph(updatedData)
+ const pureData = JSON.parse(JSON.stringify({ nodes: updatedNodes, edges: updatedEdges }));
+ this.updateGraph(pureData);
},
updateGraph(data) {
- if (!this._graph) return
-
- this._graph.setData(data)
- this._graph.render()
+ if (!this._graph) return;
+ this._graph.setData(data);
+ this._graph.render();
},
initGraph(data) {
+ const typeMap = { '疾病': 'Disease', '药品': 'Drug', '药物': 'Drug', '症状': 'Symptom', '检查': 'Check', '病因': 'Cause' };
+ const getStandardLabel = (rawType) => typeMap[rawType] || rawType;
if (this._graph!=null){
this._graph.destroy()
this._graph = null;
}
- console.log(data)
// === 1. 构建 nodeId → label 映射 ===
- const nodeIdToEnLabel = {};
+ const nodeIdToData = {};
data.nodes.forEach(node => {
- nodeIdToEnLabel[node.id] = node.data.type; // e.g. "Disease"
+ nodeIdToData[node.id] = {
+ enLabel: getStandardLabel(node.data.type),
+ rawType: node.data.type
+ };
});
- console.log(nodeIdToEnLabel)
// === 2. 处理节点:根据自身 label 设置样式 ===
const updatedNodes = data.nodes.map(node => {
- const enLabel = node.data.type;
+ const enLabel = getStandardLabel(node.data.type);
const styleConf = this.parsedStyles[enLabel] || {};
+ let fColor = styleConf.nodeFill;
+ if (!fColor) {
+ if (node.data.type === '疾病') fColor = '#EF4444';
+ else if (node.data.type === '药品' || node.data.type === '药物') fColor = '#91cc75';
+ else if (node.data.type === '症状') fColor = '#fac858';
+ else if (node.data.type === '检查') fColor = '#336eee';
+ else fColor = this.nodeFill;
+ }
return {
...node,
type: styleConf.nodeShape || this.nodeShape,
+ data: { ...node.data, label: enLabel, name: node.label },
style: {
+ ...node.style,
size: styleConf.nodeSize || this.nodeSize,
- fill: styleConf.nodeFill || this.nodeFill,
+ fill: fColor,
stroke: styleConf.nodeStroke || this.nodeStroke,
lineWidth: styleConf.nodeLineWidth || this.nodeLineWidth,
label: styleConf.nodeShowLabel !== undefined ? styleConf.nodeShowLabel : true,
@@ -365,17 +428,26 @@ export default {
// === 3. 处理边:根据 source 节点的 label 设置样式 ===
const updatedEdges = data.edges.map(edge => {
- console.log(edge)
- const sourceEnLabel = nodeIdToEnLabel[edge.source]; // e.g. "Disease"
- const styleConf = this.parsedStyles[sourceEnLabel] || {};
+ const sourceInfo = nodeIdToData[edge.source];
+ const styleConf = this.parsedStyles[sourceInfo.enLabel] || {};
+
+ let eStroke = styleConf.edgeStroke;
+ if (!eStroke) {
+ if (sourceInfo.rawType === '疾病') eStroke = 'rgba(239, 68, 68, 0.4)';
+ else if (sourceInfo.rawType === '药品' || sourceInfo.rawType === '药物') eStroke = 'rgba(145, 204, 117, 0.4)';
+ else if (sourceInfo.rawType === '症状') eStroke = 'rgba(250, 200, 88, 0.4)';
+ else eStroke = this.edgeStroke;
+ }
return {
...edge,
id: edge.data?.relationship?.id || edge.id,
type: styleConf.edgeType ||this.edgeType,
+ data: { ...edge.data, label: edge.data?.label || "" },
style: {
+ ...edge.style,
endArrow: styleConf.edgeEndArrow !== undefined ? styleConf.edgeEndArrow : true,
- stroke: styleConf.edgeStroke || this.edgeStroke,
+ stroke: eStroke,
lineWidth: styleConf.edgeLineWidth || this.edgeLineWidth,
label: styleConf.edgeShowLabel !== undefined ? styleConf.edgeShowLabel : false,
labelFontSize: styleConf.edgeFontSize || this.edgeFontSize,
@@ -402,14 +474,27 @@ export default {
container,
width,
height,
+ plugins: [
+ {
+ type: 'toolbar',
+ key: 'g6-toolbar',
+ onClick: (id) => {
+ if (this.$refs.toolbarRef) this.$refs.toolbarRef.handleToolbarAction(id);
+ },
+ getItems: () => [
+ { id: 'zoom-in', value: 'zoom-in', title: '放大' },
+ { id: 'zoom-out', value: 'zoom-out', title: '缩小' },
+ { id: 'auto-fit', value: 'auto-fit', title: '聚焦' },
+ { id: 'export', value: 'export', title: '导出图谱' },
+ ],
+ },
+ ],
layout: {
type: 'force', // 力导向布局
gravity: 0.3, // 重力系数,控制节点聚集程度
repulsion: 500, // 排斥力
attraction: 20, // 吸引力
preventOverlap: true // 防止节点重叠
-
-
},
behaviors: [ 'zoom-canvas', 'drag-element',
'click-select','focus-element', {
@@ -724,4 +809,39 @@ export default {
.dot-2 { animation-delay: -0.2s; }
.dot-3 { animation-delay: 0s; }
.dot-4 { animation-delay: 0.2s; }
+
+/* 右侧图谱外层容器 */
+.knowledge-graph {
+ position: relative !important; /* 保持相对定位,作为工具栏的参照物 */
+ flex: 1;
+ height: 100%;
+ background-color: white;
+ border-radius: 16px;
+ padding: 0 !important;
+ box-shadow: 0 4px 12px rgba(0,0,0,0.05);
+ overflow: hidden;
+ display: flex;
+}
+
+/* 图谱画布容器 */
+.graph-container {
+ width: 100% !important;
+ height: 100% !important;
+ margin: 0 !important;
+ padding: 0 !important;
+}
+
+/* 工具栏浮动修饰 */
+:deep(.custom-graph-toolbar) {
+ position: absolute !important; /* 必须绝对定位,不占物理高度 */
+ top: 0 !important;
+ right: 0 !important;
+ z-index: 9999 !important;
+ display: inline-flex !important;
+ background: rgba(255, 255, 255, 0.9) !important;
+ padding: 5px !important;
+ border-radius: 8px !important;
+ border: 1px solid #ebeef5 !important;
+ box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1) !important;
+}
\ No newline at end of file
diff --git a/vue/src/system/GraphStyle.vue b/vue/src/system/GraphStyle.vue
index 46c917c..2f91029 100644
--- a/vue/src/system/GraphStyle.vue
+++ b/vue/src/system/GraphStyle.vue
@@ -961,7 +961,10 @@ export default {
updateAllElements() {
if (!this._graph) return;
+ // 1. 获取当前状态快照
const currentActiveLabelEn = tagToLabelMap[this.activeTags];
+
+ // 2. 收集已应用的配置方案
const labelToAppliedConfigMap = {};
this.styleGroups.forEach(group => {
group.configs.forEach(conf => {
@@ -972,13 +975,33 @@ export default {
});
});
- const hexToRgba = (hex, opacity) => {
- if (!hex) return 'rgba(182, 178, 178, 0.5)';
- if (hex.startsWith('rgba')) return hex;
- let r = parseInt(hex.slice(1, 3), 16), g = parseInt(hex.slice(3, 5), 16), b = parseInt(hex.slice(5, 7), 16);
- return `rgba(${r}, ${g}, ${b}, ${opacity})`;
+ // 3. 💡 增强版颜色转换函数:完美兼容 Hex 和 RGB
+ const hexToRgba = (color, opacity) => {
+ if (!color) return `rgba(182, 178, 178, ${opacity})`;
+ // 如果已经是 rgba,直接返回
+ if (color.startsWith('rgba')) return color;
+ // A. 处理 rgb(116, 239, 68) 格式
+ if (color.startsWith('rgb')) {
+ // 将 rgb 替换为 rgba,并在结尾插入透明度
+ return color.replace('rgb', 'rgba').replace(')', `, ${opacity})`);
+ }
+ // B. 处理 #ffffff 格式
+ if (color.startsWith('#')) {
+ try {
+ let r = parseInt(color.slice(1, 3), 16),
+ g = parseInt(color.slice(3, 5), 16),
+ b = parseInt(color.slice(5, 7), 16);
+ return `rgba(${r}, ${g}, ${b}, ${opacity})`;
+ } catch (e) {
+ console.error('❌ Hex 转换失败:', color);
+ return color;
+ }
+ }
+ // C. 兜底返回原色
+ return color;
};
+ // 4. 处理节点 (Nodes)
const nodes = this.defaultData.nodes.map(node => {
const rawLabel = node.data?.label || '';
const effectiveKey = this.getEffectiveStyleKey(rawLabel);
@@ -996,46 +1019,85 @@ export default {
}
return {
- ...node, type: s?.nodeShape || 'circle',
+ ...node,
+ type: s?.nodeShape || 'circle',
style: {
- size: this.safeNum(s?.nodeSize, 60), fill: s?.nodeFill, stroke: s?.nodeStroke,
- lineWidth: this.safeNum(s?.nodeLineWidth, 2), labelText: s?.nodeShowLabel ? (node.data?.name || '') : '',
- labelFill: s?.nodeFontColor || '#ffffff', labelFontSize: this.safeNum(s?.nodeFontSize, 12),
- labelFontFamily: s?.nodeFontFamily || 'Microsoft YaHei', labelPlacement: 'center', labelWordWrap: true,
- labelMaxWidth: '150%', labelMaxLines: 3, labelTextOverflow: 'ellipsis', labelTextAlign: 'center',
+ size: this.safeNum(s?.nodeSize, 60),
+ fill: s?.nodeFill,
+ stroke: s?.nodeStroke,
+ lineWidth: this.safeNum(s?.nodeLineWidth, 2),
+ labelText: s?.nodeShowLabel ? (node.data?.name || '') : '',
+ labelFill: s?.nodeFontColor || '#ffffff',
+ labelFontSize: this.safeNum(s?.nodeFontSize, 12),
+ labelFontFamily: s?.nodeFontFamily || 'Microsoft YaHei',
+ labelPlacement: 'center',
+ labelWordWrap: true,
+ labelMaxWidth: '150%',
+ labelMaxLines: 3,
+ labelTextOverflow: 'ellipsis',
+ labelTextAlign: 'center',
}
};
});
- const edges = this.defaultData.edges.map(edge => {
+ // 5. 处理连边 (Edges)
+ const edges = this.defaultData.edges.map((edge, index) => {
const sRawLabel = this._nodeLabelMap.get(edge.source);
const effectiveKey = this.getEffectiveStyleKey(sRawLabel);
let s;
+ let sourceFrom = '';
+
if (effectiveKey === currentActiveLabelEn) {
+ sourceFrom = '实时面板控制';
s = {
- edgeType: this.edgeType, edgeStroke: this.edgeStroke, edgeLineWidth: this.edgeLineWidth,
- edgeEndArrow: this.edgeEndArrow, edgeShowLabel: this.edgeShowLabel,
- edgeFontColor: this.edgeFontColor, edgeFontSize: this.edgeFontSize, edgeFontFamily: this.edgeFontFamily
+ edgeType: this.edgeType,
+ edgeStroke: this.edgeStroke,
+ edgeLineWidth: this.edgeLineWidth,
+ edgeEndArrow: this.edgeEndArrow,
+ edgeShowLabel: this.edgeShowLabel,
+ edgeFontColor: this.edgeFontColor,
+ edgeFontSize: this.edgeFontSize,
+ edgeFontFamily: this.edgeFontFamily
};
} else {
+ sourceFrom = '缓存/方案配置';
s = labelToAppliedConfigMap[effectiveKey] || this.tagStyles[effectiveKey];
}
- const strokeColor = hexToRgba(s?.edgeStroke || '#EF4444', 0.6);
+ // 使用修正后的颜色读取逻辑
+ const finalRawColor = s?.edgeStroke || this.edgeStroke || INITIAL_FILL_MAP[effectiveKey] || '#EF4444';
+ const strokeColor = hexToRgba(finalRawColor, 0.6);
+
+ if (index === 0) {
+ console.log('3. [连边抽检] 第一条边颜色详情:');
+ console.log(' - 原始输入:', finalRawColor);
+ console.log(' - 转换输出:', strokeColor);
+ }
+
return {
- ...edge, type: s?.edgeType || 'line',
+ ...edge,
+ type: s?.edgeType || 'line',
style: {
- stroke: strokeColor, lineWidth: this.safeNum(s?.edgeLineWidth, 2), endArrow: s?.edgeEndArrow,
+ stroke: strokeColor,
+ lineWidth: this.safeNum(s?.edgeLineWidth, 2),
+ endArrow: s?.edgeEndArrow !== undefined ? s.edgeEndArrow : true,
labelText: s?.edgeShowLabel ? (edge.data?.relationship?.properties?.label || '') : '',
- labelFill: s?.edgeFontColor || '#666', labelFontSize: this.safeNum(s?.edgeFontSize, 10),
- labelFontFamily: s?.edgeFontFamily || 'Microsoft YaHei', labelBackground: true,
- labelBackgroundFill: '#fff', labelBackgroundOpacity: 0.7
+ labelFill: s?.edgeFontColor || '#666',
+ labelFontSize: this.safeNum(s?.edgeFontSize, 10),
+ labelFontFamily: s?.edgeFontFamily || 'Microsoft YaHei',
+ labelBackground: true,
+ labelBackgroundFill: '#fff',
+ labelBackgroundOpacity: 0.7
}
};
});
+
+ // 6. 提交渲染
this._graph.setData({ nodes, edges });
this._graph.render();
+ console.log('4. 图谱渲染指令已发出');
+ console.groupEnd();
},
safeNum(val, defaultVal = 1) {
const n = Number(val);