feat: relationship fields are loaded on demand

This commit is contained in:
chenos 2022-06-26 00:27:18 +08:00
parent 9dae723ca7
commit 4184f12457
2 changed files with 72 additions and 32 deletions

View File

@ -52,7 +52,11 @@ const useResource = (props: UseResourceProps) => {
}
const withoutTableFieldResource = useContext(WithoutTableFieldResource);
const __parent = useContext(BlockRequestContext);
if (!withoutTableFieldResource && __parent?.block === 'TableField' && __parent?.resource instanceof TableFieldResource) {
if (
!withoutTableFieldResource &&
__parent?.block === 'TableField' &&
__parent?.resource instanceof TableFieldResource
) {
return __parent.resource;
}
if (!association) {
@ -61,7 +65,7 @@ const useResource = (props: UseResourceProps) => {
if (sourceId) {
return api.resource(resource, sourceId);
}
return api.resource(resource, record[association?.sourceKey || 'id']);
};
@ -76,14 +80,24 @@ export const useResourceAction = (props, opts = {}) => {
const { fields } = useCollection();
const appends = fields?.filter((field) => field.target).map((field) => field.name);
const params = useActionParams(props);
if (appends?.length) {
if (!Object.keys(params).includes('appends') && appends?.length) {
params['appends'] = appends;
}
const result = useRequest(
(params) => (action ? resource[action](params).then((res) => res.data) : Promise.resolve({})),
(opts) => {
if (!action) {
return Promise.resolve({});
}
const actionParams = { ...opts };
if (params.appends) {
actionParams.appends = params.appends;
}
return resource[action](actionParams).then((res) => res.data);
},
{
...opts,
defaultParams: [params],
refreshDeps: [JSON.stringify(params.appends)],
},
);
return result;
@ -152,8 +166,8 @@ export const useFilterByTk = () => {
return recordIndex;
}
}
if (assoc) {
if (assoc) {
const association = getCollectionField(assoc);
return record?.[association.targetKey || 'id'];
}

View File

@ -1,6 +1,7 @@
import { ArrayField } from '@formily/core';
import { Schema, useField, useFieldSchema } from '@formily/react';
import React, { createContext, useContext, useEffect } from 'react';
import { ArrayField, createForm } from '@formily/core';
import { FormContext, Schema, useField, useFieldSchema } from '@formily/react';
import uniq from 'lodash/uniq';
import React, { createContext, useContext, useEffect, useMemo } from 'react';
import { useCollectionManager } from '../collection-manager';
import { BlockProvider, useBlockRequestContext } from './BlockProvider';
@ -30,48 +31,69 @@ const InternalTableBlockProvider = (props) => {
);
};
const useAssociationNames = (collection) => {
export const useAssociationNames = (collection) => {
const { getCollectionFields } = useCollectionManager();
const names = getCollectionFields(collection)
?.filter((field) => field.target)
.map((field) => field.name);
return names;
const collectionFields = getCollectionFields(collection);
const associationFields = new Set();
for (const collectionField of collectionFields) {
if (collectionField.target) {
associationFields.add(collectionField.name);
const fields = getCollectionFields(collectionField.target);
for (const field of fields) {
if (field.target) {
associationFields.add(`${collectionField.name}.${field.name}`);
}
}
}
}
const fieldSchema = useFieldSchema();
const tableSchema = fieldSchema.reduceProperties((buf, schema) => {
if (schema['x-component'] === 'TableV2') {
return schema;
}
return buf;
}, null) as Schema;
return tableSchema.reduceProperties((buf, schema) => {
if (schema['x-component'] === 'TableV2.Column') {
const s = schema.reduceProperties((buf, s) => {
if (s['x-collection-field'] && names.includes(s.name)) {
return s;
}, new Schema({}));
return uniq(
tableSchema.reduceProperties((buf, schema) => {
if (schema['x-component'] === 'TableV2.Column') {
const s = schema.reduceProperties((buf, s) => {
const [name] = (s.name as string).split('.');
if (s['x-collection-field'] && associationFields.has(name)) {
return s;
}
return buf;
}, null);
if (s) {
// 关联字段和关联的关联字段
const [firstName] = s.name.split('.');
if (associationFields.has(s.name)) {
buf.push(s.name);
} else if (associationFields.has(firstName)) {
buf.push(firstName);
}
}
return buf;
}, null);
if (s) {
buf.push(s.name);
}
}
return buf;
}, []);
return buf;
}, []),
);
};
export const TableBlockProvider = (props) => {
const params = { ...props.params };
const appends = useAssociationNames(props.collection);
const form = useMemo(() => createForm(), []);
if (props.dragSort) {
params['sort'] = ['sort'];
}
if (appends?.length) {
if (!Object.keys(params).includes('appends')) {
params['appends'] = appends;
}
return (
<BlockProvider {...props} params={params}>
<InternalTableBlockProvider {...props} params={params} />
</BlockProvider>
<FormContext.Provider value={form}>
<BlockProvider {...props} params={params}>
<InternalTableBlockProvider {...props} params={params} />
</BlockProvider>
</FormContext.Provider>
);
};
@ -119,7 +141,11 @@ export const useTableBlockProps = () => {
ctx.service.refresh();
},
onChange({ current, pageSize }, filters, sorter) {
let sort = sorter.order ? (sorter.order === `ascend` ? [sorter.field] : [`-${sorter.field}`]) : globalSort || null;
let sort = sorter.order
? sorter.order === `ascend`
? [sorter.field]
: [`-${sorter.field}`]
: globalSort || null;
ctx.service.run({ ...ctx.service.params?.[0], page: current, pageSize, sort });
},