fix(def/ui): 验收审计补丁——调试弹窗内置变量口径与 chips 区分;分组态空 flowGuid 兜底
build / build (push) Successful in 1m56s

- ExprEvalModal:内置变量条 submitterId 改显真实 id(原用 submitterName 冒充,用户照抄进
  样例 JSON 会填错类型);可用变量 chips 区分内置变量(灰底,对齐原型 .chip.bt)并让手动模式
  同样提供内置键(原型 S5「内置变量同款可插」);chips 去重,避免 formData 键与内置键同名重复。
- Defs:分组视图空 flowGuid 行不再被整体丢弃,各自单列一行;openMap 改用合成 key(__noguid__{id})
  防止与其他行共用 "" 键互相牵连;GUID 列空值显示「—」。
- 验证:npm run build 通过(1m16s,产物含 Defs / ExprEvalModal chunk);
  npx tsc --noEmit 48 条与既有基线完全一致、本次改动文件 0 条。

来源:流程中心改造-验收审计报告-B2-B6-20261012.md §三.3c / §三.5
This commit is contained in:
chenxing
2026-10-12 18:03:34 +08:00
parent 94f263d489
commit e01ef87380
2 changed files with 46 additions and 12 deletions
+24 -7
View File
@@ -121,30 +121,45 @@ async function loadInflight() {
} }
} }
/** 分组行(议题二②):同 flowGuid 折叠一行,代表行=已发布中最高版;无已发布取最高版并标「无生效版」 */ /** 分组行(议题二②):同 flowGuid 折叠一行,代表行=已发布中最高版;无已发布取最高版并标「无生效版」。
* 空 flowGuid(历史脏数据)无流程线可折叠,各自单列为一行,避免被整体丢弃。 */
const groups = computed(() => { const groups = computed(() => {
const bucket: Record<string, any[]> = {}; const bucket: Record<string, any[]> = {};
const order: string[] = []; const order: string[] = [];
const noGuid: any[] = [];
rows.value.forEach((r: any) => { rows.value.forEach((r: any) => {
const g = r.flowGuid || ""; const g = r.flowGuid || "";
if (!g) return; if (!g) {
noGuid.push(r);
return;
}
if (!bucket[g]) { if (!bucket[g]) {
bucket[g] = []; bucket[g] = [];
order.push(g); order.push(g);
} }
bucket[g].push(r); 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 vs = bucket[g].slice().sort((a: any, b: any) => b.version - a.version);
const published = vs.filter((v: any) => v.status === 1); const published = vs.filter((v: any) => v.status === 1);
const cur = published[0] || vs[0]; const cur = published[0] || vs[0];
return { 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, version: cur.version, status: cur.status, publishTime: cur.publishTime,
total: vs.length, hasPublished: published.length > 0, total: vs.length, hasPublished: published.length > 0,
versions: vs, _expanded: !!openMap.value[g], 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)。 /** 展开行:该流程线全部版本明细(行对象即 FlwDef,操作复用 rowActions)。
@@ -178,7 +193,9 @@ const groupColumns = [
{ title: "应用", key: "appKey", width: 130, align: "center", render: renderApp }, { 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: 120, render: (h: any, p: any) => h("span", `v${p.row.version} · 共 ${p.row.total} 版`) },
{ title: "状态", width: 90, align: "center", render: renderStatus }, { 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)) }, { title: "发布时间", width: 160, render: (h: any, p: any) => h("span", fmtTime(p.row.publishTime)) },
actionColumn( actionColumn(
[ [
@@ -191,8 +208,8 @@ const groupColumns = [
/** 分组态点行展开/收起(展开箭头同一路径:箭头内部态会被下一帧的 _expanded 重新校准) */ /** 分组态点行展开/收起(展开箭头同一路径:箭头内部态会被下一帧的 _expanded 重新校准) */
function onGroupRowClick(row: any) { function onGroupRowClick(row: any) {
if (row && row.flowGuid) { if (row && row._key) {
openMap.value[row.flowGuid] = !openMap.value[row.flowGuid]; openMap.value[row._key] = !openMap.value[row._key];
} }
} }
+22 -5
View File
@@ -27,6 +27,7 @@ const exprBox = ref<any>(null);
/** 内置变量(线上由引擎注入;schId 属管理端上下文不展示,nodeId/nodeName 需按调试目标自填) */ /** 内置变量(线上由引擎注入;schId 属管理端上下文不展示,nodeId/nodeName 需按调试目标自填) */
const BUILTIN_KEYS = ["instanceId", "instanceVersion", "bizType", "bizId", "submitterId", "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 picked = computed(() => instances.value.find((r) => r.id === pickedId.value) || null);
const builtinRows = computed(() => { const builtinRows = computed(() => {
const p = picked.value; const p = picked.value;
@@ -36,7 +37,7 @@ const builtinRows = computed(() => {
{ k: "instanceVersion", v: p.version }, { k: "instanceVersion", v: p.version },
{ k: "bizType", v: p.bizType }, { k: "bizType", v: p.bizType },
{ k: "bizId", v: p.bizId }, { k: "bizId", v: p.bizId },
{ k: "submitterId", v: p.submitterName || p.submitterId }, { k: "submitterId", v: p.submitterId },
{ k: "nodeId", v: "", todo: true }, { k: "nodeId", v: "", todo: true },
{ k: "nodeName", v: "", todo: true }, { k: "nodeName", v: "", todo: true },
]; ];
@@ -52,7 +53,7 @@ const formKeys = computed<string[]>(() => {
} }
}); });
/** 可用变量 chips:办件/路由日志模式=formData 键 + 内置键;手动模式=最近 50 条办件出现过的键 */ /** 手动模式的键来源:最近 50 条办件 formData 聚合出现过的键(去重后截 40) */
const manualKeys = computed<string[]>(() => { const manualKeys = computed<string[]>(() => {
const set = new Set<string>(); const set = new Set<string>();
instances.value.forEach((r) => { instances.value.forEach((r) => {
@@ -65,7 +66,11 @@ const manualKeys = computed<string[]>(() => {
}); });
return Array.from(set).slice(0, 40); 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) */ /** bizType 筛选 chips(取当前页 distinct) */
const bizTypes = computed(() => Array.from(new Set(instances.value.map((r) => r.bizType).filter(Boolean)))); const bizTypes = computed(() => Array.from(new Set(instances.value.map((r) => r.bizType).filter(Boolean))));
@@ -202,9 +207,10 @@ watch(() => props.modelValue, (v) => {
<label>表达式<span class="em-sub">AviatorScript 沙箱 · 与运行时同一求值口径</span></label> <label>表达式<span class="em-sub">AviatorScript 沙箱 · 与运行时同一求值口径</span></label>
<Input ref="exprBox" v-model="expr" class="em-mono" placeholder="表达式,如 days >= 3" :maxlength="200" /> <Input ref="exprBox" v-model="expr" class="em-mono" placeholder="表达式,如 days >= 3" :maxlength="200" />
<div v-if="chips.length" class="em-chips"> <div v-if="chips.length" class="em-chips">
<span v-for="k in chips" :key="k" class="em-chip" @click="insertChip(k)">{{ k }}</span> <span v-for="k in chips" :key="k" class="em-chip" :class="{ bt: BUILTIN_SET.has(k) }"
@click="insertChip(k)">{{ k }}</span>
</div> </div>
<div v-if="chips.length" class="em-sub">↑ 可用变量(点击插入表达式光标处)</div> <div v-if="chips.length" class="em-sub">↑ 可用变量(点击插入表达式光标处;灰色=内置变量,由运行时自动注入)</div>
</div> </div>
<!-- 模式1/2 共用办件选择器;路由日志模式选中即拉该办件 trace --> <!-- 模式1/2 共用办件选择器;路由日志模式选中即拉该办件 trace -->
@@ -345,6 +351,17 @@ watch(() => props.modelValue, (v) => {
color: #515a6e; color: #515a6e;
background: #fff; 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 { .em-chip.flt.on {
border-color: var(--brand); border-color: var(--brand);
color: var(--brand); color: var(--brand);