fix: 修改级联组件适配
This commit is contained in:
parent
847a1fae9a
commit
e03e68232e
@ -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 (
|
||||
<SchemaSettingsModalItem
|
||||
title={t('Set default sorting rules')}
|
||||
components={{ ArrayItems }}
|
||||
schema={
|
||||
{
|
||||
type: 'object',
|
||||
title: t('Set default sorting rules'),
|
||||
properties: {
|
||||
sort: {
|
||||
type: 'array',
|
||||
default: sort,
|
||||
'x-component': 'ArrayItems',
|
||||
'x-decorator': 'FormItem',
|
||||
items: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
space: {
|
||||
type: 'void',
|
||||
'x-component': 'Space',
|
||||
properties: {
|
||||
sort: {
|
||||
type: 'void',
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'ArrayItems.SortHandle',
|
||||
},
|
||||
field: {
|
||||
type: 'string',
|
||||
enum: sortFields,
|
||||
required: true,
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Select',
|
||||
'x-component-props': {
|
||||
style: {
|
||||
width: 260,
|
||||
},
|
||||
},
|
||||
},
|
||||
direction: {
|
||||
type: 'string',
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Radio.Group',
|
||||
'x-component-props': {
|
||||
optionType: 'button',
|
||||
},
|
||||
enum: [
|
||||
{
|
||||
label: t('ASC'),
|
||||
value: 'asc',
|
||||
},
|
||||
{
|
||||
label: t('DESC'),
|
||||
value: 'desc',
|
||||
},
|
||||
],
|
||||
},
|
||||
remove: {
|
||||
type: 'void',
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'ArrayItems.Remove',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
properties: {
|
||||
add: {
|
||||
type: 'void',
|
||||
title: t('Add sort field'),
|
||||
'x-component': 'ArrayItems.Addition',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
} as ISchema
|
||||
}
|
||||
onSubmit={({ sort }) => {
|
||||
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<Field>();
|
||||
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<Field>();
|
||||
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 (
|
||||
<VariableInput
|
||||
{...props}
|
||||
form={form}
|
||||
collectionField={props.collectionField}
|
||||
record={record}
|
||||
shouldChange={getShouldChange({
|
||||
collectionField: props.collectionField,
|
||||
variables,
|
||||
localVariables,
|
||||
getAllCollectionsInheritChain,
|
||||
})}
|
||||
/>
|
||||
);
|
||||
},
|
||||
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<Field>();
|
||||
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,
|
||||
},
|
||||
],
|
||||
});
|
@ -116,6 +116,7 @@ const titleField: any = {
|
||||
dn.emit('patch', {
|
||||
schema,
|
||||
});
|
||||
|
||||
dn.refresh();
|
||||
},
|
||||
};
|
||||
|
@ -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<any>();
|
||||
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',
|
||||
|
@ -40,7 +40,6 @@ const ObjectSelect = (props: Props) => {
|
||||
}
|
||||
return currentOptions.shift();
|
||||
};
|
||||
|
||||
return (
|
||||
<AntdSelect
|
||||
// @ts-ignore
|
||||
|
@ -33,6 +33,7 @@ import { filterFormBlockSettings } from '../modules/blocks/filter-blocks/form/fi
|
||||
import { filterFormItemFieldSettings } from '../modules/blocks/filter-blocks/form/filterFormItemFieldSettings';
|
||||
import { markdownBlockSettings } from '../modules/blocks/other-blocks/markdown/markdownBlockSettings';
|
||||
import { cascadeSelectComponentFieldSettings } from '../modules/fields/component/CascadeSelect/cascadeSelectComponentFieldSettings';
|
||||
import { cascaderComponentFieldSettings } from '../modules/fields/component/Cascader/cascaderComponentFieldSettings';
|
||||
import { datePickerComponentFieldSettings } from '../modules/fields/component/DatePicker/datePickerComponentFieldSettings';
|
||||
import { fileManagerComponentFieldSettings } from '../modules/fields/component/FileManager/fileManagerComponentFieldSettings';
|
||||
import { uploadAttachmentComponentFieldSettings } from '../modules/fields/component/FileManager/uploadAttachmentComponentFieldSettings';
|
||||
@ -94,5 +95,6 @@ export class SchemaSettingsPlugin extends Plugin {
|
||||
this.schemaSettingsManager.add(tagComponentFieldSettings);
|
||||
this.schemaSettingsManager.add(cascadeSelectComponentFieldSettings);
|
||||
this.schemaSettingsManager.add(uploadAttachmentComponentFieldSettings);
|
||||
this.schemaSettingsManager.add(cascaderComponentFieldSettings);
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { Field } from '@formily/core';
|
||||
import { connect, mapReadPretty, observer, useField, useForm } from '@formily/react';
|
||||
import { connect, mapReadPretty, observer, useField, useFieldSchema, useForm } from '@formily/react';
|
||||
import React from 'react';
|
||||
import {
|
||||
SchemaComponentOptions,
|
||||
|
Loading…
Reference in New Issue
Block a user