NOTIFY(2026-09-23):编辑器抄送卡片+抽屉+画布 bpmn:ServiceTask 映射、工作台「抄送我的」页签、轨迹 kind=CC 行、示意图青框卡片 CONDITION(2026-09-24):ConditionBox 互斥分支容器(分支列出口名就地编辑、无 JOIN 语义分支尾隐式汇合)、ConditionDrawer 判断服务下拉(flw_router)、convert 双向序列化(CONDITION+命名出边、uid+c 尾缀往返收敛)、validate 镜像后端口径、画布 bpmn:ExclusiveGateway 映射、轨迹「系统判断→出口」行(失败挂起提示)、示意图紫菱形(SVG 与服务端 PNG 同配色)、管理面 flw_router 维护页(/admin/routers)与办件记录「重跑路由」入口 convert 往返 54 项全过、npm run build 通过
This commit is contained in:
@@ -0,0 +1,182 @@
|
||||
<script setup lang="ts">
|
||||
// 条件路由维护(2026-09-24 二期第二批 §4.2):flw_router 判断服务注册表(全局表)。
|
||||
// CONDITION 节点的 routerKey 必须命中启用中的注册(发布校验口径);basePath 是对端 context-path,
|
||||
// 漏填必 401(规范 §4.2 同款坑)——生产 notice 为 /notice,本地为空。
|
||||
import { ref, onMounted } from "vue";
|
||||
import { Message } from "view-ui-plus";
|
||||
import MyConfirm from "@/components/MyConfirm";
|
||||
import { flowApi } from "@/api/module/flow";
|
||||
import Utils from "@/utils";
|
||||
|
||||
const loading = ref(false);
|
||||
const rows = ref<any[]>([]);
|
||||
const tableHeight = ref(Utils.useTableHeight({ isSearch: true, isOperat: true }));
|
||||
|
||||
const columns = [
|
||||
{ title: "序号", type: "index", width: 70, align: "center" },
|
||||
{ title: "注册键", key: "routerKey", width: 220 },
|
||||
{ title: "名称", key: "name", width: 160 },
|
||||
{ title: "服务目录键", key: "serviceKey", width: 110 },
|
||||
{ title: "判断端点", key: "path", minWidth: 300 },
|
||||
{
|
||||
title: "basePath",
|
||||
width: 110,
|
||||
render: (h: any, p: any) => h("span", p.row.basePath || "(空=沿用目录)"),
|
||||
},
|
||||
{
|
||||
title: "状态",
|
||||
width: 90,
|
||||
align: "center",
|
||||
render: (h: any, p: any) =>
|
||||
h("Tag", { color: p.row.status === 1 ? "green" : "gray" }, () => (p.row.status === 1 ? "启用" : "停用")),
|
||||
},
|
||||
{
|
||||
title: "操作",
|
||||
width: 150,
|
||||
align: "center",
|
||||
fixed: "right",
|
||||
render: (h: any, p: any) => [
|
||||
Utils.operatingHandle(h, "编辑", "icon-edit", () => onEdit(p.row)),
|
||||
h("span", { style: "display:inline-block;width:10px" }),
|
||||
p.row.status === 1
|
||||
? Utils.operatingHandle(h, "停用", "icon-stop", () => onDisable(p.row))
|
||||
: Utils.operatingHandle(h, "启用", "icon-play", () => onEnable(p.row)),
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
async function load() {
|
||||
loading.value = true;
|
||||
try {
|
||||
rows.value = (await flowApi.routerList().send()) || [];
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
// ---- 新增/编辑弹窗 ----
|
||||
const saveVisible = ref(false);
|
||||
const saving = ref(false);
|
||||
const formRef = ref<any>(null);
|
||||
const form = ref<any>({ id: null, routerKey: "", name: "", serviceKey: "", path: "", basePath: "" });
|
||||
const saveRules = {
|
||||
routerKey: [{ required: true, message: "请填写红色星号内容!", trigger: "blur" }],
|
||||
name: [{ required: true, message: "请填写红色星号内容!", trigger: "blur" }],
|
||||
serviceKey: [{ required: true, message: "请填写红色星号内容!", trigger: "blur" }],
|
||||
path: [{ required: true, message: "请填写红色星号内容!", trigger: "blur" }],
|
||||
};
|
||||
|
||||
function onAdd() {
|
||||
form.value = { id: null, routerKey: "", name: "", serviceKey: "notice", path: "", basePath: "" };
|
||||
saveVisible.value = true;
|
||||
}
|
||||
|
||||
function onEdit(row: any) {
|
||||
form.value = {
|
||||
id: row.id,
|
||||
routerKey: row.routerKey,
|
||||
name: row.name,
|
||||
serviceKey: row.serviceKey,
|
||||
path: row.path,
|
||||
basePath: row.basePath || "",
|
||||
};
|
||||
saveVisible.value = true;
|
||||
}
|
||||
|
||||
function onSave() {
|
||||
formRef.value?.validate(async (valid: boolean) => {
|
||||
if (!valid) return;
|
||||
saving.value = true;
|
||||
try {
|
||||
await flowApi.routerSave({
|
||||
id: form.value.id || undefined,
|
||||
routerKey: form.value.routerKey.trim(),
|
||||
name: form.value.name.trim(),
|
||||
serviceKey: form.value.serviceKey.trim(),
|
||||
path: form.value.path.trim(),
|
||||
basePath: form.value.basePath.trim(),
|
||||
}).send();
|
||||
Message.success("已保存");
|
||||
saveVisible.value = false;
|
||||
load();
|
||||
} finally {
|
||||
saving.value = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function onDisable(row: any) {
|
||||
MyConfirm({
|
||||
title: "停用",
|
||||
msg: `确定停用判断服务「${row.name || row.routerKey}」吗?`,
|
||||
info: "停用后引用它的流程定义不能发布;在途挂起办件的重跑会失败",
|
||||
async onOk() {
|
||||
await flowApi.routerStatus(row.id, false).send();
|
||||
Message.success("已停用");
|
||||
load();
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
function onEnable(row: any) {
|
||||
MyConfirm({
|
||||
title: "启用",
|
||||
msg: `确定启用判断服务「${row.name || row.routerKey}」吗?`,
|
||||
info: "启用后流程编辑器的判断服务下拉可选它,发布校验放行引用",
|
||||
async onOk() {
|
||||
await flowApi.routerStatus(row.id, true).send();
|
||||
Message.success("已启用");
|
||||
load();
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
onMounted(load);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="page-wrapper">
|
||||
<div class="main-container">
|
||||
<div class="fix mb-12">
|
||||
<Button class="fl" type="primary" size="large" @click="onAdd">新增注册</Button>
|
||||
</div>
|
||||
|
||||
<div class="search-wrap fix">
|
||||
<span class="fr" style="color: #808695; font-size: 12px; line-height: 32px">
|
||||
判断逻辑由业务方实现:引擎运行到 CONDITION 节点时按注册键同步调用(3s×3 重试),
|
||||
失败挂起、管理端办件记录里重跑路由
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<Table :columns="columns" :data="rows" :loading="loading" class="link-table table-bottom-box"
|
||||
:height="tableHeight" no-data-text="暂无数据" />
|
||||
|
||||
<Modal v-model="saveVisible" title="新增/编辑判断服务" :mask-closable="false">
|
||||
<Form ref="formRef" :model="form" :rules="saveRules" :label-width="100">
|
||||
<FormItem label="注册键" prop="routerKey">
|
||||
<Input v-model="form.routerKey" placeholder="CONDITION 节点 routerKey 引用它,如 notice.dept-judge" :maxlength="64" />
|
||||
</FormItem>
|
||||
<FormItem label="名称" prop="name">
|
||||
<Input v-model="form.name" placeholder="展示名(编辑器下拉),如 发文部门判断" :maxlength="128" />
|
||||
</FormItem>
|
||||
<FormItem label="服务目录键" prop="serviceKey">
|
||||
<Input v-model="form.serviceKey" placeholder="服务目录三级解析的 key,如 notice" :maxlength="64" />
|
||||
</FormItem>
|
||||
<FormItem label="判断端点" prop="path">
|
||||
<Input v-model="form.path" placeholder="以 / 开头,如 /oapi/notice/flow/route/dept-judge" :maxlength="255" />
|
||||
</FormItem>
|
||||
<FormItem label="basePath">
|
||||
<Input v-model="form.basePath" placeholder="对端 context-path(生产 /notice;本地无则留空)" :maxlength="64" />
|
||||
<p style="color: #808695; font-size: 12px; line-height: 1.6; margin-top: 4px">
|
||||
签名拼串要剥它,漏填必 401;留空=沿用服务目录条目自带的前缀
|
||||
</p>
|
||||
</FormItem>
|
||||
</Form>
|
||||
<template #footer>
|
||||
<Button @click="saveVisible = false">取消</Button>
|
||||
<Button type="primary" :loading="saving" @click="onSave">提交</Button>
|
||||
</template>
|
||||
</Modal>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
Reference in New Issue
Block a user