优化合同气瓶设备名称显示
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* 功能:静态检查配送订单合同气瓶候选的可读显示与交互约束。
|
||||
* 版本:v1.0.0
|
||||
* 版本:v1.1.0
|
||||
*/
|
||||
import assert from 'node:assert/strict';
|
||||
import { readFileSync } from 'node:fs';
|
||||
@@ -10,11 +10,15 @@ const display = readFileSync(new URL('../src/api/resource-display.ts', import.me
|
||||
const form = readFileSync(new URL('../src/views/resource/ResourceFieldForm.vue', import.meta.url), 'utf8');
|
||||
|
||||
assert.match(resources, /label: '合同气瓶'/, '订单气瓶字段必须使用业务名称');
|
||||
assert.match(resources, /relationOptionLabelKey: 'product_type_name'/, '气瓶候选必须显示气瓶类型名称');
|
||||
assert.match(resources, /relationOptionDisplay: 'product-name-type'/, '合同气瓶必须使用设备名称和类型组合显示');
|
||||
assert.match(resources, /请输入智能气阀名称、设备类型或设备编码搜索/, '合同气瓶必须提示可按名称、类型或编码搜索');
|
||||
assert.match(resources, /该合同暂无可用气瓶,请先为合同绑定气瓶/, '缺少无可用气瓶的业务引导');
|
||||
assert.match(resources, /filterKey: 'contract_identity'/, '订单气瓶请求必须携带合同标识');
|
||||
assert.match(display, /field\.relationOptionLabelKey/, '关系选项必须支持指定业务展示字段');
|
||||
assert.match(display, /productNameTypeLabel/, '合同气瓶必须具备名称和类型组合标签');
|
||||
assert.match(display, /duplicateCount/, '同名同类型设备必须追加编码消歧');
|
||||
assert.match(display, /product_name: '智能气阀名称'/, '合同和订单详情必须展示智能气阀名称');
|
||||
assert.doesNotMatch(form, /max-tag-count/, '合同气瓶多选必须完整展示全部已选标签');
|
||||
assert.match(form, /'请先选择配送合同'/, '父合同未选时缺少操作顺序提示');
|
||||
|
||||
console.log('合同气瓶显示检查通过:候选显示气瓶类型名称,并完整展示全部已选标签。');
|
||||
console.log('合同气瓶显示检查通过:候选显示智能气阀名称和设备类型,同名时追加编码,并完整展示全部已选标签。');
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* 功能:统一资源列表与详情页面的字段名称、关系、金额、状态和时间展示。
|
||||
* 版本:v1.2.0
|
||||
* 版本:v1.3.0
|
||||
*/
|
||||
import dayjs from 'dayjs';
|
||||
import { staffRoleLabel } from './resource-staff-relation';
|
||||
@@ -39,6 +39,7 @@ const collectionFieldAliases: Record<string, Record<string, string>> = {
|
||||
'gasorder_contract.products': {
|
||||
gasorder_contract_identity: '配送合同唯一标识',
|
||||
product_info_identity: '气瓶唯一标识',
|
||||
product_name: '智能气阀名称',
|
||||
product_code: '气瓶编码',
|
||||
product_type_name: '气瓶类型名称',
|
||||
product_params: '气瓶规格参数',
|
||||
@@ -47,6 +48,13 @@ const collectionFieldAliases: Record<string, Record<string, string>> = {
|
||||
unbind_reason: '解绑原因',
|
||||
unit_price: '约定充装单价(元)',
|
||||
},
|
||||
'gasorder_basic.items': {
|
||||
product_name: '智能气阀名称',
|
||||
product_code: '设备编码',
|
||||
product_type_name: '设备类型',
|
||||
product_params: '设备参数',
|
||||
unit_price: '成交单价(元)',
|
||||
},
|
||||
};
|
||||
|
||||
const amountKeys = new Set([
|
||||
@@ -149,7 +157,14 @@ export function optionLabel(option: ResourceRow) {
|
||||
}
|
||||
|
||||
/** 工作人员关系额外展示角色,其他关系保持原有可读名称。 */
|
||||
export function relationOptionLabel(field: ResourceField, option: ResourceRow) {
|
||||
export function relationOptionLabel(
|
||||
field: ResourceField,
|
||||
option: ResourceRow,
|
||||
options: ResourceRow[] = [],
|
||||
) {
|
||||
if (field.relationOptionDisplay === 'product-name-type') {
|
||||
return productNameTypeLabel(option, options);
|
||||
}
|
||||
const configuredLabel = field.relationOptionLabelKey
|
||||
? option[field.relationOptionLabelKey]
|
||||
: undefined;
|
||||
@@ -167,6 +182,26 @@ export function relationOptionLabel(field: ResourceField, option: ResourceRow) {
|
||||
: label;
|
||||
}
|
||||
|
||||
/** 合同气瓶优先显示具体设备名称和绑定时类型;同名同类型时追加编码以便区分。 */
|
||||
function productNameTypeLabel(option: ResourceRow, options: ResourceRow[]) {
|
||||
const name = String(option.product_name ?? '').trim();
|
||||
const type = String(option.product_type_name ?? '').trim();
|
||||
const code = String(option.product_code ?? '').trim();
|
||||
const identity = String(option.identity ?? '').trim();
|
||||
if (!name) {
|
||||
if (code) return type ? `${code}(${type})` : code;
|
||||
return identity || type || '-';
|
||||
}
|
||||
const base = type ? `${name}(${type})` : name;
|
||||
const duplicateCount = options.filter(
|
||||
(item) =>
|
||||
String(item.product_name ?? '').trim() === name &&
|
||||
String(item.product_type_name ?? '').trim() === type,
|
||||
).length;
|
||||
if (duplicateCount <= 1) return base;
|
||||
return `${base} · ${code || identity || '未编号'}`;
|
||||
}
|
||||
|
||||
function relationLabel(
|
||||
field: ResourceField,
|
||||
identity: string,
|
||||
@@ -177,7 +212,11 @@ function relationLabel(
|
||||
);
|
||||
if (!match) return identity;
|
||||
if (field.relation === '/staff_account') {
|
||||
return relationOptionLabel(field, match);
|
||||
return relationOptionLabel(
|
||||
field,
|
||||
match,
|
||||
relationOptions[field.relation ?? ''] ?? [],
|
||||
);
|
||||
}
|
||||
return field.displayRelationLabel
|
||||
? optionLabel(match)
|
||||
|
||||
@@ -87,6 +87,8 @@ export type ResourceField = {
|
||||
dynamicRelation?: ResourceDynamicRelation;
|
||||
/** 关联选项优先使用的业务展示字段。 */
|
||||
relationOptionLabelKey?: string;
|
||||
/** 关联选项的组合展示方式;合同气瓶使用设备名称、绑定类型快照和编码消歧。 */
|
||||
relationOptionDisplay?: 'product-name-type';
|
||||
/** 该字段为真时,在关联选项后追加“默认地址”。 */
|
||||
relationOptionDefaultKey?: string;
|
||||
/** 候选加载完成后自动选中该布尔字段为真的选项。 */
|
||||
@@ -568,7 +570,7 @@ export const resources: ResourceUiDefinition[] = [
|
||||
filterKey: 'gasorder_contract_identity', filterOnly: true, requiresParent: true,
|
||||
parentChangeMessage: '配送合同已变更,请重新选择该合同用户的收货地址',
|
||||
},
|
||||
}), f('gasorder_contract_product_identities', { label: '合同气瓶', required: true, type: 'identity-list', relation: '/gasorder_contract_product', placeholder: '请输入气瓶编码或类型搜索', relationOptionLabelKey: 'product_type_name', relationEmptyText: '该合同暂无可用气瓶,请先为合同绑定气瓶', relationLinkage: { parentKey: 'gasorder_contract_identity', optionParentKey: '', filterKey: 'contract_identity', filterOnly: true, requiresParent: true, parentChangeMessage: '配送合同已变更,请重新选择该合同可用的气瓶' } }), f('contact_name', { required: true }), f('contact_phone', { required: true }), f('discount_amount'), f('remark')], 'list', [
|
||||
}), f('gasorder_contract_product_identities', { label: '合同气瓶', required: true, type: 'identity-list', relation: '/gasorder_contract_product', placeholder: '请输入智能气阀名称、设备类型或设备编码搜索', relationOptionDisplay: 'product-name-type', relationEmptyText: '该合同暂无可用气瓶,请先为合同绑定气瓶', relationLinkage: { parentKey: 'gasorder_contract_identity', optionParentKey: '', filterKey: 'contract_identity', filterOnly: true, requiresParent: true, parentChangeMessage: '配送合同已变更,请重新选择该合同可用的气瓶' } }), f('contact_name', { required: true }), f('contact_phone', { required: true }), f('discount_amount'), f('remark')], 'list', [
|
||||
{ name: '分配订单', resource: '/gasorder_basic/:identity/assign', fields: [relation('delivery_basic_identity', '/delivery_basic', true), relation('staff_account_identity', '/staff_account', true, { staffRelation: { roles: ['delivery'], enabledOnly: true, workStatus: 'on_duty' } }), ...reason], visibleFor: { field: 'order_status', values: [16, 18] } },
|
||||
{ name: '开始罐装', resource: '/gasorder_basic/:identity/filling', fields: reason, visibleFor: { field: 'order_status', values: [18] } },
|
||||
{ name: '待配送', resource: '/gasorder_basic/:identity/ready', fields: reason, visibleFor: { field: 'order_status', values: [19] } },
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<!--
|
||||
功能:以响应式信息卡和子表页签展示标准资源详情。
|
||||
版本:v1.3.0
|
||||
版本:v1.4.0
|
||||
-->
|
||||
<template>
|
||||
<div class="detail-stack">
|
||||
@@ -143,7 +143,7 @@ const collections = computed(() =>
|
||||
.filter(([, value]) => Array.isArray(value) && value.length > 0)
|
||||
.map(([key, value]) => {
|
||||
const rows = value as ResourceRow[];
|
||||
const columns = [
|
||||
const availableColumns = [
|
||||
...new Set(
|
||||
rows.flatMap((row) =>
|
||||
Object.keys(row).filter(
|
||||
@@ -155,7 +155,33 @@ const collections = computed(() =>
|
||||
),
|
||||
),
|
||||
),
|
||||
].slice(0, 8);
|
||||
];
|
||||
const preferredColumns: Record<string, string[]> = {
|
||||
'gasorder_contract.products': [
|
||||
'bound_at',
|
||||
'product_name',
|
||||
'product_code',
|
||||
'product_type_name',
|
||||
'unit_price',
|
||||
'product_info_identity',
|
||||
'unbound_at',
|
||||
'unbind_reason',
|
||||
],
|
||||
'gasorder_basic.items': [
|
||||
'product_name',
|
||||
'product_code',
|
||||
'product_type_name',
|
||||
'product_params',
|
||||
'unit_price',
|
||||
'active',
|
||||
'product_info_identity',
|
||||
],
|
||||
};
|
||||
const preferred =
|
||||
preferredColumns[`${props.definition.name}.${key}`] ?? [];
|
||||
const columns = [...new Set([...preferred, ...availableColumns])]
|
||||
.filter((column) => availableColumns.includes(column))
|
||||
.slice(0, 8);
|
||||
return {
|
||||
key,
|
||||
title: resourceFieldLabel(props.definition, key),
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<!--
|
||||
功能:渲染标准资源的新建、编辑和业务动作字段控件。
|
||||
版本:v1.2.0
|
||||
版本:v1.3.0
|
||||
-->
|
||||
<template>
|
||||
<div class="field-grid">
|
||||
@@ -105,7 +105,13 @@
|
||||
:key="String(option.identity)"
|
||||
:value="String(option.identity)"
|
||||
>
|
||||
{{ relationOptionLabel(field, option) }}
|
||||
{{
|
||||
relationOptionLabel(
|
||||
field,
|
||||
option,
|
||||
relationOptions[relationResource(field)] ?? [],
|
||||
)
|
||||
}}
|
||||
</a-option>
|
||||
<template #empty>
|
||||
<div class="relation-empty">{{ relationEmptyText(field) }}</div>
|
||||
@@ -192,7 +198,13 @@ function readonlyRelationLabel(field: ResourceField) {
|
||||
const option = (props.relationOptions[relationResource(field)] ?? []).find(
|
||||
(item) => String(item.identity ?? '') === identity,
|
||||
);
|
||||
return option ? relationOptionLabel(field, option) : identity;
|
||||
return option
|
||||
? relationOptionLabel(
|
||||
field,
|
||||
option,
|
||||
props.relationOptions[relationResource(field)] ?? [],
|
||||
)
|
||||
: identity;
|
||||
}
|
||||
|
||||
/** 解析固定或由父字段动态决定的关系资源。 */
|
||||
|
||||
Reference in New Issue
Block a user