diff --git a/packages/plugins/@hera/plugin-core/src/client/index.tsx b/packages/plugins/@hera/plugin-core/src/client/index.tsx index 5084d7a95..e0c8b0c2f 100644 --- a/packages/plugins/@hera/plugin-core/src/client/index.tsx +++ b/packages/plugins/@hera/plugin-core/src/client/index.tsx @@ -76,6 +76,7 @@ import { SheetBlockToolbar, sheetBlockSettings, } from './schema-initializer/blocks/SheetBlockInitializer'; +import AssociationCascader from './schema-components/association-cascader/AssociationCascader'; export { usePDFViewerRef } from './schema-initializer'; export * from './components/custom-components/custom-components'; @@ -153,6 +154,7 @@ export class PluginCoreClient extends Plugin { this.app.addComponents({ AdminLayout, + AssociationCascader, AssociatedField, AutoComplete, CalcResult, diff --git a/packages/plugins/@hera/plugin-core/src/client/schema-components/association-cascader/AssociationCascader.tsx b/packages/plugins/@hera/plugin-core/src/client/schema-components/association-cascader/AssociationCascader.tsx new file mode 100644 index 000000000..90de53c42 --- /dev/null +++ b/packages/plugins/@hera/plugin-core/src/client/schema-components/association-cascader/AssociationCascader.tsx @@ -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({ + 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 ; +}); + +AssociationCascader.displayName = 'AssociationCascader'; +export default AssociationCascader; diff --git a/packages/plugins/@hera/plugin-core/src/client/schema-initializer/FilterFormItemCustomInitializer/FilterFormItemCustom.tsx b/packages/plugins/@hera/plugin-core/src/client/schema-initializer/CustomFilterFormItemInitializer.tsx similarity index 87% rename from packages/plugins/@hera/plugin-core/src/client/schema-initializer/FilterFormItemCustomInitializer/FilterFormItemCustom.tsx rename to packages/plugins/@hera/plugin-core/src/client/schema-initializer/CustomFilterFormItemInitializer.tsx index fcc0f2f61..50af055fb 100644 --- a/packages/plugins/@hera/plugin-core/src/client/schema-initializer/FilterFormItemCustomInitializer/FilterFormItemCustom.tsx +++ b/packages/plugins/@hera/plugin-core/src/client/schema-initializer/CustomFilterFormItemInitializer.tsx @@ -22,6 +22,7 @@ import { EditComponent, useFormBlockContext, useAPIClient, + useCompile, } from '@nocobase/client'; import { ConfigProvider, Radio, Space } from 'antd'; import React, { memo, useCallback, useContext, useMemo, Profiler } from 'react'; @@ -36,10 +37,11 @@ import { EditTitleField, SchemaSettingCollection, SchemaSettingComponent, -} from '../../schema-settings'; +} from '../schema-settings'; import _ from 'lodash'; -import { SchemaSettingsRemove } from '../../components/FormFilter/SchemaSettingsRemove'; -import { useTranslation } from '../../locale'; +import { SchemaSettingsRemove } from '../components/FormFilter/SchemaSettingsRemove'; +import { tval, useTranslation } from '../locale'; +import { ContractsController } from 'packages/plugins/@hera/plugin-rental/dist/server/actions'; const FieldComponentProps: React.FC = observer( (props) => { @@ -133,6 +135,7 @@ export const useFieldComponents = () => { { label: t('Input'), value: 'Input' }, { label: t('AutoComplete'), value: 'AutoComplete' }, { label: t('Select'), value: 'Select' }, + { label: t('AssociationCascader'), value: 'AssociationCascader' }, // { label: t('CustomSelect***'), value: 'CustomSelect' }, ]; return { @@ -148,10 +151,11 @@ export const FilterCustomItemInitializer: React.FC<{ const { t } = useTranslation(); const { scope, components } = useContext(SchemaOptionsContext); const { theme } = useGlobalTheme(); + const compile = useCompile(); const { insert } = props; const itemConfig = useSchemaInitializerItem(); const { getInterface } = useCollectionManager_deprecated(); - const { collections } = useCollectionManager_deprecated(); + const { collections, getCollectionFields } = useCollectionManager_deprecated(); const allCollection = collections.map((value) => { return { label: value.title, @@ -165,7 +169,18 @@ export const FilterCustomItemInitializer: React.FC<{ t('Add custom field'), () => ( ({ + value: field.name, + label: compile(field.uiSchema?.title), + })) ?? [] + ); + }, + }} components={{ ...components, FieldComponentProps }} > @@ -201,6 +216,24 @@ export const FilterCustomItemInitializer: React.FC<{ description: t('Select a collection field to use metadata of the field'), '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: { type: 'object', title: t('Component properties'), @@ -225,7 +258,7 @@ export const FilterCustomItemInitializer: React.FC<{ const name = field.value; const collectionComponent = field.query('.collection').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.setRequired(true); 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 || {}; let name; if (component === 'Select' || component === 'AutoComplete') { @@ -269,6 +303,7 @@ export const FilterCustomItemInitializer: React.FC<{ label: 'name', value: 'id', }, + associationField, }, 'x-compoent-custom': true, collectionName: collection, diff --git a/packages/plugins/@hera/plugin-core/src/client/schema-initializer/index.ts b/packages/plugins/@hera/plugin-core/src/client/schema-initializer/index.ts index acdb18600..deae60716 100644 --- a/packages/plugins/@hera/plugin-core/src/client/schema-initializer/index.ts +++ b/packages/plugins/@hera/plugin-core/src/client/schema-initializer/index.ts @@ -1,4 +1,4 @@ -export * from './FilterFormItemCustomInitializer/FilterFormItemCustom'; +export * from './CustomFilterFormItemInitializer'; export * from './blocks/PDFVIewerBlockInitializer'; export * from './actions/OutboundLinkActionInitializer'; export * from './actions/CreateSubmitActionInitializer';