feat(gxmu): 模块下拉改由模块注册表驱动,审批链每级支持审批人规则
- 新增模块注册表 api 与进程内缓存(首次使用拉一次、并发共用同一个请求), 启用清单驱动「可新建审批链」的模块下拉与审核列表模块筛选 - reviewFlowConfigEdit 不再维护硬编码模块清单;停用模块的历史配置按 「标题(已停用)」回显,避免下拉空白 - module → detailKey 的映射收敛到 detailKeyOf 一处,moduleDetailConfig 未命中注册表时回退 module 本身(停用模块的详情仍可打开) - 审核流每级新增「审批人规则」输入(USER:<userId> / COLLEGE_ROLE:<roleCode>, 分号拼装多段,留空沿用「指定人」),随该级提交 reviewerRule 并回显 - 新增 scripts/selfcheck-module-registry.mjs:前端无单测基建时验证下拉过滤、 detailKey 回退与停用模块回显
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
/**
|
||||
* 模块注册表的纯逻辑:选项构造、module → detailKey 映射、标题回退。
|
||||
*
|
||||
* 这里刻意不依赖 request / Vue,便于 scripts/selfcheck-module-registry.mjs
|
||||
* 在无单测基建的前端仓库里直接验证行为。副作用(拉取与缓存)在
|
||||
* src/utils/module-registry.ts。
|
||||
*/
|
||||
|
||||
/** 注册表条目(与后端 ModuleRegistry 字段一致) */
|
||||
export interface RegistryModule {
|
||||
module?: string;
|
||||
title?: string;
|
||||
detailKey?: string;
|
||||
enabled?: number;
|
||||
sortNumber?: number;
|
||||
}
|
||||
|
||||
/** 下拉选项 */
|
||||
export interface ModuleOption {
|
||||
label: string;
|
||||
value: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造模块下拉选项:只含启用模块,按 sortNumber 升序,标题取注册表 title。
|
||||
*
|
||||
* 停用模块(enabled=0)不出现在「可新建审批链」的下拉里,历史数据仍可查,
|
||||
* 见 docs/adr/0006-approval-chain-convergence.md。
|
||||
*/
|
||||
export const toModuleOptions = (list?: RegistryModule[]): ModuleOption[] => {
|
||||
return (list || [])
|
||||
.filter((item) => !!item.module && item.enabled === 1)
|
||||
.slice()
|
||||
.sort((a, b) => (a.sortNumber ?? 0) - (b.sortNumber ?? 0))
|
||||
.map((item) => ({
|
||||
label: item.title || item.module || '',
|
||||
value: item.module || ''
|
||||
}));
|
||||
};
|
||||
|
||||
/**
|
||||
* module → 详情页配置键(moduleDetailConfig.ts 的键)的唯一映射。
|
||||
*
|
||||
* 注册表里没有该模块时回退 module 本身:停用模块的历史审批链仍能打开详情,
|
||||
* 而注册表的 detail_key 与 module 不一致时以注册表为准。
|
||||
*/
|
||||
export const resolveDetailKey = (
|
||||
list: RegistryModule[] | undefined,
|
||||
module?: string
|
||||
): string | undefined => {
|
||||
if (!module) {
|
||||
return undefined;
|
||||
}
|
||||
const item = (list || []).find((entry) => entry.module === module);
|
||||
return item?.detailKey || module;
|
||||
};
|
||||
|
||||
/** 模块标题,注册表未命中时回退 module 本身,避免回显成空白 */
|
||||
export const resolveModuleTitle = (
|
||||
list: RegistryModule[] | undefined,
|
||||
module?: string
|
||||
): string | undefined => {
|
||||
if (!module) {
|
||||
return undefined;
|
||||
}
|
||||
const item = (list || []).find((entry) => entry.module === module);
|
||||
return item?.title || module;
|
||||
};
|
||||
|
||||
/**
|
||||
* 编辑存量配置时把当前值补进下拉。
|
||||
*
|
||||
* 停用模块不在启用清单里,但历史审批链仍要回显标题而不是空白/裸 module 值,
|
||||
* 因此按「标题(已停用)」补一项;已经在清单里则原样返回。
|
||||
*/
|
||||
export const ensureModuleOption = (
|
||||
options: ModuleOption[],
|
||||
module?: string,
|
||||
moduleName?: string
|
||||
): ModuleOption[] => {
|
||||
if (!module || options.some((item) => item.value === module)) {
|
||||
return options;
|
||||
}
|
||||
return [{ label: `${moduleName || module}(已停用)`, value: module }, ...options];
|
||||
};
|
||||
Reference in New Issue
Block a user