From 3fcdd9454983b4b156615ab0f323c75941a178f8 Mon Sep 17 00:00:00 2001 From: katherinehhh Date: Fri, 12 May 2023 07:20:27 +0800 Subject: [PATCH] fix:association appends (#1842) * fix: getNesterAppends filter bug * fix: associationSelect * fix: associationSelect * fix: associationSelect * fix: getAssociationAppends * fix: sub-form collection context * refactor: code improve * refactor: code improve * refactor: code improve * refactor: code improve * refactor: code improve --- .../client/src/block-provider/hooks/index.ts | 4 ++- .../AssociationFieldProvider.tsx | 25 +++++++++----- .../association-field/AssociationSelect.tsx | 12 +++---- .../antd/association-field/Editable.tsx | 34 +++++++++---------- .../antd/association-field/InternalNester.tsx | 8 +++-- .../antd/association-field/InternalPicker.tsx | 8 ++--- .../antd/association-field/InternalViewer.tsx | 11 +++--- .../antd/association-field/ReadPretty.tsx | 25 +++++++------- .../antd/association-field/context.ts | 7 ++-- .../antd/association-field/hooks.ts | 9 ++--- 10 files changed, 79 insertions(+), 64 deletions(-) diff --git a/packages/core/client/src/block-provider/hooks/index.ts b/packages/core/client/src/block-provider/hooks/index.ts index 530836b48..e3f821a3e 100644 --- a/packages/core/client/src/block-provider/hooks/index.ts +++ b/packages/core/client/src/block-provider/hooks/index.ts @@ -1074,6 +1074,7 @@ export const useAssociationFilterBlockProps = () => { export const useAssociationNames = (collection) => { const { getCollectionFields, getCollectionJoinField } = useCollectionManager(); + const { getField } = useCollection(); const collectionFields = getCollectionFields(collection); const associationFields = new Set(); for (const collectionField of collectionFields) { @@ -1098,7 +1099,8 @@ export const useAssociationNames = (collection) => { const getAssociationAppends = (schema, arr = []) => { const data = schema.reduceProperties((buf, s) => { - const collectionfield = s['x-collection-field'] && getCollectionJoinField(s['x-collection-field']); + const collectionfield = + getField(s.name) || (s['x-collection-field'] && getCollectionJoinField(s['x-collection-field'])); if ( collectionfield && ['createdBy', 'updatedBy', 'o2m', 'obo', 'oho', 'm2o', 'm2m'].includes(collectionfield.interface) diff --git a/packages/core/client/src/schema-component/antd/association-field/AssociationFieldProvider.tsx b/packages/core/client/src/schema-component/antd/association-field/AssociationFieldProvider.tsx index 0f0dda20d..d1f11e8cf 100644 --- a/packages/core/client/src/schema-component/antd/association-field/AssociationFieldProvider.tsx +++ b/packages/core/client/src/schema-component/antd/association-field/AssociationFieldProvider.tsx @@ -1,19 +1,28 @@ -import { useField, useFieldSchema } from '@formily/react'; +import { useField, useFieldSchema, observer } from '@formily/react'; import React, { useMemo } from 'react'; import { useCollectionManager } from '../../../collection-manager'; import { AssociationFieldContext } from './context'; -export function AssociationFieldProvider(props) { +export const AssociationFieldProvider = observer((props) => { const field = useField(); - const { getCollectionField } = useCollectionManager(); + const { getCollectionJoinField, getCollection } = useCollectionManager(); const fieldSchema = useFieldSchema(); + const collectionField = useMemo( - () => getCollectionField(fieldSchema['x-collection-field']), + () => getCollectionJoinField(fieldSchema['x-collection-field']), + [fieldSchema['x-collection-field'], fieldSchema.name], + ); + const isFileCollection = useMemo( + () => getCollection(collectionField?.target)?.template === 'file', [fieldSchema['x-collection-field']], ); - return ( - + const currentMode = useMemo( + () => fieldSchema['x-component-props'].mode || (isFileCollection ? 'FileManager' : 'Select'), + [fieldSchema['x-component-props'].mode], + ); + return collectionField ? ( + {props.children} - ); -} + ) : null; +}); diff --git a/packages/core/client/src/schema-component/antd/association-field/AssociationSelect.tsx b/packages/core/client/src/schema-component/antd/association-field/AssociationSelect.tsx index 50bb5a5c0..76eccb7a4 100644 --- a/packages/core/client/src/schema-component/antd/association-field/AssociationSelect.tsx +++ b/packages/core/client/src/schema-component/antd/association-field/AssociationSelect.tsx @@ -3,9 +3,10 @@ import { RecursionField, connect, mapProps, observer, useField, useFieldSchema } import { Button, Input } from 'antd'; import React, { useCallback, useEffect, useMemo, useState } from 'react'; import { useTranslation } from 'react-i18next'; -import { CollectionProvider, useCollection } from '../../../collection-manager'; +import { CollectionProvider } from '../../../collection-manager'; import { useFieldTitle } from '../../hooks'; import { ActionContext } from '../action'; +import { useAssociationFieldContext } from './hooks'; import { RemoteSelect, RemoteSelectProps } from '../remote-select'; import useServiceOptions, { useInsertSchema } from './hooks'; import schema from './schema'; @@ -18,11 +19,10 @@ export type AssociationSelectProps

= RemoteSelectProps

& { const InternalAssociationSelect = observer((props: AssociationSelectProps) => { const { fieldNames, objectValue = true } = props; const field: any = useField(); - const [visibleAddNewer, setVisibleAddNewer] = useState(false); - const { getField } = useCollection(); - const collectionField = getField(field.props.name); - const service = useServiceOptions(props); const fieldSchema = useFieldSchema(); + const [visibleAddNewer, setVisibleAddNewer] = useState(false); + const service = useServiceOptions(props); + const { options: collectionField } = useAssociationFieldContext(); const isFilterForm = fieldSchema['x-designer'] === 'FormItem.FilterFormDesigner'; const isAllowAddNew = fieldSchema['x-add-new']; const insertAddNewer = useInsertSchema('AddNewer'); @@ -74,7 +74,7 @@ const InternalAssociationSelect = observer((props: AssociationSelectProps) => { - + { - useEffect(() => { - props.mode && setCurrentMode(props.mode); - }, [props.mode]); +const EditableAssociationField = observer((props: any) => { const { multiple } = props; const field: any = useField(); const form = useForm(); const fieldSchema = useFieldSchema(); - const { getField } = useCollection(); - const { getCollection } = useCollectionManager(); - const collectionField = getField(field.props.name); - const isFileCollection = getCollection(collectionField?.target)?.template === 'file'; - const [currentMode, setCurrentMode] = useState(props.mode || (isFileCollection ? 'FileManager' : 'Select')); + const { options: collectionField, currentMode } = useAssociationFieldContext(); + const useCreateActionProps = () => { const { onClick } = useCAP(); const actionField: any = useField(); @@ -49,15 +43,21 @@ export const Editable = observer((props: any) => { }, }; }; + return ( + + {currentMode === 'Picker' && } + {currentMode === 'Nester' && } + {currentMode === 'Select' && } + {currentMode === 'SubTable' && } + {currentMode === 'FileManager' && } + + ); +}); + +export const Editable = observer((props) => { return ( - - {currentMode === 'Picker' && } - {currentMode === 'Nester' && } - {currentMode === 'Select' && } - {currentMode === 'SubTable' && } - {currentMode === 'FileManager' && } - + ); }); diff --git a/packages/core/client/src/schema-component/antd/association-field/InternalNester.tsx b/packages/core/client/src/schema-component/antd/association-field/InternalNester.tsx index cec806071..369b8bc54 100644 --- a/packages/core/client/src/schema-component/antd/association-field/InternalNester.tsx +++ b/packages/core/client/src/schema-component/antd/association-field/InternalNester.tsx @@ -2,19 +2,21 @@ import { FormLayout } from '@formily/antd'; import { RecursionField, useField, useFieldSchema } from '@formily/react'; import React, { useEffect } from 'react'; import { CollectionProvider } from '../../../collection-manager'; -import { useAssociationFieldContext, useInsertSchema } from './hooks'; +import { useInsertSchema } from './hooks'; +import { useAssociationFieldContext } from './hooks'; import schema from './schema'; export const InternalNester = () => { const field = useField(); const fieldSchema = useFieldSchema(); const insertNester = useInsertSchema('Nester'); - const { options } = useAssociationFieldContext(); + const { options: collectionField } = useAssociationFieldContext(); + useEffect(() => { insertNester(schema.Nester); }, []); return ( - + { @@ -69,10 +70,9 @@ export const InternalPicker = observer((props: any) => { const fieldSchema = useFieldSchema(); const insertAddNewer = useInsertSchema('AddNewer'); const insertSelector = useInsertSchema('Selector'); - const { getField } = useCollection(); const { t } = useTranslation(); - const collectionField = getField(field.props.name); - const addbuttonClick = () => { + const { options: collectionField } = useAssociationFieldContext(); + const addbuttonClick = () => { insertAddNewer(schema.AddNewer); setVisibleAddNewer(true); }; diff --git a/packages/core/client/src/schema-component/antd/association-field/InternalViewer.tsx b/packages/core/client/src/schema-component/antd/association-field/InternalViewer.tsx index 647a2ee5b..85057bc74 100644 --- a/packages/core/client/src/schema-component/antd/association-field/InternalViewer.tsx +++ b/packages/core/client/src/schema-component/antd/association-field/InternalViewer.tsx @@ -2,7 +2,7 @@ import { RecursionField, observer, useField, useFieldSchema } from '@formily/rea import { toArr } from '@formily/shared'; import React, { Fragment, useRef, useState } from 'react'; import { BlockAssociationContext, WithoutTableFieldResource } from '../../../block-provider'; -import { CollectionProvider, useCollection, useCollectionManager } from '../../../collection-manager'; +import { CollectionProvider } from '../../../collection-manager'; import { RecordProvider, useRecord } from '../../../record-provider'; import { FormProvider } from '../../core'; import { useCompile } from '../../hooks'; @@ -11,6 +11,7 @@ import { EllipsisWithTooltip } from '../input/EllipsisWithTooltip'; import { useFieldNames, useInsertSchema } from './hooks'; import schema from './schema'; import { getLabelFormatValue, useLabelUiSchema } from './util'; +import { useAssociationFieldContext } from './hooks'; interface IEllipsisWithTooltipRef { setPopoverVisible: (boolean) => void; @@ -26,14 +27,12 @@ export const ReadPrettyInternalViewer: React.FC = observer((props: any) => { const fieldSchema = useFieldSchema(); const recordCtx = useRecord(); const { enableLink } = fieldSchema['x-component-props']; - const { getCollectionJoinField } = useCollectionManager(); // value 做了转换,但 props.value 和原来 useField().value 的值不一致 const field = useField(); const fieldNames = useFieldNames(props); const [visible, setVisible] = useState(false); const insertViewer = useInsertSchema('Viewer'); - const { getField } = useCollection(); - const collectionField = getField(fieldSchema.name) || getCollectionJoinField(fieldSchema?.['x-collection-field']); + const { options: collectionField } = useAssociationFieldContext(); const [record, setRecord] = useState({}); const compile = useCompile(); const labelUiSchema = useLabelUiSchema(collectionField, fieldNames?.label || 'label'); @@ -98,7 +97,7 @@ export const ReadPrettyInternalViewer: React.FC = observer((props: any) => { ); }; - return collectionField ? ( + return (

@@ -113,5 +112,5 @@ export const ReadPrettyInternalViewer: React.FC = observer((props: any) => {
- ) : null; + ); }); diff --git a/packages/core/client/src/schema-component/antd/association-field/ReadPretty.tsx b/packages/core/client/src/schema-component/antd/association-field/ReadPretty.tsx index d07e91f18..746478ee5 100644 --- a/packages/core/client/src/schema-component/antd/association-field/ReadPretty.tsx +++ b/packages/core/client/src/schema-component/antd/association-field/ReadPretty.tsx @@ -3,26 +3,27 @@ import { useField, observer } from '@formily/react'; import { AssociationFieldProvider } from './AssociationFieldProvider'; import { InternalNester } from './InternalNester'; import { ReadPrettyInternalViewer } from './InternalViewer'; -import { useCollection, useCollectionManager } from '../../../collection-manager'; import { InternalSubTable } from './InternalSubTable'; import { FileManageReadPretty } from './FileManager'; +import { useAssociationFieldContext } from './hooks'; + +const ReadPrettyAssociationField = observer((props: any) => { + const { currentMode } = useAssociationFieldContext(); -export const ReadPretty = observer((props: any) => { - const field: any = useField(); - const { getField } = useCollection(); - const { getCollection } = useCollectionManager(); - const collectionField = getField(field.props.name); - const isFileCollection = getCollection(collectionField?.target)?.template === 'file'; - const [currentMode, setCurrentMode] = useState(props.mode || (isFileCollection ? 'FileManager' : 'Select')); - useEffect(() => { - props.mode && setCurrentMode(props.mode); - }, [props.mode]); return ( - + <> {['Select', 'Picker'].includes(currentMode) && } {currentMode === 'Nester' && } {currentMode === 'SubTable' && } {currentMode === 'FileManager' && } + + ); +}); + +export const ReadPretty = observer((props) => { + return ( + + ); }); diff --git a/packages/core/client/src/schema-component/antd/association-field/context.ts b/packages/core/client/src/schema-component/antd/association-field/context.ts index 371d0049d..7aa04d823 100644 --- a/packages/core/client/src/schema-component/antd/association-field/context.ts +++ b/packages/core/client/src/schema-component/antd/association-field/context.ts @@ -2,8 +2,9 @@ import { GeneralField } from '@formily/core'; import { createContext } from 'react'; export interface AssociationFieldContextProps { - options: any; - field: GeneralField; + options?: any; + field?: GeneralField; + currentMode?:string; } -export const AssociationFieldContext = createContext(null); +export const AssociationFieldContext = createContext({}); diff --git a/packages/core/client/src/schema-component/antd/association-field/hooks.ts b/packages/core/client/src/schema-component/antd/association-field/hooks.ts index 822705290..0844e93c0 100644 --- a/packages/core/client/src/schema-component/antd/association-field/hooks.ts +++ b/packages/core/client/src/schema-component/antd/association-field/hooks.ts @@ -30,15 +30,15 @@ export const useInsertSchema = (component) => { }; export function useAssociationFieldContext() { - return useContext(AssociationFieldContext) as { options: any; field: F }; + return useContext(AssociationFieldContext) as { options: any; field: F; currentMode: string }; } export default function useServiceOptions(props) { const { action = 'list', service, fieldNames } = props; const params = service?.params || {}; const fieldSchema = useFieldSchema(); - const { getField, fields } = useCollection(); - const { getCollectionFields } = useCollectionManager(); + const { getField } = useCollection(); + const { getCollectionFields, getCollectionJoinField } = useCollectionManager(); const record = useRecord(); const normalizeValues = useCallback( @@ -63,8 +63,9 @@ export default function useServiceOptions(props) { }, [props.value, normalizeValues]); const collectionField = useMemo(() => { - return getField(fieldSchema.name); + return getField(fieldSchema.name) || getCollectionJoinField(fieldSchema?.['x-collection-field']); }, [fieldSchema.name]); + const sourceValue = record?.[collectionField?.sourceKey]; const filter = useMemo(() => { const isOToAny = ['oho', 'o2m'].includes(collectionField?.interface);