diff --git a/src/views/flow/admin/Defs.vue b/src/views/flow/admin/Defs.vue index 3ff5e7a..666ca15 100644 --- a/src/views/flow/admin/Defs.vue +++ b/src/views/flow/admin/Defs.vue @@ -121,30 +121,45 @@ async function loadInflight() { } } -/** 分组行(议题二②):同 flowGuid 折叠一行,代表行=已发布中最高版;无已发布取最高版并标「无生效版」 */ +/** 分组行(议题二②):同 flowGuid 折叠一行,代表行=已发布中最高版;无已发布取最高版并标「无生效版」。 + * 空 flowGuid(历史脏数据)无流程线可折叠,各自单列为一行,避免被整体丢弃。 */ const groups = computed(() => { const bucket: Record = {}; const order: string[] = []; + const noGuid: any[] = []; rows.value.forEach((r: any) => { const g = r.flowGuid || ""; - if (!g) return; + if (!g) { + noGuid.push(r); + return; + } if (!bucket[g]) { bucket[g] = []; order.push(g); } bucket[g].push(r); }); - return order.map((g) => { + const out = order.map((g) => { const vs = bucket[g].slice().sort((a: any, b: any) => b.version - a.version); const published = vs.filter((v: any) => v.status === 1); const cur = published[0] || vs[0]; return { - flowGuid: g, id: cur.id, name: cur.name, code: cur.code, appKey: cur.appKey, + _key: g, flowGuid: g, id: cur.id, name: cur.name, code: cur.code, appKey: cur.appKey, version: cur.version, status: cur.status, publishTime: cur.publishTime, total: vs.length, hasPublished: published.length > 0, versions: vs, _expanded: !!openMap.value[g], }; }); + // 空 flowGuid 兜底:openMap 用合成 key,避免与其他行共用 "" 键互相牵连 + noGuid.forEach((r: any) => { + const k = `__noguid__${r.id}`; + out.push({ + _key: k, flowGuid: "", id: r.id, name: r.name, code: r.code, appKey: r.appKey, + version: r.version, status: r.status, publishTime: r.publishTime, + total: 1, hasPublished: r.status === 1, versions: [r], _expanded: !!openMap.value[k], + }); + }); + return out; }); /** 展开行:该流程线全部版本明细(行对象即 FlwDef,操作复用 rowActions)。 @@ -178,7 +193,9 @@ const groupColumns = [ { title: "应用", key: "appKey", width: 130, align: "center", render: renderApp }, { title: "版本", width: 120, render: (h: any, p: any) => h("span", `v${p.row.version} · 共 ${p.row.total} 版`) }, { title: "状态", width: 90, align: "center", render: renderStatus }, - { title: "GUID", width: 130, render: (h: any, p: any) => h("span", { title: p.row.flowGuid }, `${String(p.row.flowGuid).slice(0, 8)}…`) }, + { title: "GUID", width: 130, render: (h: any, p: any) => (p.row.flowGuid + ? h("span", { title: p.row.flowGuid }, `${String(p.row.flowGuid).slice(0, 8)}…`) + : h("span", { style: "color:#999" }, "—")) }, { title: "发布时间", width: 160, render: (h: any, p: any) => h("span", fmtTime(p.row.publishTime)) }, actionColumn( [ @@ -191,8 +208,8 @@ const groupColumns = [ /** 分组态点行展开/收起(展开箭头同一路径:箭头内部态会被下一帧的 _expanded 重新校准) */ function onGroupRowClick(row: any) { - if (row && row.flowGuid) { - openMap.value[row.flowGuid] = !openMap.value[row.flowGuid]; + if (row && row._key) { + openMap.value[row._key] = !openMap.value[row._key]; } } diff --git a/src/views/flow/components/ExprEvalModal.vue b/src/views/flow/components/ExprEvalModal.vue index 7160e60..6bc605f 100644 --- a/src/views/flow/components/ExprEvalModal.vue +++ b/src/views/flow/components/ExprEvalModal.vue @@ -27,6 +27,7 @@ const exprBox = ref(null); /** 内置变量(线上由引擎注入;schId 属管理端上下文不展示,nodeId/nodeName 需按调试目标自填) */ const BUILTIN_KEYS = ["instanceId", "instanceVersion", "bizType", "bizId", "submitterId", "nodeId", "nodeName"]; +const BUILTIN_SET = new Set(BUILTIN_KEYS); const picked = computed(() => instances.value.find((r) => r.id === pickedId.value) || null); const builtinRows = computed(() => { const p = picked.value; @@ -36,7 +37,7 @@ const builtinRows = computed(() => { { k: "instanceVersion", v: p.version }, { k: "bizType", v: p.bizType }, { k: "bizId", v: p.bizId }, - { k: "submitterId", v: p.submitterName || p.submitterId }, + { k: "submitterId", v: p.submitterId }, { k: "nodeId", v: "", todo: true }, { k: "nodeName", v: "", todo: true }, ]; @@ -52,7 +53,7 @@ const formKeys = computed(() => { } }); -/** 可用变量 chips:办件/路由日志模式=formData 键 + 内置键;手动模式=最近 50 条办件出现过的键 */ +/** 手动模式的键来源:最近 50 条办件 formData 聚合出现过的键(去重后截 40) */ const manualKeys = computed(() => { const set = new Set(); instances.value.forEach((r) => { @@ -65,7 +66,11 @@ const manualKeys = computed(() => { }); return Array.from(set).slice(0, 40); }); -const chips = computed(() => (mode.value === "manual" ? manualKeys.value : [...formKeys.value, ...BUILTIN_KEYS])); +/** chips:formData 键(手动模式取历史办件聚合键)+ 内置键;与键名重复时去重,内置键单独置灰标注 */ +const chips = computed(() => Array.from(new Set([ + ...(mode.value === "manual" ? manualKeys.value : formKeys.value), + ...BUILTIN_KEYS, +]))); /** bizType 筛选 chips(取当前页 distinct) */ const bizTypes = computed(() => Array.from(new Set(instances.value.map((r) => r.bizType).filter(Boolean)))); @@ -202,9 +207,10 @@ watch(() => props.modelValue, (v) => {
- {{ k }} + {{ k }}
-
↑ 可用变量(点击插入表达式光标处)
+
↑ 可用变量(点击插入表达式光标处;灰色=内置变量,由运行时自动注入)
@@ -345,6 +351,17 @@ watch(() => props.modelValue, (v) => { color: #515a6e; background: #fff; } +/* 内置变量 chip:与 formData 键区分(对齐原型 .chip.bt 口径) */ +.em-chip.bt { + border-color: #dcdee2; + color: #515a6e; + background: #f5f7fa; +} +.em-chip.bt:hover { + color: #fff; + background: #515a6e; + border-color: #515a6e; +} .em-chip.flt.on { border-color: var(--brand); color: var(--brand);