统一合同气阀候选与绑定入口

This commit is contained in:
czl231
2026-08-31 22:04:22 +08:00
parent 9a23ab2f5a
commit 0f2475098f
23 changed files with 352 additions and 47 deletions

View File

@@ -77,6 +77,10 @@ assert(listPage.includes('avatarLoader.reset()'), '列表刷新未清理头像
assert(listPage.includes('field.listRelationNameOnly && fieldValue(field, record)'), '关系列表字段尚未按气站端显示业务名称');
assert(listPage.includes('relationListName(field, record)'), '关系列表字段缺少服务端派生名称读取');
assert(listPage.includes('@open="openRelation(field, record)"'), '关系列表名称缺少关联详情入口');
assert(listPage.includes("Number(record.contract_status) === 0"), '草稿合同缺少绑定气瓶入口状态限制');
assert(listPage.includes('record.user_delivery_service_active !== false'), '合同气瓶入口未校验用户仍属当前配送点');
assert(listPage.includes('@click="bindContractProduct(record)"'), '配送合同列表缺少绑定气瓶入口');
assert(listPage.includes("name: 'contract-products-create'"), '绑定气瓶入口未进入合同气瓶新建页');
const avatarLoader = read('src/views/shared/protected-list-avatar-loader.ts');
assert(avatarLoader.includes('MAX_CONCURRENT_REQUESTS = 6'), '头像请求并发上限未与 5173 对齐');
assert(avatarLoader.includes("new Set(['staff_account', 'user_account'])"), '头像列表资源白名单不正确');
@@ -97,6 +101,8 @@ assert(!listPage.includes('placeholder="关键字段模糊搜索"'), '列表仍
assert(listPage.includes('ensureCredentialContext'), '人员资质列表缺少服务端人员上下文校验');
assert(listPage.includes("field.key === 'staff_account_identity'"), '人员范围资质列表未隐藏重复人员列');
assert(recordPage.includes('已锁定,不可更换'), '人员资质独立页未锁定所属配送人员');
assert(recordPage.includes("definition.value.name === 'gasorder_contract_product'"), '合同气瓶新建页未识别合同预填上下文');
assert(recordPage.includes("field.key === 'gasorder_contract_identity'"), '预填合同未在合同气瓶新建页锁定');
const attachmentApi = read('src/api/contract-attachment.ts');
const attachmentState = read('src/views/resource/use-contract-attachment.ts');
const detailContent = read('src/views/resource/ResourceDetailContent.vue');
@@ -124,15 +130,16 @@ assert(detailContent.includes("key.endsWith('_display_name')"), '详情页仍可
assert(detailContent.includes('hasDetailFieldLabel'), '详情页未启用中文字段白名单');
assert(detailContent.includes('查看参数'), '关联记录缺少完整 JSON 查看入口');
assert(detailContent.includes('智能气阀名称取当前设备资料'), '合同气瓶名称与快照语义未说明');
assert(resourceDisplay.includes("user_service_active: '签约用户仍属合同气站'"), '签约服务关系缺少中文业务标签');
assert(resourceDisplay.includes("user_delivery_service_active: '签约用户仍属当前配送点'"), '当前配送点服务关系缺少中文业务标签');
assert(resourceDisplay.includes("activate: '启用合同'"), '合同修订动作未中文化');
assert(recordPage.includes("record.value.user_service_active === false"), '失效服务关系下未限制合同动作');
assert(recordPage.includes("record.value.user_delivery_service_active === false"), '用户转出当前配送点后未限制合同动作');
assert(definitions.includes("relationFilters: { candidate: 'order' }"), '订单合同候选未限定可履约范围');
assert(definitions.includes("f('request_no', { required: true })"), '请求流水号未按 5173 保持人工必填');
assert(definitions.includes("f('contact_name', { required: true })"), '订单联系人未保持独立必填');
assert(definitions.includes("f('contact_phone', { required: true })"), '订单联系电话未保持独立必填');
assert(definitions.includes("filterKey: 'gasorder_contract_identity'"), '收货地址未按配送合同联动');
assert(definitions.includes("filterKey: 'contract_identity'"), '合同气瓶未按配送合同联动');
assert(definitions.includes('该合同用户暂无可绑定的智能气阀,请先由平台总后台将设备归属变更为该用户'), '合同气阀空状态缺少平台归属引导');
assert(definitions.includes("relationOptionLabelKey: 'address'"), '收货地址候选仍可能显示裸唯一标识');
assert(definitions.includes("relationOptionDisplay: 'product-name-type'"), '合同气瓶缺少名称、编码和类型组合展示');
assert(relationLinkage.includes('const versions = new Map'), '关系联动缺少过期响应版本守卫');

View File

@@ -22,7 +22,7 @@ const contracts: Record<string, ResourceDetailContract> = {
'contract_status',
'title',
'user_account_identity',
'user_service_active',
'user_delivery_service_active',
'gas_basic_identity',
'delivery_basic_identity',
'default_delivery_fee',

View File

@@ -1,6 +1,6 @@
/**
* 功能描述:统一配送点资源独立页面的字段名称和值展示。
* 版本v1.1.0。
* 版本v1.2.0。
*/
import dayjs from 'dayjs';
import type { ResourceRow } from './resource-record-form';
@@ -26,6 +26,7 @@ const aliases: Record<string, string> = {
contract: '合同',
order: '订单',
user_service_active: '签约用户仍属合同气站',
user_delivery_service_active: '签约用户仍属当前配送点',
user_account_display_name: '用户账户',
gas_basic_display_name: '气站',
delivery_basic_display_name: '配送点',

View File

@@ -421,7 +421,7 @@ const platformResources: ResourceUiDefinition[] = [
{ name: '续签合同', resource: '/gasorder_contract/:identity/renew', fields: [f('effective_at', { required: true }), f('expired_at'), ...reason], visibleFor: { field: 'contract_status', values: [11, 12, 13] } },
{ name: '终止合同', resource: '/gasorder_contract/:identity/terminate', danger: true, fields: reason, visibleFor: { field: 'contract_status', values: [11] } },
], { canCreate: true, canEdit: true }),
define('gasorder_contract_product', '合同气瓶', 'append_only', [relation('gasorder_contract_identity', '/gasorder_contract', true), relation('product_info_identity', '/product_info', true), f('unit_price')], 'list', [
define('gasorder_contract_product', '合同气瓶', 'append_only', [relation('gasorder_contract_identity', '/gasorder_contract', true), relation('product_info_identity', '/product_info', true, { label: '智能气阀', placeholder: '请选择该合同用户可绑定的智能气阀', relationEmptyText: '该合同用户暂无可绑定的智能气阀,请先由平台总后台将设备归属变更为该用户', relationLinkage: { parentKey: 'gasorder_contract_identity', filterKey: 'contract_identity', requiresParent: true, parentChangeMessage: '配送合同已变更,请重新选择该合同用户的智能气阀' } }), f('unit_price')], 'list', [
{ name: '解绑气瓶', resource: '/gasorder_contract_product/:identity/unbind', danger: true, fields: reason },
]),
define('gasorder_contract_revision', '合同修订记录', 'readonly', []),
@@ -514,7 +514,7 @@ const gasOverrides: ResourceUiDefinition[] = [
{ name: '续签合同', resource: '/gasorder_contract/:identity/renew', fields: [f('effective_at', { required: true }), f('expired_at'), ...reason], visibleFor: { field: 'contract_status', values: [11, 12, 13] } },
{ name: '终止合同', resource: '/gasorder_contract/:identity/terminate', danger: true, fields: reason, visibleFor: { field: 'contract_status', values: [11] } },
], { canCreate: true, canEdit: true }),
define('gasorder_contract_product', '合同气瓶', 'append_only', [relation('gasorder_contract_identity', '/gasorder_contract', true), relation('product_info_identity', '/product_info', true), f('unit_price')], 'list', [
define('gasorder_contract_product', '合同气瓶', 'append_only', [relation('gasorder_contract_identity', '/gasorder_contract', true), relation('product_info_identity', '/product_info', true, { label: '智能气阀', placeholder: '请选择该合同用户可绑定的智能气阀', relationEmptyText: '该合同用户暂无可绑定的智能气阀,请先由平台总后台将设备归属变更为该用户', relationLinkage: { parentKey: 'gasorder_contract_identity', filterKey: 'contract_identity', requiresParent: true, parentChangeMessage: '配送合同已变更,请重新选择该合同用户的智能气阀' } }), f('unit_price')], 'list', [
{ name: '解绑气瓶', resource: '/gasorder_contract_product/:identity/unbind', danger: true, fields: reason },
]),
define('gasorder_contract_revision', '合同修订记录', 'readonly', []),
@@ -553,7 +553,7 @@ const deliveryOverrides: ResourceUiDefinition[] = [
{ name: '续签合同', resource: '/gasorder_contract/:identity/renew', fields: [f('effective_at', { required: true }), f('expired_at'), ...reason], visibleFor: { field: 'contract_status', values: [11, 12, 13] } },
{ name: '终止合同', resource: '/gasorder_contract/:identity/terminate', danger: true, fields: reason, visibleFor: { field: 'contract_status', values: [11] } },
], { canCreate: true, canEdit: true }),
define('gasorder_contract_product', '合同气瓶', 'append_only', [relation('gasorder_contract_identity', '/gasorder_contract', true), relation('product_info_identity', '/product_info', true), f('unit_price')], 'list', [
define('gasorder_contract_product', '合同气瓶', 'append_only', [relation('gasorder_contract_identity', '/gasorder_contract', true), relation('product_info_identity', '/product_info', true, { label: '智能气阀', placeholder: '请选择该合同用户可绑定的智能气阀', relationEmptyText: '该合同用户暂无可绑定的智能气阀,请先由平台总后台将设备归属变更为该用户', relationLinkage: { parentKey: 'gasorder_contract_identity', filterKey: 'contract_identity', requiresParent: true, parentChangeMessage: '配送合同已变更,请重新选择该合同用户的智能气阀' } }), f('unit_price')], 'list', [
{ name: '解绑气瓶', resource: '/gasorder_contract_product/:identity/unbind', danger: true, fields: reason },
]),
define('gasorder_contract_revision', '合同修订记录', 'readonly', []),

View File

@@ -20,7 +20,7 @@
:color="contractStatusColor(Number(entry.rawValue))"
>{{ entry.value }}</a-tag>
<a-tag
v-else-if="entry.key === 'user_service_active'"
v-else-if="['user_service_active', 'user_delivery_service_active'].includes(entry.key)"
class="detail-status-tag"
:color="entry.rawValue === true ? 'green' : 'red'"
>{{ entry.value }}</a-tag>

View File

@@ -1,4 +1,4 @@
<!-- 功能描述承载配送点标准资源的新建详情和编辑独立页面版本v1.1.0 -->
<!-- 功能描述承载配送点标准资源的新建详情和编辑独立页面版本v1.2.0 -->
<template>
<div class="record-page">
<header class="page-header">
@@ -218,7 +218,16 @@ const summaryRecord = computed(() => (mode.value === 'detail' ? record.value : {
const formFields = computed(() =>
recordFormFields(definition.value.name, definition.value.fields, mode.value as 'create' | 'edit')
.filter((field) => field.key !== 'avatar')
.map((field) => (isCredentialResource.value && field.key === 'staff_account_identity' ? { ...field, readonly: true } : field)),
.map((field) => {
const lockedCredentialOwner = isCredentialResource.value && field.key === 'staff_account_identity';
const lockedContract =
mode.value === 'create' &&
definition.value.name === 'gasorder_contract_product' &&
field.key === 'gasorder_contract_identity' &&
route.query.relation_key === 'gasorder_contract_identity' &&
Boolean(route.query.owner_identity);
return lockedCredentialOwner || lockedContract ? { ...field, readonly: true } : field;
}),
);
const relationBusy = computed(() => relations.isLoading(formFields.value));
const relationUnavailableMessage = computed(() => relations.unavailableMessage(formFields.value));
@@ -226,7 +235,7 @@ const canEditRecord = computed(() => definition.value.canEdit && !recordEditReas
const visibleActions = computed(() =>
(definition.value.detailActions ?? []).filter(
(action) =>
!(definition.value.name === 'gasorder_contract' && record.value.user_service_active === false && action.name !== '终止合同') &&
!(definition.value.name === 'gasorder_contract' && record.value.user_delivery_service_active === false && action.name !== '终止合同') &&
(!action.visibleFor || action.visibleFor.values.includes(record.value[action.visibleFor.field] as string | number)),
),
);

View File

@@ -1,4 +1,4 @@
<!-- 功能描述展示配送点标准资源列表并导航到独立记录页版本v1.3.0 -->
<!-- 功能描述展示配送点标准资源列表并导航到独立记录页版本v1.4.0 -->
<template>
<a-card :title="listTitle" :bordered="false">
<template v-if="isCredentialList" #extra>
@@ -104,11 +104,17 @@
<a-table-column title="系统唯一标识" :width="170">
<template #cell="{ record }"><IdentityText :value="String(record.identity)" /></template>
</a-table-column>
<a-table-column title="操作" :width="220" fixed="right">
<a-table-column title="操作" :width="definition.name === 'gasorder_contract' ? 285 : 220" fixed="right">
<template #cell="{ record }">
<a-space>
<a-button v-if="definition.name === 'staff_account'" size="mini" @click="viewCredentials(record)">查看资质</a-button>
<a-button size="mini" @click="openRecord('detail', record)">详情</a-button>
<a-button
v-if="definition.name === 'gasorder_contract' && Number(record.contract_status) === 0 && record.user_delivery_service_active !== false"
size="mini"
type="primary"
@click="bindContractProduct(record)"
>绑定气瓶</a-button>
<a-tooltip v-if="definition.canEdit" :content="recordEditReason(definition, record) || '编辑记录'">
<span>
<a-button
@@ -361,6 +367,18 @@ function openRecord(mode: 'detail' | 'edit', row: ResourceRow) {
);
}
/** 从草稿合同列表进入合同气瓶新建页,并预填当前合同。 */
function bindContractProduct(row: ResourceRow) {
return router.push({
name: 'contract-products-create',
query: {
relation_key: 'gasorder_contract_identity',
owner_identity: String(row.identity ?? ''),
return_to: route.fullPath,
},
});
}
/** 进入当前配送人员的资质列表并保留来源。 */
function viewCredentials(row: ResourceRow) {
return router.push({

View File

@@ -111,6 +111,12 @@ if (
) {
fail('签约用户转出后未限制合同编辑和业务动作');
}
if (
!resourceSource.includes("filterKey: 'contract_identity'") ||
!resourceSource.includes('该合同用户暂无可绑定的智能气阀,请先由平台总后台将设备归属变更为该用户')
) {
fail('合同气阀候选未按合同联动或缺少平台归属引导');
}
if (
!ruleSource.includes('row.contract_readonly === true') ||
!recordSource.includes('record.value.contract_readonly === true') ||

View File

@@ -557,7 +557,7 @@ const platformResources: ResourceUiDefinition[] = [
{ name: '续签合同', resource: '/gasorder_contract/:identity/renew', fields: [f('effective_at', { required: true }), f('expired_at'), ...reason], visibleFor: { field: 'contract_status', values: [11, 12, 13] } },
{ name: '终止合同', resource: '/gasorder_contract/:identity/terminate', danger: true, fields: reason, visibleFor: { field: 'contract_status', values: [11] } },
], { canCreate: true, canEdit: true }),
define('gasorder_contract_product', '合同气瓶', 'append_only', [relation('gasorder_contract_identity', '/gasorder_contract', true), relation('product_info_identity', '/product_info', true), f('unit_price')], 'list', [
define('gasorder_contract_product', '合同气瓶', 'append_only', [relation('gasorder_contract_identity', '/gasorder_contract', true), relation('product_info_identity', '/product_info', true, { label: '智能气阀', placeholder: '请选择该合同用户可绑定的智能气阀', relationEmptyText: '该合同用户暂无可绑定的智能气阀,请先由平台总后台将设备归属变更为该用户', relationLinkage: { parentKey: 'gasorder_contract_identity', optionParentKey: '', filterKey: 'contract_identity', filterOnly: true, requiresParent: true, parentChangeMessage: '配送合同已变更,请重新选择该合同用户的智能气阀' } }), f('unit_price')], 'list', [
{ name: '解绑气瓶', resource: '/gasorder_contract_product/:identity/unbind', danger: true, fields: reason },
]),
define('gasorder_contract_revision', '合同修订记录', 'readonly', []),
@@ -650,7 +650,7 @@ const gasOverrides: ResourceUiDefinition[] = [
{ name: '续签合同', resource: '/gasorder_contract/:identity/renew', fields: [f('effective_at', { required: true }), f('expired_at'), ...reason], visibleFor: { field: 'contract_status', values: [11, 12, 13] } },
{ name: '终止合同', resource: '/gasorder_contract/:identity/terminate', danger: true, fields: reason, visibleFor: { field: 'contract_status', values: [11] } },
], { canCreate: true, canEdit: true }),
define('gasorder_contract_product', '合同气瓶', 'append_only', [relation('gasorder_contract_identity', '/gasorder_contract', true), relation('product_info_identity', '/product_info', true), f('unit_price')], 'list', [
define('gasorder_contract_product', '合同气瓶', 'append_only', [relation('gasorder_contract_identity', '/gasorder_contract', true), relation('product_info_identity', '/product_info', true, { label: '智能气阀', placeholder: '请选择该合同用户可绑定的智能气阀', relationEmptyText: '该合同用户暂无可绑定的智能气阀,请先由平台总后台将设备归属变更为该用户', relationLinkage: { parentKey: 'gasorder_contract_identity', optionParentKey: '', filterKey: 'contract_identity', filterOnly: true, requiresParent: true, parentChangeMessage: '配送合同已变更,请重新选择该合同用户的智能气阀' } }), f('unit_price')], 'list', [
{ name: '解绑气瓶', resource: '/gasorder_contract_product/:identity/unbind', danger: true, fields: reason },
]),
define('gasorder_contract_revision', '合同修订记录', 'readonly', []),