修复配送订单创建方合同约束
This commit is contained in:
@@ -206,7 +206,12 @@ function relationRequiresParent(field: ResourceField) {
|
||||
return Boolean(
|
||||
(linkage?.requiresParent &&
|
||||
!String(model.value[linkage.parentKey] ?? '').trim()) ||
|
||||
(field.dynamicRelation && !relationResource(field)),
|
||||
(field.dynamicRelation &&
|
||||
(!relationResource(field) ||
|
||||
(field.dynamicRelation.contextParentKey &&
|
||||
!String(
|
||||
model.value[field.dynamicRelation.contextParentKey] ?? '',
|
||||
).trim()))),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -214,6 +219,12 @@ function relationRequiresParent(field: ResourceField) {
|
||||
function relationPlaceholder(field: ResourceField) {
|
||||
if (!relationRequiresParent(field)) return field.placeholder;
|
||||
if (field.dynamicRelation) {
|
||||
if (
|
||||
field.dynamicRelation.contextParentKey &&
|
||||
!String(model.value[field.dynamicRelation.contextParentKey] ?? '').trim()
|
||||
) {
|
||||
return '请先选择配送合同';
|
||||
}
|
||||
return `请先选择${field.dynamicRelation.parentLabel}`;
|
||||
}
|
||||
return field.relationLinkage?.parentKey === 'gasorder_contract_identity'
|
||||
@@ -225,6 +236,14 @@ function relationPlaceholder(field: ResourceField) {
|
||||
function relationEmptyText(field: ResourceField) {
|
||||
if (relationRequiresParent(field)) {
|
||||
if (field.dynamicRelation) {
|
||||
if (
|
||||
field.dynamicRelation.contextParentKey &&
|
||||
!String(
|
||||
model.value[field.dynamicRelation.contextParentKey] ?? '',
|
||||
).trim()
|
||||
) {
|
||||
return '请先选择配送合同';
|
||||
}
|
||||
return `请先选择${field.dynamicRelation.parentLabel}`;
|
||||
}
|
||||
const parentName =
|
||||
|
||||
@@ -124,6 +124,14 @@
|
||||
>
|
||||
当前归属只能选择库房、气站、配送点或用户中的一个;选择新归属时会自动清空其他归属。
|
||||
</a-alert>
|
||||
<a-alert
|
||||
v-if="mode === 'create' && definition.name === 'gasorder_basic'"
|
||||
class="workflow-alert"
|
||||
type="info"
|
||||
show-icon
|
||||
>
|
||||
创建方受配送合同约束:用户、气站和配送点由合同自动带出;工作人员仅可选择合同履约组织内的启用人员。
|
||||
</a-alert>
|
||||
<a-alert
|
||||
v-if="relationUnavailableMessage"
|
||||
class="workflow-alert"
|
||||
@@ -346,6 +354,13 @@ const readonlyKeys = computed(() =>
|
||||
.filter(
|
||||
(field) =>
|
||||
field.readonlyOnCreate ||
|
||||
(field.key === 'creator_identity' &&
|
||||
Boolean(
|
||||
field.dynamicRelation?.fixedIdentityKeys?.[
|
||||
String(form.creator_type ?? '')
|
||||
],
|
||||
) &&
|
||||
Boolean(form.gasorder_contract_identity)) ||
|
||||
(field.staffRelation?.lockPrefilled && Boolean(form[field.key])) ||
|
||||
(definition.value.name === 'gasorder_contract_product' &&
|
||||
field.key === 'gasorder_contract_identity' &&
|
||||
|
||||
@@ -60,15 +60,72 @@ export function useResourceRelationLinkage(
|
||||
: field;
|
||||
}
|
||||
|
||||
/** 读取动态关系所依赖的业务上下文选项,例如当前选择的配送合同。 */
|
||||
function dynamicContextOption(field: ResourceField) {
|
||||
const contextKey = field.dynamicRelation?.contextParentKey;
|
||||
if (!contextKey) return undefined;
|
||||
const contextField = configuredFields.value.find(
|
||||
(item) => item.key === contextKey,
|
||||
);
|
||||
const contextIdentity = relationIdentity(form[contextKey]);
|
||||
if (!contextField?.relation || !contextIdentity) return undefined;
|
||||
return findOption(contextField.relation, contextIdentity);
|
||||
}
|
||||
|
||||
/** 将上下文选项转换为动态候选接口需要的精确筛选参数。 */
|
||||
function dynamicRequest(field: ResourceField) {
|
||||
const dynamic = field.dynamicRelation;
|
||||
const type = relationIdentity(dynamic ? form[dynamic.parentKey] : '');
|
||||
const option = dynamicContextOption(field);
|
||||
const filters: Record<string, string> = {};
|
||||
for (const filter of dynamic?.scopeFilters?.[type] ?? []) {
|
||||
const value = relationIdentity(option?.[filter.optionKey]);
|
||||
if (value) {
|
||||
filters[filter.filterKey] = value;
|
||||
} else if (filter.emptyFilterKey) {
|
||||
filters[filter.emptyFilterKey] = filter.emptyFilterValue ?? 'true';
|
||||
}
|
||||
}
|
||||
const identity = relationIdentity(form[field.key]);
|
||||
return {
|
||||
filters,
|
||||
preserveIdentities: identity ? [identity] : [],
|
||||
};
|
||||
}
|
||||
|
||||
/** 加载由父字段类型决定的关系候选。 */
|
||||
async function reloadDynamicOptions(field: ResourceField) {
|
||||
const resolved = resolvedField(field);
|
||||
if (!resolved.relation) return;
|
||||
const identity = relationIdentity(form[field.key]);
|
||||
const dynamic = field.dynamicRelation;
|
||||
const type = relationIdentity(dynamic ? form[dynamic.parentKey] : '');
|
||||
const contextIdentity = relationIdentity(
|
||||
dynamic?.contextParentKey ? form[dynamic.contextParentKey] : '',
|
||||
);
|
||||
const contextOption = dynamicContextOption(field);
|
||||
if (dynamic?.contextParentKey && (!contextIdentity || !contextOption)) {
|
||||
form[field.key] = '';
|
||||
relations.clear(resolved.relation);
|
||||
return;
|
||||
}
|
||||
relations.cancelSearch(resolved.relation);
|
||||
await relations.loadField(resolved, '', {
|
||||
preserveIdentities: identity ? [identity] : [],
|
||||
});
|
||||
const fixedIdentityKey = dynamic?.fixedIdentityKeys?.[type];
|
||||
if (fixedIdentityKey) {
|
||||
const fixedIdentity = relationIdentity(contextOption?.[fixedIdentityKey]);
|
||||
form[field.key] = '';
|
||||
relations.clear(resolved.relation);
|
||||
if (!fixedIdentity) return;
|
||||
await relations.ensure(resolved.relation, fixedIdentity);
|
||||
if (
|
||||
relationIdentity(form[dynamic.parentKey]) === type &&
|
||||
relationIdentity(form[dynamic.contextParentKey as string]) ===
|
||||
contextIdentity
|
||||
) {
|
||||
form[field.key] = fixedIdentity;
|
||||
}
|
||||
return;
|
||||
}
|
||||
await relations.loadField(resolved, '', dynamicRequest(field));
|
||||
}
|
||||
|
||||
function staffRequest() {
|
||||
@@ -119,9 +176,8 @@ export function useResourceRelationLinkage(
|
||||
if (!linkage) return {};
|
||||
const parentIdentity = relationIdentity(form[linkage.parentKey]);
|
||||
const rawChildValue = form[linkageItem.childField.key];
|
||||
const childIdentities = (Array.isArray(rawChildValue)
|
||||
? rawChildValue
|
||||
: [rawChildValue]
|
||||
const childIdentities = (
|
||||
Array.isArray(rawChildValue) ? rawChildValue : [rawChildValue]
|
||||
)
|
||||
.map(relationIdentity)
|
||||
.filter(Boolean);
|
||||
@@ -148,8 +204,8 @@ export function useResourceRelationLinkage(
|
||||
!relationIdentity(form[childField.key]) &&
|
||||
childField.relationAutoSelectKey
|
||||
) {
|
||||
const defaultOption = (relations.options[resource] ?? []).find(
|
||||
(option) => Boolean(option[childField.relationAutoSelectKey as string]),
|
||||
const defaultOption = (relations.options[resource] ?? []).find((option) =>
|
||||
Boolean(option[childField.relationAutoSelectKey as string]),
|
||||
);
|
||||
if (defaultOption) {
|
||||
form[childField.key] = relationIdentity(defaultOption.identity);
|
||||
@@ -263,12 +319,18 @@ export function useResourceRelationLinkage(
|
||||
) {
|
||||
const childField = linkageItem.childField;
|
||||
const linkage = childField.relationLinkage;
|
||||
if (!linkage || !childField.relation || !childIdentity || linkage.filterOnly)
|
||||
if (
|
||||
!linkage ||
|
||||
!childField.relation ||
|
||||
!childIdentity ||
|
||||
linkage.filterOnly
|
||||
)
|
||||
return;
|
||||
const option =
|
||||
findOption(childField.relation, childIdentity) ??
|
||||
(await relations.ensure(childField.relation, childIdentity));
|
||||
if (!option || relationIdentity(form[childField.key]) !== childIdentity) return;
|
||||
if (!option || relationIdentity(form[childField.key]) !== childIdentity)
|
||||
return;
|
||||
if (linkage.backfillParent) {
|
||||
const nextParent = optionParentIdentity(option, linkage.optionParentKey);
|
||||
const currentParent = relationIdentity(form[linkage.parentKey]);
|
||||
@@ -310,7 +372,23 @@ export function useResourceRelationLinkage(
|
||||
await Promise.all(
|
||||
parentLinkages.map((item) => handleParentChange(item, identity)),
|
||||
);
|
||||
const childLinkage = active.find((item) => item.childField.key === field.key);
|
||||
const contextDynamicChildren = configuredFields.value.filter(
|
||||
(item) => item.dynamicRelation?.contextParentKey === field.key,
|
||||
);
|
||||
for (const childField of contextDynamicChildren) {
|
||||
const previousIdentity = relationIdentity(form[childField.key]);
|
||||
form[childField.key] = '';
|
||||
await reloadDynamicOptions(childField);
|
||||
if (previousIdentity) {
|
||||
Message.info(
|
||||
childField.dynamicRelation?.contextChangeMessage ??
|
||||
'业务上下文已变更,已重新匹配关联数据',
|
||||
);
|
||||
}
|
||||
}
|
||||
const childLinkage = active.find(
|
||||
(item) => item.childField.key === field.key,
|
||||
);
|
||||
if (childLinkage) await handleChildChange(childLinkage, identity);
|
||||
if (
|
||||
field.key === 'gas_basic_identity' ||
|
||||
@@ -325,10 +403,27 @@ export function useResourceRelationLinkage(
|
||||
function search(field: ResourceField, keyword: string) {
|
||||
const resolved = resolvedField(field);
|
||||
if (!resolved.relation) return;
|
||||
const linkageItem = active.find((item) => item.childField.key === field.key);
|
||||
const dynamic = field.dynamicRelation;
|
||||
if (dynamic?.contextParentKey) {
|
||||
const type = relationIdentity(form[dynamic.parentKey]);
|
||||
if (!dynamicContextOption(field)) {
|
||||
relations.clear(resolved.relation);
|
||||
return;
|
||||
}
|
||||
// 合同直接确定的主体为只读值,不提供跨合同搜索入口。
|
||||
if (dynamic.fixedIdentityKeys?.[type]) return;
|
||||
relations.searchField(resolved, keyword, dynamicRequest(field));
|
||||
return;
|
||||
}
|
||||
const linkageItem = active.find(
|
||||
(item) => item.childField.key === field.key,
|
||||
);
|
||||
if (linkageItem) {
|
||||
const linkage = linkageItem.childField.relationLinkage;
|
||||
if (linkage?.requiresParent && !relationIdentity(form[linkage.parentKey])) {
|
||||
if (
|
||||
linkage?.requiresParent &&
|
||||
!relationIdentity(form[linkage.parentKey])
|
||||
) {
|
||||
relations.clear(resolved.relation);
|
||||
return;
|
||||
}
|
||||
@@ -344,6 +439,28 @@ export function useResourceRelationLinkage(
|
||||
|
||||
/** 返回保存前的父子关系错误,空字符串代表当前组合可提交。 */
|
||||
function validationMessage() {
|
||||
for (const field of configuredFields.value.filter(
|
||||
(item) => item.dynamicRelation?.contextParentKey,
|
||||
)) {
|
||||
const dynamic = field.dynamicRelation;
|
||||
if (!dynamic) continue;
|
||||
const type = relationIdentity(form[dynamic.parentKey]);
|
||||
const contextOption = dynamicContextOption(field);
|
||||
if (!type || !contextOption) continue;
|
||||
const fixedIdentityKey = dynamic.fixedIdentityKeys?.[type];
|
||||
if (fixedIdentityKey) {
|
||||
const expected = relationIdentity(contextOption[fixedIdentityKey]);
|
||||
if (!expected) {
|
||||
return (
|
||||
dynamic.missingIdentityMessages?.[type] ??
|
||||
'当前合同缺少该类型的创建方'
|
||||
);
|
||||
}
|
||||
if (relationIdentity(form[field.key]) !== expected) {
|
||||
return '创建方与当前配送合同不一致,请重新选择';
|
||||
}
|
||||
}
|
||||
}
|
||||
for (const linkageItem of active) {
|
||||
const childField = linkageItem.childField;
|
||||
const linkage = childField.relationLinkage;
|
||||
@@ -374,6 +491,24 @@ export function useResourceRelationLinkage(
|
||||
for (const field of configuredFields.value) {
|
||||
const linkage = field.relationLinkage;
|
||||
const resource = dynamicRelationResource(field, form);
|
||||
const dynamic = field.dynamicRelation;
|
||||
if (dynamic?.contextParentKey) {
|
||||
if (!relationIdentity(form[dynamic.contextParentKey])) continue;
|
||||
const type = relationIdentity(form[dynamic.parentKey]);
|
||||
const contextOption = dynamicContextOption(field);
|
||||
const fixedIdentityKey = dynamic.fixedIdentityKeys?.[type];
|
||||
if (
|
||||
type &&
|
||||
contextOption &&
|
||||
fixedIdentityKey &&
|
||||
!relationIdentity(contextOption[fixedIdentityKey])
|
||||
) {
|
||||
return (
|
||||
dynamic.missingIdentityMessages?.[type] ??
|
||||
'当前合同缺少该类型的创建方'
|
||||
);
|
||||
}
|
||||
}
|
||||
if (
|
||||
!field.required ||
|
||||
!resource ||
|
||||
|
||||
Reference in New Issue
Block a user