feat: 标准资源使用独立页面并优化详情布局

This commit is contained in:
czl231
2026-08-11 00:49:41 +08:00
parent 7242048abf
commit 13daa996a2
39 changed files with 3826 additions and 2106 deletions

View File

@@ -1,21 +1,36 @@
import { readFileSync } from 'node:fs';
/**
* 功能:校验平台总后台资源定义、页面路由与后端资源契约保持一致。
* 版本v1.1.0
*/
import { readFileSync } from 'node:fs';
import { dirname, resolve } from 'node:path';
import { fileURLToPath } from 'node:url';
const root = resolve(dirname(fileURLToPath(import.meta.url)), '..');
const source = readFileSync(resolve(root, 'src/api/resources.ts'), 'utf8');
const routes = readFileSync(resolve(root, 'src/router/routes/modules/platform.ts'), 'utf8');
const routeFiles = ['platform.ts', 'finance-route.ts'];
const routes = routeFiles
.map((name) =>
readFileSync(resolve(root, 'src/router/routes/modules', name), 'utf8'),
)
.join('\n');
const contract = JSON.parse(
readFileSync(resolve(root, 'src/contracts/platform-resources.json'), 'utf8'),
);
const backend = new Map(contract.resources.map((item) => [item.name, item]));
const frontendDefinitions = [
...source.matchAll(/define\('([^']+)',\s*'[^']+',\s*'([^']+)'/g),
...source.matchAll(
/define\(\s*'([^']+)'\s*,\s*'[^']+'\s*,\s*'([^']+)'/g,
),
].map((match) => ({ name: match[1], mode: match[2] }));
const frontendNames = frontendDefinitions.map((item) => item.name);
const embeddedResources = new Set([
'wallet_basic', 'wallet_bank', 'payment_order', 'wallet_record',
'payment_refund', 'wallet_apply_cash',
'wallet_basic',
'wallet_bank',
'payment_order',
'wallet_record',
'payment_refund',
'wallet_apply_cash',
]);
for (const name of frontendNames) {
@@ -38,11 +53,23 @@ for (const item of contract.resources) {
}
const forbidden = [
'/platform/platform_', '/gas/gas_', '/delivery/delivery_', '/staff/',
'/user/', '/ec/ec_', '/finance/fin_', '/wallet/wallet',
'delivery_task', 'delivery_track', 'delivery_track_point',
'dev_device_binding', 'dev_smart_cylinder_valve', 'dev_telemetry',
'wallet_ledger', 'wallet_recharge', 'wallet_withdrawal',
'/platform/platform_',
'/gas/gas_',
'/delivery/delivery_',
'/staff/',
'/user/',
'/ec/ec_',
'/finance/fin_',
'/wallet/wallet',
'delivery_task',
'delivery_track',
'delivery_track_point',
'dev_device_binding',
'dev_smart_cylinder_valve',
'dev_telemetry',
'wallet_ledger',
'wallet_recharge',
'wallet_withdrawal',
];
for (const value of forbidden) {
if (source.includes(value) || routes.includes(value))

View File

@@ -0,0 +1,49 @@
/**
* 功能:静态检查平台总后台全部标准资源是否具备独立记录页配置。
* 版本v1.0.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 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('<a-drawer')) fail('列表组件仍包含 CRUD Drawer');
if (existsSync(resolve(root, 'src/views/account/AccountProfilePage.vue'))) {
fail('旧账户资料组件仍存在,未统一到共享记录页');
}
const createCount = listResources.filter((item) => createModes.has(item.mode)).length;
console.log(
`资源独立页面检查通过:详情 ${listResources.length} 类,新建 ${createCount} 类,编辑 ${editableResources.length} 类。`,
);