diff --git a/vue/src/system/GraphStyle.vue b/vue/src/system/GraphStyle.vue
index dfa2345..82027c3 100644
--- a/vue/src/system/GraphStyle.vue
+++ b/vue/src/system/GraphStyle.vue
@@ -15,14 +15,11 @@
-
- {{ tag }}
+ {{ tag }}
@@ -71,7 +68,13 @@
-
+
@@ -143,7 +152,13 @@
-
+
@@ -294,24 +309,16 @@ import {ElMessageBox, ElMessage} from 'element-plus';
import {markRaw} from 'vue';
const tagToLabelMap = {
- '疾病': 'Disease', '症状': 'Symptom', '病因': 'Cause', '药品': 'Drug', '科室': 'Department', '检查': 'Check'
+ '疾病': 'Disease', '症状': 'Symptom', '病因': 'Cause', '药品': 'Drug', '科室': 'Department', '检查': 'Check','其他':'Other'
};
const INITIAL_FILL_MAP = {
- 'Disease': '#EF4444',
- 'Drug': '#91cc75',
- 'Symptom': '#fac858',
- 'Check': '#336eee',
- 'Cause': '#59d1d4',
- 'Department': '#59d1d4',
+ 'Disease': '#EF4444', 'Drug': '#91cc75', 'Symptom': '#fac858', 'Check': '#336eee',
+ 'Cause': '#59d1d4', 'Department': '#59d1d4', 'Other': '#59d1d4'
};
const INITIAL_STROKE_MAP = {
- 'Disease': '#B91C1C',
- 'Drug': '#047857',
- 'Symptom': '#B45309',
- 'Check': '#1D4ED8',
- 'Cause': '#40999b',
- 'Department': '#40999b',
+ 'Disease': '#B91C1C', 'Drug': '#047857', 'Symptom': '#B45309', 'Check': '#1D4ED8',
+ 'Cause': '#40999b', 'Department': '#40999b', 'Other': '#40999b'
};
export default {
@@ -319,7 +326,7 @@ export default {
components: {Menu},
data() {
return {
- activeTags: '',
+ activeTags: '疾病',
styleGroups: [],
existingGroups: [],
activeCollapseNames: [],
@@ -336,6 +343,7 @@ export default {
'Department': this.getInitialTagParams('Department'),
'DiseaseSite': this.getInitialTagParams('DiseaseSite'),
'Check': this.getInitialTagParams('Check'),
+ 'Other': this.getInitialTagParams('Other'),
},
nodeShowLabel: true,
nodeFontFamily: 'Microsoft YaHei, sans-serif',
@@ -353,7 +361,7 @@ export default {
edgeFontColor: '#666666',
edgeType: 'line',
edgeLineWidth: 2,
- edgeStroke: '#b6b2b2',
+ edgeStroke: '#EF4444', // 初始同步节点颜色
defaultData: {
nodes: [
{id: "node1", data: {name: "霍乱", label: "Disease"}},
@@ -384,13 +392,34 @@ export default {
}
},
watch: {
+ // 新增:监听方案勾选,同步勾选其下的所有画布
+ checkedGroupIds(newGroupIds) {
+ // 遍历所有方案
+ this.styleGroups.forEach(group => {
+ const isGroupChecked = newGroupIds.includes(group.id);
+ const childIds = group.configs.map(c => c.id);
+
+ if (isGroupChecked) {
+ // 如果方案被勾选,将子画布 ID 全部加入 checkedConfigIds (去重)
+ this.checkedConfigIds = Array.from(new Set([...this.checkedConfigIds, ...childIds]));
+ } else {
+ // 如果方案取消勾选,将子画布 ID 从 checkedConfigIds 中移除
+ this.checkedConfigIds = this.checkedConfigIds.filter(id => !childIds.includes(id));
+ }
+ });
+ },
+ // 监听节点填充色,强制同步线条色
+ nodeFill(newVal) {
+ this.edgeStroke = newVal;
+ },
nodeShowLabel: 'syncAndRefresh', nodeFontFamily: 'syncAndRefresh', nodeFontSize: 'syncAndRefresh',
nodeFontColor: 'syncAndRefresh', nodeShape: 'syncAndRefresh', nodeSize: 'syncAndRefresh',
- nodeFill: 'syncAndRefresh', nodeStroke: 'syncAndRefresh', nodeLineWidth: 'syncAndRefresh',
+ nodeStroke: 'syncAndRefresh', nodeLineWidth: 'syncAndRefresh',
edgeShowLabel: 'syncAndRefresh', edgeEndArrow: 'syncAndRefresh', edgeFontFamily: 'syncAndRefresh',
edgeFontSize: 'syncAndRefresh', edgeFontColor: 'syncAndRefresh', edgeType: 'syncAndRefresh',
edgeLineWidth: 'syncAndRefresh', edgeStroke: 'syncAndRefresh'
},
+
created() {
this._graph = null;
this._nodeLabelMap = new Map();
@@ -412,21 +441,47 @@ export default {
window.removeEventListener('resize', this.handleResize);
},
methods: {
- getStaticColor(tag) {
- const label = tagToLabelMap[tag];
- if (label === 'Disease') return '#EF4444';
- if (label === 'Drug') return '#91cc75';
- if (label === 'Symptom') return '#fac858';
- if (label === 'Check') return '#336eee';
- return '#59d1d4';
+ validateNodeSize(event) {
+ const inputVal = event.target.value;
+ const val = parseInt(inputVal);
+ if (isNaN(val) || val < 30 || val > 100) {
+ ElMessage({ message: `节点尺寸请输入 30 到 100 之间的数字`, type: 'warning', duration: 1500 });
+ event.target.value = this.nodeSize;
+ return;
+ }
+ this.nodeSize = val;
+ this.syncAndRefresh();
+ },
+ validateNodeLineWidth(event) {
+ const inputVal = event.target.value;
+ const val = parseInt(inputVal);
+ if (isNaN(val) || val < 1 || val > 5) {
+ ElMessage({ message: `边框尺寸请输入 1 到 5 之间的数字`, type: 'warning', duration: 1500 });
+ event.target.value = this.nodeLineWidth;
+ return;
+ }
+ this.nodeLineWidth = val;
+ this.syncAndRefresh();
+ },
+ validateEdgeLineWidth(event) {
+ const inputVal = event.target.value;
+ const val = parseInt(inputVal);
+ if (isNaN(val) || val < 1 || val > 5) {
+ ElMessage({ message: `线条粗细请输入 1 到 5 之间的数字`, type: 'warning', duration: 1500 });
+ event.target.value = this.edgeLineWidth;
+ return;
+ }
+ this.edgeLineWidth = val;
+ this.syncAndRefresh();
},
getInitialTagParams(label) {
+ const fill = INITIAL_FILL_MAP[label] || '#59d1d4';
return {
nodeShowLabel: true, nodeFontFamily: 'Microsoft YaHei, sans-serif', nodeFontSize: 12, nodeFontColor: '#ffffff',
- nodeShape: 'circle', nodeSize: 60, nodeFill: INITIAL_FILL_MAP[label] || '#59d1d4',
+ nodeShape: 'circle', nodeSize: 60, nodeFill: fill,
nodeStroke: INITIAL_STROKE_MAP[label] || '#40999b', nodeLineWidth: 2, edgeShowLabel: true, edgeEndArrow: true,
edgeFontFamily: 'Microsoft YaHei, sans-serif', edgeFontSize: 10, edgeFontColor: '#666666', edgeType: 'line',
- edgeLineWidth: 2, edgeStroke: '#b6b2b2'
+ edgeLineWidth: 2, edgeStroke: fill // 初始线条颜色同步填充色
};
},
handleTagClick(tag) {
@@ -474,6 +529,14 @@ 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})`;
+ };
+
const nodes = this.defaultData.nodes.map(node => {
const labelEn = node.data?.label || '';
const s = labelToAppliedConfigMap[labelEn] || this.tagStyles[labelEn];
@@ -488,35 +551,32 @@ export default {
}
};
});
- let edgeS = this;
- if (this.usingConfigIds.length > 0) {
- const lastAppliedId = this.usingConfigIds[this.usingConfigIds.length - 1];
- this.styleGroups.forEach(g => {
- const found = g.configs.find(c => c.id === lastAppliedId);
- if (found) edgeS = found.styles;
- });
- }
- const hexToRgba = (hex, opacity) => {
- if (!hex) return 'rgba(182, 178, 178, 0.5)';
- 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})`;
- };
+
const edges = this.defaultData.edges.map(edge => {
- const s = edgeS;
const sLabel = this._nodeLabelMap.get(edge.source);
- const sourceNodeStyles = labelToAppliedConfigMap[sLabel] || this.tagStyles[sLabel];
- const dynamicStroke = hexToRgba(sourceNodeStyles?.nodeFill, 0.5);
+ // 获取源节点对应的样式(可能是方案里的,也可能是实时调整的)
+ const s = labelToAppliedConfigMap[sLabel] || this.tagStyles[sLabel] || this;
+
+ // 线条颜色直接取该标签配置下的 edgeStroke
+ const strokeColor = hexToRgba(s.edgeStroke, 0.6);
+
return {
...edge, type: s.edgeType || 'line',
style: {
- stroke: dynamicStroke, lineWidth: this.safeNum(s.edgeLineWidth, 2), endArrow: s.edgeEndArrow,
+ stroke: strokeColor,
+ lineWidth: this.safeNum(s.edgeLineWidth, 2),
+ endArrow: s.edgeEndArrow,
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
}
};
});
+
this._graph.setData({nodes, edges});
this._graph.render();
},
@@ -533,7 +593,6 @@ export default {
...conf, styles: typeof conf.styles === 'string' ? JSON.parse(conf.styles) : conf.styles
}))
}));
- if (this.styleGroups.length > 0 && this.activeCollapseNames.length === 0) this.activeCollapseNames = [this.styleGroups[0].id];
}
} catch (err) {
console.error("加载配置失败:", err);
@@ -583,7 +642,9 @@ export default {
},
handleSaveClick() {
this.fetchGroupNames();
- this.saveForm.canvas_name = `样式_${new Date().toLocaleTimeString([], {hour: '2-digit', minute: '2-digit'})}`;
+
+ // 使用 Date.now() 获取当前 13 位毫秒时间戳
+ this.saveForm.canvas_name = Date.now().toString();
this.saveDialogVisible = true;
},
async confirmSave() {
@@ -615,8 +676,7 @@ export default {
this.fetchConfigs();
this.updateAllElements();
}
- } catch (err) {
- }
+ } catch (err) {}
},
async deleteGroup(groupId) {
try {
@@ -626,19 +686,27 @@ export default {
this.fetchConfigs();
this.updateAllElements();
}
- } catch (err) {
- }
+ } catch (err) {}
},
async handleUnifiedBatchDelete() {
try {
- await ElMessageBox.confirm(`确定执行批量删除吗?`);
+ await ElMessageBox.confirm(
+ '确定执行批量删除吗?',
+ '批量删除', // 这里添加标题
+ {
+ confirmButtonText: '确定',
+ cancelButtonText: '取消',
+ type: 'warning',
+ // 确保标题和内容对齐
+ distinguishCancelAndClose: true,
+ }
+ );
for (const gid of this.checkedGroupIds) await deleteGraphStyleGroup(gid);
if (this.checkedConfigIds.length > 0) await batchDeleteGraphStyle({ids: this.checkedConfigIds});
this.clearSelection();
this.fetchConfigs();
this.updateAllElements();
- } catch (e) {
- }
+ } catch (e) {}
},
clearSelection() {
this.checkedConfigIds = [];
@@ -652,6 +720,44 @@ export default {
\ No newline at end of file
+
+/* 统一修改所有弹窗和消息框的标题与取消按钮 */
+:deep(.el-dialog__title),
+:deep(.el-message-box__title) {
+ color: #000000 !important;
+ font-weight: 600 !important;
+}
+
+:deep(.el-dialog__header),
+:deep(.el-message-box__header) {
+ text-align: left !important;
+}
+
+:deep(.el-dialog__footer .el-button:first-child),
+:deep(.el-message-box__btns .el-button:first-child) {
+ background-color: #e6e6e6 !important;
+ border-color: #e6e6e6 !important;
+ color: #333 !important;
+}
+:deep(.el-message-box__btns .el-button--primary) {
+ background-color: #1559f3 !important;
+ border-color: #1559f3 !important;
+}
+
+
+