/** * 功能:静态检查平台总后台全部标准资源是否具备独立记录页配置。 * 版本:v1.2.0 */ import { readFileSync, existsSync } from 'node:fs'; import { fileURLToPath } from 'node:url'; import { dirname, resolve } from 'node:path'; const root = resolve(dirname(fileURLToPath(import.meta.url)), '..'); const contract = JSON.parse(readFileSync(resolve(root, 'src/contracts/platform-resources.json'), 'utf8')); const routeSource = [ 'platform.ts', 'finance-route.ts', ].map((file) => readFileSync(resolve(root, 'src/router/routes/modules', file), 'utf8')).join('\n'); const routeBuilderSource = readFileSync(resolve(root, 'src/router/routes/modules/resource-route-builder.ts'), 'utf8'); const ruleSource = readFileSync(resolve(root, 'src/api/resource-page-rules.ts'), 'utf8'); const listSource = readFileSync(resolve(root, 'src/views/shared/CrudListPage.vue'), 'utf8'); const detailSource = readFileSync(resolve(root, 'src/views/resource/ResourceDetailContent.vue'), 'utf8'); const displaySource = readFileSync(resolve(root, 'src/api/resource-display.ts'), 'utf8'); const resourceSource = readFileSync(resolve(root, 'src/api/resources.ts'), 'utf8'); const treeResources = new Set(['ec_category', 'platform_menu']); const listResources = contract.resources.filter((item) => !treeResources.has(item.name)); const createModes = new Set(['writable', 'editable', 'append_only', 'managed']); const editModes = new Set(['writable', 'editable', 'managed']); const editableResources = listResources.filter((item) => editModes.has(item.mode)); function fail(message) { throw new Error(`资源独立页面检查失败:${message}`); } const missingRoutes = listResources .filter((item) => !routeSource.includes(`'/${item.name}'`)) .map((item) => item.name); if (missingRoutes.length) fail(`路由未覆盖 ${missingRoutes.join('、')}`); const missingRules = editableResources .filter((item) => !new RegExp(`\\n\\s*${item.name}:\\s*\\{`).test(ruleSource)) .map((item) => item.name); if (missingRules.length) fail(`编辑字段规则未覆盖 ${missingRules.join('、')}`); for (const marker of ["makeRecordRoute('create'", "makeRecordRoute('detail'", "makeRecordRoute('edit'"]) { if (!routeBuilderSource.includes(marker)) fail(`通用路由生成器缺少 ${marker}`); } if (listSource.includes(' props.definition.resource, () => staffType.value]', ) ) { fail('工作人员角色菜单切换未触发列表重新加载'); } if (existsSync(resolve(root, 'src/views/account/AccountProfilePage.vue'))) { fail('旧账户资料组件仍存在,未统一到共享记录页'); } if (!detailSource.includes('resourceFieldLabel(definition, column, collection.key)')) { fail('聚合详情表格未按集合上下文解析中文字段名称'); } for (const marker of [ "'gasorder_contract.products'", "product_info_identity: '气瓶唯一标识'", "product_code: '气瓶编码'", "if (key === 'contract_status') return contractStatusLabel(Number(value))", "terminate: '终止合同'", "key === 'expired_at'", "return '待补录'", ]) { if (!displaySource.includes(marker)) fail(`合同详情中文展示缺少 ${marker}`); } if (!resourceSource.includes("visibleFor: { field: 'contract_status', values: [0] }")) { fail('合同启用动作未限制为草稿状态'); } if (!resourceSource.includes("visibleFor: { field: 'contract_status', values: [11, 12, 13] }")) { fail('合同续签动作未覆盖已终止状态'); } if (!detailSource.includes("!['deleted_at', 'DeletedAt'].includes(column)")) { fail('聚合详情表未隐藏公共软删除字段'); } for (const marker of [ "Number(row.contract_status) !== 0", "![0, 1].includes(Number(row.status))", "只有草稿状态的合同可以编辑", "停用、已归档或已冻结的合同不可编辑", ]) { if (!ruleSource.includes(marker)) fail(`合同编辑状态规则缺少 ${marker}`); } if (!listSource.includes('recordEditReason(record)')) { fail('合同列表缺少编辑禁用原因提示'); } const createCount = listResources.filter((item) => createModes.has(item.mode)).length; console.log( `资源独立页面检查通过:详情 ${listResources.length} 类,新建 ${createCount} 类,编辑 ${editableResources.length} 类。`, );