From 71af0f16a9e55c17be581341c99e2710a1698bf6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=A2=AB=E9=9B=A8=E6=B0=B4=E8=BF=87=E6=BB=A4=E7=9A=84?= =?UTF-8?q?=E7=A9=BA=E6=B0=94-Rairn?= <958414905@qq.com> Date: Sat, 22 Apr 2023 11:04:10 +0800 Subject: [PATCH] fix: improve the display of the title field (#1741) * fix: fix the displaying problem of Select * fix: fix error * fix: filter out fields * feat: format date * feat: optimize * fix: fix error * feat: use the default title field * fix: fix bug --- .../Configuration/CollectionFields.tsx | 10 ++- .../collection-manager/interfaces/linkTo.ts | 5 ++ .../src/collection-manager/interfaces/m2m.tsx | 7 +- .../src/collection-manager/interfaces/m2o.tsx | 5 ++ .../src/collection-manager/interfaces/o2m.tsx | 7 +- .../src/collection-manager/interfaces/o2o.tsx | 5 ++ .../association-select/AssociationSelect.tsx | 8 +- .../antd/form-item/FormItem.tsx | 8 +- .../antd/remote-select/RemoteSelect.tsx | 77 +++++++++++++++++-- .../DataTemplates/FormDataTemplates.tsx | 27 ++++--- 10 files changed, 133 insertions(+), 26 deletions(-) diff --git a/packages/core/client/src/collection-manager/Configuration/CollectionFields.tsx b/packages/core/client/src/collection-manager/Configuration/CollectionFields.tsx index 87513f6e5..a8ceb5bc4 100644 --- a/packages/core/client/src/collection-manager/Configuration/CollectionFields.tsx +++ b/packages/core/client/src/collection-manager/Configuration/CollectionFields.tsx @@ -42,6 +42,12 @@ const titlePrompt = 'Default title for each record'; const expectTypes = ['string', 'integer', 'bigInt', 'float', 'double', 'decimal', 'date', 'dateonly', 'time']; const excludeInterfaces = ['icon']; +// 是否可以作为标题字段 +export const isTitleField = (field) => { + if (!field) return false; + return !field.isForeignKey && expectTypes.includes(field.type) && !excludeInterfaces.includes(field.interface); +}; + const CurrentFields = (props) => { const compile = useCompile(); const { getInterface } = useCollectionManager(); @@ -91,7 +97,7 @@ const CurrentFields = (props) => { }); }; - return expectTypes.includes(record.type) && !excludeInterfaces.includes(record.interface) ? ( + return isTitleField(record) ? ( { }); }; - return expectTypes.includes(record.type) && !excludeInterfaces.includes(record.interface) ? ( + return isTitleField(record) ? ( { +AssociationSelect.Designer = function Designer() { const { getCollectionFields, getInterface, getCollectionJoinField, getCollection } = useCollectionManager(); const { getField, template } = useCollection(); const { form } = useFormBlockContext(); @@ -99,7 +100,6 @@ AssociationSelect.Designer = () => { const fieldSchema = useFieldSchema(); const { t } = useTranslation(); const tk = useFilterByTk(); - const {} = useCollection(); const { dn, refresh, insertAdjacent } = useDesignable(); const compile = useCompile(); const collectionField = getField(fieldSchema['name']) || getCollectionJoinField(fieldSchema['x-collection-field']); @@ -134,7 +134,7 @@ AssociationSelect.Designer = () => { } const options = targetFields - .filter((field) => !field?.target && field.type !== 'boolean') + .filter((field) => isTitleField(field)) .map((field) => ({ value: field?.name, label: compile(field?.uiSchema?.title) || field?.name, @@ -691,7 +691,7 @@ AssociationSelect.Designer = () => { * 用于筛选表单区块 * @returns */ -AssociationSelect.FilterDesigner = () => { +AssociationSelect.FilterDesigner = function FilterDesigner() { const { getCollectionFields, getInterface, getCollectionJoinField } = useCollectionManager(); const { getField } = useCollection(); const { form } = useFormBlockContext(); diff --git a/packages/core/client/src/schema-component/antd/form-item/FormItem.tsx b/packages/core/client/src/schema-component/antd/form-item/FormItem.tsx index 4a2d954df..f15bdb99f 100644 --- a/packages/core/client/src/schema-component/antd/form-item/FormItem.tsx +++ b/packages/core/client/src/schema-component/antd/form-item/FormItem.tsx @@ -9,6 +9,7 @@ import { useTranslation } from 'react-i18next'; import { ACLCollectionFieldProvider } from '../../../acl/ACLProvider'; import { BlockRequestContext, useFilterByTk, useFormBlockContext } from '../../../block-provider'; import { Collection, useCollection, useCollectionManager } from '../../../collection-manager'; +import { isTitleField } from '../../../collection-manager/Configuration/CollectionFields'; import { GeneralSchemaDesigner, SchemaSettings } from '../../../schema-settings'; import { useCompile, useDesignable, useFieldComponentOptions } from '../../hooks'; import { BlockItem } from '../block-item'; @@ -70,7 +71,7 @@ export const FormItem: any = observer((props: any) => { ); }); -FormItem.Designer = () => { +FormItem.Designer = function Designer() { const { getCollectionFields, getInterface, getCollectionJoinField, getCollection } = useCollectionManager(); const { getField } = useCollection(); const tk = useFilterByTk(); @@ -97,11 +98,14 @@ FormItem.Designer = () => { initialValue['required'] = field.required; } const options = targetFields - .filter((field) => !field?.target && field.type !== 'boolean') + .filter((field) => { + return isTitleField(field); + }) .map((field) => ({ value: field?.name, label: compile(field?.uiSchema?.title) || field?.name, })); + let readOnlyMode = 'editable'; if (fieldSchema['x-disabled'] === true) { readOnlyMode = 'readonly'; diff --git a/packages/core/client/src/schema-component/antd/remote-select/RemoteSelect.tsx b/packages/core/client/src/schema-component/antd/remote-select/RemoteSelect.tsx index f5efee628..a30817e86 100644 --- a/packages/core/client/src/schema-component/antd/remote-select/RemoteSelect.tsx +++ b/packages/core/client/src/schema-component/antd/remote-select/RemoteSelect.tsx @@ -1,9 +1,11 @@ import { LoadingOutlined } from '@ant-design/icons'; -import { connect, mapProps, mapReadPretty } from '@formily/react'; -import { SelectProps } from 'antd'; +import { connect, mapProps, mapReadPretty, useFieldSchema } from '@formily/react'; +import { SelectProps, Tag } from 'antd'; +import moment from 'moment'; import React, { useCallback, useEffect, useMemo, useRef } from 'react'; import { ResourceActionOptions, useRequest } from '../../../api-client'; import { mergeFilter } from '../../../block-provider/SharedFilterProvider'; +import { useCollection, useCollectionManager } from '../../../collection-manager'; import { useCompile } from '../../hooks'; import { Select, defaultFieldNames } from '../select'; import { ReadPretty } from './ReadPretty'; @@ -15,6 +17,7 @@ export type RemoteSelectProps

= SelectProps & { wait?: number; manual?: boolean; mapOptions?: (data: any) => RemoteSelectProps['fieldNames']; + targetField?: any; service: ResourceActionOptions

; }; @@ -28,10 +31,73 @@ const InternalRemoteSelect = connect( objectValue, manual = true, mapOptions, + targetField: _targetField, ...others } = props; const compile = useCompile(); const firstRun = useRef(false); + const fieldSchema = useFieldSchema(); + const { getField } = useCollection(); + const { getCollectionJoinField } = useCollectionManager(); + const collectionField = getField(fieldSchema.name); + const targetField = + _targetField || + (collectionField?.target && + fieldNames?.label && + getCollectionJoinField(`${collectionField.target}.${fieldNames.label}`)); + + const mapOptionsToTags = useCallback( + (options) => { + try { + return options.map((option) => { + let label = option[fieldNames.label]; + + if (targetField?.uiSchema?.enum) { + if (Array.isArray(label)) { + label = label + .map((item, index) => { + const option = targetField.uiSchema.enum.find((i) => i.value === item); + if (option) { + return ( + + {option?.label || item} + + ); + } else { + return {item}; + } + }) + .reverse(); + } else { + const item = targetField.uiSchema.enum.find((i) => i.value === label); + if (item) { + label = {item.label}; + } + } + } + + if (targetField?.type === 'date') { + label = moment(label).format('YYYY-MM-DD'); + } + + if (mapOptions) { + return mapOptions({ + [fieldNames.label]: label, + [fieldNames.value]: option[fieldNames.value], + }); + } + return { + [fieldNames.label]: label || option[fieldNames.value], + [fieldNames.value]: option[fieldNames.value], + }; + }); + } catch (err) { + console.error(err); + return options; + } + }, + [targetField?.uiSchema, fieldNames], + ); const { data, run, loading } = useRequest( { @@ -82,11 +148,8 @@ const InternalRemoteSelect = connect( const getOptionsByFieldNames = useCallback( (item) => { - if (mapOptions) { - return mapOptions(item); - } return Object.keys(fieldNames).reduce((obj, key) => { - const value = item[fieldNames[key]]; + let value = item[fieldNames[key]]; if (value) { // support hidden, disabled, etc. obj[['label', 'value', 'options'].includes(key) ? fieldNames[key] : key] = @@ -138,7 +201,7 @@ const InternalRemoteSelect = connect( value={value} {...others} loading={loading} - options={options} + options={mapOptionsToTags(options)} /> ); }, diff --git a/packages/core/client/src/schema-settings/DataTemplates/FormDataTemplates.tsx b/packages/core/client/src/schema-settings/DataTemplates/FormDataTemplates.tsx index a740da360..5b449d084 100644 --- a/packages/core/client/src/schema-settings/DataTemplates/FormDataTemplates.tsx +++ b/packages/core/client/src/schema-settings/DataTemplates/FormDataTemplates.tsx @@ -21,9 +21,10 @@ export const FormDataTemplates = observer((props: any) => { const { useProps } = props; const { defaultValues, collectionName } = useProps(); const { collectionList, getEnableFieldTree } = useCollectionState(collectionName); - const { getCollection } = useCollectionManager(); + const { getCollection, getCollectionField } = useCollectionManager(); const collection = getCollection(collectionName); const { t } = useTranslation(); + const field = getCollectionField(`${collectionName}.${collection?.titleField || 'id'}`); return ( { multiple: false, objectValue: false, manual: false, - mapOptions: (item) => { - return { - ...item, - [collection.titleField || 'label']: `#${item.id} ${item[collection.titleField] || ''}`, - value: item.id, - }; + targetField: field, + mapOptions(option) { + try { + const label = collection?.titleField || 'id'; + option[label] = ( + <> + #{option.id} {option[label]} + + ); + return option; + } catch (error) { + console.error(error); + return option; + } }, fieldNames: { - label: collection.titleField || 'label', - value: 'value', + label: collection?.titleField || 'id', + value: 'id', }, }, 'x-reactions': [