diff --git a/vue/src/system/GraphStyle.vue b/vue/src/system/GraphStyle.vue
index b5fa14d..b4ce351 100644
--- a/vue/src/system/GraphStyle.vue
+++ b/vue/src/system/GraphStyle.vue
@@ -462,8 +462,14 @@ export default {
methods: {
handleEditConfig(item) {
if (this.saveTimer) clearTimeout(this.saveTimer);
- this.isInitialEcho = true;
+ // 如果点击的是当前正在编辑的配置,则退出编辑状态
+ if (this.editingConfigId === item.id) {
+ this.exitEditingMode();
+ return;
+ }
+
+ this.isInitialEcho = true;
this.editingConfigId = item.id;
this.editingConfigLabel = item.current_label;
this.activeTags = item.current_label;
@@ -474,6 +480,32 @@ export default {
return;
}
+ // 将配置应用到控制面板变量
+ this.applyStylesToPanel(s);
+
+ const labelEn = tagToLabelMap[item.current_label];
+ if (labelEn) this.tagStyles[labelEn] = JSON.parse(JSON.stringify(s));
+
+ // 确保该配置在 usingConfigIds 中
+ if (!this.usingConfigIds.includes(item.id)) {
+ this.styleGroups.forEach(g => {
+ g.configs.forEach(c => {
+ if (this.usingConfigIds.includes(c.id) && c.current_label === item.current_label) {
+ this.usingConfigIds = this.usingConfigIds.filter(id => id !== c.id);
+ }
+ });
+ });
+ this.usingConfigIds.push(item.id);
+ }
+
+ this.updateAllElements();
+ this.$nextTick(() => {
+ setTimeout(() => { this.isInitialEcho = false; }, 100);
+ });
+ },
+
+ // 抽离:将样式对象应用到左侧面板变量
+ applyStylesToPanel(s) {
this.nodeShowLabel = s.nodeShowLabel;
this.nodeFontFamily = s.nodeFontFamily;
this.nodeFontSize = s.nodeFontSize;
@@ -491,27 +523,28 @@ export default {
this.edgeType = s.edgeType;
this.edgeLineWidth = s.edgeLineWidth;
this.edgeStroke = s.edgeStroke;
+ },
- const labelEn = tagToLabelMap[item.current_label];
- if (labelEn) this.tagStyles[labelEn] = JSON.parse(JSON.stringify(s));
+ // 退出编辑模式:恢复控制栏到初始默认值
+ exitEditingMode() {
+ this.editingConfigId = null;
+ this.editingConfigLabel = '';
- if (!this.usingConfigIds.includes(item.id)) {
- this.styleGroups.forEach(g => {
- g.configs.forEach(c => {
- if (this.usingConfigIds.includes(c.id) && c.current_label === item.current_label) {
- this.usingConfigIds = this.usingConfigIds.filter(id => id !== c.id);
- }
- });
- });
- this.usingConfigIds.push(item.id);
- }
+ // 获取当前标签对应的系统初始默认样式
+ const labelEn = tagToLabelMap[this.activeTags];
+ const defaultStyle = this.getInitialTagParams(labelEn);
+
+ this.isInitialEcho = true;
+ // 1. 恢复控制面板UI
+ this.applyStylesToPanel(defaultStyle);
+ // 2. 恢复本地缓存(使图谱在该标签下也回归默认预览色)
+ this.tagStyles[labelEn] = JSON.parse(JSON.stringify(defaultStyle));
- this.updateAllElements();
this.$nextTick(() => {
- setTimeout(() => {
- this.isInitialEcho = false;
- }, 100);
+ this.isInitialEcho = false;
+ this.updateAllElements();
});
+ ElMessage.info("已退出编辑模式,控制栏已恢复默认");
},
syncAndRefresh() {
@@ -529,9 +562,11 @@ export default {
edgeLineWidth: this.edgeLineWidth, edgeStroke: this.edgeStroke
};
+ // 实时预览更新
this.tagStyles[labelEn] = currentStyle;
this.updateAllElements();
+ // 只有在编辑模式下才同步到数据库
if (this.editingConfigId) {
if (this.saveTimer) clearTimeout(this.saveTimer);
const currentEditId = this.editingConfigId;
@@ -593,12 +628,12 @@ export default {
}
this.edgeLineWidth = val;
},
- getInitialTagParams(label) {
- const fill = INITIAL_FILL_MAP[label] || '#59d1d4';
+ getInitialTagParams(labelEn) {
+ const fill = INITIAL_FILL_MAP[labelEn] || '#59d1d4';
return {
nodeShowLabel: true, nodeFontFamily: 'Microsoft YaHei, sans-serif', nodeFontSize: 12, nodeFontColor: '#ffffff',
nodeShape: 'circle', nodeSize: 60, nodeFill: fill,
- nodeStroke: INITIAL_STROKE_MAP[label] || '#40999b', nodeLineWidth: 2, edgeShowLabel: true, edgeEndArrow: true,
+ nodeStroke: INITIAL_STROKE_MAP[labelEn] || '#40999b', nodeLineWidth: 2, edgeShowLabel: true, edgeEndArrow: true,
edgeFontFamily: 'Microsoft YaHei, sans-serif', edgeFontSize: 10, edgeFontColor: '#666666', edgeType: 'line',
edgeLineWidth: 2, edgeStroke: fill
};
@@ -623,10 +658,17 @@ export default {
performTagSwitch(tag) {
this.activeTags = tag;
const labelEn = tagToLabelMap[tag];
- const style = this.tagStyles[labelEn];
+
+ // 如果不在编辑模式,切换标签时让控制栏显示该标签的默认样式
+ const style = this.editingConfigId ? this.tagStyles[labelEn] : this.getInitialTagParams(labelEn);
+
if (style) {
this.isInitialEcho = true;
- Object.assign(this, style);
+ this.applyStylesToPanel(style);
+ // 如果是退出编辑后的切换,也要更新预览缓存
+ if (!this.editingConfigId) {
+ this.tagStyles[labelEn] = JSON.parse(JSON.stringify(style));
+ }
this.$nextTick(() => { this.isInitialEcho = false; });
}
this.updateAllElements();
@@ -757,7 +799,7 @@ export default {
const currentActiveConf = activeGroup.configs.find(c => c.current_label === this.activeTags);
if (currentActiveConf) {
this.isInitialEcho = true;
- Object.assign(this, currentActiveConf.styles);
+ this.applyStylesToPanel(currentActiveConf.styles);
this.editingConfigId = currentActiveConf.id;
this.editingConfigLabel = currentActiveConf.current_label;
this.$nextTick(() => { this.isInitialEcho = false; });
@@ -778,8 +820,7 @@ export default {
if (idx > -1) {
this.usingConfigIds.splice(idx, 1);
if (this.editingConfigId === item.id) {
- this.editingConfigId = null;
- this.editingConfigLabel = '';
+ this.exitEditingMode(); // 退出应用的同时退出编辑
}
} else {
this.handleEditConfig(item);
@@ -787,59 +828,36 @@ export default {
this.updateAllElements();
},
- // 修改 validateGroupConstraint 函数
validateGroupConstraint(groupName, labelName, excludeId = null) {
const group = this.styleGroups.find(g => g.group_name === groupName);
if (!group) return true;
- // 1. 检查标签是否重复
const isLabelExist = group.configs.some(c => c.current_label === labelName && c.id !== excludeId);
if (isLabelExist) {
- // 使用 alert 而不是 confirm,因为它不需要处理“取消”逻辑,且必须加 .catch() 规避报错
- ElMessageBox.alert(
- `方案【${groupName}】中已存在【${labelName}】标签的配置,请先删除旧配置或选择其他方案。`,
- '校验失败',
- { type: 'error' }
- ).catch(() => {}); // 捕获关闭弹窗时的异常
+ ElMessageBox.alert(`方案【${groupName}】中已存在【${labelName}】标签的配置,请先删除旧配置或选择其他方案。`, '校验失败', { type: 'error' }).catch(() => {});
return false;
}
- // 2. 检查总量是否已达5个
if (group.configs.length >= 5 && !group.configs.some(c => c.id === excludeId)) {
- ElMessageBox.alert(
- `方案【${groupName}】的配置已满(上限5个),无法添加。`,
- '校验失败',
- { type: 'error' }
- ).catch(() => {});
+ ElMessageBox.alert(`方案【${groupName}】的配置已满(上限5个),无法添加。`, '校验失败', { type: 'error' }).catch(() => {});
return false;
}
-
return true;
},
async moveConfigToGroup(config, targetGroup) {
- // 移动时的校验
- if (!this.validateGroupConstraint(targetGroup.group_name, config.current_label, config.id)) {
- return;
- }
-
+ if (!this.validateGroupConstraint(targetGroup.group_name, config.current_label, config.id)) return;
try {
const payload = {
- id: config.id,
- canvas_name: config.canvas_name,
- group_name: targetGroup.group_name,
- current_label: config.current_label,
- styles: config.styles,
- is_auto_save: false
+ id: config.id, canvas_name: config.canvas_name, group_name: targetGroup.group_name,
+ current_label: config.current_label, styles: config.styles, is_auto_save: false
};
const res = await saveGraphStyle(payload);
if (res.code === 200) {
ElMessage.success(`已移动至【${targetGroup.group_name}】`);
await this.fetchConfigs();
}
- } catch (err) {
- ElMessage.error("操作失败");
- }
+ } catch (err) { ElMessage.error("操作失败"); }
},
handleSaveClick() {
@@ -849,22 +867,12 @@ export default {
},
async confirmSave() {
- if (!this.saveForm.group_name?.trim() || !this.saveForm.canvas_name?.trim()) {
- return ElMessage.warning("请完善名称");
- }
-
- // 保存时的校验
- if (!this.validateGroupConstraint(this.saveForm.group_name.trim(), this.activeTags)) {
- return;
- }
-
+ if (!this.saveForm.group_name?.trim() || !this.saveForm.canvas_name?.trim()) return ElMessage.warning("请完善名称");
+ if (!this.validateGroupConstraint(this.saveForm.group_name.trim(), this.activeTags)) return;
const labelEn = tagToLabelMap[this.activeTags];
const payload = {
- canvas_name: this.saveForm.canvas_name.trim(),
- group_name: this.saveForm.group_name.trim(),
- current_label: this.activeTags,
- styles: { ...this.tagStyles[labelEn] },
- is_auto_save: false
+ canvas_name: this.saveForm.canvas_name.trim(), group_name: this.saveForm.group_name.trim(),
+ current_label: this.activeTags, styles: { ...this.tagStyles[labelEn] }, is_auto_save: false
};
const res = await saveGraphStyle(payload);
if (res.code === 200) {
@@ -873,95 +881,73 @@ export default {
await this.fetchConfigs();
}
},
- // ===========================================================================
async applyWholeGroup(group) {
if (this.saveTimer) clearTimeout(this.saveTimer);
this.isInitialEcho = true;
this.editingConfigId = null;
this.editingConfigLabel = '';
-
try {
const REQUIRED_TAGS = ['疾病', '症状', '药品', '检查', '其他'];
const currentLabels = group.configs.map(conf => conf.current_label);
- const hasTags = new Set(currentLabels);
- const missingTags = REQUIRED_TAGS.filter(tag => !hasTags.has(tag));
-
+ const missingTags = REQUIRED_TAGS.filter(tag => !new Set(currentLabels).has(tag));
if (missingTags.length > 0) {
this.isInitialEcho = false;
- return ElMessageBox.alert(
- `该方案配置不完整,无法应用。
缺失:${missingTags.join('、')}`,
- '提示', { dangerouslyUseHTMLString: true, type: 'warning' }
- );
+ return ElMessageBox.alert(`该方案配置不完整,缺失:${missingTags.join('、')}`, '提示', { type: 'warning' }).catch(() => {});
}
-
this.usingConfigIds = group.configs.map(c => c.id);
const res = await applyGraphStyleGroup(group.id);
if (res.code === 200) {
await this.fetchConfigs();
- if (group.configs.length > 0) {
- this.handleEditConfig(group.configs[0]);
- }
+ // 应用全案后,默认开启第一个配置的编辑模式
+ if (group.configs.length > 0) this.handleEditConfig(group.configs[0]);
ElMessage.success(`已应用方案【${group.group_name}】`);
}
- } catch (err) {
- this.isInitialEcho = false;
- ElMessage.error("切换失败");
- }
+ } catch (err) { this.isInitialEcho = false; ElMessage.error("切换失败"); }
},
+
resetStyle() {
const labelEn = tagToLabelMap[this.activeTags];
const initial = this.getInitialTagParams(labelEn);
this.tagStyles[labelEn] = initial;
this.isInitialEcho = true;
- Object.assign(this, initial);
+ this.applyStylesToPanel(initial);
this.$nextTick(() => {
this.isInitialEcho = false;
this.syncAndRefresh();
});
},
+
async deleteSingleConfig(id) {
if (this.usingConfigIds.includes(id)) return ElMessage.error("应用中无法删除");
try {
await ElMessageBox.confirm('确定删除吗?', '提示');
const res = await deleteGraphStyle(id);
- if (res.code === 200) {
- ElMessage.success("删除成功");
- this.fetchConfigs();
- }
+ if (res.code === 200) { ElMessage.success("删除成功"); this.fetchConfigs(); }
} catch (err) { }
},
+
async deleteGroup(groupId) {
const group = this.styleGroups.find(g => g.id === groupId);
if (!group || group.is_active) return ElMessage.error("应用中无法删除");
try {
await ElMessageBox.confirm('确定删除全案吗?', '提示');
const res = await deleteGraphStyleGroup(groupId);
- if (res.code === 200) {
- ElMessage.success("已删除");
- this.fetchConfigs();
- }
+ if (res.code === 200) { ElMessage.success("已删除"); this.fetchConfigs(); }
} catch (err) { }
},
+
async handleUnifiedBatchDelete() {
if (this.checkedConfigIds.length === 0 && this.checkedGroupIds.length === 0) return;
try {
await ElMessageBox.confirm('确定批量删除吗?', '提示');
- if (this.checkedGroupIds.length > 0) {
- for (const gid of this.checkedGroupIds) await deleteGraphStyleGroup(gid);
- }
- if (this.checkedConfigIds.length > 0) {
- await batchDeleteGraphStyle({ ids: this.checkedConfigIds });
- }
- ElMessage.success("成功");
- this.clearSelection();
- this.fetchConfigs();
+ if (this.checkedGroupIds.length > 0) { for (const gid of this.checkedGroupIds) await deleteGraphStyleGroup(gid); }
+ if (this.checkedConfigIds.length > 0) { await batchDeleteGraphStyle({ ids: this.checkedConfigIds }); }
+ ElMessage.success("成功"); this.clearSelection(); this.fetchConfigs();
} catch (e) { }
},
- clearSelection() {
- this.checkedConfigIds = [];
- this.checkedGroupIds = [];
- },
+
+ clearSelection() { this.checkedConfigIds = []; this.checkedGroupIds = []; },
handleResize() {
if (this._graph && this.$refs.graphContainer) {
this._graph.setSize(this.$refs.graphContainer.clientWidth, this.$refs.graphContainer.clientHeight);