优化配送订单收货地址联动显示
This commit is contained in:
@@ -150,7 +150,18 @@ export function optionLabel(option: ResourceRow) {
|
||||
|
||||
/** 工作人员关系额外展示角色,其他关系保持原有可读名称。 */
|
||||
export function relationOptionLabel(field: ResourceField, option: ResourceRow) {
|
||||
const label = optionLabel(option);
|
||||
const configuredLabel = field.relationOptionLabelKey
|
||||
? option[field.relationOptionLabelKey]
|
||||
: undefined;
|
||||
const label = configuredLabel == null || configuredLabel === ''
|
||||
? optionLabel(option)
|
||||
: String(configuredLabel);
|
||||
if (
|
||||
field.relationOptionDefaultKey &&
|
||||
option[field.relationOptionDefaultKey]
|
||||
) {
|
||||
return `${label}(默认地址)`;
|
||||
}
|
||||
return field.relation === '/staff_account'
|
||||
? `${label}(${staffRoleLabel(option.role_code)})`
|
||||
: label;
|
||||
|
||||
@@ -33,6 +33,10 @@ export type ResourceRelationLinkage = {
|
||||
backfillParent?: boolean;
|
||||
/** 仅使用父字段筛选候选项,不校验候选项中的父标识。 */
|
||||
filterOnly?: boolean;
|
||||
/** 父字段为空时不加载候选项,并禁用当前关联选择器。 */
|
||||
requiresParent?: boolean;
|
||||
/** 父字段变化并清空当前值时展示的中文提示。 */
|
||||
parentChangeMessage?: string;
|
||||
};
|
||||
|
||||
export type ResourceField = {
|
||||
@@ -56,6 +60,14 @@ export type ResourceField = {
|
||||
readonlyOnCreate?: boolean;
|
||||
unknownValueLabel?: string;
|
||||
relationLinkage?: ResourceRelationLinkage;
|
||||
/** 关联选项优先使用的业务展示字段。 */
|
||||
relationOptionLabelKey?: string;
|
||||
/** 该字段为真时,在关联选项后追加“默认地址”。 */
|
||||
relationOptionDefaultKey?: string;
|
||||
/** 候选加载完成后自动选中该布尔字段为真的选项。 */
|
||||
relationAutoSelectKey?: string;
|
||||
/** 关联候选为空时展示的业务引导。 */
|
||||
relationEmptyText?: string;
|
||||
staffRelation?: import('./resource-staff-relation').StaffRelationPolicy;
|
||||
};
|
||||
|
||||
@@ -502,7 +514,16 @@ export const resources: ResourceUiDefinition[] = [
|
||||
{ name: '解绑气瓶', resource: '/gasorder_contract_product/:identity/unbind', danger: true, fields: reason },
|
||||
]),
|
||||
define('gasorder_contract_revision', '合同修订记录', 'readonly', []),
|
||||
define('gasorder_basic', '气体配送订单', 'append_only', [f('request_no', { required: true }), relation('gasorder_contract_identity', '/gasorder_contract', true), f('creator_type', { required: true, type: 'select', options: resourceSearchEnumOptions('gasorder_basic', 'creator_type') }), f('creator_identity', { required: true }), relation('user_address_identity', '/user_address', true), f('gasorder_contract_product_identities', { required: true, type: 'identity-list', relation: '/gasorder_contract_product' }), f('contact_name', { required: true }), f('contact_phone', { required: true }), f('discount_amount'), f('remark')], 'list', [
|
||||
define('gasorder_basic', '气体配送订单', 'append_only', [f('request_no', { required: true }), relation('gasorder_contract_identity', '/gasorder_contract', true, { label: '配送合同', placeholder: '请选择配送合同' }), f('creator_type', { required: true, type: 'select', options: resourceSearchEnumOptions('gasorder_basic', 'creator_type') }), f('creator_identity', { required: true }), relation('user_address_identity', '/user_address', true, {
|
||||
label: '收货地址', placeholder: '请先选择配送合同,再选择该合同用户的收货地址',
|
||||
relationOptionLabelKey: 'address', relationOptionDefaultKey: 'is_default',
|
||||
relationAutoSelectKey: 'is_default', relationEmptyText: '该合同用户暂无收货地址,请先维护用户地址',
|
||||
relationLinkage: {
|
||||
parentKey: 'gasorder_contract_identity', optionParentKey: '',
|
||||
filterKey: 'gasorder_contract_identity', filterOnly: true, requiresParent: true,
|
||||
parentChangeMessage: '配送合同已变更,请重新选择该合同用户的收货地址',
|
||||
},
|
||||
}), f('gasorder_contract_product_identities', { required: true, type: 'identity-list', relation: '/gasorder_contract_product', placeholder: '请先选择配送合同,再选择该合同可用的气瓶', 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] } },
|
||||
|
||||
@@ -90,7 +90,7 @@
|
||||
<a-select
|
||||
v-else
|
||||
v-model="model[field.key]"
|
||||
:disabled="disabledSet.has(field.key)"
|
||||
:disabled="disabledSet.has(field.key) || relationRequiresParent(field)"
|
||||
:multiple="field.type === 'identity-list'"
|
||||
:placeholder="field.placeholder"
|
||||
:loading="relationLoading[field.relation ?? '']"
|
||||
@@ -106,6 +106,9 @@
|
||||
>
|
||||
{{ relationOptionLabel(field, option) }}
|
||||
</a-option>
|
||||
<template #empty>
|
||||
<div class="relation-empty">{{ relationEmptyText(field) }}</div>
|
||||
</template>
|
||||
</a-select>
|
||||
<div
|
||||
v-if="disabledSet.has(field.key) && (field.showIdentityCopy || field.staffRelation?.showIdentityCopy) && !field.readonlyRelationText && model[field.key]"
|
||||
@@ -191,6 +194,27 @@ function readonlyRelationLabel(field: ResourceField) {
|
||||
return option ? relationOptionLabel(field, option) : identity;
|
||||
}
|
||||
|
||||
/** 父级尚未选择时禁用联动下拉,避免用户误以为可以跨合同选择。 */
|
||||
function relationRequiresParent(field: ResourceField) {
|
||||
const linkage = field.relationLinkage;
|
||||
return Boolean(
|
||||
linkage?.requiresParent &&
|
||||
!String(model.value[linkage.parentKey] ?? '').trim(),
|
||||
);
|
||||
}
|
||||
|
||||
/** 根据父级和候选状态给出明确的关联选择引导。 */
|
||||
function relationEmptyText(field: ResourceField) {
|
||||
if (relationRequiresParent(field)) {
|
||||
const parentName =
|
||||
field.relationLinkage?.parentKey === 'gasorder_contract_identity'
|
||||
? '配送合同'
|
||||
: '上级数据';
|
||||
return `请先选择${parentName}`;
|
||||
}
|
||||
return field.relationEmptyText ?? '暂无数据';
|
||||
}
|
||||
|
||||
/** 为历史未知编码补充只读选项,避免下拉框退回显示原始值。 */
|
||||
function selectOptions(field: ResourceField) {
|
||||
const options = [...(field.options ?? [])];
|
||||
|
||||
@@ -124,6 +124,14 @@
|
||||
>
|
||||
当前归属只能选择库房、气站、配送点或用户中的一个;选择新归属时会自动清空其他归属。
|
||||
</a-alert>
|
||||
<a-alert
|
||||
v-if="relationUnavailableMessage"
|
||||
class="workflow-alert"
|
||||
type="warning"
|
||||
show-icon
|
||||
>
|
||||
{{ relationUnavailableMessage }}
|
||||
</a-alert>
|
||||
<a-form :model="form" layout="vertical">
|
||||
<ResourceFieldForm
|
||||
v-model="form"
|
||||
@@ -143,7 +151,7 @@
|
||||
/>
|
||||
</a-form>
|
||||
<div class="form-actions">
|
||||
<a-button type="primary" :loading="saving" @click="save">保存</a-button>
|
||||
<a-button type="primary" :loading="saving" :disabled="Boolean(relationUnavailableMessage)" @click="save">保存</a-button>
|
||||
<a-button :disabled="saving" @click="cancelForm">取消</a-button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -258,6 +266,9 @@ const staffOwnerGuard = useStaffCredentialOwnerGuard({
|
||||
const resolvedStaffType = staffOwnerGuard.resolvedStaffType;
|
||||
const relations = staffOwnerGuard.relations;
|
||||
const relationLinkage = useResourceRelationLinkage(form, relations);
|
||||
const relationUnavailableMessage = computed(() =>
|
||||
relationLinkage.unavailableMessage(),
|
||||
);
|
||||
const productOwnershipKeys = [
|
||||
'warehouse_identity',
|
||||
'gas_basic_identity',
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* 功能:协调资源表单中显式启用的父子关联下拉、搜索和保存前校验。
|
||||
* 版本:v1.0.0
|
||||
* 功能:协调资源表单中显式启用的多组父子关联下拉、搜索和保存前校验。
|
||||
* 版本:v1.1.0
|
||||
*/
|
||||
import { Message } from '@arco-design/web-vue';
|
||||
import type { ResourceField } from '@/api/resources';
|
||||
@@ -24,7 +24,7 @@ export function useResourceRelationLinkage(
|
||||
form: Record<string, any>,
|
||||
relations: ResourceRelations,
|
||||
) {
|
||||
let active: ActiveLinkage | undefined;
|
||||
let active: ActiveLinkage[] = [];
|
||||
let organizationStaffField: ResourceField | undefined;
|
||||
let initialized = false;
|
||||
|
||||
@@ -34,21 +34,19 @@ export function useResourceRelationLinkage(
|
||||
);
|
||||
}
|
||||
|
||||
/** 收集页面内全部显式联动,允许一个父字段同时驱动多个业务子项。 */
|
||||
function configure(fields: ResourceField[]) {
|
||||
const childField = fields.find((field) => field.relationLinkage);
|
||||
active = fields
|
||||
.filter((field) => field.relationLinkage)
|
||||
.map((childField) => ({
|
||||
childField,
|
||||
parentField: fields.find(
|
||||
(field) => field.key === childField.relationLinkage?.parentKey,
|
||||
),
|
||||
}));
|
||||
organizationStaffField = fields.find(
|
||||
(field) => field.staffRelation?.organizationScoped,
|
||||
);
|
||||
if (!childField?.relationLinkage) {
|
||||
active = undefined;
|
||||
return;
|
||||
}
|
||||
active = {
|
||||
childField,
|
||||
parentField: fields.find(
|
||||
(field) => field.key === childField.relationLinkage?.parentKey,
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
function staffRequest() {
|
||||
@@ -94,62 +92,63 @@ export function useResourceRelationLinkage(
|
||||
await reloadStaffOptions();
|
||||
}
|
||||
|
||||
function childRequest() {
|
||||
if (!active?.childField.relationLinkage) return {};
|
||||
const linkage = active.childField.relationLinkage;
|
||||
function childRequest(linkageItem: ActiveLinkage) {
|
||||
const linkage = linkageItem.childField.relationLinkage;
|
||||
if (!linkage) return {};
|
||||
const parentIdentity = relationIdentity(form[linkage.parentKey]);
|
||||
const childIdentity = relationIdentity(form[active.childField.key]);
|
||||
const rawChildValue = form[linkageItem.childField.key];
|
||||
const childIdentities = (Array.isArray(rawChildValue)
|
||||
? rawChildValue
|
||||
: [rawChildValue]
|
||||
)
|
||||
.map(relationIdentity)
|
||||
.filter(Boolean);
|
||||
return {
|
||||
filters: linkedRelationFilters(parentIdentity, linkage.filterKey),
|
||||
preserveIdentities: childIdentity ? [childIdentity] : [],
|
||||
preserveIdentities: childIdentities,
|
||||
};
|
||||
}
|
||||
|
||||
async function reloadChildOptions() {
|
||||
const childField = active?.childField;
|
||||
const resource = childField?.relation;
|
||||
if (!resource) return;
|
||||
/** 加载一组子选项,并在配置要求时自动选中默认业务记录。 */
|
||||
async function reloadChildOptions(linkageItem: ActiveLinkage) {
|
||||
const childField = linkageItem.childField;
|
||||
const linkage = childField.relationLinkage;
|
||||
const resource = childField.relation;
|
||||
if (!linkage || !resource) return;
|
||||
const parentIdentity = relationIdentity(form[linkage.parentKey]);
|
||||
if (linkage.requiresParent && !parentIdentity) {
|
||||
relations.clear(resource);
|
||||
return;
|
||||
}
|
||||
relations.cancelSearch(resource);
|
||||
await relations.loadField(childField, '', childRequest());
|
||||
await relations.loadField(childField, '', childRequest(linkageItem));
|
||||
if (
|
||||
!relationIdentity(form[childField.key]) &&
|
||||
childField.relationAutoSelectKey
|
||||
) {
|
||||
const defaultOption = (relations.options[resource] ?? []).find(
|
||||
(option) => Boolean(option[childField.relationAutoSelectKey as string]),
|
||||
);
|
||||
if (defaultOption) {
|
||||
form[childField.key] = relationIdentity(defaultOption.identity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** 预加载普通关联项,并单独按父级条件加载启用联动的子选项。 */
|
||||
/** 预加载普通关联项,并分别按父级条件加载所有启用联动的子选项。 */
|
||||
async function preload(fields: ResourceField[]) {
|
||||
initialized = false;
|
||||
configure(fields);
|
||||
if (!active?.childField.relationLinkage || !active.childField.relation) {
|
||||
await relations.preload(
|
||||
fields.filter((field) => field.key !== organizationStaffField?.key),
|
||||
);
|
||||
await relations.ensureValues(fields, form);
|
||||
await reloadStaffOptions();
|
||||
initialized = true;
|
||||
return;
|
||||
}
|
||||
|
||||
const linkedChildKeys = new Set(active.map((item) => item.childField.key));
|
||||
await relations.preload(
|
||||
fields.filter(
|
||||
(field) =>
|
||||
field.key !== active?.childField.key &&
|
||||
!linkedChildKeys.has(field.key) &&
|
||||
field.key !== organizationStaffField?.key,
|
||||
),
|
||||
);
|
||||
const linkage = active.childField.relationLinkage;
|
||||
const parentIdentity = relationIdentity(form[linkage.parentKey]);
|
||||
const childIdentity = relationIdentity(form[active.childField.key]);
|
||||
if (parentIdentity && active.parentField?.relation) {
|
||||
await relations.ensure(active.parentField.relation, parentIdentity);
|
||||
}
|
||||
if (childIdentity) {
|
||||
await relations.ensure(active.childField.relation, childIdentity);
|
||||
}
|
||||
const staffIdentity = relationIdentity(
|
||||
organizationStaffField ? form[organizationStaffField.key] : '',
|
||||
);
|
||||
if (staffIdentity && organizationStaffField?.relation) {
|
||||
await relations.ensure(organizationStaffField.relation, staffIdentity);
|
||||
}
|
||||
await reloadChildOptions();
|
||||
await relations.ensureValues(fields, form);
|
||||
await Promise.all(active.map((item) => reloadChildOptions(item)));
|
||||
await reloadStaffOptions();
|
||||
initialized = true;
|
||||
|
||||
@@ -157,58 +156,61 @@ export function useResourceRelationLinkage(
|
||||
if (warning) Message.warning(`当前组织归属需要确认:${warning}`);
|
||||
}
|
||||
|
||||
async function handleParentChange(parentIdentity: string) {
|
||||
if (!active?.childField.relationLinkage || !active.childField.relation)
|
||||
return;
|
||||
const linkage = active.childField.relationLinkage;
|
||||
const childIdentity = relationIdentity(form[active.childField.key]);
|
||||
async function handleParentChange(
|
||||
linkageItem: ActiveLinkage,
|
||||
parentIdentity: string,
|
||||
) {
|
||||
const childField = linkageItem.childField;
|
||||
const linkage = childField.relationLinkage;
|
||||
if (!linkage || !childField.relation) return;
|
||||
const childIdentity = relationIdentity(form[childField.key]);
|
||||
if (linkage.filterOnly) relations.clear(childField.relation);
|
||||
if (linkage.filterOnly && childIdentity) {
|
||||
form[active.childField.key] = '';
|
||||
Message.info('合同已变更,请重新选择该合同可绑定的气瓶');
|
||||
form[childField.key] = childField.type === 'identity-list' ? [] : '';
|
||||
Message.info(
|
||||
linkage.parentChangeMessage ?? '上级数据已变更,请重新选择关联数据',
|
||||
);
|
||||
}
|
||||
if (childIdentity && !linkage.filterOnly) {
|
||||
const option =
|
||||
findOption(active.childField.relation, childIdentity) ??
|
||||
(await relations.ensure(active.childField.relation, childIdentity));
|
||||
findOption(childField.relation, childIdentity) ??
|
||||
(await relations.ensure(childField.relation, childIdentity));
|
||||
if (
|
||||
relationIdentity(form[linkage.parentKey]) !== parentIdentity ||
|
||||
relationIdentity(form[active.childField.key]) !== childIdentity
|
||||
relationIdentity(form[childField.key]) !== childIdentity
|
||||
) {
|
||||
return;
|
||||
}
|
||||
if (
|
||||
shouldClearLinkedOption(parentIdentity, option, linkage.optionParentKey)
|
||||
) {
|
||||
form[active.childField.key] = '';
|
||||
Message.info('所属气站已变更,请重新选择配送点');
|
||||
form[childField.key] = '';
|
||||
Message.info(
|
||||
linkage.parentChangeMessage ?? '所属气站已变更,请重新选择配送点',
|
||||
);
|
||||
}
|
||||
}
|
||||
await reloadChildOptions();
|
||||
await reloadChildOptions(linkageItem);
|
||||
}
|
||||
|
||||
async function handleChildChange(childIdentity: string) {
|
||||
if (!active?.childField.relationLinkage || !active.childField.relation)
|
||||
async function handleChildChange(
|
||||
linkageItem: ActiveLinkage,
|
||||
childIdentity: string,
|
||||
) {
|
||||
const childField = linkageItem.childField;
|
||||
const linkage = childField.relationLinkage;
|
||||
if (!linkage || !childField.relation || !childIdentity || linkage.filterOnly)
|
||||
return;
|
||||
const linkage = active.childField.relationLinkage;
|
||||
if (!childIdentity) return;
|
||||
if (linkage.filterOnly) return;
|
||||
const option =
|
||||
findOption(active.childField.relation, childIdentity) ??
|
||||
(await relations.ensure(active.childField.relation, childIdentity));
|
||||
if (
|
||||
!option ||
|
||||
relationIdentity(form[active.childField.key]) !== childIdentity
|
||||
) {
|
||||
return;
|
||||
}
|
||||
findOption(childField.relation, childIdentity) ??
|
||||
(await relations.ensure(childField.relation, childIdentity));
|
||||
if (!option || relationIdentity(form[childField.key]) !== childIdentity) return;
|
||||
if (linkage.backfillParent) {
|
||||
const nextParent = optionParentIdentity(option, linkage.optionParentKey);
|
||||
const currentParent = relationIdentity(form[linkage.parentKey]);
|
||||
if (nextParent && active.parentField?.relation) {
|
||||
await relations.ensure(active.parentField.relation, nextParent);
|
||||
if (relationIdentity(form[active.childField.key]) !== childIdentity) {
|
||||
return;
|
||||
}
|
||||
if (nextParent && linkageItem.parentField?.relation) {
|
||||
await relations.ensure(linkageItem.parentField.relation, nextParent);
|
||||
if (relationIdentity(form[childField.key]) !== childIdentity) return;
|
||||
}
|
||||
if (currentParent !== nextParent) {
|
||||
form[linkage.parentKey] = nextParent;
|
||||
@@ -217,29 +219,41 @@ export function useResourceRelationLinkage(
|
||||
}
|
||||
}
|
||||
}
|
||||
await reloadChildOptions();
|
||||
await reloadChildOptions(linkageItem);
|
||||
}
|
||||
|
||||
/** 响应用户主动修改关联字段;初始化回显不会触发自动清理。 */
|
||||
async function change(field: ResourceField, value: unknown) {
|
||||
if (!initialized || !active?.childField.relationLinkage) return;
|
||||
if (!initialized) return;
|
||||
const identity = relationIdentity(value);
|
||||
if (field.key === active.childField.relationLinkage.parentKey) {
|
||||
await handleParentChange(identity);
|
||||
await synchronizeStaff();
|
||||
} else if (field.key === active.childField.key) {
|
||||
await handleChildChange(identity);
|
||||
await synchronizeStaff();
|
||||
} else if (field.key === organizationStaffField?.key) {
|
||||
const parentLinkages = active.filter(
|
||||
(item) => item.childField.relationLinkage?.parentKey === field.key,
|
||||
);
|
||||
await Promise.all(
|
||||
parentLinkages.map((item) => handleParentChange(item, identity)),
|
||||
);
|
||||
const childLinkage = active.find((item) => item.childField.key === field.key);
|
||||
if (childLinkage) await handleChildChange(childLinkage, identity);
|
||||
if (
|
||||
field.key === 'gas_basic_identity' ||
|
||||
field.key === 'delivery_basic_identity' ||
|
||||
field.key === organizationStaffField?.key
|
||||
) {
|
||||
await synchronizeStaff();
|
||||
}
|
||||
}
|
||||
|
||||
/** 搜索联动子项时始终保留父级过滤和当前选项。 */
|
||||
/** 搜索联动子项时始终保留对应父级过滤和当前选项。 */
|
||||
function search(field: ResourceField, keyword: string) {
|
||||
if (!field.relation) return;
|
||||
if (field.key === active?.childField.key) {
|
||||
relations.searchField(field, keyword, childRequest());
|
||||
const linkageItem = active.find((item) => item.childField.key === field.key);
|
||||
if (linkageItem) {
|
||||
const linkage = linkageItem.childField.relationLinkage;
|
||||
if (linkage?.requiresParent && !relationIdentity(form[linkage.parentKey])) {
|
||||
relations.clear(field.relation);
|
||||
return;
|
||||
}
|
||||
relations.searchField(field, keyword, childRequest(linkageItem));
|
||||
return;
|
||||
}
|
||||
if (field.key === organizationStaffField?.key) {
|
||||
@@ -251,30 +265,52 @@ export function useResourceRelationLinkage(
|
||||
|
||||
/** 返回保存前的父子关系错误,空字符串代表当前组合可提交。 */
|
||||
function validationMessage() {
|
||||
if (!active?.childField.relationLinkage || !active.childField.relation)
|
||||
return '';
|
||||
const linkage = active.childField.relationLinkage;
|
||||
if (linkage.filterOnly) return '';
|
||||
const parentIdentity = relationIdentity(form[linkage.parentKey]);
|
||||
const childIdentity = relationIdentity(form[active.childField.key]);
|
||||
const option = findOption(active.childField.relation, childIdentity);
|
||||
const linkedMessage = linkedRelationValidationMessage(
|
||||
parentIdentity,
|
||||
childIdentity,
|
||||
option,
|
||||
linkage.optionParentKey,
|
||||
);
|
||||
if (linkedMessage) return linkedMessage;
|
||||
for (const linkageItem of active) {
|
||||
const childField = linkageItem.childField;
|
||||
const linkage = childField.relationLinkage;
|
||||
if (!linkage || !childField.relation || linkage.filterOnly) continue;
|
||||
const parentIdentity = relationIdentity(form[linkage.parentKey]);
|
||||
const childIdentity = relationIdentity(form[childField.key]);
|
||||
const linkedMessage = linkedRelationValidationMessage(
|
||||
parentIdentity,
|
||||
childIdentity,
|
||||
findOption(childField.relation, childIdentity),
|
||||
linkage.optionParentKey,
|
||||
);
|
||||
if (linkedMessage) return linkedMessage;
|
||||
}
|
||||
const staffField = organizationStaffField;
|
||||
if (!staffField?.relation) return '';
|
||||
const staffIdentity = relationIdentity(form[staffField.key]);
|
||||
return staffOrganizationValidationMessage(
|
||||
parentIdentity,
|
||||
childIdentity,
|
||||
relationIdentity(form.gas_basic_identity),
|
||||
relationIdentity(form.delivery_basic_identity),
|
||||
staffIdentity,
|
||||
findOption(staffField.relation, staffIdentity),
|
||||
);
|
||||
}
|
||||
|
||||
return { preload, change, search, validationMessage };
|
||||
/** 必填联动候选为空时返回业务引导,用于阻止提交无效表单。 */
|
||||
function unavailableMessage() {
|
||||
for (const linkageItem of active) {
|
||||
const field = linkageItem.childField;
|
||||
const linkage = field.relationLinkage;
|
||||
if (
|
||||
!field.required ||
|
||||
!field.relation ||
|
||||
!field.relationEmptyText ||
|
||||
!linkage?.requiresParent ||
|
||||
!relationIdentity(form[linkage.parentKey]) ||
|
||||
relations.loading[field.relation]
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
if ((relations.options[field.relation] ?? []).length === 0) {
|
||||
return field.relationEmptyText;
|
||||
}
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
return { preload, change, search, validationMessage, unavailableMessage };
|
||||
}
|
||||
|
||||
@@ -183,6 +183,15 @@ export function useResourceRelations(
|
||||
timers.delete(resource);
|
||||
}
|
||||
|
||||
/** 清空依赖父级但当前尚无有效父级的候选项。 */
|
||||
function clear(resource: string | undefined) {
|
||||
if (!resource) return;
|
||||
cancelSearch(resource);
|
||||
requestGuard.begin(resource);
|
||||
options[resource] = [];
|
||||
loading[resource] = false;
|
||||
}
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
for (const resource of timers.keys()) cancelSearch(resource);
|
||||
});
|
||||
@@ -198,6 +207,7 @@ export function useResourceRelations(
|
||||
search,
|
||||
searchField,
|
||||
cancelSearch,
|
||||
clear,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user