feat(condition): 编辑器支持表达式判断——判断方式切换 + 出口条件就地编辑 + 表达式调试

- ConditionNode 增 judgeMode/conditions(SERVICE 缺省,旧定义天然兼容);DefEdgeJson/DefNodeJson 透传 condition/judgeMode
- convert.ts 双向透传:CONDITION 分支首边带 condition,序列化顺序=分支顺序(求值优先级保序)
- ConditionDrawer 判断方式 Radio(服务/表达式);ConditionBox 表达式模式分支头部条件输入(序号即优先级)
- validate.ts 镜像校验:表达式模式每出口条件必填(语法由后端发布期拦)
- Routers 页加「表达式调试」Modal(/admin/router/eval,与线上同一求值核心)
- addBranch/removeBranch 同步维护 conditions 占位
This commit is contained in:
chenxing
2026-10-10 18:52:54 +08:00
parent a4cc8ea2fa
commit acbf601e7a
8 changed files with 205 additions and 20 deletions
@@ -1,9 +1,9 @@
<script setup lang="ts">
// 条件分支配置抽屉(2026-09-24):结构与 NotifyDrawer 同源(本地表单 + 确定回写)。
// 只管节点名与判断服务(flw_router 下拉);出口命名/分支编排 ConditionBox 就地做。
// 管节点名与判断方式(2026-10-10 二选一:服务/表达式);出口命名/条件表达式/分支编排 ConditionBox 就地做。
import { computed, inject, reactive, watch } from "vue";
import { Message } from "view-ui-plus";
import { ConditionNode, EDITOR_CTX } from "../model";
import { ConditionNode, EDITOR_CTX, JudgeMode } from "../model";
const props = defineProps<{
modelValue: boolean;
@@ -21,6 +21,7 @@ const ctx = inject(EDITOR_CTX)!;
const form = reactive({
name: "",
routerKey: "",
judgeMode: "SERVICE" as JudgeMode,
});
function syncFromNode(): void {
@@ -28,6 +29,7 @@ function syncFromNode(): void {
if (!n) return;
form.name = n.name;
form.routerKey = n.routerKey || "";
form.judgeMode = n.judgeMode === "EXPRESSION" ? "EXPRESSION" : "SERVICE";
}
watch(
@@ -56,6 +58,16 @@ const routerHint = computed(() => {
return `调用 ${r.serviceKey}${r.path};返回出口名即分支走向`;
});
/** 切换判断方式:表达式模式下 conditions 补齐占位(与 outlets 同位) */
function switchJudgeMode(mode: JudgeMode): void {
form.judgeMode = mode;
const n = props.node;
if (n && mode === "EXPRESSION") {
n.conditions = n.conditions || [];
while (n.conditions.length < n.outlets.length) n.conditions.push("");
}
}
function onOk(): void {
const n = props.node;
if (!n) {
@@ -66,12 +78,17 @@ function onOk(): void {
Message.warning("节点名称不能为空");
return;
}
if (!form.routerKey) {
if (form.judgeMode === "SERVICE" && !form.routerKey) {
Message.warning("请选择判断服务(未配置的判断服务运行到该节点会挂起)");
return;
}
n.name = form.name.trim();
n.routerKey = form.routerKey;
n.routerKey = form.judgeMode === "SERVICE" ? form.routerKey : "";
n.judgeMode = form.judgeMode;
if (form.judgeMode === "EXPRESSION") {
n.conditions = n.conditions || [];
while (n.conditions.length < n.outlets.length) n.conditions.push("");
}
emit("update:modelValue", false);
}
@@ -96,6 +113,17 @@ function onRemove(): void {
</div>
<div class="fld">
<label>判断方式</label>
<RadioGroup :model-value="form.judgeMode" @on-change="switchJudgeMode">
<Radio label="SERVICE">服务(外部判断接口)</Radio>
<Radio label="EXPRESSION">表达式</Radio>
</RadioGroup>
<div class="hint">
简单条件用表达式在编辑器内闭环;复杂判断(查库/调外部系统)沿用注册的判断服务
</div>
</div>
<div v-if="form.judgeMode === 'SERVICE'" class="fld">
<label>判断服务</label>
<Select v-model="form.routerKey" filterable placeholder="请选择判断服务(flw_router 注册)">
<Option v-for="o in routerOptions" :key="o.value" :value="o.value" :label="o.label" />
@@ -108,6 +136,15 @@ function onRemove(): void {
</div>
</div>
<div v-else class="fld">
<label>表达式说明</label>
<div class="hint">
每个出口在分支列头部就地填写 AviatorScript 条件(如 amount &gt; 1000);按分支顺序取
首个为真的出口。变量=表单字段 + 内置(schId/bizType/bizId/submitterId/instanceId 等)。
变量未提供或条件全不为真时流程挂起(不配默认出口),可在"条件路由"页调试表达式
</div>
</div>
<div class="fld">
<label>出口与分支</label>
<div class="hint">