feat: 子表格新增快速添加功能 (#1122)

Co-authored-by: sealday <zhanglin@daoyoucloud.com>
Reviewed-on: daoyoucloud/tachybase#1122
Reviewed-by: sealday <zhanglin@daoyoucloud.com>
Co-authored-by: wjh <wwwjh0710@163.com>
Co-committed-by: wjh <wwwjh0710@163.com>
This commit is contained in:
wjh 2024-06-05 14:39:54 +08:00 committed by sealday
parent d0a4615ef7
commit 019a42b0ed
8 changed files with 703 additions and 10 deletions

View File

@ -830,5 +830,6 @@
"Designer properties": "Designer properties", "Designer properties": "Designer properties",
"Load": "Load", "Load": "Load",
"Dump": "Dump", "Dump": "Dump",
"Chang on Parent":"Chang on Parent" "Chang on Parent":"Chang on Parent",
"Please enter search content":"Please enter search content"
} }

View File

@ -933,5 +933,6 @@
"Dump": "存储", "Dump": "存储",
"Sorry, the page you visited does not exist.": "对不起,您访问的页面不存在。", "Sorry, the page you visited does not exist.": "对不起,您访问的页面不存在。",
"Back Home": "回到主页", "Back Home": "回到主页",
"Chang on Parent": "选择父级" "Chang on Parent": "选择父级",
"Please enter search content":"请输入查询内容"
} }

View File

