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

View File

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