From e03e68232e0937347eb112d0739b649d916f7460 Mon Sep 17 00:00:00 2001 From: wjh Date: Tue, 12 Mar 2024 20:40:58 +0800 Subject: [PATCH 1/3] =?UTF-8?q?fix:=20=E4=BF=AE=E6=94=B9=E7=BA=A7=E8=81=94?= =?UTF-8?q?=E7=BB=84=E4=BB=B6=E9=80=82=E9=85=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cascaderComponentFieldSettings.tsx | 390 ++++++++++++++++++ .../Select/selectComponentFieldSettings.tsx | 1 + .../association-field/InternalCascader.tsx | 33 +- .../schema-component/antd/select/Select.tsx | 1 - .../schema-settings/SchemaSettingsPlugin.ts | 2 + .../association-field/Editable.tsx | 2 +- 6 files changed, 407 insertions(+), 22 deletions(-) create mode 100644 packages/core/client/src/modules/fields/component/Cascader/cascaderComponentFieldSettings.tsx diff --git a/packages/core/client/src/modules/fields/component/Cascader/cascaderComponentFieldSettings.tsx b/packages/core/client/src/modules/fields/component/Cascader/cascaderComponentFieldSettings.tsx new file mode 100644 index 000000000..cde650901 --- /dev/null +++ b/packages/core/client/src/modules/fields/component/Cascader/cascaderComponentFieldSettings.tsx @@ -0,0 +1,390 @@ +import { Field } from '@formily/core'; +import { ISchema, useField, useFieldSchema } from '@formily/react'; +import _ from 'lodash'; +import React from 'react'; +import { useTranslation } from 'react-i18next'; +import { SchemaSettings } from '../../../../application/schema-settings/SchemaSettings'; +import { useFormBlockContext } from '../../../../block-provider'; +import { + useCollectionManager_deprecated, + useCollection_deprecated, + useSortFields, +} from '../../../../collection-manager'; +import { useFieldComponentName } from '../../../../common/useFieldComponentName'; +import { useRecord } from '../../../../record-provider'; +import { removeNullCondition, useDesignable, useFieldModeOptions, useIsAddNewForm } from '../../../../schema-component'; +import { isSubMode } from '../../../../schema-component/antd/association-field/util'; +import { DynamicComponentProps } from '../../../../schema-component/antd/filter/DynamicComponent'; +import { + useIsAssociationField, + useIsFieldReadPretty, + useIsSelectFieldMode, + useTitleFieldOptions, +} from '../../../../schema-component/antd/form-item/FormItem.Settings'; +import { useColumnSchema } from '../../../../schema-component/antd/table-v2/Table.Column.Decorator'; +import { SchemaSettingsModalItem, VariableInput, getShouldChange } from '../../../../schema-settings'; +import { SchemaSettingsDataScope } from '../../../../schema-settings/SchemaSettingsDataScope'; +import { useLocalVariables, useVariables } from '../../../../variables'; +import { useCollectionField } from '../utils'; +import { ArrayItems } from '@formily/antd-v5'; + +export const SchemaSettingsSortingRule = function SortRuleConfigure(props) { + const field = useField(); + const { dn } = useDesignable(); + const { t } = useTranslation(); + const currentSchema = useFieldSchema(); + const { getField } = useCollection_deprecated(); + const { getCollectionJoinField } = useCollectionManager_deprecated(); + const fieldSchema = props?.fieldSchema ?? currentSchema; + const collectionField = getField(fieldSchema['name']) || getCollectionJoinField(fieldSchema['x-collection-field']); + const sortFields = useSortFields(collectionField?.target); + const defaultSort = fieldSchema['x-component-props']?.service?.params?.sort || []; + const sort = defaultSort?.map((item: string) => { + return item?.startsWith('-') + ? { + field: item.substring(1), + direction: 'desc', + } + : { + field: item, + direction: 'asc', + }; + }); + return ( + { + const sortArr = sort.map((item) => { + return item.direction === 'desc' ? `-${item.field}` : item.field; + }); + _.set(field.componentProps, 'service.params.sort', sortArr); + props?.onSubmitCallBack?.(sortArr); + fieldSchema['x-component-props']['service']['params']['sort'] = field.componentProps?.service.params?.sort; + const componentProps = fieldSchema['x-component-props']; + dn.emit('patch', { + schema: { + ['x-uid']: fieldSchema['x-uid'], + 'x-component-props': componentProps, + }, + }); + }} + /> + ); +}; + +const titleField: any = { + name: 'titleField', + type: 'select', + useComponentProps() { + const { t } = useTranslation(); + const field = useField(); + const { dn } = useDesignable(); + const options = useTitleFieldOptions(); + const { uiSchema, fieldSchema: tableColumnSchema, collectionField: tableColumnField } = useColumnSchema(); + const schema = useFieldSchema(); + const fieldSchema = tableColumnSchema || schema; + const targetCollectionField = useCollectionField(); + const collectionField = tableColumnField || targetCollectionField; + // 处理多对一关系标题显示 + const { getCollectionFields } = useCollectionManager_deprecated(); + const fieldNames = { + ...collectionField?.uiSchema?.['x-component-props']?.['fieldNames'], + ...field?.componentProps?.fieldNames, + ...fieldSchema?.['x-component-props']?.['fieldNames'], + }; + return { + title: t('Title field'), + options, + value: fieldNames?.label, + onChange(label) { + const schema = { + ['x-uid']: fieldSchema['x-uid'], + }; + const newFieldNames = { + ...collectionField?.uiSchema?.['x-component-props']?.['fieldNames'], + ...fieldSchema['x-component-props']?.['fieldNames'], + label, + }; + fieldSchema['x-component-props'] = fieldSchema['x-component-props'] || {}; + fieldSchema['x-component-props']['fieldNames'] = newFieldNames; + // 处理多对一关系标题显示 + const target = getCollectionFields(collectionField.target).find((field) => field.name === label); + if (target.interface === 'm2o') { + fieldSchema['x-component-props']['x-next-title'] = { + label, + collection: target.collectionName, + }; + } else { + fieldSchema['x-component-props']['x-next-title'] = null; + } + schema['x-component-props'] = fieldSchema['x-component-props']; + field.componentProps.fieldNames = fieldSchema['x-component-props'].fieldNames; + const path = field.path?.splice(field.path?.length - 1, 1); + field.form.query(`${path.concat(`*.` + fieldSchema.name)}`).forEach((f) => { + f.componentProps.fieldNames = newFieldNames; + }); + dn.emit('patch', { + schema, + }); + + dn.refresh(); + }, + }; + }, +}; + +export const allowMultiple: any = { + name: 'allowMultiple', + type: 'switch', + useVisible() { + const isFieldReadPretty = useIsFieldReadPretty(); + const collectionField = useCollectionField(); + return !isFieldReadPretty && ['hasMany', 'belongsToMany'].includes(collectionField?.type); + }, + useComponentProps() { + const { t } = useTranslation(); + const field = useField(); + const { fieldSchema: tableColumnSchema } = useColumnSchema(); + const schema = useFieldSchema(); + const fieldSchema = tableColumnSchema || schema; + const { dn, refresh } = useDesignable(); + return { + title: t('Allow multiple'), + checked: + fieldSchema['x-component-props']?.multiple === undefined ? true : fieldSchema['x-component-props'].multiple, + onChange(value) { + const schema = { + ['x-uid']: fieldSchema['x-uid'], + }; + fieldSchema['x-component-props'] = fieldSchema['x-component-props'] || {}; + field.componentProps = field.componentProps || {}; + + fieldSchema['x-component-props'].multiple = value; + field.componentProps.multiple = value; + + schema['x-component-props'] = fieldSchema['x-component-props']; + dn.emit('patch', { + schema, + }); + refresh(); + }, + }; + }, +}; + +const setDefaultSortingRules = { + name: 'setDefaultSortingRules', + Component: SchemaSettingsSortingRule, +}; + +const setTheDataScope: any = { + name: 'setTheDataScope', + Component: SchemaSettingsDataScope, + useComponentProps() { + const { getCollectionJoinField, getAllCollectionsInheritChain } = useCollectionManager_deprecated(); + const { getField } = useCollection_deprecated(); + const { form } = useFormBlockContext(); + const record = useRecord(); + const field = useField(); + const { fieldSchema: tableColumnSchema, collectionField: tableColumnField } = useColumnSchema(); + const schema = useFieldSchema(); + const fieldSchema = tableColumnSchema || schema; + const collectionField = + tableColumnField || getField(fieldSchema['name']) || getCollectionJoinField(fieldSchema['x-collection-field']); + const variables = useVariables(); + const localVariables = useLocalVariables(); + const { dn } = useDesignable(); + return { + collectionName: collectionField?.target, + defaultFilter: fieldSchema?.['x-component-props']?.service?.params?.filter || {}, + form, + dynamicComponent: (props: DynamicComponentProps) => { + return ( + + ); + }, + onSubmit: ({ filter }) => { + filter = removeNullCondition(filter); + _.set(field.componentProps, 'service.params.filter', filter); + fieldSchema['x-component-props']['service']['params']['filter'] = filter; + const componentProps = fieldSchema['x-component-props']; + const path = field.path?.splice(field.path?.length - 1, 1); + field.form.query(`${path.concat(`*.` + fieldSchema.name)}`).forEach((f) => { + f.componentProps = componentProps; + }); + dn.emit('patch', { + schema: { + ['x-uid']: fieldSchema['x-uid'], + 'x-component-props': componentProps, + }, + }); + dn.refresh(); + }, + }; + }, +}; + +const fieldComponent: any = { + name: 'fieldComponent', + type: 'select', + useComponentProps() { + const { t } = useTranslation(); + const field = useField(); + const { fieldSchema: tableColumnSchema, collectionField } = useColumnSchema(); + const schema = useFieldSchema(); + const fieldSchema = tableColumnSchema || schema; + const fieldModeOptions = useFieldModeOptions({ fieldSchema: tableColumnSchema, collectionField }); + const isAddNewForm = useIsAddNewForm(); + const fieldMode = useFieldComponentName(); + const { dn } = useDesignable(); + return { + title: t('Field component'), + options: fieldModeOptions, + value: fieldMode, + onChange(mode) { + const schema = { + ['x-uid']: fieldSchema['x-uid'], + }; + fieldSchema['x-component-props'] = fieldSchema['x-component-props'] || {}; + fieldSchema['x-component-props']['mode'] = mode; + schema['x-component-props'] = fieldSchema['x-component-props']; + field.componentProps = field.componentProps || {}; + field.componentProps.mode = mode; + + // 子表单状态不允许设置默认值 + if (isSubMode(fieldSchema) && isAddNewForm) { + // @ts-ignore + schema.default = null; + fieldSchema.default = null; + field?.setInitialValue?.(null); + field?.setValue?.(null); + } + + void dn.emit('patch', { + schema, + }); + dn.refresh(); + }, + }; + }, +}; + +export const cascaderComponentFieldSettings = new SchemaSettings({ + name: 'fieldSettings:component:Cascader', + items: [ + { + ...fieldComponent, + useVisible: useIsAssociationField, + }, + { + ...setTheDataScope, + useVisible() { + const isSelectFieldMode = useIsSelectFieldMode(); + const isFieldReadPretty = useIsFieldReadPretty(); + return isSelectFieldMode && !isFieldReadPretty; + }, + }, + { + ...setDefaultSortingRules, + useComponentProps() { + const { fieldSchema } = useColumnSchema(); + return { + fieldSchema, + }; + }, + useVisible() { + const isSelectFieldMode = useIsSelectFieldMode(); + const isFieldReadPretty = useIsFieldReadPretty(); + return isSelectFieldMode && !isFieldReadPretty; + }, + }, + { + ...titleField, + useVisible: useIsAssociationField, + }, + ], +}); diff --git a/packages/core/client/src/modules/fields/component/Select/selectComponentFieldSettings.tsx b/packages/core/client/src/modules/fields/component/Select/selectComponentFieldSettings.tsx index f107afef3..876b0f833 100644 --- a/packages/core/client/src/modules/fields/component/Select/selectComponentFieldSettings.tsx +++ b/packages/core/client/src/modules/fields/component/Select/selectComponentFieldSettings.tsx @@ -116,6 +116,7 @@ const titleField: any = { dn.emit('patch', { schema, }); + dn.refresh(); }, }; diff --git a/packages/core/client/src/schema-component/antd/association-field/InternalCascader.tsx b/packages/core/client/src/schema-component/antd/association-field/InternalCascader.tsx index 1a3b56449..4c106227a 100644 --- a/packages/core/client/src/schema-component/antd/association-field/InternalCascader.tsx +++ b/packages/core/client/src/schema-component/antd/association-field/InternalCascader.tsx @@ -4,11 +4,11 @@ import { FormProvider, connect, createSchemaField, observer, useField, useFieldS import { uid } from '@formily/shared'; import { Input, Space, Spin, Tag } from 'antd'; import dayjs from 'dayjs'; -import React, { useCallback, useEffect, useMemo, useState } from 'react'; +import React, { useEffect, useMemo, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { css, useAPIClient, useCollectionManager_deprecated } from '../../..'; import { mergeFilter } from '../../../filter-provider/utils'; -import { CustomCascader, SchemaComponent, useCompile } from '../..'; +import { CustomCascader, SchemaComponent, useCompile, useDesignable } from '../..'; import useServiceOptions, { useAssociationFieldContext } from './hooks'; const EMPTY = 'N/A'; @@ -25,30 +25,21 @@ const Cascade = connect((props) => { const { data, mapOptions, onChange } = props; const [selectedOptions, setSelectedOptions] = useState([]); const [options, setOptions] = useState(data); + const fieldSchema = useFieldSchema(); const [loading, setLoading] = useState(false); - const compile = useCompile(); const api = useAPIClient(); - const service = useServiceOptions(props); const { options: collectionField, field: associationField } = useAssociationFieldContext(); const resource = api.resource(collectionField.target); - const { getCollectionJoinField, getInterface } = useCollectionManager_deprecated(); const fieldNames = associationField?.componentProps?.fieldNames; - const FieldSchema = useFieldSchema(); - const targetField = - collectionField?.target && - fieldNames?.label && - getCollectionJoinField(`${collectionField.target}.${fieldNames.label}`); - const operator = useMemo(() => { - if (targetField?.interface) { - return getInterface(targetField.interface)?.filterable?.operators[0].value || '$includes'; - } - return '$includes'; - }, [targetField]); + const fieldFilter = fieldSchema['x-component-props']['service']['params']['filter']; const field: any = useField(); useEffect(() => { if (props.value) { const values = Array.isArray(props.value) - ? extractLastNonNullValueObjects(props.value?.filter((v) => v.value), true) + ? extractLastNonNullValueObjects( + props.value?.filter((v) => v.value), + true, + ) : transformNestedData(props.value); const defaultData = values?.map?.((v) => { return v.id; @@ -60,11 +51,9 @@ const Cascade = connect((props) => { const handleGetOptions = async () => { const response = await resource.list({ pageSize: 9999, - params: service?.params, - filter: mergeFilter([service?.params?.filter, filter]), + filter: mergeFilter([fieldFilter, filter]), tree: true, }); - return response?.data?.data; }; @@ -139,6 +128,9 @@ const Cascade = connect((props) => { defaultValue={selectedOptions} options={options} onChange={(value, option) => handleSelect(option)} + onDropdownVisibleChange={(visible) => { + onDropdownVisibleChange(visible); + }} changeOnSelect placeholder="Please select" /> @@ -218,6 +210,7 @@ export const InternalCascader = observer( ...props, style: { width: '100%' }, }, + 'x-read-pretty': 'false', }, remove: { type: 'void', diff --git a/packages/core/client/src/schema-component/antd/select/Select.tsx b/packages/core/client/src/schema-component/antd/select/Select.tsx index 3d9784817..35781655e 100644 --- a/packages/core/client/src/schema-component/antd/select/Select.tsx +++ b/packages/core/client/src/schema-component/antd/select/Select.tsx @@ -40,7 +40,6 @@ const ObjectSelect = (props: Props) => { } return currentOptions.shift(); }; - return ( Date: Wed, 13 Mar 2024 12:04:46 +0800 Subject: [PATCH 2/3] =?UTF-8?q?fix:=20=E4=BF=AE=E6=94=B9=E7=BA=A7=E8=81=94?= =?UTF-8?q?=E7=BB=84=E4=BB=B6=E9=80=82=E9=85=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cascaderComponentFieldSettings.tsx | 71 +++++++------------ .../association-field/InternalCascader.tsx | 7 +- 2 files changed, 31 insertions(+), 47 deletions(-) diff --git a/packages/core/client/src/modules/fields/component/Cascader/cascaderComponentFieldSettings.tsx b/packages/core/client/src/modules/fields/component/Cascader/cascaderComponentFieldSettings.tsx index cde650901..3aaf801bd 100644 --- a/packages/core/client/src/modules/fields/component/Cascader/cascaderComponentFieldSettings.tsx +++ b/packages/core/client/src/modules/fields/component/Cascader/cascaderComponentFieldSettings.tsx @@ -132,8 +132,21 @@ export const SchemaSettingsSortingRule = function SortRuleConfigure(props) { }); _.set(field.componentProps, 'service.params.sort', sortArr); props?.onSubmitCallBack?.(sortArr); - fieldSchema['x-component-props']['service']['params']['sort'] = field.componentProps?.service.params?.sort; + const service = fieldSchema['x-component-props']?.service; + if (service) { + service.params['sort'] = field.componentProps?.service.params?.sort; + } else { + fieldSchema['x-component-props']['service'] = { + params: { + sort: field.componentProps?.service.params?.sort, + }, + }; + } const componentProps = fieldSchema['x-component-props']; + const path = field.path?.splice(field.path?.length - 1, 1); + field.form.query(`${path.concat(`*.` + fieldSchema.name)}`).forEach((f) => { + f.componentProps = componentProps; + }); dn.emit('patch', { schema: { ['x-uid']: fieldSchema['x-uid'], @@ -206,45 +219,6 @@ const titleField: any = { }, }; -export const allowMultiple: any = { - name: 'allowMultiple', - type: 'switch', - useVisible() { - const isFieldReadPretty = useIsFieldReadPretty(); - const collectionField = useCollectionField(); - return !isFieldReadPretty && ['hasMany', 'belongsToMany'].includes(collectionField?.type); - }, - useComponentProps() { - const { t } = useTranslation(); - const field = useField(); - const { fieldSchema: tableColumnSchema } = useColumnSchema(); - const schema = useFieldSchema(); - const fieldSchema = tableColumnSchema || schema; - const { dn, refresh } = useDesignable(); - return { - title: t('Allow multiple'), - checked: - fieldSchema['x-component-props']?.multiple === undefined ? true : fieldSchema['x-component-props'].multiple, - onChange(value) { - const schema = { - ['x-uid']: fieldSchema['x-uid'], - }; - fieldSchema['x-component-props'] = fieldSchema['x-component-props'] || {}; - field.componentProps = field.componentProps || {}; - - fieldSchema['x-component-props'].multiple = value; - field.componentProps.multiple = value; - - schema['x-component-props'] = fieldSchema['x-component-props']; - dn.emit('patch', { - schema, - }); - refresh(); - }, - }; - }, -}; - const setDefaultSortingRules = { name: 'setDefaultSortingRules', Component: SchemaSettingsSortingRule, @@ -290,7 +264,16 @@ const setTheDataScope: any = { onSubmit: ({ filter }) => { filter = removeNullCondition(filter); _.set(field.componentProps, 'service.params.filter', filter); - fieldSchema['x-component-props']['service']['params']['filter'] = filter; + const service = fieldSchema['x-component-props']?.service; + if (service) { + service.params['filter'] = filter; + } else { + fieldSchema['x-component-props']['service'] = { + params: { + filter: { ...filter }, + }, + }; + } const componentProps = fieldSchema['x-component-props']; const path = field.path?.splice(field.path?.length - 1, 1); field.form.query(`${path.concat(`*.` + fieldSchema.name)}`).forEach((f) => { @@ -363,9 +346,8 @@ export const cascaderComponentFieldSettings = new SchemaSettings({ { ...setTheDataScope, useVisible() { - const isSelectFieldMode = useIsSelectFieldMode(); const isFieldReadPretty = useIsFieldReadPretty(); - return isSelectFieldMode && !isFieldReadPretty; + return !isFieldReadPretty; }, }, { @@ -377,9 +359,8 @@ export const cascaderComponentFieldSettings = new SchemaSettings({ }; }, useVisible() { - const isSelectFieldMode = useIsSelectFieldMode(); const isFieldReadPretty = useIsFieldReadPretty(); - return isSelectFieldMode && !isFieldReadPretty; + return !isFieldReadPretty; }, }, { diff --git a/packages/core/client/src/schema-component/antd/association-field/InternalCascader.tsx b/packages/core/client/src/schema-component/antd/association-field/InternalCascader.tsx index 4c106227a..4bb1ab11b 100644 --- a/packages/core/client/src/schema-component/antd/association-field/InternalCascader.tsx +++ b/packages/core/client/src/schema-component/antd/association-field/InternalCascader.tsx @@ -31,7 +31,8 @@ const Cascade = connect((props) => { const { options: collectionField, field: associationField } = useAssociationFieldContext(); const resource = api.resource(collectionField.target); const fieldNames = associationField?.componentProps?.fieldNames; - const fieldFilter = fieldSchema['x-component-props']['service']['params']['filter']; + const fieldFilter = fieldSchema['x-component-props']?.service?.params?.filter; + const sort = fieldSchema['x-component-props']?.service?.params?.sort; const field: any = useField(); useEffect(() => { if (props.value) { @@ -52,6 +53,7 @@ const Cascade = connect((props) => { const response = await resource.list({ pageSize: 9999, filter: mergeFilter([fieldFilter, filter]), + sort, tree: true, }); return response?.data?.data; @@ -210,7 +212,7 @@ export const InternalCascader = observer( ...props, style: { width: '100%' }, }, - 'x-read-pretty': 'false', + 'x-read-pretty': false, }, remove: { type: 'void', @@ -243,6 +245,7 @@ export const InternalCascader = observer( ...props, style: { width: '100%' }, }, + 'x-read-pretty': false, }} /> ) : ( From 7df5c093b01923e12b3a0222f96c628c8b252efe Mon Sep 17 00:00:00 2001 From: wjh Date: Wed, 13 Mar 2024 12:07:50 +0800 Subject: [PATCH 3/3] =?UTF-8?q?fix:=20=E4=BF=AE=E6=94=B9=E7=BA=A7=E8=81=94?= =?UTF-8?q?=E7=BB=84=E4=BB=B6=E9=80=82=E9=85=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../fields/component/Select/selectComponentFieldSettings.tsx | 1 - .../core/client/src/schema-component/antd/select/Select.tsx | 1 + .../src/client/schema-components/association-field/Editable.tsx | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/core/client/src/modules/fields/component/Select/selectComponentFieldSettings.tsx b/packages/core/client/src/modules/fields/component/Select/selectComponentFieldSettings.tsx index 876b0f833..f107afef3 100644 --- a/packages/core/client/src/modules/fields/component/Select/selectComponentFieldSettings.tsx +++ b/packages/core/client/src/modules/fields/component/Select/selectComponentFieldSettings.tsx @@ -116,7 +116,6 @@ const titleField: any = { dn.emit('patch', { schema, }); - dn.refresh(); }, }; diff --git a/packages/core/client/src/schema-component/antd/select/Select.tsx b/packages/core/client/src/schema-component/antd/select/Select.tsx index 35781655e..3d9784817 100644 --- a/packages/core/client/src/schema-component/antd/select/Select.tsx +++ b/packages/core/client/src/schema-component/antd/select/Select.tsx @@ -40,6 +40,7 @@ const ObjectSelect = (props: Props) => { } return currentOptions.shift(); }; + return (