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
This commit is contained in:
parent
7b892cec50
commit
71af0f16a9
@ -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) ? (
|
||||
<Tooltip title={t(titlePrompt)} placement="right" overlayInnerStyle={{ textAlign: 'center' }}>
|
||||
<Switch
|
||||
size="small"
|
||||
@ -201,7 +207,7 @@ const InheritFields = (props) => {
|
||||
});
|
||||
};
|
||||
|
||||
return expectTypes.includes(record.type) && !excludeInterfaces.includes(record.interface) ? (
|
||||
return isTitleField(record) ? (
|
||||
<Tooltip title={t(titlePrompt)} placement="right" overlayInnerStyle={{ textAlign: 'center' }}>
|
||||
<Switch
|
||||
size="small"
|
||||
|
@ -47,6 +47,11 @@ export const linkTo: IField = {
|
||||
},
|
||||
availableTypes: ['belongsToMany'],
|
||||
schemaInitialize(schema: ISchema, { readPretty, block, targetCollection }) {
|
||||
if (targetCollection?.titleField && schema['x-component-props']) {
|
||||
schema['x-component-props'].fieldNames = schema['x-component-props'].fieldNames || { value: 'id' };
|
||||
schema['x-component-props'].fieldNames.label = targetCollection.titleField;
|
||||
}
|
||||
|
||||
if (targetCollection?.template === 'file') {
|
||||
const fieldNames = schema['x-component-props']['fieldNames'] || { label: 'preview', value: 'id' };
|
||||
fieldNames.label = 'preview';
|
||||
|
@ -53,6 +53,11 @@ export const m2m: IField = {
|
||||
},
|
||||
availableTypes: ['belongsToMany'],
|
||||
schemaInitialize(schema: ISchema, { readPretty, block, targetCollection }) {
|
||||
if (targetCollection?.titleField && schema['x-component-props']) {
|
||||
schema['x-component-props'].fieldNames = schema['x-component-props'].fieldNames || { value: 'id' };
|
||||
schema['x-component-props'].fieldNames.label = targetCollection.titleField;
|
||||
}
|
||||
|
||||
if (targetCollection?.template === 'file') {
|
||||
const fieldNames = schema['x-component-props']['fieldNames'] || { label: 'preview', value: 'id' };
|
||||
fieldNames.label = 'preview';
|
||||
|
@ -52,6 +52,11 @@ export const m2o: IField = {
|
||||
},
|
||||
availableTypes:['belongsTo'],
|
||||
schemaInitialize(schema: ISchema, { block, readPretty, targetCollection }) {
|
||||
if (targetCollection?.titleField && schema['x-component-props']) {
|
||||
schema['x-component-props'].fieldNames = schema['x-component-props'].fieldNames || { value: 'id' };
|
||||
schema['x-component-props'].fieldNames.label = targetCollection.titleField;
|
||||
}
|
||||
|
||||
if (targetCollection?.template === 'file') {
|
||||
const fieldNames = schema['x-component-props']['fieldNames'] || { label: 'preview', value: 'id' };
|
||||
fieldNames.label = 'preview';
|
||||
|
@ -51,7 +51,12 @@ export const o2m: IField = {
|
||||
},
|
||||
},
|
||||
availableTypes: ['hasMany'],
|
||||
schemaInitialize(schema: ISchema, { field, block, readPretty }) {
|
||||
schemaInitialize(schema: ISchema, { field, block, readPretty, targetCollection }) {
|
||||
if (targetCollection?.titleField && schema['x-component-props']) {
|
||||
schema['x-component-props'].fieldNames = schema['x-component-props'].fieldNames || { value: 'id' };
|
||||
schema['x-component-props'].fieldNames.label = targetCollection.titleField;
|
||||
}
|
||||
|
||||
if (block === 'Form') {
|
||||
if (schema['x-component'] === 'TableField') {
|
||||
const association = `${field.collectionName}.${field.name}`;
|
||||
|
@ -475,6 +475,11 @@ export const obo: IField = {
|
||||
schema['x-component-props']['size'] = 'small';
|
||||
}
|
||||
|
||||
if (targetCollection?.titleField && schema['x-component-props']) {
|
||||
schema['x-component-props'].fieldNames = schema['x-component-props'].fieldNames || { value: 'id' };
|
||||
schema['x-component-props'].fieldNames.label = targetCollection.titleField;
|
||||
}
|
||||
|
||||
if (targetCollection?.template === 'file') {
|
||||
const fieldNames = schema['x-component-props']['fieldNames'] || { label: 'preview', value: 'id' };
|
||||
fieldNames.label = 'preview';
|
||||
|
@ -13,6 +13,7 @@ import {
|
||||
useCollectionManager,
|
||||
useSortFields,
|
||||
} from '../../../collection-manager';
|
||||
import { isTitleField } from '../../../collection-manager/Configuration/CollectionFields';
|
||||
import { GeneralSchemaDesigner, SchemaSettings } from '../../../schema-settings';
|
||||
import { useCompile, useDesignable, useFieldComponentOptions, useFieldTitle } from '../../hooks';
|
||||
import { removeNullCondition } from '../filter';
|
||||
@ -91,7 +92,7 @@ interface AssociationSelectInterface {
|
||||
|
||||
export const AssociationSelect = InternalAssociationSelect as unknown as AssociationSelectInterface;
|
||||
|
||||
AssociationSelect.Designer = () => {
|
||||
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();
|
||||
|
@ -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';
|
||||
|
@ -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<P = any> = SelectProps<P, any> & {
|
||||
wait?: number;
|
||||
manual?: boolean;
|
||||
mapOptions?: (data: any) => RemoteSelectProps['fieldNames'];
|
||||
targetField?: any;
|
||||
service: ResourceActionOptions<P>;
|
||||
};
|
||||
|
||||
@ -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 (
|
||||
<Tag key={index} color={option.color} style={{ marginRight: 3 }}>
|
||||
{option?.label || item}
|
||||
</Tag>
|
||||
);
|
||||
} else {
|
||||
return <Tag>{item}</Tag>;
|
||||
}
|
||||
})
|
||||
.reverse();
|
||||
} else {
|
||||
const item = targetField.uiSchema.enum.find((i) => i.value === label);
|
||||
if (item) {
|
||||
label = <Tag color={item.color}>{item.label}</Tag>;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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)}
|
||||
/>
|
||||
);
|
||||
},
|
||||
|
@ -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 (
|
||||
<SchemaComponent
|
||||
@ -83,16 +84,24 @@ export const FormDataTemplates = observer((props: any) => {
|
||||
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': [
|
||||
|
Loading…
Reference in New Issue
Block a user