统一平台资源中文展示并修复模拟订单状态
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* 功能:静态检查三套管理后台的账户角色中文展示与无效头像摘要规则。
|
||||
* 版本:v1.0.0
|
||||
* 版本:v1.1.0
|
||||
*/
|
||||
import { readFileSync } from 'node:fs';
|
||||
import { dirname, resolve } from 'node:path';
|
||||
@@ -27,14 +27,19 @@ const platformSummary = source(
|
||||
|
||||
expectIncludes(
|
||||
platformResources,
|
||||
"fixedAdminRole('气站管理员')",
|
||||
"fixedAdminRole('gas_account')",
|
||||
'平台总后台缺少气站管理员中文映射',
|
||||
);
|
||||
expectIncludes(
|
||||
platformResources,
|
||||
"fixedAdminRole('配送点管理员')",
|
||||
"fixedAdminRole('delivery_account')",
|
||||
'平台总后台缺少配送点管理员中文映射',
|
||||
);
|
||||
expectIncludes(
|
||||
platformResources,
|
||||
"resourceSearchEnumOptions(resource, 'role_code')",
|
||||
'平台总后台固定管理员角色未读取后端中文枚举契约',
|
||||
);
|
||||
expectIncludes(
|
||||
platformResources,
|
||||
"define('delivery_account', '配送点账户'",
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
// 功能描述:静态校验配送订单列表优先显示可读创建方,并保留唯一标识复制入口。
|
||||
// 版本:v1.1.0
|
||||
// 版本:v1.2.0
|
||||
import fs from 'node:fs';
|
||||
|
||||
const resources = fs.readFileSync(new URL('../src/api/resources.ts', import.meta.url), 'utf8');
|
||||
const listPage = fs.readFileSync(new URL('../src/views/shared/CrudListPage.vue', import.meta.url), 'utf8');
|
||||
const detailPage = fs.readFileSync(new URL('../src/views/resource/ResourceDetailContent.vue', import.meta.url), 'utf8');
|
||||
const resourceDisplay = fs.readFileSync(new URL('../src/api/resource-display.ts', import.meta.url), 'utf8');
|
||||
const detailContract = fs.readFileSync(new URL('../src/api/resource-detail-contract.ts', import.meta.url), 'utf8');
|
||||
const listFieldDisplay = fs.readFileSync(new URL('../src/views/shared/resource-list-field-display.ts', import.meta.url), 'utf8');
|
||||
|
||||
const assertions = [
|
||||
[resources.includes("gasorder_basic_identity: '配送订单唯一标识'"), '状态记录中的配送订单标识缺少中文名称'],
|
||||
@@ -14,10 +16,10 @@ const assertions = [
|
||||
[detailPage.includes("'contract_display_name'"), '订单详情未隐藏重复的合同标题辅助字段'],
|
||||
[detailPage.includes("column.endsWith('_at')) return 150"), '关联记录的日期时间列未固定为 150px'],
|
||||
[detailPage.includes("key.endsWith('_masked')"), '详情页未去除重复的脱敏辅助字段'],
|
||||
[detailPage.includes("'order_no',\n 'request_no',\n 'order_status'"), '订单详情未将订单号置于主要位置'],
|
||||
[detailPage.includes("'gasorder_basic.assignments'"), '分配记录缺少固定业务列'],
|
||||
[detailPage.includes("['assignments', 'items', 'statuses'].includes(key)"), '订单关联表仍会泄漏任意英文响应字段'],
|
||||
[detailPage.includes("'gasorder_basic.statuses'"), '状态记录缺少固定中文业务列'],
|
||||
[detailContract.includes("'order_no', 'request_no', 'order_status'"), '订单详情未将订单号置于主要位置'],
|
||||
[detailContract.includes('assignments: {'), '分配记录缺少固定业务列'],
|
||||
[detailPage.includes('const contract = resourceDetailContract(props.definition.name)'), '订单关联表仍未使用固定资源契约'],
|
||||
[detailContract.includes('statuses: {'), '状态记录缺少固定中文业务列'],
|
||||
[resourceDisplay.includes("active: '是否有效'"), '订单明细 active 字段未中文化'],
|
||||
[resourceDisplay.includes("String(value) === 'order created'"), '历史订单创建原因未中文化'],
|
||||
[detailPage.includes("creator_identity: 'creator_display_name'"), '订单创建方未使用可读名称'],
|
||||
@@ -31,6 +33,8 @@ const assertions = [
|
||||
[resources.includes("listDisplayKey: 'contract_display_name'"), '订单列表未配置合同标题展示字段'],
|
||||
[listPage.includes('field.listDisplayIdentityCopy && identityFieldValue(field, record)'), '可读名称分支未优先于通用唯一标识分支'],
|
||||
[listPage.includes(':name="displayListField(field, record)"'), '创建方复制组件未使用列表可读名称'],
|
||||
[listFieldDisplay.includes("gasorder_basic: ["), '订单列表缺少专属业务列顺序'],
|
||||
[listFieldDisplay.includes("'order_no', 'request_no', 'order_status'"), '订单列表未优先显示订单号'],
|
||||
];
|
||||
|
||||
for (const [passed, message] of assertions) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* 功能:静态检查资源详情关联表中的设备参数可完整查看且不会撑宽表格。
|
||||
* 版本:v1.1.0
|
||||
* 版本:v1.2.0
|
||||
*/
|
||||
import assert from 'node:assert/strict';
|
||||
import { readFileSync } from 'node:fs';
|
||||
@@ -10,11 +10,11 @@ const detail = readFileSync(
|
||||
'utf8',
|
||||
);
|
||||
|
||||
assert.match(detail, /isCollectionJsonColumn\(column\)/, '关联表 JSON 字段缺少专用展示分支');
|
||||
assert.match(detail, /isCollectionJsonField\(definition\.name, collection\.key, column\)/, '关联表 JSON 字段缺少专用展示分支');
|
||||
assert.match(detail, />查看参数<\/a-button>/, '设备参数缺少完整查看入口');
|
||||
assert.match(detail, /formatCollectionJson\(record\[column\]\)/, '设备参数没有格式化完整内容');
|
||||
assert.match(detail, /JSON\.stringify\(JSON\.parse\(text\), null, 2\)/, '字符串 JSON 未格式化');
|
||||
assert.match(detail, /isCollectionJsonColumn\(column\)\) return 100/, '设备参数列未使用紧凑宽度');
|
||||
assert.match(detail, /isCollectionJsonField\(props\.definition\.name, collectionKey, column\)/, '设备参数列未使用契约化紧凑宽度');
|
||||
assert.match(detail, /max-width: min\(560px, 70vw\)/, '参数浮层缺少视口宽度限制');
|
||||
assert.match(detail, /class="collection-table-shell"/, '关联表缺少独立宽度约束容器');
|
||||
assert.match(detail, /\.detail-stack[\s\S]*?min-width: 0;/, '详情栈仍可能被子内容反向撑宽');
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
/**
|
||||
* 功能描述:校验平台48类资源均具备中文展示字段,并防止列表、详情退回数据库ID或动态英文列。
|
||||
* 版本:v1.0.0
|
||||
*/
|
||||
import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
import process from 'node:process';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
|
||||
const currentDirectory = path.dirname(fileURLToPath(import.meta.url));
|
||||
const root = path.resolve(currentDirectory, '..');
|
||||
|
||||
function read(relativePath) {
|
||||
return fs.readFileSync(path.join(root, relativePath), 'utf8');
|
||||
}
|
||||
|
||||
function assertIncludes(source, expected, message) {
|
||||
if (!source.includes(expected)) throw new Error(message);
|
||||
}
|
||||
|
||||
const resources = read('src/api/resources.ts');
|
||||
const display = read('src/api/resource-display.ts');
|
||||
const detailContract = read('src/api/resource-detail-contract.ts');
|
||||
const detailPage = read('src/views/resource/ResourceDetailContent.vue');
|
||||
const listPage = read('src/views/shared/CrudListPage.vue');
|
||||
|
||||
const resourceNames = [...resources.matchAll(/\bdefine\('([^']+)'/g)].map(
|
||||
(match) => match[1],
|
||||
);
|
||||
if (resourceNames.length !== 48 || new Set(resourceNames).size !== 48) {
|
||||
throw new Error(`平台资源定义应为48类,当前读取到${resourceNames.length}类`);
|
||||
}
|
||||
if (/define\([^;]*?'readonly'\s*,\s*\[\s*\]/s.test(resources)) {
|
||||
throw new Error('只读资源不得继续使用空字段契约');
|
||||
}
|
||||
|
||||
const labelBlock = resources.match(
|
||||
/const fieldLabels: Record<string, string> = \{([\s\S]*?)\n\};/,
|
||||
)?.[1];
|
||||
if (!labelBlock) throw new Error('无法读取全局中文字段字典');
|
||||
const labels = new Set(
|
||||
[...labelBlock.matchAll(/^\s{2}([A-Za-z_][A-Za-z0-9_]*):\s*'[^']+'/gm)].map(
|
||||
(match) => match[1],
|
||||
),
|
||||
);
|
||||
const usedKeys = new Set(
|
||||
[...resources.matchAll(/\b(?:f|relation)\('([^']+)'/g)].map(
|
||||
(match) => match[1],
|
||||
),
|
||||
);
|
||||
const missingLabels = [...usedKeys].filter((key) => !labels.has(key));
|
||||
if (missingLabels.length) {
|
||||
throw new Error(`资源字段缺少中文名称:${missingLabels.join('、')}`);
|
||||
}
|
||||
|
||||
if (/title="ID"|data-index="id"/.test(listPage)) {
|
||||
throw new Error('标准资源列表不得把数据库ID作为业务列展示');
|
||||
}
|
||||
assertIncludes(listPage, 'title="系统唯一标识"', '列表必须中文标注系统唯一标识');
|
||||
assertIncludes(
|
||||
listPage,
|
||||
'class="resource-table-shell"',
|
||||
'列表必须使用内部横向滚动容器',
|
||||
);
|
||||
assertIncludes(
|
||||
display,
|
||||
'hasResourceFieldLabel',
|
||||
'详情必须提供未知字段中文契约检查',
|
||||
);
|
||||
assertIncludes(
|
||||
detailPage,
|
||||
'!hasResourceFieldLabel(props.definition, actualKey)',
|
||||
'详情不得直接回显未配置字段',
|
||||
);
|
||||
assertIncludes(
|
||||
detailPage,
|
||||
'resourceDetailContract(props.definition.name)',
|
||||
'详情关联表必须使用资源专属固定列契约',
|
||||
);
|
||||
for (const collection of [
|
||||
'products', 'revisions', 'items', 'assignments', 'statuses',
|
||||
'tracks', 'confirmations', 'payments',
|
||||
]) {
|
||||
assertIncludes(
|
||||
detailContract,
|
||||
`${collection}: {`,
|
||||
`缺少关联记录固定列契约:${collection}`,
|
||||
);
|
||||
}
|
||||
|
||||
process.stdout.write('平台48类资源中文展示契约检查通过\n');
|
||||
@@ -158,9 +158,8 @@ const resourcesSource = await readFile(
|
||||
new URL('../src/api/resources.ts', import.meta.url),
|
||||
'utf8',
|
||||
);
|
||||
assert.equal(
|
||||
(resourcesSource.match(/relationLinkage:/g) ?? []).length,
|
||||
3,
|
||||
assert.ok(
|
||||
(resourcesSource.match(/relationLinkage:/g) ?? []).length >= 3,
|
||||
'联动配置必须显式启用于工作人员、用户服务关系和配送合同的配送点字段',
|
||||
);
|
||||
assert.match(resourcesSource, /filterKey: 'gas_basic_identities'/);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* 功能:静态检查用户地址列表的账户名称展示、标识降级与复制入口。
|
||||
* 版本:v1.0.0
|
||||
* 版本:v1.1.0
|
||||
*/
|
||||
import { readFileSync } from 'node:fs';
|
||||
import { dirname, resolve } from 'node:path';
|
||||
@@ -24,8 +24,8 @@ const fieldDisplay = source('src/views/shared/resource-list-field-display.ts');
|
||||
expectIncludes(resources, "listLabel: '用户账户'", '列表列名未改为用户账户');
|
||||
expectIncludes(resources, 'listRelationNameOnly: true', '用户地址未启用账户名称展示');
|
||||
expectIncludes(listPage, '<RelationNameText', '列表未使用账户名称组件');
|
||||
expectIncludes(fieldDisplay, 'return match ? optionLabel(match) : identity;', '关系名称缺失时未降级显示标识');
|
||||
expectIncludes(relationName, '用户唯一标识:${identity}', '缺少完整标识悬停提示');
|
||||
expectIncludes(fieldDisplay, "return match ? optionLabel(match) : '名称加载失败';", '关系名称缺失时未显示明确错误');
|
||||
expectIncludes(relationName, '`${identityLabel}:${identity}`', '缺少完整标识悬停提示');
|
||||
expectIncludes(relationName, '@click.stop="copyIdentity"', '缺少标识复制入口');
|
||||
|
||||
console.log('用户地址展示检查通过:账户名称、标识降级、悬停与复制入口均已覆盖。');
|
||||
console.log('用户地址展示检查通过:账户名称、加载失败提示、悬停与复制入口均已覆盖。');
|
||||
|
||||
Reference in New Issue
Block a user