feat: 增加工作人员组织联动
This commit is contained in:
@@ -0,0 +1,195 @@
|
||||
/**
|
||||
* 功能:协调资源表单中显式启用的父子关联下拉、搜索和保存前校验。
|
||||
* 版本:v1.0.0
|
||||
*/
|
||||
import { Message } from '@arco-design/web-vue';
|
||||
import type { ResourceField } from '@/api/resources';
|
||||
import {
|
||||
linkedRelationFilters,
|
||||
linkedRelationValidationMessage,
|
||||
optionParentIdentity,
|
||||
relationIdentity,
|
||||
shouldClearLinkedOption,
|
||||
} from './resource-relation-linkage-policy';
|
||||
import type { ResourceRelations } from './use-resource-relations';
|
||||
|
||||
type ActiveLinkage = {
|
||||
childField: ResourceField;
|
||||
parentField?: ResourceField;
|
||||
};
|
||||
|
||||
export function useResourceRelationLinkage(
|
||||
form: Record<string, any>,
|
||||
relations: ResourceRelations,
|
||||
) {
|
||||
let active: ActiveLinkage | undefined;
|
||||
let initialized = false;
|
||||
|
||||
function findOption(resource: string, identity: string) {
|
||||
return (relations.options[resource] ?? []).find(
|
||||
(row) => relationIdentity(row.identity) === identity,
|
||||
);
|
||||
}
|
||||
|
||||
function configure(fields: ResourceField[]) {
|
||||
const childField = fields.find((field) => field.relationLinkage);
|
||||
if (!childField?.relationLinkage) {
|
||||
active = undefined;
|
||||
return;
|
||||
}
|
||||
active = {
|
||||
childField,
|
||||
parentField: fields.find(
|
||||
(field) => field.key === childField.relationLinkage?.parentKey,
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
function childRequest() {
|
||||
if (!active?.childField.relationLinkage) return {};
|
||||
const linkage = active.childField.relationLinkage;
|
||||
const parentIdentity = relationIdentity(form[linkage.parentKey]);
|
||||
const childIdentity = relationIdentity(form[active.childField.key]);
|
||||
return {
|
||||
filters: linkedRelationFilters(parentIdentity, linkage.filterKey),
|
||||
preserveIdentities: childIdentity ? [childIdentity] : [],
|
||||
};
|
||||
}
|
||||
|
||||
async function reloadChildOptions() {
|
||||
const resource = active?.childField.relation;
|
||||
if (!resource) return;
|
||||
relations.cancelSearch(resource);
|
||||
await relations.load(resource, '', childRequest());
|
||||
}
|
||||
|
||||
/** 预加载普通关联项,并单独按父级条件加载启用联动的子选项。 */
|
||||
async function preload(fields: ResourceField[]) {
|
||||
initialized = false;
|
||||
configure(fields);
|
||||
if (!active?.childField.relationLinkage || !active.childField.relation) {
|
||||
await relations.preload(fields);
|
||||
initialized = true;
|
||||
return;
|
||||
}
|
||||
|
||||
await relations.preload(
|
||||
fields.filter((field) => field.key !== active?.childField.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);
|
||||
}
|
||||
await reloadChildOptions();
|
||||
initialized = true;
|
||||
|
||||
const warning = validationMessage();
|
||||
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]);
|
||||
if (childIdentity) {
|
||||
const option =
|
||||
findOption(active.childField.relation, childIdentity) ??
|
||||
(await relations.ensure(active.childField.relation, childIdentity));
|
||||
if (
|
||||
relationIdentity(form[linkage.parentKey]) !== parentIdentity ||
|
||||
relationIdentity(form[active.childField.key]) !== childIdentity
|
||||
) {
|
||||
return;
|
||||
}
|
||||
if (
|
||||
shouldClearLinkedOption(
|
||||
parentIdentity,
|
||||
option,
|
||||
linkage.optionParentKey,
|
||||
)
|
||||
) {
|
||||
form[active.childField.key] = '';
|
||||
Message.info('所属气站已变更,请重新选择配送点');
|
||||
}
|
||||
}
|
||||
await reloadChildOptions();
|
||||
}
|
||||
|
||||
async function handleChildChange(childIdentity: string) {
|
||||
if (!active?.childField.relationLinkage || !active.childField.relation)
|
||||
return;
|
||||
const linkage = active.childField.relationLinkage;
|
||||
if (!childIdentity) return;
|
||||
const option =
|
||||
findOption(active.childField.relation, childIdentity) ??
|
||||
(await relations.ensure(active.childField.relation, childIdentity));
|
||||
if (
|
||||
!option ||
|
||||
relationIdentity(form[active.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 (currentParent !== nextParent) {
|
||||
form[linkage.parentKey] = nextParent;
|
||||
if (!nextParent && currentParent) {
|
||||
Message.info('平台主管配送点不隶属于气站,已清空所属气站');
|
||||
}
|
||||
}
|
||||
}
|
||||
await reloadChildOptions();
|
||||
}
|
||||
|
||||
/** 响应用户主动修改关联字段;初始化回显不会触发自动清理。 */
|
||||
async function change(field: ResourceField, value: unknown) {
|
||||
if (!initialized || !active?.childField.relationLinkage) return;
|
||||
const identity = relationIdentity(value);
|
||||
if (field.key === active.childField.relationLinkage.parentKey) {
|
||||
await handleParentChange(identity);
|
||||
} else if (field.key === active.childField.key) {
|
||||
await handleChildChange(identity);
|
||||
}
|
||||
}
|
||||
|
||||
/** 搜索联动子项时始终保留父级过滤和当前选项。 */
|
||||
function search(field: ResourceField, keyword: string) {
|
||||
if (!field.relation) return;
|
||||
if (field.key === active?.childField.key) {
|
||||
relations.search(field.relation, keyword, childRequest());
|
||||
return;
|
||||
}
|
||||
relations.search(field.relation, keyword);
|
||||
}
|
||||
|
||||
/** 返回保存前的父子关系错误,空字符串代表当前组合可提交。 */
|
||||
function validationMessage() {
|
||||
if (!active?.childField.relationLinkage || !active.childField.relation)
|
||||
return '';
|
||||
const linkage = active.childField.relationLinkage;
|
||||
const parentIdentity = relationIdentity(form[linkage.parentKey]);
|
||||
const childIdentity = relationIdentity(form[active.childField.key]);
|
||||
const option = findOption(active.childField.relation, childIdentity);
|
||||
return linkedRelationValidationMessage(
|
||||
parentIdentity,
|
||||
childIdentity,
|
||||
option,
|
||||
linkage.optionParentKey,
|
||||
);
|
||||
}
|
||||
|
||||
return { preload, change, search, validationMessage };
|
||||
}
|
||||
Reference in New Issue
Block a user