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:
@@ -1,7 +1,8 @@
|
||||
<script setup lang="ts">
|
||||
// 条件分支容器(2026-09-24):紫系区分并行橙;与 ParallelBox 的本质差异——无 JOIN 语义,
|
||||
// 分支按出口名互斥选路(运行时调判断服务),分支尾隐式汇合到容器后继。
|
||||
// 分支头部的出口名 Input 即 contentJson 里 CONDITION 命名出边的 name(判断接口 outlets 契约)。
|
||||
// 分支按出口名互斥选路(运行时调判断服务/表达式求值),分支尾隐式汇合到容器后继。
|
||||
// 分支头部的出口名 Input 即 contentJson 里 CONDITION 命名出边的 name(判断接口 outlets 契约);
|
||||
// EXPRESSION 模式(2026-10-10)下分支头部再就地编辑出边 condition,序号即求值优先级。
|
||||
import { computed, inject } from "vue";
|
||||
import { BRANCH_LABELS, EDITOR_CTX, MAX_BRANCHES, MIN_BRANCHES, ConditionNode } from "../model";
|
||||
import NodeList from "./NodeList.vue";
|
||||
@@ -14,8 +15,10 @@ const issues = computed(() => ctx.issueOf(props.node.uid));
|
||||
const hasError = computed(() => issues.value.some((i) => i.level === "error"));
|
||||
const canRemoveBranch = computed(() => props.node.branches.length > MIN_BRANCHES);
|
||||
const canAddBranch = computed(() => props.node.branches.length < MAX_BRANCHES);
|
||||
const expression = computed(() => props.node.judgeMode === "EXPRESSION");
|
||||
|
||||
const routerLabel = computed(() => {
|
||||
if (expression.value) return "表达式判断(按分支顺序取首个为真)";
|
||||
if (!props.node.routerKey) return "判断服务:未选择";
|
||||
const r = ctx.routers.find((x) => x.routerKey === props.node.routerKey);
|
||||
return r ? `判断服务:${r.name}(${props.node.routerKey})` : `判断服务:${props.node.routerKey}`;
|
||||
@@ -25,19 +28,28 @@ const routerLabel = computed(() => {
|
||||
function renameOutlet(i: number, v: string): void {
|
||||
props.node.outlets[i] = v;
|
||||
}
|
||||
|
||||
/** 出口条件就地编辑(EXPRESSION 模式;与 outlets 下标一一对应) */
|
||||
function editCondition(i: number, v: string): void {
|
||||
props.node.conditions = props.node.conditions || [];
|
||||
while (props.node.conditions.length <= i) props.node.conditions.push("");
|
||||
props.node.conditions[i] = v;
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="condition-box" :class="{ error: hasError }">
|
||||
<div class="cb-title" @click="ctx.openNode(node.uid)">
|
||||
条件分支(按出口互斥选路)
|
||||
<span class="cb-hint">(点击标题配置判断服务)</span>
|
||||
<span class="cb-hint">(点击标题配置{{ expression ? "表达式" : "判断服务" }})</span>
|
||||
</div>
|
||||
<div class="cb-router">{{ routerLabel }}</div>
|
||||
<div class="cb-cols">
|
||||
<div v-for="(branch, i) in node.branches" :key="i" class="cb-col">
|
||||
<div class="cb-col-head">
|
||||
<span class="cb-col-no">{{ BRANCH_LABELS[i] || i + 1 }}</span>
|
||||
<span class="cb-col-no" :title="expression ? '表达式求值优先级' : undefined">
|
||||
{{ BRANCH_LABELS[i] || i + 1 }}
|
||||
</span>
|
||||
<input
|
||||
class="cb-outlet"
|
||||
:value="node.outlets[i]"
|
||||
@@ -57,6 +69,14 @@ function renameOutlet(i: number, v: string): void {
|
||||
<span class="cb-col-del" title="删除分支">×</span>
|
||||
</Poptip>
|
||||
</div>
|
||||
<input
|
||||
v-if="expression"
|
||||
class="cb-cond"
|
||||
:value="(node.conditions || [])[i] || ''"
|
||||
placeholder="条件表达式,如 amount > 1000"
|
||||
maxlength="200"
|
||||
@input="editCondition(i, ($event.target as HTMLInputElement).value)"
|
||||
/>
|
||||
<NodeList :items="branch" :container="`${node.uid}:${i}`" />
|
||||
</div>
|
||||
</div>
|
||||
@@ -142,6 +162,25 @@ function renameOutlet(i: number, v: string): void {
|
||||
outline: none;
|
||||
border-color: #9254de;
|
||||
}
|
||||
.cb-cond {
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
border: 1px dashed #d3b8f9;
|
||||
border-radius: 6px;
|
||||
padding: 2px 8px;
|
||||
font-size: 12px;
|
||||
color: #5b3fa8;
|
||||
font-family: Consolas, Monaco, monospace;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
.cb-cond:focus {
|
||||
outline: none;
|
||||
border-color: #9254de;
|
||||
border-style: solid;
|
||||
}
|
||||
.cb-cond::placeholder {
|
||||
color: #c5b3e8;
|
||||
}
|
||||
.cb-col-del {
|
||||
flex: none;
|
||||
cursor: pointer;
|
||||
|
||||
Reference in New Issue
Block a user