feat: support association-cascader filter form item

This commit is contained in:
sealday 2024-03-22 02:36:54 +08:00
parent 5489c9e569
commit 436088d7b9
4 changed files with 101 additions and 8 deletions

View File

@ -76,6 +76,7 @@ import {
SheetBlockToolbar, SheetBlockToolbar,
sheetBlockSettings, sheetBlockSettings,
} from './schema-initializer/blocks/SheetBlockInitializer'; } from './schema-initializer/blocks/SheetBlockInitializer';
import AssociationCascader from './schema-components/association-cascader/AssociationCascader';
export { usePDFViewerRef } from './schema-initializer'; export { usePDFViewerRef } from './schema-initializer';
export * from './components/custom-components/custom-components'; export * from './components/custom-components/custom-components';
@ -153,6 +154,7 @@ export class PluginCoreClient extends Plugin {
this.app.addComponents({ this.app.addComponents({
AdminLayout, AdminLayout,
AssociationCascader,
AssociatedField, AssociatedField,
AutoComplete, AutoComplete,
CalcResult, CalcResult,

View File

@ -0,0 +1,56 @@
import React, { useMemo } from 'react';
import { Cascader } from 'antd';
import { connect, useFieldSchema } from '@formily/react';
import { useCollectionManager, useRequest } from '@nocobase/client';
import _ from 'lodash';
interface Option {
name: string | number;
id: string;
children?: Option[];
}
const AssociationCascader = connect((props) => {
const fieldSchema = useFieldSchema();
const collection = fieldSchema['collectionName'];
const associationField = props.associationField;
const cm = useCollectionManager();
const titleField = cm.getCollection(collection).titleField;
const joinTitleField = cm.getCollection(collection + '.' + associationField).titleField;
const { data } = useRequest<any>({
resource: collection,
action: 'list',
params: {
appends: [associationField],
fields: [titleField],
pageSize: 99999,
},
});
const options = useMemo(() => {
const dict = {};
data?.data.forEach((item) => {
if (item[associationField]) {
dict[item[associationField][joinTitleField]] ??= [];
dict[item[associationField][joinTitleField]].push(item[titleField]);
}
});
const options: Option[] = [];
_.forEach(dict, (values: any, key) => {
options.push({
name: key,
id: key,
children: values.map((value) => ({
name: value,
id: value,
})),
});
});
return options;
}, [associationField, joinTitleField, titleField, data?.data]);
return <Cascader options={options} {...props} showSearch />;
});
AssociationCascader.displayName = 'AssociationCascader';
export default AssociationCascader;

View File

@ -22,6 +22,7 @@ import {
EditComponent, EditComponent,
useFormBlockContext, useFormBlockContext,
useAPIClient, useAPIClient,
useCompile,
} from '@nocobase/client'; } from '@nocobase/client';
import { ConfigProvider, Radio, Space } from 'antd'; import { ConfigProvider, Radio, Space } from 'antd';
import React, { memo, useCallback, useContext, useMemo, Profiler } from 'react'; import React, { memo, useCallback, useContext, useMemo, Profiler } from 'react';
@ -36,10 +37,11 @@ import {
EditTitleField, EditTitleField,
SchemaSettingCollection, SchemaSettingCollection,
SchemaSettingComponent, SchemaSettingComponent,
} from '../../schema-settings'; } from '../schema-settings';
import _ from 'lodash'; import _ from 'lodash';
import { SchemaSettingsRemove } from '../../components/FormFilter/SchemaSettingsRemove'; import { SchemaSettingsRemove } from '../components/FormFilter/SchemaSettingsRemove';
import { useTranslation } from '../../locale'; import { tval, useTranslation } from '../locale';
import { ContractsController } from 'packages/plugins/@hera/plugin-rental/dist/server/actions';
const FieldComponentProps: React.FC = observer( const FieldComponentProps: React.FC = observer(
(props) => { (props) => {
@ -133,6 +135,7 @@ export const useFieldComponents = () => {
{ label: t('Input'), value: 'Input' }, { label: t('Input'), value: 'Input' },
{ label: t('AutoComplete'), value: 'AutoComplete' }, { label: t('AutoComplete'), value: 'AutoComplete' },
{ label: t('Select'), value: 'Select' }, { label: t('Select'), value: 'Select' },
{ label: t('AssociationCascader'), value: 'AssociationCascader' },
// { label: t('CustomSelect***'), value: 'CustomSelect' }, // { label: t('CustomSelect***'), value: 'CustomSelect' },
]; ];
return { return {
@ -148,10 +151,11 @@ export const FilterCustomItemInitializer: React.FC<{
const { t } = useTranslation(); const { t } = useTranslation();
const { scope, components } = useContext(SchemaOptionsContext); const { scope, components } = useContext(SchemaOptionsContext);
const { theme } = useGlobalTheme(); const { theme } = useGlobalTheme();
const compile = useCompile();
const { insert } = props; const { insert } = props;
const itemConfig = useSchemaInitializerItem(); const itemConfig = useSchemaInitializerItem();
const { getInterface } = useCollectionManager_deprecated(); const { getInterface } = useCollectionManager_deprecated();
const { collections } = useCollectionManager_deprecated(); const { collections, getCollectionFields } = useCollectionManager_deprecated();
const allCollection = collections.map((value) => { const allCollection = collections.map((value) => {
return { return {
label: value.title, label: value.title,
@ -165,7 +169,18 @@ export const FilterCustomItemInitializer: React.FC<{
t('Add custom field'), t('Add custom field'),
() => ( () => (
<SchemaComponentOptions <SchemaComponentOptions
scope={{ ...scope, useCollectionManager_deprecated }} scope={{
...scope,
useCollectionManager_deprecated,
useAssociationFields(collection?: string | undefined | null) {
return (
getCollectionFields(collection)?.map((field) => ({
value: field.name,
label: compile(field.uiSchema?.title),
})) ?? []
);
},
}}
components={{ ...components, FieldComponentProps }} components={{ ...components, FieldComponentProps }}
> >
<FormLayout layout={'vertical'}> <FormLayout layout={'vertical'}>
@ -201,6 +216,24 @@ export const FilterCustomItemInitializer: React.FC<{
description: t('Select a collection field to use metadata of the field'), description: t('Select a collection field to use metadata of the field'),
'x-visible': false, 'x-visible': false,
}, },
associationField: {
type: 'string',
title: tval('Association field'),
'x-decorator': 'FormItem',
'x-component': 'Select',
'x-reactions': [
{
dependencies: ['collection', 'component'],
when: "{{$deps[1] === 'AssociationCascader'}}",
fulfill: {
schema: {
'x-visible': '{{$deps[0] ? true : false}}',
enum: '{{ useAssociationFields($deps[0]) }}',
},
},
},
],
},
props: { props: {
type: 'object', type: 'object',
title: t('Component properties'), title: t('Component properties'),
@ -225,7 +258,7 @@ export const FilterCustomItemInitializer: React.FC<{
const name = field.value; const name = field.value;
const collectionComponent = field.query('.collection').take() as Field; const collectionComponent = field.query('.collection').take() as Field;
const propsComponent = field.query('.props').take() as Field; const propsComponent = field.query('.props').take() as Field;
if (name === 'Select' || name === 'AutoComplete') { if (name === 'Select' || name === 'AutoComplete' || name === 'AssociationCascader') {
collectionComponent.setDisplay('visible'); collectionComponent.setDisplay('visible');
collectionComponent.setRequired(true); collectionComponent.setRequired(true);
propsComponent.setDisplay('none'); propsComponent.setDisplay('none');
@ -244,7 +277,8 @@ export const FilterCustomItemInitializer: React.FC<{
}); });
}, },
}); });
const { title, component, collection } = values; const { title, component, collection, associationField } = values;
console.log('=-=======', associationField);
const defaultSchema = getInterface(component)?.default?.uiSchema || {}; const defaultSchema = getInterface(component)?.default?.uiSchema || {};
let name; let name;
if (component === 'Select' || component === 'AutoComplete') { if (component === 'Select' || component === 'AutoComplete') {
@ -269,6 +303,7 @@ export const FilterCustomItemInitializer: React.FC<{
label: 'name', label: 'name',
value: 'id', value: 'id',
}, },
associationField,
}, },
'x-compoent-custom': true, 'x-compoent-custom': true,
collectionName: collection, collectionName: collection,

View File

@ -1,4 +1,4 @@
export * from './FilterFormItemCustomInitializer/FilterFormItemCustom'; export * from './CustomFilterFormItemInitializer';
export * from './blocks/PDFVIewerBlockInitializer'; export * from './blocks/PDFVIewerBlockInitializer';
export * from './actions/OutboundLinkActionInitializer'; export * from './actions/OutboundLinkActionInitializer';
export * from './actions/CreateSubmitActionInitializer'; export * from './actions/CreateSubmitActionInitializer';