feat(condition): 条件路由变量契约收口 + 子应用对接健康度面板(议题一 P0/P1 + 议题二 P2)
build / build (push) Successful in 2m51s
build / build (push) Successful in 2m51s
议题一(条件路由体验收口): - 编辑器动作入口上移顶栏与「保存草稿」同排,右栏「快捷入口」整块删除(流程图痛点 7) - 发布期变量引用静态校验:validateModel 增加 knownVars 参数,出边表达式引用未在已知变量中的标识符给 warn 级提示。只提示不阻断——拼错与「运行时才有的动态变量」在静态期无法区分,宁可放过 - CONDITION 判断方式文案业务语言化:「服务(外部判断接口)/表达式」→「到达该节点时才能确定/提交时就已确定」,各补一行说明;syncFromNode 取值归一化逻辑未动,零兼容风险 - 内置 8 变量与表达式变量提取抽到 def-editor/model.ts 单一来源(EXPR_BUILTIN_VARS/extractExprVars/unknownExprVars),ConditionBox 与 ExprEvalModal 改为消费,去掉两份本地重复实现 议题二(子应用接入健康度): - AppSetting.vue 新增 tab3「对接健康度」:每应用一行(评分色块/结论/六项检查 chips/结论说明),问题应用 bad>warn>ok 置顶;首次切入该 tab 才请求,避免进页面就多打一次聚合查询 - Callbacks.vue 新增 appKey 筛选框 + query.appKey 预填,承接健康度面板「查推送日志」跳转 - api 层新增 callbackHealth() 数据来源为已有资产(flw_callback_reg / flw_callback_log),零新增表。对齐《子应用接入流程中心规范.md》§4.2/§7 与《条件路由与子应用接入-痛点调研-20261014.md》。vite build --mode base 通过,产物已构建进 front/dist/。
This commit is contained in:
@@ -8,11 +8,13 @@
|
||||
import {
|
||||
BRANCH_LABELS,
|
||||
DeptOption,
|
||||
EXPR_BUILTIN_SET,
|
||||
EditorItem,
|
||||
EditorModel,
|
||||
MAX_BRANCHES,
|
||||
MIN_BRANCHES,
|
||||
RouterOption,
|
||||
unknownExprVars,
|
||||
} from "./model";
|
||||
|
||||
export type IssueLevel = "error" | "warn";
|
||||
@@ -28,11 +30,23 @@ export interface Issue {
|
||||
text: string;
|
||||
}
|
||||
|
||||
export function validateModel(model: EditorModel, depts: DeptOption[], routers: RouterOption[] = []): Issue[] {
|
||||
/**
|
||||
* @param availableVars 该归属应用近期办件 formData 顶层键聚合(编辑器已拉取)。
|
||||
* 仅用于表达式变量的"疑似拼错"**警告**(2026-10-15 P0),不参与任何 error 级判定——
|
||||
* 为空数组时退化为仅比对内置变量,宁少报不误杀(动态变量场景)。
|
||||
*/
|
||||
export function validateModel(
|
||||
model: EditorModel,
|
||||
depts: DeptOption[],
|
||||
routers: RouterOption[] = [],
|
||||
availableVars: string[] = []
|
||||
): Issue[] {
|
||||
const issues: Issue[] = [];
|
||||
const push = (uid: string, level: IssueLevel, path: string, msg: string): void => {
|
||||
issues.push({ uid, level, path, msg, text: `${path}:${msg}` });
|
||||
};
|
||||
/** 已知变量集:formData 聚合键 + 内置变量(与 ConditionBox chips 同口径) */
|
||||
const knownVars: ReadonlySet<string> = new Set<string>([...availableVars, ...EXPR_BUILTIN_SET]);
|
||||
|
||||
const rec = (items: EditorItem[], path: string): void => {
|
||||
items.forEach((item) => {
|
||||
@@ -114,6 +128,16 @@ export function validateModel(model: EditorModel, depts: DeptOption[], routers:
|
||||
if (!cond.trim()) {
|
||||
push(item.uid, "error", path,
|
||||
`出口「${o || i + 1}」未配条件表达式(表达式模式下每个出口必须配置,发布会被拦截)`);
|
||||
return;
|
||||
}
|
||||
// 变量引用静态校验(2026-10-15 P0):疑似拼错的键给 warn,**不阻断**发布。
|
||||
// 理由:formData 键由子应用在运行期决定,动态变量场景误杀代价高于漏报;
|
||||
// 服务端 DefValidator.warnBuiltinMisspelling 是权威口径(含 AST 级解析)。
|
||||
const unknown = unknownExprVars(cond, knownVars);
|
||||
if (unknown.length) {
|
||||
push(item.uid, "warn", path,
|
||||
`出口「${o || i + 1}」表达式引用了未在已知变量中的 ${unknown
|
||||
.map((v) => `「${v}」`).join("、")},疑似拼错(若为动态变量可忽略)`);
|
||||
}
|
||||
});
|
||||
} else if (!item.routerKey) {
|
||||
|
||||
Reference in New Issue
Block a user