修复合同详情字段中文显示

通用详情页复用中文字段字典,并为合同气瓶快照补充上下文名称。
合同状态按模型常量显示中文,数据库字段和 API 保持不变。
已通过资源页面检查、类型检查和生产构建。
This commit is contained in:
czl231
2026-08-12 19:49:41 +08:00
parent 3cad8fd0ba
commit deea31d79e
6 changed files with 154 additions and 6 deletions

View File

@@ -1,6 +1,6 @@
/**
* 功能:静态检查平台总后台全部标准资源是否具备独立记录页配置。
* 版本v1.1.0
* 版本v1.2.0
*/
import { readFileSync, existsSync } from 'node:fs';
import { fileURLToPath } from 'node:url';
@@ -15,6 +15,8 @@ const routeSource = [
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 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']);
@@ -49,6 +51,17 @@ if (
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))",
]) {
if (!displaySource.includes(marker)) fail(`合同详情中文展示缺少 ${marker}`);
}
const createCount = listResources.filter((item) => createModes.has(item.mode)).length;
console.log(

View File

@@ -1,10 +1,14 @@
/**
* 功能:统一资源列表与详情页面的字段名称、关系、金额、状态和时间展示。
* 版本v1.1.0
* 版本v1.2.0
*/
import dayjs from 'dayjs';
import { staffRoleLabel } from './resource-staff-relation';
import type { ResourceField, ResourceUiDefinition } from './resources';
import {
defaultResourceFieldLabel,
type ResourceField,
type ResourceUiDefinition,
} from './resources';
import type { RecordPageMode, ResourceRow } from './resource-page-rules';
const aliases: Record<string, string> = {
@@ -30,6 +34,21 @@ const aliases: Record<string, string> = {
is_system: '系统内置',
};
/** 聚合子表字段可能与全局同名字段具有不同业务语义,按父资源和集合名称覆盖。 */
const collectionFieldAliases: Record<string, Record<string, string>> = {
'gasorder_contract.products': {
gasorder_contract_identity: '配送合同唯一标识',
product_info_identity: '气瓶唯一标识',
product_code: '气瓶编码',
product_type_name: '气瓶类型名称',
product_params: '气瓶规格参数',
bound_at: '绑定时间',
unbound_at: '解绑时间',
unbind_reason: '解绑原因',
unit_price: '约定充装单价(元)',
},
};
const amountKeys = new Set([
'amount',
'unit_price',
@@ -72,11 +91,16 @@ export function primaryRecord(detail: ResourceRow): ResourceRow {
export function resourceFieldLabel(
definition: ResourceUiDefinition,
key: string,
collectionKey = '',
) {
const normalized = key.endsWith('_masked') ? key.slice(0, -7) : key;
const collectionAliases =
collectionFieldAliases[`${definition.name}.${collectionKey}`];
return (
collectionAliases?.[normalized] ??
definition.fields.find((field) => field.key === normalized)?.label ??
aliases[key] ??
defaultResourceFieldLabel(normalized) ??
aliases[normalized] ??
key
);
}
@@ -96,6 +120,19 @@ export function recordStatusColor(status: number) {
);
}
/** 将合同业务状态转换为模型常量对应的中文名称。 */
export function contractStatusLabel(status: number) {
return (
{
0: '草稿',
10: '待处理',
11: '生效中',
12: '已过期',
13: '已终止',
}[status] ?? `未知(${status}`
);
}
/** 选择关系记录的首选可读名称。 */
export function optionLabel(option: ResourceRow) {
return String(
@@ -141,6 +178,7 @@ export function displayRawValue(key: string, value: unknown) {
if (value == null || value === '') return '-';
if (typeof value === 'boolean') return value ? '是' : '否';
if (key === 'status') return recordStatusLabel(Number(value));
if (key === 'contract_status') return contractStatusLabel(Number(value));
if (
amountKeys.has(key) ||
key.endsWith('_amount') ||

View File

@@ -184,6 +184,7 @@ const fieldLabels: Record<string, string> = {
default_delivery_fee: '默认配送费(元)',
signed_at: '签署时间',
effective_at: '生效时间',
bound_at: '绑定时间',
unit_price: '单价(元)',
unbound_at: '解绑时间',
revision_no: '修订号',
@@ -203,6 +204,8 @@ const fieldLabels: Record<string, string> = {
confirmed_at: '确认时间',
sort_no: '排序',
product_code: '商品编码',
product_type_name: '产品类型名称',
product_params: '产品规格参数',
price_amount: '售价(元)',
stock_quantity: '库存',
value: '属性值',
@@ -258,6 +261,11 @@ const fieldLabels: Record<string, string> = {
withdrawable: '计入可提现余额',
};
/** 返回字段的全局中文名称,供未显式声明字段的只读页面统一兜底。 */
export function defaultResourceFieldLabel(key: string) {
return fieldLabels[key];
}
const numbers = new Set([
'sort_no', 'stock_quantity', 'quantity', 'score', 'version_no',
'attempt_no', 'target_product_status',

View File

@@ -1,6 +1,6 @@
<!--
功能以响应式信息卡和子表页签展示标准资源详情
版本v1.2.0
版本v1.3.0
-->
<template>
<div class="detail-stack">
@@ -27,7 +27,7 @@
<a-table-column
v-for="column in collection.columns"
:key="column"
:title="resourceFieldLabel(definition, column)"
:title="resourceFieldLabel(definition, column, collection.key)"
:width="column.includes('identity') ? 220 : 160"
ellipsis
tooltip