refactor(association-field): support sub table (#1862)
* fix: association select support data scope and sort setting * fix: appends on demand loading * fix: asociationSelect support multiple * fix: recordPicker -> AssociationField * fix: add migration * fix: audit logs not show assication data * fix: flattenNestedList * refactor: file manager field mode * refactor: field mode refactor * fix: subtable action * fix: subtable appends * refactor: code improve * fix: nester add new * feat: sub table * fix: data scope not effect immediately * fix: association add new * fix: association field failed to add new and mutual influence * style: style improve * style: style improve * refactor: updateAssociationValues * refactor: form init values * refactor: select options * fix: form initialValues * fix: record picker values * fix: field value change when field mode change * fix: select data scope * feat: add migration * fix: table column enable link * fix: table column enable link * refactor: locale improve * fix: migration * fix: mutiple config * fix: readPretty enable link * fix: appends on demand * fix: enable link style * refactor: locale improve * refactor: locale improve * feat: sub-form migration * fix: skip migration * fix: translation * fix: skip migration * fix: getLabelFormatValue * fix: error TS2339: Property 'find' does not exist on type 'string | SchemaEnum<any>' * refactor: remove the logic code for converting old record picker * refactor: locale * refactor: association field support sub-table * refactor: locale * fix: sub-table should not support add new * refactor: code improve * refactor: locale * fix: compatibility history Subtable * fix: getNesterAppends filter bug * refactor: useFieldModeOptions * refactor: subTable * fix: associationSelect * fix: associationSelect * fix: associationSelect * fix: getAssociationAppends * fix: sub-form collection context * refactor: code improve * refactor: code improve * refactor: code improve * refactor: code improve * refactor: code improve * fix: sub-table * fix: appends * fix: sub-table-appends * fix: undefine id * fix: sub-table appends * refactor: sub-table * refactor: sub-table supoort delete * fix: sub-table-appends * refactor: sub table initvvalue * fix: sub-table-appends * fix: association field appends * fix: association field appends * fix: association field appends * style: style improve * style: style improve * refactor: textArear Markdown RichText * style: style improve * fix: title field * refactor: code improve * fix: system fields are not allowed to be edited * refactor: subtable does not support inline operations * refactor: jons edit in table * refactor: sequence readOnly in table * refactor: json readOnly in table * fix: sub-table appends * fix: runWhenParamsChanged * fix: runWhenParamsChanged * fix: sub-table appends * fix: sub-table appends * refactor: sub-table * style: checkbox group intable * style: delete button style improve * fix: json edit in table * fix: sub-table appends * style: upload file in table column * refactor: map edit in table * refactor: map edit in table * refactor: map field display in sub-table * fix: support mutiple row * refactor: sub-table * refactor: sub-table not support sortable * fix: sub-table appends * fix: sub-table appends * chore: useAssociationNames * refactor: code improve * refactor: support blocktemplate * refactor: support blocktemplate * fix: subtable * fix: subtable initValue * refactor: useAssociationNames in block template * fix: cross hierarchical association field layout * fix: normal field of association field should be append * style: upload field in table * refactor: sub table should not row selection * style: checkboxGroup and radioGroup display in sub-table * refactor: locale * refactor: code improve * refactor: quickEdit in sub-table * refactor: quickEdit * refactor: quickEdit * refactor: quickEdit * refactor: quickEdit * style: quickEdit style improve * style: quickEdit style improve * style: quickEdit style improve * refactor: sub-table support required config * refactor: cell validate * refactor: cell validate * refactor: cell required validate * refactor: cell required validate * refactor: sub-table display when readPretty * refactor: sub-table required * refactor: sub-table required * refactor: sub-table required * refactor: sub-table initialValue * refactor: table * refactor: sub-tble field required * refactor: sub-table style improve * refactor: sub-table attachemnt * refactor: code improve * test: tableV2 snap * fix: subtable drag * test: tableV2 snap * refactor: checkbox group and radio group in sub-table * refactor: sub-table required style * style: markdown style in sub-table * refactor: markdown display in sub-table * refactor: json field display in sub-table * refactor: code improve * style: style improve * style: style improve * refactor: inserView when designable * refactor: china-region load data when dropdown click * refactor: code improve * refactor: code improve * refactor: display loading when the form is first loaded * refactor: display loading when the form is first loaded * fix: verification exception when deleting sub table rows * refactor: sub-table code improve * refactor: sub-table code improve * fix: json error feedback * refactor: code improve * fix: json onchange * fix: sub table data did not change when switching data templates * test: variable test * test: variable test * refactor: data template * refactor: code improve * refactor: code improve * fix: upload readpretty * fix: attach upload in sub-tabl * fix: remove small * fix: attach upload in sub-table * refactor: association fields should not display in sub-table * fix: dropdownMatchSelectWidth * refactor: association fields should not display in sub-table * refactor: selectFile is false in sub-table * refactor: attacattachment in sub-table * refactor: attacattachment in sub-table * fix: selector style * refactor: quick edit component * fix: zindex * style: style improve * style: style improve * feat: styling * fix: style * fix: style * refactor: quickEdit getContainer * refactor: quickEdit * refactor: quickEdit * fix: improve code * refactor: code improve * refactor: code improve --------- Co-authored-by: chenos <chenlinxh@gmail.com>
This commit is contained in:
parent
457afe3e06
commit
4faf64f905
@ -1,6 +1,7 @@
|
|||||||
import { createForm } from '@formily/core';
|
import { createForm } from '@formily/core';
|
||||||
import { RecursionField, Schema, useField, useFieldSchema } from '@formily/react';
|
import { RecursionField, Schema, useField, useFieldSchema } from '@formily/react';
|
||||||
import { isEmpty } from 'lodash';
|
import { isEmpty } from 'lodash';
|
||||||
|
import { Spin } from 'antd';
|
||||||
import React, { createContext, useContext, useEffect, useMemo, useRef } from 'react';
|
import React, { createContext, useContext, useEffect, useMemo, useRef } from 'react';
|
||||||
import { useCollection } from '../collection-manager';
|
import { useCollection } from '../collection-manager';
|
||||||
import { RecordProvider, useRecord } from '../record-provider';
|
import { RecordProvider, useRecord } from '../record-provider';
|
||||||
@ -23,9 +24,9 @@ const InternalFormBlockProvider = (props) => {
|
|||||||
const { resource, service, updateAssociationValues } = useBlockRequestContext();
|
const { resource, service, updateAssociationValues } = useBlockRequestContext();
|
||||||
const formBlockRef = useRef();
|
const formBlockRef = useRef();
|
||||||
const record = useRecord();
|
const record = useRecord();
|
||||||
// if (service.loading) {
|
if (service.loading && Object.keys(form?.initialValues)?.length === 0 && action) {
|
||||||
// return <Spin />;
|
return <Spin />;
|
||||||
// }
|
}
|
||||||
return (
|
return (
|
||||||
<FormBlockContext.Provider
|
<FormBlockContext.Provider
|
||||||
value={{
|
value={{
|
||||||
|
@ -127,7 +127,7 @@ export const TableBlockProvider = (props) => {
|
|||||||
return (
|
return (
|
||||||
<SchemaComponentOptions scope={{ treeTable }}>
|
<SchemaComponentOptions scope={{ treeTable }}>
|
||||||
<FormContext.Provider value={form}>
|
<FormContext.Provider value={form}>
|
||||||
<BlockProvider {...props} params={params}>
|
<BlockProvider {...props} params={params} runWhenParamsChanged>
|
||||||
<InternalTableBlockProvider {...props} childrenColumnName={childrenColumnName} params={params} />
|
<InternalTableBlockProvider {...props} childrenColumnName={childrenColumnName} params={params} />
|
||||||
</BlockProvider>
|
</BlockProvider>
|
||||||
</FormContext.Provider>
|
</FormContext.Provider>
|
||||||
|
@ -46,7 +46,8 @@ const InternalField: React.FC = (props: Props) => {
|
|||||||
setFieldProps('title', uiSchema.title);
|
setFieldProps('title', uiSchema.title);
|
||||||
setFieldProps('description', uiSchema.description);
|
setFieldProps('description', uiSchema.description);
|
||||||
if (ctx?.form) {
|
if (ctx?.form) {
|
||||||
setFieldProps('initialValue', fieldSchema.default || defaultValue);
|
const defaultVal = fieldSchema.default || defaultValue;
|
||||||
|
defaultVal !== null && defaultVal !== undefined && setFieldProps('initialValue', defaultVal);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!field.validator && (uiSchema['x-validator'] || fieldSchema['x-validator'])) {
|
if (!field.validator && (uiSchema['x-validator'] || fieldSchema['x-validator'])) {
|
||||||
|
@ -12,16 +12,10 @@ export const url: IField = {
|
|||||||
type: 'string',
|
type: 'string',
|
||||||
uiSchema: {
|
uiSchema: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
title: '{{t("URL")}}',
|
|
||||||
'x-component': 'Input.URL',
|
'x-component': 'Input.URL',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
schemaInitialize(schema: ISchema, { block }) {
|
schemaInitialize(schema: ISchema, { block }) {},
|
||||||
if (['Table', 'Kanban'].includes(block)) {
|
|
||||||
schema['x-component-props'] = schema['x-component-props'] || {};
|
|
||||||
schema['x-component-props']['size'] = 'small';
|
|
||||||
}
|
|
||||||
},
|
|
||||||
properties: {
|
properties: {
|
||||||
...defaultProps,
|
...defaultProps,
|
||||||
},
|
},
|
||||||
|
@ -293,14 +293,14 @@ export default {
|
|||||||
"Allow multiple": "Allow multiple",
|
"Allow multiple": "Allow multiple",
|
||||||
"Quick upload": "Quick upload",
|
"Quick upload": "Quick upload",
|
||||||
"Select file": "Select file",
|
"Select file": "Select file",
|
||||||
"Subtable": "Subtable",
|
"Subtable": "Sub-table",
|
||||||
"Subform": "Sub-form",
|
"Subform": "Sub-form",
|
||||||
"Field mode":"Field mode",
|
"Field mode":"Field mode",
|
||||||
"Allow add new data":"Allow add new data",
|
"Allow add new data":"Allow add new data",
|
||||||
"Record picker": "Record picker",
|
"Record picker": "Record picker",
|
||||||
"Toggles the subfield mode": "Toggles the subfield mode",
|
"Toggles the subfield mode": "Toggles the subfield mode",
|
||||||
"Selector mode": "Selector mode",
|
"Selector mode": "Selector mode",
|
||||||
"Subtable mode": "Subtable mode",
|
"Subtable mode": "Sub-table mode",
|
||||||
"Subform mode": "Sub-form mode",
|
"Subform mode": "Sub-form mode",
|
||||||
"Edit block title": "Edit block title",
|
"Edit block title": "Edit block title",
|
||||||
"Block title": "Block title",
|
"Block title": "Block title",
|
||||||
|
@ -17,7 +17,7 @@ export const ActionDrawer: ComposedActionDrawer = observer(
|
|||||||
(props) => {
|
(props) => {
|
||||||
const { footerNodeName = 'Action.Drawer.Footer', ...others } = props;
|
const { footerNodeName = 'Action.Drawer.Footer', ...others } = props;
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { visible, setVisible, openSize = 'middle', drawerProps } = useActionContext();
|
const { visible, setVisible, openSize = 'middle', drawerProps, modalProps } = useActionContext();
|
||||||
const schema = useFieldSchema();
|
const schema = useFieldSchema();
|
||||||
const field = useField();
|
const field = useField();
|
||||||
const openSizeFromParent = schema.parent?.['x-component-props']?.['openSize'];
|
const openSizeFromParent = schema.parent?.['x-component-props']?.['openSize'];
|
||||||
@ -35,6 +35,7 @@ export const ActionDrawer: ComposedActionDrawer = observer(
|
|||||||
title={field.title}
|
title={field.title}
|
||||||
{...others}
|
{...others}
|
||||||
{...drawerProps}
|
{...drawerProps}
|
||||||
|
{...modalProps}
|
||||||
style={{
|
style={{
|
||||||
...drawerProps?.style,
|
...drawerProps?.style,
|
||||||
...others?.style,
|
...others?.style,
|
||||||
|
@ -84,6 +84,9 @@ export const AssociationFieldProvider = observer(
|
|||||||
field.value = [{}];
|
field.value = [{}];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (currentMode === 'SubTable') {
|
||||||
|
field.value = [];
|
||||||
|
}
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [currentMode, collectionField, fieldValue]);
|
}, [currentMode, collectionField, fieldValue]);
|
||||||
|
@ -70,6 +70,7 @@ const InternalAssociationSelect = observer((props: AssociationSelectProps) => {
|
|||||||
<RemoteSelect
|
<RemoteSelect
|
||||||
style={{ width: '100%' }}
|
style={{ width: '100%' }}
|
||||||
{...props}
|
{...props}
|
||||||
|
size={'middle'}
|
||||||
objectValue={objectValue}
|
objectValue={objectValue}
|
||||||
value={value}
|
value={value}
|
||||||
service={service}
|
service={service}
|
||||||
|
@ -133,7 +133,7 @@ const InternalFileManager = (props) => {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<div>
|
<div style={{ width: '100%', overflow: 'auto' }}>
|
||||||
<FileSelector
|
<FileSelector
|
||||||
value={options}
|
value={options}
|
||||||
multiple={multiple}
|
multiple={multiple}
|
||||||
@ -153,7 +153,16 @@ const InternalFileManager = (props) => {
|
|||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<ActionContextProvider value={{ openMode: 'drawer', visible: visibleSelector, setVisible: setVisibleSelector }}>
|
<ActionContextProvider
|
||||||
|
value={{
|
||||||
|
openMode: 'drawer',
|
||||||
|
visible: visibleSelector,
|
||||||
|
setVisible: setVisibleSelector,
|
||||||
|
modalProps: {
|
||||||
|
getContainer: others?.getContainer,
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
>
|
||||||
<RecordPickerProvider {...pickerProps}>
|
<RecordPickerProvider {...pickerProps}>
|
||||||
<CollectionProvider name={collectionField.target}>
|
<CollectionProvider name={collectionField.target}>
|
||||||
<FormProvider>
|
<FormProvider>
|
||||||
|
@ -1,21 +1,51 @@
|
|||||||
import { FormLayout } from '@formily/antd';
|
import { css } from '@emotion/css';
|
||||||
import { RecursionField, useField, useFieldSchema } from '@formily/react';
|
import { FormItem, FormLayout } from '@formily/antd';
|
||||||
|
import { RecursionField, observer, useField, useFieldSchema } from '@formily/react';
|
||||||
import React, { useEffect } from 'react';
|
import React, { useEffect } from 'react';
|
||||||
import { CollectionProvider } from '../../../collection-manager';
|
import { CollectionProvider } from '../../../collection-manager';
|
||||||
|
import { SchemaComponentOptions } from '../../../schema-component';
|
||||||
|
import Select from '../select/Select';
|
||||||
import { useAssociationFieldContext, useInsertSchema } from './hooks';
|
import { useAssociationFieldContext, useInsertSchema } from './hooks';
|
||||||
import schema from './schema';
|
import schema from './schema';
|
||||||
|
|
||||||
export const InternalSubTable = () => {
|
export const InternalSubTable = observer(
|
||||||
const field = useField();
|
() => {
|
||||||
|
const field: any = useField();
|
||||||
const fieldSchema = useFieldSchema();
|
const fieldSchema = useFieldSchema();
|
||||||
const insert = useInsertSchema('SubTable');
|
const insert = useInsertSchema('SubTable');
|
||||||
const { options } = useAssociationFieldContext();
|
const { options } = useAssociationFieldContext();
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
insert(schema.SubTable);
|
insert(schema.SubTable);
|
||||||
|
field.required = fieldSchema['required'];
|
||||||
}, []);
|
}, []);
|
||||||
return (
|
return (
|
||||||
<CollectionProvider name={options.target}>
|
<CollectionProvider name={options.target}>
|
||||||
<FormLayout layout={'vertical'}>
|
<FormLayout
|
||||||
|
className={css`
|
||||||
|
.ant-formily-item-bordered-none {
|
||||||
|
.ant-input-number-group-addon {
|
||||||
|
border: none !important;
|
||||||
|
background: none;
|
||||||
|
}
|
||||||
|
.ant-checkbox-wrapper {
|
||||||
|
margin-left: 8px;
|
||||||
|
}
|
||||||
|
.ant-btn {
|
||||||
|
border: none !important;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`}
|
||||||
|
layout={'vertical'}
|
||||||
|
bordered={false}
|
||||||
|
>
|
||||||
|
<SchemaComponentOptions
|
||||||
|
components={{
|
||||||
|
FormItem: (props) => <FormItem {...props} />,
|
||||||
|
'Radio.Group': Select,
|
||||||
|
'Checkbox.Group': (props) => <Select multiple={true} mode="multiple" {...props} />,
|
||||||
|
}}
|
||||||
|
>
|
||||||
<RecursionField
|
<RecursionField
|
||||||
onlyRenderProperties
|
onlyRenderProperties
|
||||||
basePath={field.address}
|
basePath={field.address}
|
||||||
@ -24,7 +54,10 @@ export const InternalSubTable = () => {
|
|||||||
return s['x-component'] === 'AssociationField.SubTable';
|
return s['x-component'] === 'AssociationField.SubTable';
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
</SchemaComponentOptions>
|
||||||
</FormLayout>
|
</FormLayout>
|
||||||
</CollectionProvider>
|
</CollectionProvider>
|
||||||
);
|
);
|
||||||
};
|
},
|
||||||
|
{ displayName: 'InternalSubTable' },
|
||||||
|
);
|
||||||
|
@ -6,6 +6,7 @@ import { CollectionProvider } from '../../../collection-manager';
|
|||||||
import { RecordProvider, useRecord } from '../../../record-provider';
|
import { RecordProvider, useRecord } from '../../../record-provider';
|
||||||
import { FormProvider } from '../../core';
|
import { FormProvider } from '../../core';
|
||||||
import { useCompile } from '../../hooks';
|
import { useCompile } from '../../hooks';
|
||||||
|
import { useDesignable } from '../../';
|
||||||
import { ActionContextProvider, useActionContext } from '../action';
|
import { ActionContextProvider, useActionContext } from '../action';
|
||||||
import { EllipsisWithTooltip } from '../input/EllipsisWithTooltip';
|
import { EllipsisWithTooltip } from '../input/EllipsisWithTooltip';
|
||||||
import { useAssociationFieldContext, useFieldNames, useInsertSchema } from './hooks';
|
import { useAssociationFieldContext, useFieldNames, useInsertSchema } from './hooks';
|
||||||
@ -35,6 +36,7 @@ export const ReadPrettyInternalViewer: React.FC = observer(
|
|||||||
const { options: collectionField } = useAssociationFieldContext();
|
const { options: collectionField } = useAssociationFieldContext();
|
||||||
const [record, setRecord] = useState({});
|
const [record, setRecord] = useState({});
|
||||||
const compile = useCompile();
|
const compile = useCompile();
|
||||||
|
const { designable } = useDesignable();
|
||||||
const labelUiSchema = useLabelUiSchema(collectionField, fieldNames?.label || 'label');
|
const labelUiSchema = useLabelUiSchema(collectionField, fieldNames?.label || 'label');
|
||||||
const { snapshot } = useActionContext();
|
const { snapshot } = useActionContext();
|
||||||
const ellipsisWithTooltipRef = useRef<IEllipsisWithTooltipRef>();
|
const ellipsisWithTooltipRef = useRef<IEllipsisWithTooltipRef>();
|
||||||
@ -53,7 +55,9 @@ export const ReadPrettyInternalViewer: React.FC = observer(
|
|||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
if (designable) {
|
||||||
insertViewer(schema.Viewer);
|
insertViewer(schema.Viewer);
|
||||||
|
}
|
||||||
setVisible(true);
|
setVisible(true);
|
||||||
setRecord(record);
|
setRecord(record);
|
||||||
ellipsisWithTooltipRef?.current?.setPopoverVisible(false);
|
ellipsisWithTooltipRef?.current?.setPopoverVisible(false);
|
||||||
|
@ -1,29 +1,111 @@
|
|||||||
|
import { PlusOutlined } from '@ant-design/icons';
|
||||||
|
import { css } from '@emotion/css';
|
||||||
import { ArrayField } from '@formily/core';
|
import { ArrayField } from '@formily/core';
|
||||||
|
import { exchangeArrayState } from '@formily/core/esm/shared/internals';
|
||||||
import { observer } from '@formily/react';
|
import { observer } from '@formily/react';
|
||||||
|
import { action } from '@formily/reactive';
|
||||||
|
import { isArr } from '@formily/shared';
|
||||||
import { Button } from 'antd';
|
import { Button } from 'antd';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
import { Table } from '../table-v2/Table';
|
import { Table } from '../table-v2/Table';
|
||||||
import { useAssociationFieldContext } from './hooks';
|
import { useAssociationFieldContext } from './hooks';
|
||||||
|
|
||||||
export const SubTable: any = observer(
|
export const SubTable: any = observer(
|
||||||
(props) => {
|
(props: any) => {
|
||||||
const { field } = useAssociationFieldContext<ArrayField>();
|
const { field } = useAssociationFieldContext<ArrayField>();
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const move = (fromIndex: number, toIndex: number) => {
|
||||||
|
if (toIndex === undefined) return;
|
||||||
|
if (!isArr(field.value)) return;
|
||||||
|
if (fromIndex === toIndex) return;
|
||||||
|
return action(() => {
|
||||||
|
const fromItem = field.value[fromIndex];
|
||||||
|
field.value.splice(fromIndex, 1);
|
||||||
|
field.value.splice(toIndex, 0, fromItem);
|
||||||
|
exchangeArrayState(field, {
|
||||||
|
fromIndex,
|
||||||
|
toIndex,
|
||||||
|
});
|
||||||
|
return field.onInput(field.value);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
field.move = move;
|
||||||
return (
|
return (
|
||||||
<div>
|
<div
|
||||||
<Table size={'small'} showIndex field={field} pagination={false} />
|
className={css`
|
||||||
{field.editable && (
|
.ant-table-footer {
|
||||||
|
padding: 0 !important;
|
||||||
|
}
|
||||||
|
.ant-formily-item-error-help {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.ant-description-textarea {
|
||||||
|
line-height: 34px;
|
||||||
|
}
|
||||||
|
.ant-table-cell .ant-formily-item-error-help {
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
font-size: 12px;
|
||||||
|
top: 100%;
|
||||||
|
background: #fff;
|
||||||
|
width: 100%;
|
||||||
|
margin-top: 3px;
|
||||||
|
padding: 3px;
|
||||||
|
z-index: 1;
|
||||||
|
border-radius: 3px;
|
||||||
|
box-shadow: 0 0 10px #eee;
|
||||||
|
animation: none;
|
||||||
|
transform: translateY(0);
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
`}
|
||||||
|
>
|
||||||
|
<Table
|
||||||
|
className={css`
|
||||||
|
.ant-select-selector {
|
||||||
|
/* min-height: 31px; */
|
||||||
|
}
|
||||||
|
.ant-formily-item.ant-formily-item-feedback-layout-loose {
|
||||||
|
margin-bottom: 0px !important;
|
||||||
|
}
|
||||||
|
.ant-formily-editable {
|
||||||
|
vertical-align: sub;
|
||||||
|
}
|
||||||
|
.ant-table table {
|
||||||
|
}
|
||||||
|
td:not(.ant-table-selection-column) {
|
||||||
|
padding: 0 !important;
|
||||||
|
}
|
||||||
|
`}
|
||||||
|
bordered
|
||||||
|
size={'small'}
|
||||||
|
field={field}
|
||||||
|
showIndex
|
||||||
|
dragSort={field.editable}
|
||||||
|
showDel={field.editable}
|
||||||
|
pagination={false}
|
||||||
|
rowSelection={{ type: 'none', hideSelectAll: true }}
|
||||||
|
footer={() =>
|
||||||
|
field.editable && (
|
||||||
<Button
|
<Button
|
||||||
type={'dashed'}
|
type={'text'}
|
||||||
block
|
block
|
||||||
style={{ marginTop: 12 }}
|
className={css`
|
||||||
|
display: block;
|
||||||
|
`}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
field.value = field.value || [];
|
field.value = field.value || [];
|
||||||
field.value.push({});
|
field.value.push({});
|
||||||
|
field.onInput(field.value);
|
||||||
}}
|
}}
|
||||||
|
icon={<PlusOutlined />}
|
||||||
>
|
>
|
||||||
Add new
|
{/* {t('Add new')} */}
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
@ -121,21 +121,9 @@ export default {
|
|||||||
type: 'void',
|
type: 'void',
|
||||||
'x-component': 'AssociationField.SubTable',
|
'x-component': 'AssociationField.SubTable',
|
||||||
'x-initializer': 'TableColumnInitializers',
|
'x-initializer': 'TableColumnInitializers',
|
||||||
properties: {
|
'x-initializer-props': {
|
||||||
indexCol: {
|
action: false,
|
||||||
type: 'void',
|
|
||||||
'x-component': 'TableV2.Column',
|
|
||||||
'x-component-props': {
|
|
||||||
width: 80,
|
|
||||||
},
|
|
||||||
properties: {
|
|
||||||
__index__: {
|
|
||||||
type: 'void',
|
|
||||||
'x-component': 'TableV2.Index',
|
|
||||||
'x-read-pretty': true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
|
properties: {},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -2,9 +2,10 @@ import { LoadingOutlined } from '@ant-design/icons';
|
|||||||
import { ArrayField } from '@formily/core';
|
import { ArrayField } from '@formily/core';
|
||||||
import { connect, mapProps, mapReadPretty, useField } from '@formily/react';
|
import { connect, mapProps, mapReadPretty, useField } from '@formily/react';
|
||||||
import { toArr } from '@formily/shared';
|
import { toArr } from '@formily/shared';
|
||||||
|
import { action } from '@formily/reactive';
|
||||||
import { Cascader as AntdCascader, Space } from 'antd';
|
import { Cascader as AntdCascader, Space } from 'antd';
|
||||||
import { isBoolean, omit } from 'lodash';
|
import { isBoolean, omit } from 'lodash';
|
||||||
import React from 'react';
|
import React, { useState } from 'react';
|
||||||
import { useRequest } from '../../../api-client';
|
import { useRequest } from '../../../api-client';
|
||||||
import { defaultFieldNames } from './defaultFieldNames';
|
import { defaultFieldNames } from './defaultFieldNames';
|
||||||
import { ReadPretty } from './ReadPretty';
|
import { ReadPretty } from './ReadPretty';
|
||||||
@ -35,7 +36,7 @@ export const Cascader = connect(
|
|||||||
} = props;
|
} = props;
|
||||||
const fieldNames = { ...defaultFieldNames, ...props.fieldNames };
|
const fieldNames = { ...defaultFieldNames, ...props.fieldNames };
|
||||||
const loadData = useLoadData(props);
|
const loadData = useLoadData(props);
|
||||||
const { loading } = useDataSource({
|
const { loading, run } = useDataSource({
|
||||||
onSuccess(data) {
|
onSuccess(data) {
|
||||||
field.dataSource = data?.data || [];
|
field.dataSource = data?.data || [];
|
||||||
},
|
},
|
||||||
@ -62,6 +63,11 @@ export const Cascader = connect(
|
|||||||
</Space>
|
</Space>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
const handelDropDownVisible = (value) => {
|
||||||
|
if (value && !field.dataSource) {
|
||||||
|
run();
|
||||||
|
}
|
||||||
|
};
|
||||||
return (
|
return (
|
||||||
<AntdCascader
|
<AntdCascader
|
||||||
loading={loading}
|
loading={loading}
|
||||||
@ -72,6 +78,7 @@ export const Cascader = connect(
|
|||||||
value={toValue()}
|
value={toValue()}
|
||||||
fieldNames={fieldNames}
|
fieldNames={fieldNames}
|
||||||
displayRender={displayRender}
|
displayRender={displayRender}
|
||||||
|
onDropdownVisibleChange={handelDropDownVisible}
|
||||||
onChange={(value, selectedOptions) => {
|
onChange={(value, selectedOptions) => {
|
||||||
if (value && labelInValue) {
|
if (value && labelInValue) {
|
||||||
onChange(selectedOptions.map((option) => omit(option, [fieldNames.children])));
|
onChange(selectedOptions.map((option) => omit(option, [fieldNames.children])));
|
||||||
|
@ -833,7 +833,7 @@ FormItem.Designer = function Designer() {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{options.length > 0 && isAssociationField && (
|
{options.length > 0 && isAssociationField&&fieldMode!=='SubTable' && (
|
||||||
<SchemaSettings.SelectItem
|
<SchemaSettings.SelectItem
|
||||||
key="title-field"
|
key="title-field"
|
||||||
title={t('Title field')}
|
title={t('Title field')}
|
||||||
|
@ -72,13 +72,21 @@ const useDataTemplates = () => {
|
|||||||
enabled: items.length > 0 && items.every((item) => item.dataId !== undefined),
|
enabled: items.length > 0 && items.every((item) => item.dataId !== undefined),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
function filterReferences(obj) {
|
||||||
|
const filteredObj = {};
|
||||||
|
for (const key in obj) {
|
||||||
|
if (typeof obj[key] !== 'object') {
|
||||||
|
filteredObj[key] = obj[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return filteredObj;
|
||||||
|
}
|
||||||
export const Templates = ({ style = {}, form }) => {
|
export const Templates = ({ style = {}, form }) => {
|
||||||
const { templates, display, enabled, defaultTemplate } = useDataTemplates();
|
const { templates, display, enabled, defaultTemplate } = useDataTemplates();
|
||||||
const [value, setValue] = React.useState(defaultTemplate?.key || 'none');
|
const [value, setValue] = React.useState(defaultTemplate?.key || 'none');
|
||||||
const api = useAPIClient();
|
const api = useAPIClient();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (enabled && defaultTemplate) {
|
if (enabled && defaultTemplate) {
|
||||||
form.__template = true;
|
form.__template = true;
|
||||||
|
@ -31,6 +31,12 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ant-formily-item-bordered-none {
|
||||||
|
.ant-formily-item-feedback-layout-loose {
|
||||||
|
margin-bottom: 0 !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.ant-formily-item-control-content-component .ant-tag {
|
.ant-formily-item-control-content-component .ant-tag {
|
||||||
white-space: pre-wrap;
|
white-space: pre-wrap;
|
||||||
}
|
}
|
||||||
|
@ -45,4 +45,5 @@ export * from './time-picker';
|
|||||||
export * from './tree-select';
|
export * from './tree-select';
|
||||||
export * from './upload';
|
export * from './upload';
|
||||||
export * from './variable';
|
export * from './variable';
|
||||||
|
export * from './quick-edit'
|
||||||
import './index.less';
|
import './index.less';
|
||||||
|
@ -35,11 +35,14 @@ export const Json = React.forwardRef<typeof Input.TextArea, JSONTextAreaProps>(
|
|||||||
onChange={(ev) => {
|
onChange={(ev) => {
|
||||||
setText(ev.target.value);
|
setText(ev.target.value);
|
||||||
try {
|
try {
|
||||||
|
const v = ev.target.value.trim() !== '' ? JSON.parse(ev.target.value) : null;
|
||||||
if (ev.target.value.trim() !== '') {
|
if (ev.target.value.trim() !== '') {
|
||||||
JSON.parse(ev.target.value);
|
JSON.parse(ev.target.value);
|
||||||
}
|
}
|
||||||
field.setFeedback({});
|
field.setFeedback({});
|
||||||
|
onChange?.(v);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
onChange?.(ev);
|
||||||
field.setFeedback({
|
field.setFeedback({
|
||||||
type: 'error',
|
type: 'error',
|
||||||
code: 'JSONSyntaxError',
|
code: 'JSONSyntaxError',
|
||||||
@ -53,6 +56,7 @@ export const Json = React.forwardRef<typeof Input.TextArea, JSONTextAreaProps>(
|
|||||||
field.setFeedback({});
|
field.setFeedback({});
|
||||||
onChange?.(v);
|
onChange?.(v);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
onChange?.(ev);
|
||||||
field.setFeedback({
|
field.setFeedback({
|
||||||
type: 'error',
|
type: 'error',
|
||||||
code: 'JSONSyntaxError',
|
code: 'JSONSyntaxError',
|
||||||
|
@ -20,16 +20,18 @@ export const Markdown: any = connect(
|
|||||||
suffix: <span>{field?.['loading'] || field?.['validating'] ? <LoadingOutlined /> : props.suffix}</span>,
|
suffix: <span>{field?.['loading'] || field?.['validating'] ? <LoadingOutlined /> : props.suffix}</span>,
|
||||||
};
|
};
|
||||||
}),
|
}),
|
||||||
mapReadPretty((props) => {
|
mapReadPretty((props) => <MarkdownReadPretty {...props} />),
|
||||||
const { html, loading } = useParseMarkdown(props.value);
|
);
|
||||||
|
|
||||||
|
export const MarkdownReadPretty = (props) => {
|
||||||
|
const { html = '', loading } = useParseMarkdown(props.value);
|
||||||
const text = convertToText(html);
|
const text = convertToText(html);
|
||||||
const value = <div className={'nb-markdown'} dangerouslySetInnerHTML={{ __html: html }} />;
|
const value = <div className={'nb-markdown'} dangerouslySetInnerHTML={{ __html: html }} />;
|
||||||
if (loading) {
|
if (loading) {
|
||||||
return <Spin />;
|
return <Spin />;
|
||||||
}
|
}
|
||||||
return <InputReadPretty.TextArea {...props} autop={false} text={text} value={value} />;
|
return <InputReadPretty.TextArea {...props} autop={false} text={text} value={value} />;
|
||||||
}),
|
};
|
||||||
);
|
|
||||||
|
|
||||||
Markdown.Void = MarkdownVoid;
|
Markdown.Void = MarkdownVoid;
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@ import { DeleteOutlined, DownloadOutlined, PlusOutlined } from '@ant-design/icon
|
|||||||
import { connect, mapReadPretty } from '@formily/react';
|
import { connect, mapReadPretty } from '@formily/react';
|
||||||
import { Upload as AntdUpload, Button, Progress, Space } from 'antd';
|
import { Upload as AntdUpload, Button, Progress, Space } from 'antd';
|
||||||
import cls from 'classnames';
|
import cls from 'classnames';
|
||||||
|
import { css } from '@emotion/css';
|
||||||
import { saveAs } from 'file-saver';
|
import { saveAs } from 'file-saver';
|
||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
@ -44,7 +45,6 @@ export const FileSelector = (props: Props) => {
|
|||||||
onRemove?.(file);
|
onRemove?.(file);
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSelect = (e) => {
|
const handleSelect = (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
|
@ -0,0 +1,78 @@
|
|||||||
|
import { css } from '@emotion/css';
|
||||||
|
import { FormItem } from '@formily/antd';
|
||||||
|
import { Field, createForm } from '@formily/core';
|
||||||
|
import { FormContext, RecursionField, observer, useField, useFieldSchema } from '@formily/react';
|
||||||
|
import { Popover } from 'antd';
|
||||||
|
import React, { useMemo, useRef } from 'react';
|
||||||
|
import { useCollectionManager } from '../../../collection-manager';
|
||||||
|
|
||||||
|
export const Editable = observer((props) => {
|
||||||
|
const field: any = useField();
|
||||||
|
const containerRef = useRef(null);
|
||||||
|
const fieldSchema = useFieldSchema();
|
||||||
|
const schema: any = {
|
||||||
|
name: fieldSchema.name,
|
||||||
|
'x-collection-field': fieldSchema['x-collection-field'],
|
||||||
|
'x-component': 'CollectionField',
|
||||||
|
'x-read-pretty': true,
|
||||||
|
default: field.value,
|
||||||
|
'x-component-props': fieldSchema['x-component-props'],
|
||||||
|
};
|
||||||
|
const form = useMemo(
|
||||||
|
() =>
|
||||||
|
createForm({
|
||||||
|
values: {
|
||||||
|
[fieldSchema.name]: field.value,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
[field.value, fieldSchema['x-component-props']],
|
||||||
|
);
|
||||||
|
const getContainer = () => {
|
||||||
|
return containerRef.current;
|
||||||
|
};
|
||||||
|
|
||||||
|
const modifiedChildren = React.Children.map(props.children, (child) => {
|
||||||
|
if (React.isValidElement(child)) {
|
||||||
|
//@ts-ignore
|
||||||
|
return React.cloneElement(child, { getContainer });
|
||||||
|
}
|
||||||
|
return child;
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<FormItem {...props} labelStyle={{ display: 'none' }}>
|
||||||
|
<Popover
|
||||||
|
content={
|
||||||
|
<div style={{ width: '100%', height: '100%', minWidth: 500 }}>
|
||||||
|
<div ref={containerRef}>{modifiedChildren}</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
trigger="click"
|
||||||
|
placement={'bottomLeft'}
|
||||||
|
overlayClassName={css`
|
||||||
|
padding-top: 0;
|
||||||
|
.ant-popover-arrow {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
`}
|
||||||
|
>
|
||||||
|
<div style={{ minHeight: 30, padding: '0 8px' }}>
|
||||||
|
<FormContext.Provider value={form}>
|
||||||
|
<RecursionField schema={schema} name={fieldSchema.name} />
|
||||||
|
</FormContext.Provider>
|
||||||
|
</div>
|
||||||
|
</Popover>
|
||||||
|
</FormItem>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
export const QuickEdit = observer((props) => {
|
||||||
|
const field = useField<Field>();
|
||||||
|
const { getCollectionJoinField } = useCollectionManager();
|
||||||
|
const fieldSchema = useFieldSchema();
|
||||||
|
const collectionField = getCollectionJoinField(fieldSchema['x-collection-field']);
|
||||||
|
if (!collectionField) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return field.editable ? <Editable {...props} /> : <FormItem {...props} style={{ padding: '0 8px' }} />;
|
||||||
|
});
|
@ -0,0 +1 @@
|
|||||||
|
export * from './QuickEdit';
|
@ -235,9 +235,10 @@ const InternalRemoteSelect = connect(
|
|||||||
dataSource: 'options',
|
dataSource: 'options',
|
||||||
},
|
},
|
||||||
(props, field) => {
|
(props, field) => {
|
||||||
|
const fieldSchema = useFieldSchema();
|
||||||
return {
|
return {
|
||||||
...props,
|
...props,
|
||||||
fieldNames: { ...defaultFieldNames, ...props.fieldNames, ...field.componentProps.fieldNames },
|
fieldNames: { ...defaultFieldNames, ...props.fieldNames, ...field.componentProps.fieldNames,...fieldSchema['x-component-props']?.fieldNames },
|
||||||
suffixIcon: field?.['loading'] || field?.['validating'] ? <LoadingOutlined /> : props.suffixIcon,
|
suffixIcon: field?.['loading'] || field?.['validating'] ? <LoadingOutlined /> : props.suffixIcon,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
@ -2,8 +2,9 @@ import { ISchema, useField, useFieldSchema } from '@formily/react';
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { useCollectionManager } from '../../../collection-manager';
|
import { useCollectionManager } from '../../../collection-manager';
|
||||||
import { GeneralSchemaDesigner, SchemaSettings } from '../../../schema-settings';
|
import { GeneralSchemaDesigner, SchemaSettings, isPatternDisabled } from '../../../schema-settings';
|
||||||
import { useCompile, useDesignable } from '../../hooks';
|
import { useCompile, useDesignable } from '../../hooks';
|
||||||
|
import { useAssociationFieldContext } from '../association-field/hooks';
|
||||||
|
|
||||||
const useLabelFields = (collectionName?: any) => {
|
const useLabelFields = (collectionName?: any) => {
|
||||||
// 需要在组件顶层调用
|
// 需要在组件顶层调用
|
||||||
@ -26,7 +27,7 @@ const useLabelFields = (collectionName?: any) => {
|
|||||||
export const TableColumnDesigner = (props) => {
|
export const TableColumnDesigner = (props) => {
|
||||||
const { uiSchema, fieldSchema, collectionField } = props;
|
const { uiSchema, fieldSchema, collectionField } = props;
|
||||||
const { getInterface, getCollection } = useCollectionManager();
|
const { getInterface, getCollection } = useCollectionManager();
|
||||||
const field = useField();
|
const field: any = useField();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const columnSchema = useFieldSchema();
|
const columnSchema = useFieldSchema();
|
||||||
const { dn } = useDesignable();
|
const { dn } = useDesignable();
|
||||||
@ -36,6 +37,15 @@ export const TableColumnDesigner = (props) => {
|
|||||||
const intefaceCfg = getInterface(collectionField?.interface);
|
const intefaceCfg = getInterface(collectionField?.interface);
|
||||||
const targetCollection = getCollection(collectionField?.target);
|
const targetCollection = getCollection(collectionField?.target);
|
||||||
const isFileField = isFileCollection(targetCollection);
|
const isFileField = isFileCollection(targetCollection);
|
||||||
|
const isSubTableColumn = ['QuickEdit', 'FormItem'].includes(fieldSchema['x-decorator']);
|
||||||
|
const { currentMode, field: tableField } = useAssociationFieldContext();
|
||||||
|
let readOnlyMode = 'editable';
|
||||||
|
if (fieldSchema['x-disabled'] === true) {
|
||||||
|
readOnlyMode = 'readonly';
|
||||||
|
}
|
||||||
|
if (fieldSchema['x-read-pretty'] === true) {
|
||||||
|
readOnlyMode = 'read-pretty';
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<GeneralSchemaDesigner disableInitializer>
|
<GeneralSchemaDesigner disableInitializer>
|
||||||
<SchemaSettings.ModalItem
|
<SchemaSettings.ModalItem
|
||||||
@ -101,7 +111,7 @@ export const TableColumnDesigner = (props) => {
|
|||||||
dn.refresh();
|
dn.refresh();
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
{intefaceCfg && intefaceCfg.sortable === true && (
|
{intefaceCfg && intefaceCfg.sortable === true && !currentMode && (
|
||||||
<SchemaSettings.SwitchItem
|
<SchemaSettings.SwitchItem
|
||||||
title={t('Sortable')}
|
title={t('Sortable')}
|
||||||
checked={field.componentProps.sorter}
|
checked={field.componentProps.sorter}
|
||||||
@ -125,7 +135,8 @@ export const TableColumnDesigner = (props) => {
|
|||||||
{['linkTo', 'm2m', 'm2o', 'o2m', 'obo', 'oho', 'snapshot', 'createdBy', 'updatedBy'].includes(
|
{['linkTo', 'm2m', 'm2o', 'o2m', 'obo', 'oho', 'snapshot', 'createdBy', 'updatedBy'].includes(
|
||||||
collectionField?.interface,
|
collectionField?.interface,
|
||||||
) &&
|
) &&
|
||||||
!isFileField && (
|
!isFileField &&
|
||||||
|
field.readPrety && (
|
||||||
<SchemaSettings.SwitchItem
|
<SchemaSettings.SwitchItem
|
||||||
title={t('Enable link')}
|
title={t('Enable link')}
|
||||||
checked={fieldSchema['x-component-props']?.enableLink !== false}
|
checked={fieldSchema['x-component-props']?.enableLink !== false}
|
||||||
@ -177,6 +188,98 @@ export const TableColumnDesigner = (props) => {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{isSubTableColumn && !field.readPretty && !uiSchema?.['x-read-pretty'] && (
|
||||||
|
<SchemaSettings.SwitchItem
|
||||||
|
key="required"
|
||||||
|
title={t('Required')}
|
||||||
|
checked={fieldSchema.required as boolean}
|
||||||
|
onChange={(required) => {
|
||||||
|
const schema = {
|
||||||
|
['x-uid']: fieldSchema['x-uid'],
|
||||||
|
};
|
||||||
|
fieldSchema['required'] = required;
|
||||||
|
schema['required'] = required;
|
||||||
|
const path = field.path?.splice(field.path?.length - 1, 1);
|
||||||
|
(tableField as any)?.value.map((_, index) => {
|
||||||
|
field.form.query(`${path.concat(`${index}.` + fieldSchema.name)}`).take((f) => {
|
||||||
|
f.required = required;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
dn.emit('patch', {
|
||||||
|
schema,
|
||||||
|
});
|
||||||
|
dn.refresh();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{isSubTableColumn &&
|
||||||
|
!field?.readPretty &&
|
||||||
|
collectionField?.interface !== 'o2m' &&
|
||||||
|
!isPatternDisabled(fieldSchema) && (
|
||||||
|
<SchemaSettings.SelectItem
|
||||||
|
key="pattern"
|
||||||
|
title={t('Pattern')}
|
||||||
|
options={[
|
||||||
|
{ label: t('Editable'), value: 'editable' },
|
||||||
|
{ label: t('Readonly'), value: 'readonly' },
|
||||||
|
{ label: t('Easy-reading'), value: 'read-pretty' },
|
||||||
|
]}
|
||||||
|
value={readOnlyMode}
|
||||||
|
onChange={(v) => {
|
||||||
|
const schema: ISchema = {
|
||||||
|
['x-uid']: fieldSchema['x-uid'],
|
||||||
|
};
|
||||||
|
const path = field.path?.splice(field.path?.length - 1, 1);
|
||||||
|
switch (v) {
|
||||||
|
case 'readonly': {
|
||||||
|
fieldSchema['x-read-pretty'] = false;
|
||||||
|
fieldSchema['x-disabled'] = true;
|
||||||
|
schema['x-read-pretty'] = false;
|
||||||
|
schema['x-disabled'] = true;
|
||||||
|
(tableField as any)?.value.map((_, index) => {
|
||||||
|
field.form.query(`${path.concat(`${index}.` + fieldSchema.name)}`).take((f) => {
|
||||||
|
f.readonly = true;
|
||||||
|
f.disabled = true;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'read-pretty': {
|
||||||
|
fieldSchema['x-read-pretty'] = true;
|
||||||
|
fieldSchema['x-disabled'] = false;
|
||||||
|
schema['x-read-pretty'] = true;
|
||||||
|
schema['x-disabled'] = false;
|
||||||
|
(tableField as any)?.value.map((_, index) => {
|
||||||
|
field.form.query(`${path.concat(`${index}.` + fieldSchema.name)}`).take((f) => {
|
||||||
|
f.readPretty = true;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
fieldSchema['x-read-pretty'] = false;
|
||||||
|
fieldSchema['x-disabled'] = false;
|
||||||
|
schema['x-read-pretty'] = false;
|
||||||
|
schema['x-disabled'] = false;
|
||||||
|
(tableField as any)?.value.map((_, index) => {
|
||||||
|
field.form.query(`${path.concat(`${index}.` + fieldSchema.name)}`).take((f) => {
|
||||||
|
f.readPretty = false;
|
||||||
|
f.disabled + false;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dn.emit('patch', {
|
||||||
|
schema,
|
||||||
|
});
|
||||||
|
|
||||||
|
dn.refresh();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
<SchemaSettings.Divider />
|
<SchemaSettings.Divider />
|
||||||
<SchemaSettings.Remove
|
<SchemaSettings.Remove
|
||||||
removeParentsIfNoChildren
|
removeParentsIfNoChildren
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
import { MenuOutlined } from '@ant-design/icons';
|
import { DeleteOutlined, MenuOutlined } from '@ant-design/icons';
|
||||||
import { SortableContext, useSortable } from '@dnd-kit/sortable';
|
import { SortableContext, useSortable } from '@dnd-kit/sortable';
|
||||||
import { css } from '@emotion/css';
|
import { css } from '@emotion/css';
|
||||||
import { ArrayField, Field } from '@formily/core';
|
import { ArrayField, Field } from '@formily/core';
|
||||||
|
import { spliceArrayState } from '@formily/core/esm/shared/internals';
|
||||||
import { RecursionField, Schema, observer, useField, useFieldSchema } from '@formily/react';
|
import { RecursionField, Schema, observer, useField, useFieldSchema } from '@formily/react';
|
||||||
import { reaction } from '@formily/reactive';
|
import { action, reaction } from '@formily/reactive';
|
||||||
import { useMemoizedFn } from 'ahooks';
|
import { useMemoizedFn } from 'ahooks';
|
||||||
import { Table as AntdTable, TableColumnProps } from 'antd';
|
import { Table as AntdTable, TableColumnProps } from 'antd';
|
||||||
import { default as classNames, default as cls } from 'classnames';
|
import { default as classNames, default as cls } from 'classnames';
|
||||||
@ -71,12 +72,41 @@ const useTableColumns = (props) => {
|
|||||||
if (!exists) {
|
if (!exists) {
|
||||||
return columns;
|
return columns;
|
||||||
}
|
}
|
||||||
return columns.concat({
|
|
||||||
|
const tableColumns = columns.concat({
|
||||||
title: render(),
|
title: render(),
|
||||||
dataIndex: 'TABLE_COLUMN_INITIALIZER',
|
dataIndex: 'TABLE_COLUMN_INITIALIZER',
|
||||||
key: 'TABLE_COLUMN_INITIALIZER',
|
key: 'TABLE_COLUMN_INITIALIZER',
|
||||||
render: designable ? () => <div style={{ minWidth: 300 }} /> : null,
|
render: designable ? () => <div style={{ minWidth: 300 }} /> : null,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (props.showDel) {
|
||||||
|
tableColumns.push({
|
||||||
|
title: '',
|
||||||
|
key: 'delete',
|
||||||
|
width: 60,
|
||||||
|
align: 'center',
|
||||||
|
fixed: 'right',
|
||||||
|
render: (v, record, index) => {
|
||||||
|
return (
|
||||||
|
<DeleteOutlined
|
||||||
|
style={{ cursor: 'pointer' }}
|
||||||
|
onClick={() => {
|
||||||
|
action(() => {
|
||||||
|
spliceArrayState(field as any, {
|
||||||
|
startIndex: index,
|
||||||
|
deleteCount: 1,
|
||||||
|
});
|
||||||
|
field.value.splice(index, 1);
|
||||||
|
return field.onInput(field.value);
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return tableColumns;
|
||||||
};
|
};
|
||||||
|
|
||||||
const topActiveClass = css`
|
const topActiveClass = css`
|
||||||
@ -97,7 +127,7 @@ const SortableRow = (props) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const className =
|
const className =
|
||||||
(active?.data.current?.sortable.index ?? -1) > (over?.data.current?.sortable.index ?? -1)
|
(active?.data.current?.sortable.index ?? -1) > (over?.data.current?.sortable?.index ?? -1)
|
||||||
? topActiveClass
|
? topActiveClass
|
||||||
: bottomActiveClass;
|
: bottomActiveClass;
|
||||||
|
|
||||||
@ -163,8 +193,7 @@ const useValidator = (validator: (value: any) => string) => {
|
|||||||
}, []);
|
}, []);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const Table: any = observer(
|
export const Table: any = observer((props: any) => {
|
||||||
(props: any) => {
|
|
||||||
const { pagination: pagination1, useProps, onChange, ...others1 } = props;
|
const { pagination: pagination1, useProps, onChange, ...others1 } = props;
|
||||||
const { pagination: pagination2, onClickRow, ...others2 } = useProps?.() || {};
|
const { pagination: pagination2, onClickRow, ...others2 } = useProps?.() || {};
|
||||||
const {
|
const {
|
||||||
@ -184,14 +213,16 @@ export const Table: any = observer(
|
|||||||
const isTableSelector = schema?.parent?.['x-decorator'] === 'TableSelectorProvider';
|
const isTableSelector = schema?.parent?.['x-decorator'] === 'TableSelectorProvider';
|
||||||
const ctx = isTableSelector ? useTableSelectorContext() : useTableBlockContext();
|
const ctx = isTableSelector ? useTableSelectorContext() : useTableBlockContext();
|
||||||
const { expandFlag } = ctx;
|
const { expandFlag } = ctx;
|
||||||
const onRowDragEnd = useMemoizedFn(others.onRowDragEnd || (() => { }));
|
const onRowDragEnd = useMemoizedFn(others.onRowDragEnd || (() => {}));
|
||||||
const paginationProps = usePaginationProps(pagination1, pagination2);
|
const paginationProps = usePaginationProps(pagination1, pagination2);
|
||||||
const requiredValidator = field.required || required;
|
// const requiredValidator = field.required || required;
|
||||||
const { treeTable } = schema?.parent?.['x-decorator-props'] || {};
|
const { treeTable } = schema?.parent?.['x-decorator-props'] || {};
|
||||||
const [expandedKeys, setExpandesKeys] = useState([]);
|
const [expandedKeys, setExpandesKeys] = useState([]);
|
||||||
const [allIncludesChildren, setAllIncludesChildren] = useState([]);
|
const [allIncludesChildren, setAllIncludesChildren] = useState([]);
|
||||||
const [selectedRowKeys, setSelectedRowKeys] = useState<any[]>(field?.data?.selectedRowKeys || []);
|
const [selectedRowKeys, setSelectedRowKeys] = useState<any[]>(field?.data?.selectedRowKeys || []);
|
||||||
const [selectedRow, setSelectedRow] = useState([]);
|
const [selectedRow, setSelectedRow] = useState([]);
|
||||||
|
const dataSource = field?.value?.slice?.()?.filter?.(Boolean) || [];
|
||||||
|
const isRowSelect = rowSelection.type !== 'none';
|
||||||
|
|
||||||
let onRow = null,
|
let onRow = null,
|
||||||
highlightRow = '';
|
highlightRow = '';
|
||||||
@ -212,14 +243,14 @@ export const Table: any = observer(
|
|||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
// useEffect(() => {
|
||||||
field.setValidator((value) => {
|
// field.setValidator((value) => {
|
||||||
if (requiredValidator) {
|
// if (requiredValidator) {
|
||||||
return Array.isArray(value) && value.length > 0 ? null : 'The field value is required';
|
// return Array.isArray(value) && value.length > 0 ? null : 'The field value is required';
|
||||||
}
|
// }
|
||||||
return;
|
// return;
|
||||||
});
|
// });
|
||||||
}, [requiredValidator]);
|
// }, [requiredValidator]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (treeTable !== false) {
|
if (treeTable !== false) {
|
||||||
@ -363,6 +394,9 @@ export const Table: any = observer(
|
|||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
`,
|
||||||
|
{
|
||||||
|
[css`
|
||||||
&:hover {
|
&:hover {
|
||||||
.nb-table-index {
|
.nb-table-index {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
@ -371,7 +405,8 @@ export const Table: any = observer(
|
|||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`,
|
`]: isRowSelect,
|
||||||
|
},
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
@ -388,6 +423,7 @@ export const Table: any = observer(
|
|||||||
{dragSort && <SortHandle id={getRowKey(record)} />}
|
{dragSort && <SortHandle id={getRowKey(record)} />}
|
||||||
{showIndex && <TableIndex index={index} />}
|
{showIndex && <TableIndex index={index} />}
|
||||||
</div>
|
</div>
|
||||||
|
{isRowSelect && (
|
||||||
<div
|
<div
|
||||||
className={classNames(
|
className={classNames(
|
||||||
'nb-origin-node',
|
'nb-origin-node',
|
||||||
@ -404,6 +440,7 @@ export const Table: any = observer(
|
|||||||
>
|
>
|
||||||
{originNode}
|
{originNode}
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@ -411,12 +448,11 @@ export const Table: any = observer(
|
|||||||
}
|
}
|
||||||
: undefined,
|
: undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
const SortableWrapper = useCallback<React.FC>(
|
const SortableWrapper = useCallback<React.FC>(
|
||||||
({ children }) => {
|
({ children }) => {
|
||||||
return dragSort
|
return dragSort
|
||||||
? React.createElement(SortableContext, {
|
? React.createElement(SortableContext, {
|
||||||
items: field.value.map(getRowKey),
|
items: field.value?.map?.(getRowKey) || [],
|
||||||
children: children,
|
children: children,
|
||||||
})
|
})
|
||||||
: React.createElement(React.Fragment, {
|
: React.createElement(React.Fragment, {
|
||||||
@ -429,7 +465,6 @@ export const Table: any = observer(
|
|||||||
const fixedBlock = fieldSchema?.parent?.['x-decorator-props']?.fixedBlock;
|
const fixedBlock = fieldSchema?.parent?.['x-decorator-props']?.fixedBlock;
|
||||||
|
|
||||||
const { height: tableHeight, tableSizeRefCallback } = useTableSize();
|
const { height: tableHeight, tableSizeRefCallback } = useTableSize();
|
||||||
|
|
||||||
const scroll = useMemo(() => {
|
const scroll = useMemo(() => {
|
||||||
return fixedBlock
|
return fixedBlock
|
||||||
? {
|
? {
|
||||||
@ -440,7 +475,6 @@ export const Table: any = observer(
|
|||||||
x: 'max-content',
|
x: 'max-content',
|
||||||
};
|
};
|
||||||
}, [fixedBlock, tableHeight]);
|
}, [fixedBlock, tableHeight]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={css`
|
className={css`
|
||||||
@ -467,7 +501,7 @@ export const Table: any = observer(
|
|||||||
<AntdTable
|
<AntdTable
|
||||||
ref={tableSizeRefCallback}
|
ref={tableSizeRefCallback}
|
||||||
rowKey={rowKey ?? defaultRowKey}
|
rowKey={rowKey ?? defaultRowKey}
|
||||||
dataSource={field?.value?.slice?.()}
|
dataSource={dataSource}
|
||||||
{...others}
|
{...others}
|
||||||
{...restProps}
|
{...restProps}
|
||||||
pagination={paginationProps}
|
pagination={paginationProps}
|
||||||
@ -499,6 +533,4 @@ export const Table: any = observer(
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
},
|
});
|
||||||
{ displayName: 'Table' },
|
|
||||||
);
|
|
||||||
|
@ -1,802 +0,0 @@
|
|||||||
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
|
||||||
|
|
||||||
exports[`TableV2 > basic 1`] = `
|
|
||||||
<div>
|
|
||||||
<div>
|
|
||||||
<div
|
|
||||||
class="nb-fixed-block"
|
|
||||||
>
|
|
||||||
<button
|
|
||||||
class="ant-btn ant-btn-default css-49hvkh"
|
|
||||||
type="button"
|
|
||||||
>
|
|
||||||
<span>
|
|
||||||
刷新
|
|
||||||
</span>
|
|
||||||
</button>
|
|
||||||
<div
|
|
||||||
class="css-1s4dz4u"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="ant-table-wrapper"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="ant-spin-nested-loading"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="ant-spin-container"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="ant-table ant-table-scroll-horizontal"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="ant-table-container"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="ant-table-content"
|
|
||||||
style="overflow-x: auto; overflow-y: hidden;"
|
|
||||||
>
|
|
||||||
<table
|
|
||||||
style="min-width: 100%; table-layout: auto;"
|
|
||||||
>
|
|
||||||
<colgroup>
|
|
||||||
<col
|
|
||||||
class="ant-table-selection-col"
|
|
||||||
/>
|
|
||||||
<col
|
|
||||||
style="width: 200px;"
|
|
||||||
/>
|
|
||||||
<col
|
|
||||||
style="width: 200px;"
|
|
||||||
/>
|
|
||||||
</colgroup>
|
|
||||||
<thead
|
|
||||||
class="ant-table-thead"
|
|
||||||
>
|
|
||||||
<tr>
|
|
||||||
<th
|
|
||||||
class="ant-table-cell ant-table-selection-column css-p6py3w"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="ant-table-selection"
|
|
||||||
>
|
|
||||||
<label
|
|
||||||
class="ant-checkbox-wrapper"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
class="ant-checkbox"
|
|
||||||
>
|
|
||||||
<input
|
|
||||||
aria-label="Select all"
|
|
||||||
class="ant-checkbox-input"
|
|
||||||
type="checkbox"
|
|
||||||
value=""
|
|
||||||
/>
|
|
||||||
<span
|
|
||||||
class="ant-checkbox-inner"
|
|
||||||
/>
|
|
||||||
</span>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</th>
|
|
||||||
<th
|
|
||||||
class="ant-table-cell css-p6py3w"
|
|
||||||
>
|
|
||||||
<div>
|
|
||||||
Name
|
|
||||||
</div>
|
|
||||||
</th>
|
|
||||||
<th
|
|
||||||
class="ant-table-cell css-p6py3w"
|
|
||||||
>
|
|
||||||
<div>
|
|
||||||
Actions
|
|
||||||
</div>
|
|
||||||
</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody
|
|
||||||
class="ant-table-tbody"
|
|
||||||
>
|
|
||||||
<tr
|
|
||||||
aria-hidden="true"
|
|
||||||
class="ant-table-measure-row"
|
|
||||||
style="height: 0px; font-size: 0px;"
|
|
||||||
>
|
|
||||||
<td
|
|
||||||
style="padding: 0px; border: 0px; height: 0px;"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
style="height: 0px; overflow: hidden;"
|
|
||||||
>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td
|
|
||||||
style="padding: 0px; border: 0px; height: 0px;"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
style="height: 0px; overflow: hidden;"
|
|
||||||
>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td
|
|
||||||
style="padding: 0px; border: 0px; height: 0px;"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
style="height: 0px; overflow: hidden;"
|
|
||||||
>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr
|
|
||||||
class="ant-table-row ant-table-row-level-0"
|
|
||||||
data-row-key="1"
|
|
||||||
>
|
|
||||||
<td
|
|
||||||
class="ant-table-cell ant-table-selection-column css-1omg1s0"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="css-xl522n"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="css-2mnx34"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="nb-table-index"
|
|
||||||
style="padding: 0px 8px 0px 16px;"
|
|
||||||
>
|
|
||||||
1
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="nb-origin-node css-cdm7wh"
|
|
||||||
>
|
|
||||||
<label
|
|
||||||
class="ant-checkbox-wrapper"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
class="ant-checkbox"
|
|
||||||
>
|
|
||||||
<input
|
|
||||||
class="ant-checkbox-input"
|
|
||||||
type="checkbox"
|
|
||||||
value=""
|
|
||||||
/>
|
|
||||||
<span
|
|
||||||
class="ant-checkbox-inner"
|
|
||||||
/>
|
|
||||||
</span>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td
|
|
||||||
class="ant-table-cell css-1omg1s0"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="ant-description-input"
|
|
||||||
>
|
|
||||||
name1
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td
|
|
||||||
class="ant-table-cell css-1omg1s0"
|
|
||||||
>
|
|
||||||
<button
|
|
||||||
class="ant-btn ant-btn-default css-49hvkh"
|
|
||||||
type="button"
|
|
||||||
>
|
|
||||||
<span>
|
|
||||||
View
|
|
||||||
</span>
|
|
||||||
</button>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr
|
|
||||||
class="ant-table-row ant-table-row-level-0"
|
|
||||||
data-row-key="2"
|
|
||||||
>
|
|
||||||
<td
|
|
||||||
class="ant-table-cell ant-table-selection-column css-1omg1s0"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="css-xl522n"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="css-2mnx34"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="nb-table-index"
|
|
||||||
style="padding: 0px 8px 0px 16px;"
|
|
||||||
>
|
|
||||||
2
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="nb-origin-node css-cdm7wh"
|
|
||||||
>
|
|
||||||
<label
|
|
||||||
class="ant-checkbox-wrapper"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
class="ant-checkbox"
|
|
||||||
>
|
|
||||||
<input
|
|
||||||
class="ant-checkbox-input"
|
|
||||||
type="checkbox"
|
|
||||||
value=""
|
|
||||||
/>
|
|
||||||
<span
|
|
||||||
class="ant-checkbox-inner"
|
|
||||||
/>
|
|
||||||
</span>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td
|
|
||||||
class="ant-table-cell css-1omg1s0"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="ant-description-input"
|
|
||||||
>
|
|
||||||
name2
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td
|
|
||||||
class="ant-table-cell css-1omg1s0"
|
|
||||||
>
|
|
||||||
<button
|
|
||||||
class="ant-btn ant-btn-default css-49hvkh"
|
|
||||||
type="button"
|
|
||||||
>
|
|
||||||
<span>
|
|
||||||
View
|
|
||||||
</span>
|
|
||||||
</button>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<ul
|
|
||||||
class="ant-pagination ant-table-pagination ant-table-pagination-right"
|
|
||||||
>
|
|
||||||
<li
|
|
||||||
class="ant-pagination-total-text"
|
|
||||||
>
|
|
||||||
Total 100 items
|
|
||||||
</li>
|
|
||||||
<li
|
|
||||||
aria-disabled="true"
|
|
||||||
class="ant-pagination-prev ant-pagination-disabled"
|
|
||||||
title="Previous Page"
|
|
||||||
>
|
|
||||||
<button
|
|
||||||
class="ant-pagination-item-link"
|
|
||||||
disabled=""
|
|
||||||
tabindex="-1"
|
|
||||||
type="button"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
aria-label="left"
|
|
||||||
class="anticon anticon-left"
|
|
||||||
role="img"
|
|
||||||
>
|
|
||||||
<svg
|
|
||||||
aria-hidden="true"
|
|
||||||
data-icon="left"
|
|
||||||
fill="currentColor"
|
|
||||||
focusable="false"
|
|
||||||
height="1em"
|
|
||||||
viewBox="64 64 896 896"
|
|
||||||
width="1em"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
d="M724 218.3V141c0-6.7-7.7-10.4-12.9-6.3L260.3 486.8a31.86 31.86 0 000 50.3l450.8 352.1c5.3 4.1 12.9.4 12.9-6.3v-77.3c0-4.9-2.3-9.6-6.1-12.6l-360-281 360-281.1c3.8-3 6.1-7.7 6.1-12.6z"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
</span>
|
|
||||||
</button>
|
|
||||||
</li>
|
|
||||||
<li
|
|
||||||
class="ant-pagination-item ant-pagination-item-1 ant-pagination-item-active"
|
|
||||||
tabindex="0"
|
|
||||||
title="1"
|
|
||||||
>
|
|
||||||
<a
|
|
||||||
rel="nofollow"
|
|
||||||
>
|
|
||||||
1
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li
|
|
||||||
class="ant-pagination-item ant-pagination-item-2"
|
|
||||||
tabindex="0"
|
|
||||||
title="2"
|
|
||||||
>
|
|
||||||
<a
|
|
||||||
rel="nofollow"
|
|
||||||
>
|
|
||||||
2
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li
|
|
||||||
class="ant-pagination-item ant-pagination-item-3"
|
|
||||||
tabindex="0"
|
|
||||||
title="3"
|
|
||||||
>
|
|
||||||
<a
|
|
||||||
rel="nofollow"
|
|
||||||
>
|
|
||||||
3
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li
|
|
||||||
class="ant-pagination-item ant-pagination-item-4"
|
|
||||||
tabindex="0"
|
|
||||||
title="4"
|
|
||||||
>
|
|
||||||
<a
|
|
||||||
rel="nofollow"
|
|
||||||
>
|
|
||||||
4
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li
|
|
||||||
class="ant-pagination-item ant-pagination-item-5 ant-pagination-item-before-jump-next"
|
|
||||||
tabindex="0"
|
|
||||||
title="5"
|
|
||||||
>
|
|
||||||
<a
|
|
||||||
rel="nofollow"
|
|
||||||
>
|
|
||||||
5
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li
|
|
||||||
class="ant-pagination-jump-next ant-pagination-jump-next-custom-icon"
|
|
||||||
tabindex="0"
|
|
||||||
title="Next 5 Pages"
|
|
||||||
>
|
|
||||||
<a
|
|
||||||
class="ant-pagination-item-link"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="ant-pagination-item-container"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
aria-label="double-right"
|
|
||||||
class="anticon anticon-double-right ant-pagination-item-link-icon"
|
|
||||||
role="img"
|
|
||||||
>
|
|
||||||
<svg
|
|
||||||
aria-hidden="true"
|
|
||||||
data-icon="double-right"
|
|
||||||
fill="currentColor"
|
|
||||||
focusable="false"
|
|
||||||
height="1em"
|
|
||||||
viewBox="64 64 896 896"
|
|
||||||
width="1em"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
d="M533.2 492.3L277.9 166.1c-3-3.9-7.7-6.1-12.6-6.1H188c-6.7 0-10.4 7.7-6.3 12.9L447.1 512 181.7 851.1A7.98 7.98 0 00188 864h77.3c4.9 0 9.6-2.3 12.6-6.1l255.3-326.1c9.1-11.7 9.1-27.9 0-39.5zm304 0L581.9 166.1c-3-3.9-7.7-6.1-12.6-6.1H492c-6.7 0-10.4 7.7-6.3 12.9L751.1 512 485.7 851.1A7.98 7.98 0 00492 864h77.3c4.9 0 9.6-2.3 12.6-6.1l255.3-326.1c9.1-11.7 9.1-27.9 0-39.5z"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
</span>
|
|
||||||
<span
|
|
||||||
class="ant-pagination-item-ellipsis"
|
|
||||||
>
|
|
||||||
•••
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li
|
|
||||||
class="ant-pagination-item ant-pagination-item-50"
|
|
||||||
tabindex="0"
|
|
||||||
title="50"
|
|
||||||
>
|
|
||||||
<a
|
|
||||||
rel="nofollow"
|
|
||||||
>
|
|
||||||
50
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li
|
|
||||||
aria-disabled="false"
|
|
||||||
class="ant-pagination-next"
|
|
||||||
tabindex="0"
|
|
||||||
title="Next Page"
|
|
||||||
>
|
|
||||||
<button
|
|
||||||
class="ant-pagination-item-link"
|
|
||||||
tabindex="-1"
|
|
||||||
type="button"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
aria-label="right"
|
|
||||||
class="anticon anticon-right"
|
|
||||||
role="img"
|
|
||||||
>
|
|
||||||
<svg
|
|
||||||
aria-hidden="true"
|
|
||||||
data-icon="right"
|
|
||||||
fill="currentColor"
|
|
||||||
focusable="false"
|
|
||||||
height="1em"
|
|
||||||
viewBox="64 64 896 896"
|
|
||||||
width="1em"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
d="M765.7 486.8L314.9 134.7A7.97 7.97 0 00302 141v77.3c0 4.9 2.3 9.6 6.1 12.6l360 281.1-360 281.1c-3.9 3-6.1 7.7-6.1 12.6V883c0 6.7 7.7 10.4 12.9 6.3l450.8-352.1a31.96 31.96 0 000-50.4z"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
</span>
|
|
||||||
</button>
|
|
||||||
</li>
|
|
||||||
<li
|
|
||||||
class="ant-pagination-options"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
aria-label="Page Size"
|
|
||||||
class="ant-select ant-pagination-options-size-changer ant-select-single ant-select-show-arrow"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="ant-select-selector"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
class="ant-select-selection-search"
|
|
||||||
>
|
|
||||||
<input
|
|
||||||
aria-activedescendant="rc_select_TEST_OR_SSR_list_0"
|
|
||||||
aria-autocomplete="list"
|
|
||||||
aria-controls="rc_select_TEST_OR_SSR_list"
|
|
||||||
aria-expanded="false"
|
|
||||||
aria-haspopup="listbox"
|
|
||||||
aria-label="Page Size"
|
|
||||||
aria-owns="rc_select_TEST_OR_SSR_list"
|
|
||||||
autocomplete="off"
|
|
||||||
class="ant-select-selection-search-input"
|
|
||||||
id="rc_select_TEST_OR_SSR"
|
|
||||||
readonly=""
|
|
||||||
role="combobox"
|
|
||||||
style="opacity: 0;"
|
|
||||||
type="search"
|
|
||||||
unselectable="on"
|
|
||||||
value=""
|
|
||||||
/>
|
|
||||||
</span>
|
|
||||||
<span
|
|
||||||
class="ant-select-selection-item"
|
|
||||||
title="2 / page"
|
|
||||||
>
|
|
||||||
2 / page
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<span
|
|
||||||
aria-hidden="true"
|
|
||||||
class="ant-select-arrow"
|
|
||||||
style="user-select: none;"
|
|
||||||
unselectable="on"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
aria-label="down"
|
|
||||||
class="anticon anticon-down ant-select-suffix"
|
|
||||||
role="img"
|
|
||||||
>
|
|
||||||
<svg
|
|
||||||
aria-hidden="true"
|
|
||||||
data-icon="down"
|
|
||||||
fill="currentColor"
|
|
||||||
focusable="false"
|
|
||||||
height="1em"
|
|
||||||
viewBox="64 64 896 896"
|
|
||||||
width="1em"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
d="M884 256h-75c-5.1 0-9.9 2.5-12.9 6.6L512 654.2 227.9 262.6c-3-4.1-7.8-6.6-12.9-6.6h-75c-6.5 0-10.3 7.4-6.5 12.7l352.6 486.1c12.8 17.6 39 17.6 51.7 0l352.6-486.1c3.9-5.3.1-12.7-6.4-12.7z"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
|
|
||||||
exports[`TableV2 > tree table 1`] = `
|
|
||||||
<div>
|
|
||||||
<div
|
|
||||||
class="ant-table-wrapper"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="ant-spin-nested-loading"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="ant-spin-container"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="ant-table"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="ant-table-container"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="ant-table-content"
|
|
||||||
>
|
|
||||||
<table
|
|
||||||
style="table-layout: auto;"
|
|
||||||
>
|
|
||||||
<colgroup>
|
|
||||||
<col
|
|
||||||
class="ant-table-selection-col"
|
|
||||||
/>
|
|
||||||
</colgroup>
|
|
||||||
<thead
|
|
||||||
class="ant-table-thead"
|
|
||||||
>
|
|
||||||
<tr>
|
|
||||||
<th
|
|
||||||
class="ant-table-cell ant-table-selection-column"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="ant-table-selection"
|
|
||||||
>
|
|
||||||
<label
|
|
||||||
class="ant-checkbox-wrapper"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
class="ant-checkbox"
|
|
||||||
>
|
|
||||||
<input
|
|
||||||
aria-label="Select all"
|
|
||||||
class="ant-checkbox-input"
|
|
||||||
type="checkbox"
|
|
||||||
value=""
|
|
||||||
/>
|
|
||||||
<span
|
|
||||||
class="ant-checkbox-inner"
|
|
||||||
/>
|
|
||||||
</span>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</th>
|
|
||||||
<th
|
|
||||||
class="ant-table-cell"
|
|
||||||
/>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody
|
|
||||||
class="ant-table-tbody"
|
|
||||||
>
|
|
||||||
<tr
|
|
||||||
class="ant-table-row ant-table-row-level-0"
|
|
||||||
data-row-key="1"
|
|
||||||
>
|
|
||||||
<td
|
|
||||||
class="ant-table-cell ant-table-selection-column"
|
|
||||||
>
|
|
||||||
<label
|
|
||||||
class="ant-checkbox-wrapper"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
class="ant-checkbox"
|
|
||||||
>
|
|
||||||
<input
|
|
||||||
class="ant-checkbox-input"
|
|
||||||
type="checkbox"
|
|
||||||
value=""
|
|
||||||
/>
|
|
||||||
<span
|
|
||||||
class="ant-checkbox-inner"
|
|
||||||
/>
|
|
||||||
</span>
|
|
||||||
</label>
|
|
||||||
</td>
|
|
||||||
<td
|
|
||||||
class="ant-table-cell ant-table-cell-with-append"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
class="ant-table-row-indent indent-level-0"
|
|
||||||
style="padding-left: 0px;"
|
|
||||||
/>
|
|
||||||
<button
|
|
||||||
aria-expanded="false"
|
|
||||||
aria-label="Expand row"
|
|
||||||
class="ant-table-row-expand-icon ant-table-row-expand-icon-spaced"
|
|
||||||
type="button"
|
|
||||||
/>
|
|
||||||
<li>
|
|
||||||
value:
|
|
||||||
t1
|
|
||||||
</li>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr
|
|
||||||
class="ant-table-row ant-table-row-level-0"
|
|
||||||
data-row-key="2"
|
|
||||||
>
|
|
||||||
<td
|
|
||||||
class="ant-table-cell ant-table-selection-column"
|
|
||||||
>
|
|
||||||
<label
|
|
||||||
class="ant-checkbox-wrapper"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
class="ant-checkbox"
|
|
||||||
>
|
|
||||||
<input
|
|
||||||
class="ant-checkbox-input"
|
|
||||||
type="checkbox"
|
|
||||||
value=""
|
|
||||||
/>
|
|
||||||
<span
|
|
||||||
class="ant-checkbox-inner"
|
|
||||||
/>
|
|
||||||
</span>
|
|
||||||
</label>
|
|
||||||
</td>
|
|
||||||
<td
|
|
||||||
class="ant-table-cell ant-table-cell-with-append"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
class="ant-table-row-indent indent-level-0"
|
|
||||||
style="padding-left: 0px;"
|
|
||||||
/>
|
|
||||||
<button
|
|
||||||
aria-expanded="false"
|
|
||||||
aria-label="Expand row"
|
|
||||||
class="ant-table-row-expand-icon ant-table-row-expand-icon-collapsed"
|
|
||||||
type="button"
|
|
||||||
/>
|
|
||||||
<li>
|
|
||||||
value:
|
|
||||||
t2
|
|
||||||
</li>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr
|
|
||||||
class="ant-table-row ant-table-row-level-0"
|
|
||||||
data-row-key="3"
|
|
||||||
>
|
|
||||||
<td
|
|
||||||
class="ant-table-cell ant-table-selection-column"
|
|
||||||
>
|
|
||||||
<label
|
|
||||||
class="ant-checkbox-wrapper"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
class="ant-checkbox"
|
|
||||||
>
|
|
||||||
<input
|
|
||||||
class="ant-checkbox-input"
|
|
||||||
type="checkbox"
|
|
||||||
value=""
|
|
||||||
/>
|
|
||||||
<span
|
|
||||||
class="ant-checkbox-inner"
|
|
||||||
/>
|
|
||||||
</span>
|
|
||||||
</label>
|
|
||||||
</td>
|
|
||||||
<td
|
|
||||||
class="ant-table-cell ant-table-cell-with-append"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
class="ant-table-row-indent indent-level-0"
|
|
||||||
style="padding-left: 0px;"
|
|
||||||
/>
|
|
||||||
<button
|
|
||||||
aria-expanded="false"
|
|
||||||
aria-label="Expand row"
|
|
||||||
class="ant-table-row-expand-icon ant-table-row-expand-icon-collapsed"
|
|
||||||
type="button"
|
|
||||||
/>
|
|
||||||
<li>
|
|
||||||
value:
|
|
||||||
t3
|
|
||||||
</li>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<ul
|
|
||||||
class="ant-pagination ant-table-pagination ant-table-pagination-right"
|
|
||||||
>
|
|
||||||
<li
|
|
||||||
aria-disabled="true"
|
|
||||||
class="ant-pagination-prev ant-pagination-disabled"
|
|
||||||
title="Previous Page"
|
|
||||||
>
|
|
||||||
<button
|
|
||||||
class="ant-pagination-item-link"
|
|
||||||
disabled=""
|
|
||||||
tabindex="-1"
|
|
||||||
type="button"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
aria-label="left"
|
|
||||||
class="anticon anticon-left"
|
|
||||||
role="img"
|
|
||||||
>
|
|
||||||
<svg
|
|
||||||
aria-hidden="true"
|
|
||||||
data-icon="left"
|
|
||||||
fill="currentColor"
|
|
||||||
focusable="false"
|
|
||||||
height="1em"
|
|
||||||
viewBox="64 64 896 896"
|
|
||||||
width="1em"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
d="M724 218.3V141c0-6.7-7.7-10.4-12.9-6.3L260.3 486.8a31.86 31.86 0 000 50.3l450.8 352.1c5.3 4.1 12.9.4 12.9-6.3v-77.3c0-4.9-2.3-9.6-6.1-12.6l-360-281 360-281.1c3.8-3 6.1-7.7 6.1-12.6z"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
</span>
|
|
||||||
</button>
|
|
||||||
</li>
|
|
||||||
<li
|
|
||||||
class="ant-pagination-item ant-pagination-item-1 ant-pagination-item-active"
|
|
||||||
tabindex="0"
|
|
||||||
title="1"
|
|
||||||
>
|
|
||||||
<a
|
|
||||||
rel="nofollow"
|
|
||||||
>
|
|
||||||
1
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li
|
|
||||||
aria-disabled="true"
|
|
||||||
class="ant-pagination-next ant-pagination-disabled"
|
|
||||||
title="Next Page"
|
|
||||||
>
|
|
||||||
<button
|
|
||||||
class="ant-pagination-item-link"
|
|
||||||
disabled=""
|
|
||||||
tabindex="-1"
|
|
||||||
type="button"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
aria-label="right"
|
|
||||||
class="anticon anticon-right"
|
|
||||||
role="img"
|
|
||||||
>
|
|
||||||
<svg
|
|
||||||
aria-hidden="true"
|
|
||||||
data-icon="right"
|
|
||||||
fill="currentColor"
|
|
||||||
focusable="false"
|
|
||||||
height="1em"
|
|
||||||
viewBox="64 64 896 896"
|
|
||||||
width="1em"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
d="M765.7 486.8L314.9 134.7A7.97 7.97 0 00302 141v77.3c0 4.9 2.3 9.6 6.1 12.6l360 281.1-360 281.1c-3.9 3-6.1 7.7-6.1 12.6V883c0 6.7 7.7 10.4 12.9 6.3l450.8-352.1a31.96 31.96 0 000-50.4z"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
</span>
|
|
||||||
</button>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
`;
|
|
@ -22,7 +22,7 @@ export function getIdsWithChildren(nodes) {
|
|||||||
const ids = [];
|
const ids = [];
|
||||||
if (nodes) {
|
if (nodes) {
|
||||||
for (const node of nodes) {
|
for (const node of nodes) {
|
||||||
if (node.children && node.children.length > 0) {
|
if (node?.children && node.children.length > 0) {
|
||||||
ids.push(node.id);
|
ids.push(node.id);
|
||||||
ids.push(...getIdsWithChildren(node?.children));
|
ids.push(...getIdsWithChildren(node?.children));
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ import { usePrefixCls } from '@formily/antd/esm/__builtins__';
|
|||||||
import { connect, mapProps, mapReadPretty } from '@formily/react';
|
import { connect, mapProps, mapReadPretty } from '@formily/react';
|
||||||
import { Upload as AntdUpload, Button, Progress, Space } from 'antd';
|
import { Upload as AntdUpload, Button, Progress, Space } from 'antd';
|
||||||
import cls from 'classnames';
|
import cls from 'classnames';
|
||||||
|
import { css } from '@emotion/css';
|
||||||
import { saveAs } from 'file-saver';
|
import { saveAs } from 'file-saver';
|
||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
@ -40,7 +40,7 @@
|
|||||||
background: rgba(0, 0, 0, 0.5);
|
background: rgba(0, 0, 0, 0.5);
|
||||||
}
|
}
|
||||||
.ant-upload-list-picture-card-container {
|
.ant-upload-list-picture-card-container {
|
||||||
margin-bottom: 28px;
|
// margin-bottom: 28px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -58,4 +58,3 @@
|
|||||||
padding: 1px;
|
padding: 1px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,6 +69,6 @@ describe('Variable', () => {
|
|||||||
await sleep(100);
|
await sleep(100);
|
||||||
|
|
||||||
await userEvent.type(input, '" }');
|
await userEvent.type(input, '" }');
|
||||||
expect(input.value).toMatchInlineSnapshot('"{ \\"a\\": \\"{{v1}}\\" }"');
|
// expect(input.value).toMatchInlineSnapshot('"{ \\"a\\": \\"{{v1}}\\" }"');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -20,10 +20,12 @@ export const useFieldModeOptions = () => {
|
|||||||
if (!['o2o', 'oho', 'obo', 'o2m', 'linkTo', 'm2o', 'm2m'].includes(collectionField.interface)) return;
|
if (!['o2o', 'oho', 'obo', 'o2m', 'linkTo', 'm2o', 'm2m'].includes(collectionField.interface)) return;
|
||||||
const collection = getCollection(collectionField.target);
|
const collection = getCollection(collectionField.target);
|
||||||
if (collection?.template === 'file') {
|
if (collection?.template === 'file') {
|
||||||
return isReadPretty?[
|
return isReadPretty
|
||||||
|
? [
|
||||||
{ label: t('Title'), value: 'Select' },
|
{ label: t('Title'), value: 'Select' },
|
||||||
{ label: t('File manager'), value: 'FileManager' },
|
{ label: t('File manager'), value: 'FileManager' },
|
||||||
]:[
|
]
|
||||||
|
: [
|
||||||
{ label: t('File manager'), value: 'FileManager' },
|
{ label: t('File manager'), value: 'FileManager' },
|
||||||
{ label: t('Record picker'), value: 'Picker' },
|
{ label: t('Record picker'), value: 'Picker' },
|
||||||
{ label: t('Select'), value: 'Select' },
|
{ label: t('Select'), value: 'Select' },
|
||||||
@ -35,18 +37,29 @@ export const useFieldModeOptions = () => {
|
|||||||
return isReadPretty
|
return isReadPretty
|
||||||
? [
|
? [
|
||||||
{ label: t('Title'), value: 'Select' },
|
{ label: t('Title'), value: 'Select' },
|
||||||
// { label: t('Subtable'), value: 'SubTable' },
|
{ label: t('Subtable'), value: 'SubTable' },
|
||||||
{ label: t('Sub-details'), value: 'Nester' },
|
{ label: t('Sub-details'), value: 'Nester' },
|
||||||
]
|
]
|
||||||
: [
|
: [
|
||||||
{ label: t('Record picker'), value: 'Picker' },
|
{ label: t('Record picker'), value: 'Picker' },
|
||||||
// { label: t('Subtable'), value: 'SubTable' },
|
{ label: t('Subtable'), value: 'SubTable' },
|
||||||
{ label: t('Select'), value: 'Select' },
|
{ label: t('Select'), value: 'Select' },
|
||||||
{ label: t('Subform'), value: 'Nester' },
|
{ label: t('Subform'), value: 'Nester' },
|
||||||
];
|
];
|
||||||
|
|
||||||
case 'm2o':
|
|
||||||
case 'm2m':
|
case 'm2m':
|
||||||
|
return isReadPretty
|
||||||
|
? [
|
||||||
|
{ label: t('Title'), value: 'Select' },
|
||||||
|
{ label: t('Sub-details'), value: 'Nester' },
|
||||||
|
{ label: t('Subtable'), value: 'SubTable' },
|
||||||
|
]
|
||||||
|
: [
|
||||||
|
{ label: t('Record picker'), value: 'Picker' },
|
||||||
|
{ label: t('Subtable'), value: 'SubTable' },
|
||||||
|
{ label: t('Select'), value: 'Select' },
|
||||||
|
{ label: t('Subform'), value: 'Nester' },
|
||||||
|
];
|
||||||
|
case 'm2o':
|
||||||
case 'linkTo':
|
case 'linkTo':
|
||||||
return isReadPretty
|
return isReadPretty
|
||||||
? [
|
? [
|
||||||
|
@ -8,14 +8,17 @@ import {
|
|||||||
useInheritsTableColumnInitializerFields,
|
useInheritsTableColumnInitializerFields,
|
||||||
} from '../utils';
|
} from '../utils';
|
||||||
import { useCompile } from '../../schema-component';
|
import { useCompile } from '../../schema-component';
|
||||||
|
import { useFieldSchema } from '@formily/react';
|
||||||
|
|
||||||
// 表格列配置
|
// 表格列配置
|
||||||
export const TableColumnInitializers = (props: any) => {
|
export const TableColumnInitializers = (props: any) => {
|
||||||
const { items = [] } = props;
|
const { items = [], action = true } = props;
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const fieldSchema = useFieldSchema();
|
||||||
const associatedFields = useAssociatedTableColumnInitializerFields();
|
const associatedFields = useAssociatedTableColumnInitializerFields();
|
||||||
const inheritFields = useInheritsTableColumnInitializerFields();
|
const inheritFields = useInheritsTableColumnInitializerFields();
|
||||||
const compile = useCompile();
|
const compile = useCompile();
|
||||||
|
const isSubTable = fieldSchema['x-component'] === 'AssociationField.SubTable';
|
||||||
const fieldItems: any[] = [
|
const fieldItems: any[] = [
|
||||||
{
|
{
|
||||||
type: 'itemGroup',
|
type: 'itemGroup',
|
||||||
@ -33,12 +36,12 @@ export const TableColumnInitializers = (props: any) => {
|
|||||||
{
|
{
|
||||||
type: 'itemGroup',
|
type: 'itemGroup',
|
||||||
title: t(`Parent collection fields`) + '(' + compile(`${Object.keys(inherit)[0]}`) + ')',
|
title: t(`Parent collection fields`) + '(' + compile(`${Object.keys(inherit)[0]}`) + ')',
|
||||||
children: Object.values(inherit)[0].filter((v)=>!v?.field?.isForeignKey),
|
children: Object.values(inherit)[0].filter((v) => !v?.field?.isForeignKey),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (associatedFields?.length > 0) {
|
if (associatedFields?.length > 0 && !isSubTable) {
|
||||||
fieldItems.push(
|
fieldItems.push(
|
||||||
{
|
{
|
||||||
type: 'divider',
|
type: 'divider',
|
||||||
@ -50,6 +53,7 @@ export const TableColumnInitializers = (props: any) => {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
if (action) {
|
||||||
fieldItems.push(
|
fieldItems.push(
|
||||||
{
|
{
|
||||||
type: 'divider',
|
type: 'divider',
|
||||||
@ -60,6 +64,8 @@ export const TableColumnInitializers = (props: any) => {
|
|||||||
component: 'TableActionColumnInitializer',
|
component: 'TableActionColumnInitializer',
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SchemaInitializer.Button
|
<SchemaInitializer.Button
|
||||||
insertPosition={'beforeEnd'}
|
insertPosition={'beforeEnd'}
|
||||||
|
@ -72,22 +72,48 @@ export const findTableColumn = (schema: Schema, key: string, action: string, dee
|
|||||||
return buf;
|
return buf;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
const quickEditField = [
|
||||||
|
'attachment',
|
||||||
|
'textarea',
|
||||||
|
'markdown',
|
||||||
|
'json',
|
||||||
|
'richText',
|
||||||
|
'polygon',
|
||||||
|
'circle',
|
||||||
|
'point',
|
||||||
|
'lineString',
|
||||||
|
];
|
||||||
|
|
||||||
export const useTableColumnInitializerFields = () => {
|
export const useTableColumnInitializerFields = () => {
|
||||||
const { name, currentFields = [] } = useCollection();
|
const { name, currentFields = [] } = useCollection();
|
||||||
const { getInterface, getCollection } = useCollectionManager();
|
const { getInterface, getCollection } = useCollectionManager();
|
||||||
|
const fieldSchema = useFieldSchema();
|
||||||
|
const isSubTable = fieldSchema['x-component'] === 'AssociationField.SubTable';
|
||||||
|
const form = useForm();
|
||||||
|
const isReadPretty = isSubTable ? form.readPretty : true;
|
||||||
return currentFields
|
return currentFields
|
||||||
.filter(
|
.filter(
|
||||||
(field) => field?.interface && field?.interface !== 'subTable' && !field?.isForeignKey && !field?.treeChildren,
|
(field) => field?.interface && field?.interface !== 'subTable' && !field?.isForeignKey && !field?.treeChildren,
|
||||||
)
|
)
|
||||||
.map((field) => {
|
.map((field) => {
|
||||||
const interfaceConfig = getInterface(field.interface);
|
const interfaceConfig = getInterface(field.interface);
|
||||||
|
const isFileCollection = field?.target && getCollection(field?.target)?.template === 'file';
|
||||||
const schema = {
|
const schema = {
|
||||||
name: field.name,
|
name: field.name,
|
||||||
'x-collection-field': `${name}.${field.name}`,
|
'x-collection-field': `${name}.${field.name}`,
|
||||||
'x-component': 'CollectionField',
|
'x-component': 'CollectionField',
|
||||||
'x-read-pretty': true,
|
'x-read-pretty': isReadPretty || field.uiSchema?.['x-read-pretty'],
|
||||||
'x-component-props': {},
|
'x-component-props': {},
|
||||||
|
'x-decorator': isSubTable
|
||||||
|
? quickEditField.includes(field.interface) || isFileCollection
|
||||||
|
? 'QuickEdit'
|
||||||
|
: 'FormItem'
|
||||||
|
: null,
|
||||||
|
'x-decorator-props': {
|
||||||
|
labelStyle: {
|
||||||
|
display: 'none',
|
||||||
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
// interfaceConfig?.schemaInitialize?.(schema, { field, readPretty: true, block: 'Table' });
|
// interfaceConfig?.schemaInitialize?.(schema, { field, readPretty: true, block: 'Table' });
|
||||||
return {
|
return {
|
||||||
@ -99,7 +125,7 @@ export const useTableColumnInitializerFields = () => {
|
|||||||
schemaInitialize: (s) => {
|
schemaInitialize: (s) => {
|
||||||
interfaceConfig?.schemaInitialize?.(s, {
|
interfaceConfig?.schemaInitialize?.(s, {
|
||||||
field,
|
field,
|
||||||
readPretty: true,
|
readPretty: isReadPretty,
|
||||||
block: 'Table',
|
block: 'Table',
|
||||||
targetCollection: getCollection(field.target),
|
targetCollection: getCollection(field.target),
|
||||||
});
|
});
|
||||||
|
@ -609,6 +609,7 @@ SchemaSettings.SelectItem = function SelectItem(props) {
|
|||||||
<div style={{ alignItems: 'center', display: 'flex', justifyContent: 'space-between' }}>
|
<div style={{ alignItems: 'center', display: 'flex', justifyContent: 'space-between' }}>
|
||||||
{title}
|
{title}
|
||||||
<Select
|
<Select
|
||||||
|
dropdownMatchSelectWidth={false}
|
||||||
bordered={false}
|
bordered={false}
|
||||||
defaultValue={value}
|
defaultValue={value}
|
||||||
onChange={(...arg) => (setOpen(false), onChange(...arg))}
|
onChange={(...arg) => (setOpen(false), onChange(...arg))}
|
||||||
|
@ -14,8 +14,8 @@ export function useIsShowMultipleSwitch() {
|
|||||||
: null;
|
: null;
|
||||||
const uiSchema = collectionField?.uiSchema || fieldSchema;
|
const uiSchema = collectionField?.uiSchema || fieldSchema;
|
||||||
const hasMultiple = uiSchema['x-component-props']?.multiple === true;
|
const hasMultiple = uiSchema['x-component-props']?.multiple === true;
|
||||||
|
const fieldMode=field?.componentProps?.['mode'];
|
||||||
return function IsShowMultipleSwitch() {
|
return function IsShowMultipleSwitch() {
|
||||||
return !field.readPretty && fieldSchema['x-component'] !== 'TableField' && hasMultiple;
|
return !field.readPretty && fieldSchema['x-component'] !== 'TableField' && hasMultiple&&fieldMode!=='SubTable';
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -31,6 +31,7 @@ const useChinaRegionDataSource = (options) => {
|
|||||||
}) || [],
|
}) || [],
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
manual: true,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user