@ -1,3 +1,4 @@
import { useCollectionManager } from '@tachybase/client';
import { ArrayItems } from '@tachybase/components'; import { ArrayItems } from '@tachybase/components';
import { Field, ISchema, useField, useFieldSchema } from '@tachybase/schema'; import { Field, ISchema, useField, useFieldSchema } from '@tachybase/schema';
@ -6,7 +7,7 @@ import { useTranslation } from 'react-i18next';
import { SchemaSettings } from '../../../../application/schema-settings/SchemaSettings'; import { SchemaSettings } from '../../../../application/schema-settings/SchemaSettings';
import { useCollectionManager_deprecated, useSortFields } from '../../../../collection-manager'; import { useCollectionManager_deprecated, useSortFields } from '../../../../collection-manager';
import { useFieldComponentName } from '../../../../common/useFieldComponentName'; import { useFieldComponentName } from '../../../../common/useFieldComponentName';
import { useDesignable, useFieldModeOptions, useIsAddNewForm } from '../../../../schema-component'; import { useCompile, useDesignable, useFieldModeOptions, useIsAddNewForm } from '../../../../schema-component';
import { isSubMode } from '../../../../schema-component/antd/association-field/util'; import { isSubMode } from '../../../../schema-component/antd/association-field/util';
import { useIsAssociationField, useIsFieldReadPretty } from '../../../../schema-component/antd/form-item'; import { useIsAssociationField, useIsFieldReadPretty } from '../../../../schema-component/antd/form-item';
@ -242,7 +243,188 @@ export const allowAddNewData = {
}, },
}; };
export const isQuickAddTabs = {
name: 'isquickaddtabs',
type: 'switch',
useVisible() {
const readPretty = useIsFieldReadPretty();
const isAssociationField = useIsAssociationField();
return !readPretty && isAssociationField;
},
useComponentProps() {
const { t } = useTranslation();
const field = useField<Field>();
const fieldSchema = useFieldSchema();
const { dn, refresh } = useDesignable();
return {
title: t('Is Quick Add Tabs'),
checked: fieldSchema['x-component-props']?.isQuickAdd || false,
onChange(value) {
const schema = {
['x-uid']: fieldSchema['x-uid'],
};
field.componentProps['isQuickAdd'] = value;
fieldSchema['x-component-props'] = fieldSchema['x-component-props'] || {};
fieldSchema['x-component-props']['isQuickAdd'] = value;
schema['x-component-props'] = fieldSchema['x-component-props'];
dn.emit('patch', {
schema,
});
refresh();
},
};
},
};
export const setQuickAddTabs = {
name: 'setquickaddtabs',
type: 'select',
useComponentProps() {
const { t } = useTranslation();
const field = useField<Field>();
const compile = useCompile();
const fieldSchema = useFieldSchema();
const cm = useCollectionManager();
const options = cm.getCollection(fieldSchema['x-collection-field']);
const defVal = fieldSchema['x-component-props']['quickAddField'] || 'none';
const { dn } = useDesignable();
const isAddNewForm = useIsAddNewForm();
const fieldTabsOptions = options.fields
.map((item) => {
if (item.interface === 'm2o' || item.interface === 'select') {
return {
...item,
label: compile(item.uiSchema?.title),
value: item.name,
};
}
})
.filter(Boolean);
fieldTabsOptions.unshift({
label: 'none',
value: 'none',
});
return {
title: t('Set Quick Add Tabs'),
options: fieldTabsOptions,
value: defVal,
onChange(mode) {
const schema = {
['x-uid']: fieldSchema['x-uid'],
};
fieldSchema['x-component-props'] = fieldSchema['x-component-props'] || {};
fieldSchema['x-component-props']['quickAddField'] = {
fieldInterface: fieldTabsOptions.find((item) => item.value === mode)['interface'] || 'none',
value: mode,
};
schema['x-component-props'] = fieldSchema['x-component-props'];
field.componentProps = field.componentProps || {};
field.componentProps['quickAddField'] = fieldSchema['x-component-props']['quickAddField'];
// 子表单状态不允许设置默认值
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();
},
};
},
useVisible() {
const fieldSchema = useFieldSchema();
return fieldSchema['x-component-props']['isQuickAdd'];
},
};
export const setQuickAddParentTabs = {
name: 'setquickaddparenttabs',
type: 'select',
useComponentProps() {
const { t } = useTranslation();
const field = useField<Field>();
const compile = useCompile();
const fieldSchema = useFieldSchema();
const cm = useCollectionManager();
const { value: quickField } = fieldSchema['x-component-props']?.['quickAddField'] || {};
const options = cm.getCollectionFields(`${fieldSchema['x-collection-field']}.${quickField}`);
const { dn } = useDesignable();
const isAddNewForm = useIsAddNewForm();
const fieldTabsOptions = options
.map((item) => {
if (item.interface === 'm2o')
return {
...item,
label: compile(item.uiSchema.title),
value: item.name,
};
})
.filter(Boolean);
fieldTabsOptions.unshift({
label: t('none'),
value: 'none',
});
const defValue = fieldSchema['x-component-props']?.['quickAddParentCollection']?.value || 'none';
return {
title: t('Set Quick Add Parent Tabs'),
options: fieldTabsOptions,
value: defValue,
onChange(mode) {
const schema = {
['x-uid']: fieldSchema['x-uid'],
};
fieldSchema['x-component-props'] = fieldSchema['x-component-props'] || {};
fieldSchema['x-component-props']['quickAddParentCollection'] = {
collectionField: `${fieldSchema['x-collection-field']}.${quickField}.${mode}`,
value: mode,
};
schema['x-component-props'] = fieldSchema['x-component-props'];
field.componentProps = field.componentProps || {};
field.componentProps['quickAddParentCollection'] = {
collectionField: `${fieldSchema['x-collection-field']}.${quickField}.${mode}`,
value: 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();
},
};
},
useVisible() {
const fieldSchema = useFieldSchema();
return (
fieldSchema['x-component-props']['isQuickAdd'] &&
fieldSchema['x-component-props']['quickAddField'] &&
fieldSchema['x-component-props']['quickAddField'] !== 'none'
);
},
};
export const subTablePopoverComponentFieldSettings = new SchemaSettings({ export const subTablePopoverComponentFieldSettings = new SchemaSettings({
name: 'fieldSettings:component:SubTable', name: 'fieldSettings:component:SubTable',
items: [fieldComponent, allowAddNewData, allowSelectExistingRecord, setDefaultSortingRules], items: [
fieldComponent,
allowAddNewData,
allowSelectExistingRecord,
setDefaultSortingRules,
isQuickAddTabs,
setQuickAddTabs,
setQuickAddParentTabs,
],
}); });

View File

@ -1,4 +1,4 @@
import React, { useContext, useMemo, useState } from 'react'; import React, { useContext, useEffect, useMemo, useState } from 'react';
import { import {
action, action,
ArrayField, ArrayField,
@ -7,11 +7,13 @@ import {
observer, observer,
RecursionField, RecursionField,
useFieldSchema, useFieldSchema,
useForm,
} from '@tachybase/schema'; } from '@tachybase/schema';
import { Button } from 'antd'; import { useAsyncEffect } from 'ahooks';
import { Button, Tabs } from 'antd';
import { createStyles } from 'antd-style'; import { createStyles } from 'antd-style';
import { unionBy, uniqBy } from 'lodash'; import { set, unionBy, uniqBy } from 'lodash';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { import {
@ -21,11 +23,12 @@ import {
SchemaComponentOptions, SchemaComponentOptions,
useActionContext, useActionContext,
} from '../..'; } from '../..';
import { useAPIClient, useRequest } from '../../../api-client';
import { useCreateActionProps } from '../../../block-provider/hooks'; import { useCreateActionProps } from '../../../block-provider/hooks';
import { FormActiveFieldsProvider } from '../../../block-provider/hooks/useFormActiveFields'; import { FormActiveFieldsProvider } from '../../../block-provider/hooks/useFormActiveFields';
import { TableSelectorParamsProvider } from '../../../block-provider/TableSelectorProvider'; import { TableSelectorParamsProvider } from '../../../block-provider/TableSelectorProvider';
import { CollectionProvider_deprecated } from '../../../collection-manager'; import { CollectionProvider_deprecated } from '../../../collection-manager';
import { CollectionRecordProvider, useCollectionRecord } from '../../../data-source'; import { CollectionRecordProvider, useCollectionManager, useCollectionRecord } from '../../../data-source';
import { markRecordAsNew } from '../../../data-source/collection-record/isNewRecord'; import { markRecordAsNew } from '../../../data-source/collection-record/isNewRecord';
import { FlagProvider } from '../../../flag-provider'; import { FlagProvider } from '../../../flag-provider';
import { useCompile } from '../../hooks'; import { useCompile } from '../../hooks';
@ -33,6 +36,7 @@ import { ActionContextProvider } from '../action';
import { Table } from '../table-v2/Table'; import { Table } from '../table-v2/Table';
import { useAssociationFieldContext, useFieldNames } from './hooks'; import { useAssociationFieldContext, useFieldNames } from './hooks';
import { useTableSelectorProps } from './InternalPicker'; import { useTableSelectorProps } from './InternalPicker';
import { InternalTabs } from './SubTabs/InternamTabs';
import { getLabelFormatValue, useLabelUiSchema } from './util'; import { getLabelFormatValue, useLabelUiSchema } from './util';
const useStyles = createStyles(({ css }) => { const useStyles = createStyles(({ css }) => {
@ -106,7 +110,7 @@ export const SubTable: any = observer(
const compile = useCompile(); const compile = useCompile();
const labelUiSchema = useLabelUiSchema(collectionField, fieldNames?.label || 'label'); const labelUiSchema = useLabelUiSchema(collectionField, fieldNames?.label || 'label');
const recordV2 = useCollectionRecord(); const recordV2 = useCollectionRecord();
const [fieldValue, setFieldValue] = useState([]);
const move = (fromIndex: number, toIndex: number) => { const move = (fromIndex: number, toIndex: number) => {
if (toIndex === undefined) return; if (toIndex === undefined) return;
if (!isArr(field.value)) return; if (!isArr(field.value)) return;
@ -122,6 +126,7 @@ export const SubTable: any = observer(
return field.onInput(field.value); return field.onInput(field.value);
}); });
}; };
field.move = move; field.move = move;
const options = useMemo(() => { const options = useMemo(() => {
@ -172,11 +177,17 @@ export const SubTable: any = observer(
const filter = list.length ? { $and: [{ [`${targetKey}.$ne`]: list }] } : {}; const filter = list.length ? { $and: [{ [`${targetKey}.$ne`]: list }] } : {};
return filter; return filter;
}; };
const tabsProps = {
...props,
fieldValue,
setFieldValue,
};
return ( return (
<div className={styles.container}> <div className={styles.container}>
<FlagProvider isInSubTable> <FlagProvider isInSubTable>
<CollectionRecordProvider record={null} parentRecord={recordV2}> <CollectionRecordProvider record={null} parentRecord={recordV2}>
<FormActiveFieldsProvider name="nester"> <FormActiveFieldsProvider name="nester">
<InternalTabs {...tabsProps} />
<Table <Table
className={styles.table} className={styles.table}
bordered bordered
@ -185,6 +196,7 @@ export const SubTable: any = observer(
showIndex showIndex
dragSort={field.editable} dragSort={field.editable}
showDel={field.editable} showDel={field.editable}
setFieldValue={setFieldValue}
pagination={!!field.componentProps.pagination} pagination={!!field.componentProps.pagination}
rowSelection={{ type: 'none', hideSelectAll: true }} rowSelection={{ type: 'none', hideSelectAll: true }}
footer={() => footer={() =>
@ -198,6 +210,7 @@ export const SubTable: any = observer(
onClick={() => { onClick={() => {
field.value = field.value || []; field.value = field.value || [];
field.value.push(markRecordAsNew({})); field.value.push(markRecordAsNew({}));
setFieldValue([...field.value]);
}} }}
> >
{t('Add new')} {t('Add new')}

View File

@ -0,0 +1,265 @@
import React, { useEffect, useState } from 'react';
import { ArrayField, observer, onFieldChange, Schema, useFieldSchema, useFormEffects } from '@tachybase/schema';
import { CheckOutlined, CheckSquareOutlined, SearchOutlined } from '@ant-design/icons';
import { useAsyncEffect, useDeepCompareEffect } from 'ahooks';
import { Badge, Button, Input, Space, Tabs } from 'antd';
import flat from 'flat';
import { useTranslation } from 'react-i18next';
import { useAPIClient } from '../../../../api-client';
import { useCollectionManager } from '../../../../data-source';
import { markRecordAsNew } from '../../../../data-source/collection-record/isNewRecord';
import { useAssociationFieldContext } from '../hooks';
import { useFieldServiceFilter } from './hook';
export const InternalTabs = observer((props) => {
const { fieldValue, setFieldValue } = props as any;
const fieldSchema = useFieldSchema();
const cm = useCollectionManager();
const api = useAPIClient();
const isQuickAdd = fieldSchema['parent']['x-component-props']['isQuickAdd'];
const { value: quickAddField, fieldInterface } = fieldSchema['parent']['x-component-props']?.['quickAddField'] || {};
const quickAddParentField = fieldSchema['parent']['x-component-props']['quickAddParentCollection'];
const [options, setOptions] = useState([]);
const [defOptions, setDefOptions] = useState([]);
const { field, options: collectionField } = useAssociationFieldContext<ArrayField>();
const { t } = useTranslation();
const [changeForm, setChangeForm] = useState<any>();
const tableSchema = fieldSchema.reduceProperties((buf, schema) => {
const found = schema.reduceProperties(
(buf, schema) => {
if (schema.name === quickAddField) {
return schema;
}
return buf;
},
new Schema({ name: 'not-found' }),
);
if (found.name === quickAddField) {
return found;
}
return buf;
}, new Schema({}));
const tabparams = tableSchema['x-component-props']?.['service']?.['params'];
const [fieldServiceFilter, setFieldServiceFilter] = useFieldServiceFilter(tabparams?.filter);
const formFilter = flat(tabparams?.filter || {});
const formFieldFilter = Object.values(formFilter)
?.map((item) => {
const field = item as String;
const match = field.match(/^{{\$nForm\.(.*?)\./);
if (match) return match[1];
})
.filter(Boolean);
useAsyncEffect(async () => {
const itemParams = {};
const optionsItem = [];
if (tabparams?.filter && !fieldServiceFilter) return;
if ((quickAddField || quickAddField !== 'none' || !isQuickAdd) && fieldSchema.properties) {
const params = { pageSize: 99999, filter: JSON.stringify(fieldServiceFilter) };
if (quickAddParentField && quickAddParentField?.value !== 'none') {
params['appends'] = [quickAddParentField.value];
const collection = cm.getCollection(quickAddParentField.collectionField);
const parentItem = await api.request({
url: collection.name + ':list',
params: { pageSize: 9999 },
});
itemParams['parentTitleField'] = collection.titleField;
itemParams['parentOptions'] = parentItem?.data?.data;
}
if (tableSchema && fieldInterface === 'm2o') {
itemParams['service'] = tableSchema['x-component-props'].service;
itemParams['collectionName'] = cm.getCollection(tableSchema['x-collection-field']).name;
const childrenItem = await api.request({
url: itemParams['collectionName'] + ':list',
params,
});
itemParams['childrenTitleField'] = cm.getCollection(itemParams['collectionName']).titleField;
itemParams['childrenOptions'] = childrenItem?.data?.data;
if (itemParams['parentOptions']?.length && itemParams['childrenOptions']?.length) {
itemParams['parentOptions'].forEach((parentItem) => {
const items = itemParams['childrenOptions']
.map((item) => {
if (item[quickAddParentField?.value]?.id === parentItem.id) {
return {
...item,
label: item[itemParams['childrenTitleField']],
keys: item.id,
value: item.id,
checked: false,
};
}
})
.filter(Boolean);
if (!items.length) return;
optionsItem.push({
...parentItem,
value: parentItem?.id,
label: parentItem[itemParams['parentTitleField']],
key: parentItem.id,
childrenItems: items,
});
});
} else if (
itemParams['childrenOptions']?.length &&
(!quickAddParentField || quickAddParentField?.value === 'none')
) {
itemParams['childrenOptions'].forEach((item) => {
optionsItem.push({
...item,
label: item[itemParams['childrenTitleField']],
value: item?.id,
key: item?.id,
checked: false,
});
});
}
setOptions(optionsItem);
setDefOptions(optionsItem);
} else if (tableSchema) {
const fieldItem = cm.getCollectionField(tableSchema['x-collection-field']);
if (!fieldItem?.uiSchema || !fieldItem?.uiSchema.enum) return;
fieldItem.uiSchema.enum.forEach((item) => {
optionsItem.push(item);
});
setOptions(optionsItem);
setDefOptions(optionsItem);
}
}
}, [fieldServiceFilter, fieldSchema, changeForm]);
useDeepCompareEffect(() => {
if (!defOptions.length) return;
const fieldTabs = field.value;
if (quickAddParentField && quickAddParentField?.value !== 'none') {
const filterParantOptions = tabsParantFilterOptions(defOptions, fieldTabs, quickAddField);
const filterOptions = tabsParantFilterOptions(options, fieldTabs, quickAddField);
setDefOptions(filterParantOptions);
setOptions(filterOptions);
} else {
const filterDefOptions = tabsFilterOptions(options, fieldTabs, quickAddField);
setDefOptions(filterDefOptions);
const filterOptions = tabsFilterOptions(options, fieldTabs, quickAddField);
setOptions(filterOptions);
}
}, [quickAddField, fieldValue]);
useFormEffects(() => {
onFieldChange(formFieldFilter, (field) => {
setChangeForm(field);
});
});
const onSelect = (value) => {
if (quickAddParentField && quickAddParentField.value !== 'none') {
const filterOption = defOptions
.map((item) => {
const filterItem = item?.childrenItems?.filter((childrenItem) => childrenItem?.label?.includes(value));
if (item?.label?.includes(value) || filterItem.length) {
return {
...item,
childrenItems: filterItem.length ? filterItem : item.childrenItems,
};
}
})
.filter(Boolean);
setOptions(filterOption);
} else {
const filterOption = defOptions.filter((item) => item?.label?.includes(value));
setOptions(filterOption);
}
};
const onChange = (item) => {
field.value = field.value || [];
const addItem = {};
addItem[quickAddField] = item;
field.value.push(markRecordAsNew(addItem));
setFieldValue([...field.value]);
};
return isQuickAdd && quickAddField && quickAddField !== 'none' ? (
<div>
<Input
placeholder={t('Please enter search content')}
prefix={<SearchOutlined />}
onChange={(e) => {
onSelect(e.target.value);
}}
/>
{quickAddParentField && quickAddParentField?.value !== 'none' ? (
<>
{options.length ? (
<Tabs
tabPosition="left"
items={options.map((item) => ({
...item,
children: (
<Space>
{item?.childrenItems?.map((childrenitem, index) => (
<Button
key={index}
onClick={() => {
onChange(childrenitem);
}}
icon={childrenitem.checked ? <CheckOutlined /> : null}
>
{childrenitem.label}
</Button>
))}
</Space>
),
}))}
style={{ height: '30vh', overflow: 'auto', padding: '10px' }}
></Tabs>
) : null}
</>
) : (
<Space style={{ height: '30vh', overflow: 'auto', padding: '10px' }}>
{options.map((item, index) => (
<Button
key={index}
onClick={() => {
onChange(item);
}}
icon={item.checked ? <CheckOutlined /> : null}
>
{item.label}
</Button>
))}
</Space>
)}
</div>
) : null;
});
const tabsParantFilterOptions = (options, fieldTabs, arrayField) => {
const filterOptions = options?.map((oItem) => {
const filterItem = oItem.childrenItems.map((childrenItem) => {
const fieldTabsValue = fieldTabs.find((item) => item[arrayField]?.value === childrenItem.value);
return {
...childrenItem,
checked: fieldTabsValue ? true : false,
};
});
return {
...oItem,
childrenItems: filterItem,
};
});
return filterOptions;
};
const tabsFilterOptions = (optitons, filterTabs, arrayField) => {
const filterOptions = optitons.map((item) => {
const filterValue = filterTabs.find((filterTabsItem) => filterTabsItem[arrayField]?.value === item.value);
return {
...item,
checked: filterValue ? true : false,
};
});
return filterOptions;
};

View File

@ -0,0 +1,58 @@
import { useEffect, useState } from 'react';
import { DEBOUNCE_WAIT, isVariable, mergeFilter, useParseDataScopeFilter } from '@tachybase/client';
import { reaction } from '@tachybase/schema';
import { flatten, getValuesByPath } from '@tachybase/utils/client';
import _ from 'lodash';
import { getPath } from '../../../../variables/utils/getPath';
import { getVariableName } from '../../../../variables/utils/getVariableName';
export const useFieldServiceFilter = (filter, originalFilter?) => {
const [fieldServiceFilter, setFieldServiceFilter] = useState(null);
const { parseFilter, findVariable } = useParseDataScopeFilter();
useEffect(() => {
const filterFromSchema = filter;
const _run = async () => {
const result = await parseFilter(mergeFilter([filterFromSchema || originalFilter]));
setFieldServiceFilter(result);
};
const run = _.debounce(_run, DEBOUNCE_WAIT);
_run();
const dispose = reaction(() => {
// 这一步主要是为了使 reaction 能够收集到依赖
const flat = flatten(filterFromSchema, {
breakOn({ key }) {
return key.startsWith('$') && key !== '$and' && key !== '$or';
},
transformValue(value) {
if (!isVariable(value)) {
return value;
}
const variableName = getVariableName(value);
const variable = findVariable(variableName);
if (process.env.NODE_ENV !== 'production' && !variable) {
throw new Error(`useServiceOptions: can not find variable ${variableName}`);
}
const result = getValuesByPath(
{
[variableName]: variable?.ctx || {},
},
getPath(value),
);
return result;
},
});
return flat;
}, run);
return dispose;
}, [filter, findVariable, originalFilter, parseFilter]);
return [fieldServiceFilter, setFieldServiceFilter];
};

View File

@ -13,6 +13,7 @@ import {
useCollectionField_deprecated, useCollectionField_deprecated,
useCollectionManager_deprecated, useCollectionManager_deprecated,
} from '../../../collection-manager'; } from '../../../collection-manager';
import { useCollection, useCollectionManager } from '../../../data-source';
import { useRecord } from '../../../record-provider'; import { useRecord } from '../../../record-provider';
import { useColumnSchema } from '../../../schema-component/antd/table-v2/Table.Column.Decorator'; import { useColumnSchema } from '../../../schema-component/antd/table-v2/Table.Column.Decorator';
import { generalSettingsItems } from '../../../schema-items/GeneralSettings'; import { generalSettingsItems } from '../../../schema-items/GeneralSettings';
@ -305,6 +306,177 @@ export const formItemSettings = new SchemaSettings({
return form && !isFormReadPretty && validateSchema; return form && !isFormReadPretty && validateSchema;
}, },
}, },
{
name: 'isquickaddtabs',
type: 'switch',
useVisible() {
const readPretty = useIsFieldReadPretty();
const isAssociationField = useIsAssociationField();
const fieldMode = useFieldMode();
return !readPretty && isAssociationField && ['SubTable'].includes(fieldMode);
},
useComponentProps() {
const { t } = useTranslation();
const field = useField<Field>();
const fieldSchema = useFieldSchema();
const { dn, refresh } = useDesignable();
return {
title: t('Is Quick Add Tabs'),
checked: fieldSchema['x-component-props']?.isQuickAdd || false,
onChange(value) {
const schema = {
['x-uid']: fieldSchema['x-uid'],
};
field.componentProps['isQuickAdd'] = value;
fieldSchema['x-component-props'] = fieldSchema['x-component-props'] || {};
fieldSchema['x-component-props']['isQuickAdd'] = value;
schema['x-component-props'] = fieldSchema['x-component-props'];
dn.emit('patch', {
schema,
});
refresh();
},
};
},
},
{
name: 'setquickaddtabs',
type: 'select',
useComponentProps() {
const { t } = useTranslation();
const field = useField<Field>();
const compile = useCompile();
const fieldSchema = useFieldSchema();
const cm = useCollectionManager();
const options = cm.getCollection(fieldSchema['x-collection-field']);
const defVal = fieldSchema['x-component-props']['quickAddField'] || 'none';
const { dn } = useDesignable();
const isAddNewForm = useIsAddNewForm();
const fieldTabsOptions = options.fields
.map((item) => {
if (item.interface === 'm2o' || item.interface === 'select') {
return {
...item,
label: compile(item.uiSchema?.title),
value: item.name,
};
}
})
.filter(Boolean);
fieldTabsOptions.unshift({
label: 'none',
value: 'none',
});
return {
title: t('Set Quick Add Tabs'),
options: fieldTabsOptions,
value: defVal,
onChange(mode) {
const schema = {
['x-uid']: fieldSchema['x-uid'],
};
fieldSchema['x-component-props'] = fieldSchema['x-component-props'] || {};
fieldSchema['x-component-props']['quickAddField'] = {
fieldInterface: fieldTabsOptions.find((item) => item.value === mode)['interface'] || 'none',
value: mode,
};
schema['x-component-props'] = fieldSchema['x-component-props'];
field.componentProps = field.componentProps || {};
field.componentProps['quickAddField'] = fieldSchema['x-component-props']['quickAddField'];
// 子表单状态不允许设置默认值
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();
},
};
},
useVisible() {
const fieldSchema = useFieldSchema();
return fieldSchema['x-component-props']['isQuickAdd'];
},
},
{
name: 'setquickaddparenttabs',
type: 'select',
useComponentProps() {
const { t } = useTranslation();
const field = useField<Field>();
const compile = useCompile();
const fieldSchema = useFieldSchema();
const cm = useCollectionManager();
const { value: quickField } = fieldSchema['x-component-props']?.['quickAddField'] || {};
const options = cm.getCollectionFields(`${fieldSchema['x-collection-field']}.${quickField}`);
const { dn } = useDesignable();
const isAddNewForm = useIsAddNewForm();
const fieldTabsOptions = options
.map((item) => {
if (item.interface === 'm2o')
return {
...item,
label: compile(item.uiSchema.title),
value: item.name,
};
})
.filter(Boolean);
fieldTabsOptions.unshift({
label: t('none'),
value: 'none',
});
const defValue = fieldSchema['x-component-props']?.['quickAddParentCollection']?.value || 'none';
return {
title: t('Set Quick Add Parent Tabs'),
options: fieldTabsOptions,
value: defValue,
onChange(mode) {
const schema = {
['x-uid']: fieldSchema['x-uid'],
};
fieldSchema['x-component-props'] = fieldSchema['x-component-props'] || {};
fieldSchema['x-component-props']['quickAddParentCollection'] = {
collectionField: `${fieldSchema['x-collection-field']}.${quickField}.${mode}`,
value: mode,
};
schema['x-component-props'] = fieldSchema['x-component-props'];
field.componentProps = field.componentProps || {};
field.componentProps['quickAddParentCollection'] = {
collectionField: `${fieldSchema['x-collection-field']}.${quickField}.${mode}`,
value: 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();
},
};
},
useVisible() {
const fieldSchema = useFieldSchema();
return (
fieldSchema['x-component-props']['isQuickAdd'] &&
fieldSchema['x-component-props']['quickAddField'] &&
fieldSchema['x-component-props']['quickAddField'] !== 'none'
);
},
},
{ {
name: 'defaultValue', name: 'defaultValue',
Component: SchemaSettingsDefaultValue, Component: SchemaSettingsDefaultValue,

View File

@ -46,7 +46,7 @@ const useArrayField = (props) => {
return (props.field || field) as ArrayField; return (props.field || field) as ArrayField;
}; };
const useTableColumns = (props: { showDel?: boolean; isSubTable?: boolean }) => { const useTableColumns = (props: { showDel?: boolean; isSubTable?: boolean; setFieldValue?: any }) => {
const { t } = useTranslation(); const { t } = useTranslation();
const { styles } = useStyles(); const { styles } = useStyles();
const field = useArrayField(props); const field = useArrayField(props);
@ -162,6 +162,7 @@ const useTableColumns = (props: { showDel?: boolean; isSubTable?: boolean }) =>
}); });
field.value.splice(index, 1); field.value.splice(index, 1);
field.initialValue?.splice(index, 1); field.initialValue?.splice(index, 1);
props.setFieldValue([...field.value]);
return field.onInput(field.value); return field.onInput(field.value);
}); });
}} }}