强化配送订单合同调度约束

This commit is contained in:
czl231
2026-08-15 19:19:15 +08:00
parent 963e497bf3
commit 42a4fc2f41
15 changed files with 501 additions and 52 deletions

View File

@@ -1,6 +1,6 @@
<!--
功能承载资源详情页中的审核流转归属调整和菜单分配等短业务操作
版本v1.0.0
版本v1.1.0
-->
<template>
<a-modal
@@ -21,11 +21,15 @@
<a-alert v-if="isProductLifecycleAction" class="action-alert" type="info" show-icon>
当前状态{{ currentProductStatusLabel }}请选择一个不同的目标状态服务端会校验检修和订单占用情况
</a-alert>
<a-alert v-if="isGasorderAssignmentAction" class="action-alert" type="info" show-icon>
{{ assignmentScopeMessage }}
</a-alert>
<a-form :model="form" layout="vertical">
<ResourceFieldForm
v-model="form"
:fields="actionFields"
:required-keys="requiredKeys"
:disabled-keys="disabledKeys"
:relation-options="relations.options"
:relation-loading="relations.loading"
@change-relation="changeRelation"
@@ -62,6 +66,30 @@ const relations = useResourceRelations();
const isProductLifecycleAction = computed(
() => props.action?.resource === '/product_info/:identity/lifecycle',
);
const isGasorderAssignmentAction = computed(
() => props.action?.resource === '/gasorder_basic/:identity/assign',
);
/** 合同指定点始终锁定;无指定点的已分配订单也只能在当前点内改派。 */
const lockedAssignmentDeliveryIdentity = computed(() => {
return String(props.record.delivery_basic_identity ?? '').trim();
});
const disabledKeys = computed(() =>
isGasorderAssignmentAction.value && lockedAssignmentDeliveryIdentity.value
? ['delivery_basic_identity']
: [],
);
const assignmentScopeMessage = computed(() => {
if (
Number(props.record.order_status) === 16 &&
lockedAssignmentDeliveryIdentity.value
) {
return '配送合同已指定履约配送点,本次只能从该配送点的在岗且资质有效人员中分配。';
}
if (lockedAssignmentDeliveryIdentity.value) {
return '订单已完成配送点分配,本次仅允许在当前配送点内改派配送人员。';
}
return '配送合同未指定配送点,请先从合同气站直属的启用配送点中选择,再选择该点配送人员。';
});
const actionFields = computed(() =>
(props.action?.fields ?? []).map((field) =>
isProductLifecycleAction.value && field.key === 'product_status'
@@ -99,13 +127,52 @@ const ownershipKeys = [
'user_account_identity',
];
/** 业务动作字段不启用记录页联动,只沿用普通关联搜索。 */
/** 为订单分配动作保留履约范围,其余业务动作沿用普通关联搜索。 */
function searchRelation(field: ResourceField, keyword: string) {
if (isGasorderAssignmentAction.value) {
if (field.key === 'delivery_basic_identity') {
relations.searchField(field, keyword, {
filters: assignmentDeliveryFilters(),
});
return;
}
if (field.key === 'staff_account_identity') {
const deliveryIdentity = String(
form.delivery_basic_identity ?? '',
).trim();
if (!deliveryIdentity) {
relations.clear(field.relation);
return;
}
relations.searchField(field, keyword, {
filters: assignmentStaffFilters(deliveryIdentity),
});
return;
}
}
relations.searchField(field, keyword);
}
/** 选择智能气阀的新归属时清空其余互斥归属,避免提交非法多重归属。 */
/** 处理订单配送点级联及智能气阀互斥归属,避免提交已经失效的关联值。 */
function changeRelation(field: ResourceField, value: unknown) {
if (
isGasorderAssignmentAction.value &&
field.key === 'delivery_basic_identity'
) {
form.staff_account_identity = undefined;
const deliveryIdentity = String(value ?? '').trim();
const staffField = actionFields.value.find(
(item) => item.key === 'staff_account_identity',
);
if (!staffField || !deliveryIdentity) {
relations.clear('/staff_account');
return;
}
void relations.loadField(staffField, '', {
filters: assignmentStaffFilters(deliveryIdentity),
});
return;
}
if (
!isOwnershipAction.value ||
!ownershipKeys.includes(field.key) ||
@@ -119,6 +186,47 @@ function changeRelation(field: ResourceField, value: unknown) {
}
}
/** 将订单履约气站转换为配送点候选接口的精确筛选参数。 */
function assignmentDeliveryFilters(): Record<string, string> {
const gasIdentity = String(props.record.gas_basic_identity ?? '').trim();
return gasIdentity ? { gas_basic_identities: gasIdentity } : {};
}
/** 配送人员必须同时属于订单气站和当前选择的配送点。 */
function assignmentStaffFilters(deliveryIdentity: string) {
const filters: Record<string, string> = {
delivery_basic_identities: deliveryIdentity,
};
const gasIdentity = String(props.record.gas_basic_identity ?? '').trim();
if (gasIdentity) filters.gas_basic_identities = gasIdentity;
return filters;
}
/** 按合同和订单快照初始化分配动作,禁止预加载全平台候选。 */
async function initializeGasorderAssignment() {
const deliveryField = actionFields.value.find(
(field) => field.key === 'delivery_basic_identity',
);
const staffField = actionFields.value.find(
(field) => field.key === 'staff_account_identity',
);
if (!deliveryField || !staffField) return;
relations.clear('/delivery_basic');
relations.clear('/staff_account');
const lockedIdentity = lockedAssignmentDeliveryIdentity.value;
if (lockedIdentity) {
form.delivery_basic_identity = lockedIdentity;
await relations.ensure('/delivery_basic', lockedIdentity);
await relations.loadField(staffField, '', {
filters: assignmentStaffFilters(lockedIdentity),
});
return;
}
await relations.loadField(deliveryField, '', {
filters: assignmentDeliveryFilters(),
});
}
watch(
() => [props.visible, props.action?.name] as const,
async ([visible]) => {
@@ -128,6 +236,10 @@ watch(
? props.record[field.key]
: undefined;
}
if (isGasorderAssignmentAction.value) {
await initializeGasorderAssignment();
return;
}
await relations.preload(actionFields.value);
if (props.action.resource.includes('/menu')) {
try {