feat(condition): 条件路由变量契约收口 + 子应用对接健康度面板(议题一 P0/P1 + 议题二 P2)
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:
chenxing
2026-10-15 14:51:04 +08:00
parent 0542279636
commit 1369b103ee
9 changed files with 305 additions and 50 deletions
+25 -1
View File
@@ -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) {