mirror of
https://github.com/nocobase/nocobase
synced 2024-11-15 16:15:44 +00:00
updates
This commit is contained in:
parent
8d298de6fe
commit
07fa09e412
@ -20,6 +20,7 @@ import cls from 'classnames';
|
||||
import { MenuOutlined } from '@ant-design/icons';
|
||||
import { FormLayout } from '@formily/antd';
|
||||
import IconPicker from '../../components/icon-picker';
|
||||
import { useSchemaComponent } from '../../components/schema-renderer';
|
||||
|
||||
export const Action: any = observer((props: any) => {
|
||||
const { useAction = useDefaultAction, icon, ...others } = props;
|
||||
@ -188,6 +189,7 @@ Action.Dropdown = observer((props: any) => {
|
||||
const { buttonProps = {}, ...others } = props;
|
||||
const { schema } = useDesignable();
|
||||
const componentProps = schema.parent['x-component-props'] || {};
|
||||
const icon = buttonProps.icon || componentProps['icon'];
|
||||
return (
|
||||
<Dropdown
|
||||
trigger={['click']}
|
||||
@ -198,7 +200,13 @@ Action.Dropdown = observer((props: any) => {
|
||||
</Menu>
|
||||
}
|
||||
>
|
||||
<Button {...buttonProps} {...componentProps}>{schema.title || schema.parent.title}</Button>
|
||||
<Button
|
||||
{...buttonProps}
|
||||
{...componentProps}
|
||||
icon={<IconPicker type={icon} />}
|
||||
>
|
||||
{schema.title || schema.parent.title}
|
||||
</Button>
|
||||
</Dropdown>
|
||||
);
|
||||
});
|
||||
@ -212,6 +220,10 @@ Action.Popover = observer((props) => {
|
||||
console.log('Action.Popover', schema, fieldSchema);
|
||||
const componentProps =
|
||||
(schema.parent && schema.parent['x-component-props']) || {};
|
||||
const designableBarComponent = schema.parent
|
||||
? schema.parent['x-designable-bar']
|
||||
: null;
|
||||
const DesignableBar = useSchemaComponent(designableBarComponent);
|
||||
return (
|
||||
<Popover
|
||||
visible={visible}
|
||||
@ -248,7 +260,10 @@ Action.Popover = observer((props) => {
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<Button {...componentProps}>{schema.parent.title || schema.title}</Button>
|
||||
<Button {...componentProps}>
|
||||
{schema.parent.title || schema.title}
|
||||
{DesignableBar && <DesignableBar />}
|
||||
</Button>
|
||||
</Popover>
|
||||
);
|
||||
});
|
||||
|
@ -16,6 +16,7 @@ import {
|
||||
RecursionField,
|
||||
Schema,
|
||||
ISchema,
|
||||
useForm,
|
||||
} from '@formily/react';
|
||||
import {
|
||||
Menu,
|
||||
@ -58,9 +59,10 @@ import {
|
||||
import { uid } from '@formily/shared';
|
||||
import { useRequest } from 'ahooks';
|
||||
import { SchemaField } from '../../components/schema-renderer';
|
||||
import { useFormContext } from '../form';
|
||||
import { useResourceContext } from '../';
|
||||
import { cloneDeep } from 'lodash';
|
||||
import { options } from '../database-field/interfaces';
|
||||
import { useDisplayFieldsContext } from '../form';
|
||||
|
||||
const generateGridBlock = (schema: ISchema) => {
|
||||
const name = schema.name || uid();
|
||||
@ -126,211 +128,111 @@ function generateCardItemSchema(component) {
|
||||
{ key: uid(), field1: uid(), field2: uid() },
|
||||
{ key: uid(), field1: uid(), field2: uid() },
|
||||
{ key: uid(), field1: uid(), field2: uid() },
|
||||
{ key: uid(), field1: uid(), field2: uid() },
|
||||
{ key: uid(), field1: uid(), field2: uid() },
|
||||
{ key: uid(), field1: uid(), field2: uid() },
|
||||
{ key: uid(), field1: uid(), field2: uid() },
|
||||
],
|
||||
'x-component-props': {
|
||||
rowKey: 'key',
|
||||
dragSort: true,
|
||||
showIndex: true,
|
||||
},
|
||||
properties: {
|
||||
[`action_bar_${uid()}`]: {
|
||||
[uid()]: {
|
||||
type: 'void',
|
||||
'x-component': 'Table.ActionBar',
|
||||
'x-designable-bar': 'Table.ActionBar.DesignableBar',
|
||||
properties: {
|
||||
action1: {
|
||||
[uid()]: {
|
||||
type: 'void',
|
||||
name: 'action1',
|
||||
title: '筛选',
|
||||
'x-component': 'Action',
|
||||
properties: {
|
||||
popover1: {
|
||||
type: 'void',
|
||||
title: '弹窗标题',
|
||||
'x-decorator': 'Form',
|
||||
'x-component': 'Action.Popover',
|
||||
'x-component-props': {},
|
||||
properties: {
|
||||
filter: {
|
||||
name: 'filter',
|
||||
type: 'object',
|
||||
'x-component': 'Filter',
|
||||
properties: {
|
||||
column1: {
|
||||
type: 'void',
|
||||
title: '字段1',
|
||||
'x-component': 'Filter.Column',
|
||||
'x-component': 'Table.Filter',
|
||||
'x-designable-bar': 'Table.Filter.DesignableBar',
|
||||
'x-component-props': {
|
||||
operations: [
|
||||
{ label: '等于', value: 'eq' },
|
||||
{ label: '不等于', value: 'ne' },
|
||||
],
|
||||
},
|
||||
properties: {
|
||||
field1: {
|
||||
type: 'string',
|
||||
'x-component': 'Input',
|
||||
fieldNames: [],
|
||||
},
|
||||
},
|
||||
},
|
||||
column2: {
|
||||
type: 'void',
|
||||
title: '字段2',
|
||||
'x-component': 'Filter.Column',
|
||||
'x-component-props': {
|
||||
operations: [
|
||||
{ label: '大于', value: 'gt' },
|
||||
{ label: '小于', value: 'lt' },
|
||||
{
|
||||
label: '非空',
|
||||
value: 'notNull',
|
||||
noValue: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
properties: {
|
||||
field1: {
|
||||
type: 'number',
|
||||
'x-component': 'InputNumber',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
action2: {
|
||||
[uid()]: {
|
||||
type: 'void',
|
||||
name: 'action1',
|
||||
title: '新增',
|
||||
'x-component': 'Action',
|
||||
'x-designable-bar': 'Action.DesignableBar',
|
||||
'x-designable-bar': 'Table.Action.DesignableBar',
|
||||
properties: {
|
||||
drawer1: {
|
||||
modal: {
|
||||
type: 'void',
|
||||
title: '抽屉标题',
|
||||
title: '新增数据',
|
||||
'x-decorator': 'Form',
|
||||
'x-component': 'Action.Modal',
|
||||
'x-component-props': {
|
||||
useOkAction: '{{ Table.useTableCreateAction }}',
|
||||
},
|
||||
properties: {
|
||||
field1: {
|
||||
type: 'string',
|
||||
title: '字段1',
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Input',
|
||||
},
|
||||
field2: {
|
||||
type: 'string',
|
||||
title: '字段2',
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Input',
|
||||
[uid()]: {
|
||||
type: 'void',
|
||||
'x-component': 'Grid',
|
||||
'x-component-props': {
|
||||
addNewComponent: 'AddNew.FormItem',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
action3: {
|
||||
},
|
||||
[uid()]: {
|
||||
type: 'void',
|
||||
name: 'action1',
|
||||
title: '删除',
|
||||
'x-component': 'Action',
|
||||
'x-designable-bar': 'Table.Action.DesignableBar',
|
||||
'x-component-props': {
|
||||
useAction: '{{ Table.useTableDestroyAction }}',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
[`a_${uid()}`]: {
|
||||
[uid()]: {
|
||||
type: 'void',
|
||||
'x-component': 'Table.ActionBar',
|
||||
'x-component-props': {
|
||||
align: 'bottom',
|
||||
},
|
||||
properties: {
|
||||
pagination: {
|
||||
[uid()]: {
|
||||
type: 'void',
|
||||
'x-component': 'Table.Pagination',
|
||||
'x-component-props': {},
|
||||
},
|
||||
},
|
||||
},
|
||||
[`column_${uid()}`]: {
|
||||
[uid()]: {
|
||||
type: 'void',
|
||||
title: '排序',
|
||||
'x-component': 'Table.Column',
|
||||
properties: {
|
||||
sort: {
|
||||
type: 'void',
|
||||
'x-component': 'Table.SortHandle',
|
||||
},
|
||||
},
|
||||
},
|
||||
[`column_${uid()}`]: {
|
||||
type: 'void',
|
||||
title: '序号',
|
||||
'x-component': 'Table.Column',
|
||||
properties: {
|
||||
index: {
|
||||
type: 'void',
|
||||
'x-component': 'Table.Index',
|
||||
},
|
||||
},
|
||||
},
|
||||
[`column_${uid()}`]: {
|
||||
type: 'void',
|
||||
title: '字段1',
|
||||
'x-component': 'Table.Column',
|
||||
'x-component-props': {
|
||||
// title: 'z1',
|
||||
className: 'nb-table-operation',
|
||||
},
|
||||
'x-designable-bar': 'Table.Column.DesignableBar',
|
||||
properties: {
|
||||
field1: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
'x-read-pretty': true,
|
||||
'x-decorator-props': {
|
||||
feedbackLayout: 'popover',
|
||||
},
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Input',
|
||||
},
|
||||
},
|
||||
},
|
||||
[`column_${uid()}`]: {
|
||||
[uid()]: {
|
||||
type: 'void',
|
||||
title: '字段2',
|
||||
'x-component': 'Table.Column',
|
||||
'x-designable-bar': 'Table.Column.DesignableBar',
|
||||
'x-component': 'Action.Dropdown',
|
||||
'x-component-props': {
|
||||
buttonProps: {
|
||||
icon: 'EllipsisOutlined',
|
||||
},
|
||||
},
|
||||
properties: {
|
||||
field2: {
|
||||
type: 'string',
|
||||
// title: '字段2',
|
||||
required: true,
|
||||
'x-read-pretty': true,
|
||||
'x-decorator-props': {
|
||||
feedbackLayout: 'popover',
|
||||
},
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Input',
|
||||
},
|
||||
},
|
||||
},
|
||||
[`column_${uid()}`]: {
|
||||
[uid()]: {
|
||||
type: 'void',
|
||||
title: '操作',
|
||||
'x-component': 'Table.Column',
|
||||
properties: {
|
||||
title: '操作 1',
|
||||
'x-component': 'Menu.Action',
|
||||
'x-component-props': {
|
||||
style: {
|
||||
minWidth: 150,
|
||||
},
|
||||
disabled: true,
|
||||
},
|
||||
},
|
||||
[uid()]: {
|
||||
type: 'void',
|
||||
name: 'action1',
|
||||
title: '查看',
|
||||
'x-component': 'Action',
|
||||
'x-component': 'Menu.Action',
|
||||
'x-designable-bar': 'Table.Action.DesignableBar',
|
||||
properties: {
|
||||
drawer1: {
|
||||
@ -385,7 +287,7 @@ function generateCardItemSchema(component) {
|
||||
type: 'void',
|
||||
name: 'action1',
|
||||
title: '修改',
|
||||
'x-component': 'Action',
|
||||
'x-component': 'Menu.Action',
|
||||
'x-designable-bar': 'Table.Action.DesignableBar',
|
||||
properties: {
|
||||
drawer1: {
|
||||
@ -419,7 +321,7 @@ function generateCardItemSchema(component) {
|
||||
[uid()]: {
|
||||
type: 'void',
|
||||
title: '删除',
|
||||
'x-component': 'Action',
|
||||
'x-component': 'Menu.Action',
|
||||
'x-component-props': {
|
||||
useAction: '{{ Table.useTableDestroyAction }}',
|
||||
},
|
||||
@ -428,6 +330,50 @@ function generateCardItemSchema(component) {
|
||||
},
|
||||
},
|
||||
},
|
||||
[uid()]: {
|
||||
type: 'void',
|
||||
title: '字段1',
|
||||
'x-component': 'Table.Column',
|
||||
'x-component-props': {
|
||||
// title: 'z1',
|
||||
},
|
||||
'x-designable-bar': 'Table.Column.DesignableBar',
|
||||
properties: {
|
||||
field1: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
'x-read-pretty': true,
|
||||
'x-decorator-props': {
|
||||
feedbackLayout: 'popover',
|
||||
},
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Input',
|
||||
},
|
||||
},
|
||||
},
|
||||
[uid()]: {
|
||||
type: 'void',
|
||||
title: '字段2',
|
||||
'x-component': 'Table.Column',
|
||||
'x-component-props': {
|
||||
// title: 'z1',
|
||||
},
|
||||
'x-designable-bar': 'Table.Column.DesignableBar',
|
||||
properties: {
|
||||
field2: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
'x-read-pretty': true,
|
||||
'x-decorator-props': {
|
||||
feedbackLayout: 'popover',
|
||||
},
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Input',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Form: {
|
||||
type: 'void',
|
||||
name: uid(),
|
||||
@ -509,6 +455,7 @@ AddNew.CardItem = observer((props: any) => {
|
||||
console.log({ collections });
|
||||
return (
|
||||
<Dropdown
|
||||
trigger={['click']}
|
||||
overlayStyle={{
|
||||
minWidth: 200,
|
||||
}}
|
||||
@ -520,7 +467,7 @@ AddNew.CardItem = observer((props: any) => {
|
||||
<Menu
|
||||
onClick={async (info) => {
|
||||
let data: ISchema;
|
||||
let collectionName = null;
|
||||
let resourceName = null;
|
||||
if (['addNewTable', 'addNewForm'].includes(info.key)) {
|
||||
const values = await FormDialog(`新建数据表`, () => {
|
||||
return (
|
||||
@ -539,12 +486,12 @@ AddNew.CardItem = observer((props: any) => {
|
||||
data = generateCardItemSchema(
|
||||
info.key === 'addNewTable' ? 'Table' : 'Form',
|
||||
);
|
||||
collectionName = values.name;
|
||||
resourceName = values.name;
|
||||
} else if (info.key !== 'Markdown') {
|
||||
const keys = info.key.split('.');
|
||||
const component = keys.shift();
|
||||
const tableName = keys.join('.');
|
||||
collectionName = tableName;
|
||||
resourceName = tableName;
|
||||
data = generateCardItemSchema(component);
|
||||
console.log('info.keyPath', component, tableName);
|
||||
} else {
|
||||
@ -553,9 +500,9 @@ AddNew.CardItem = observer((props: any) => {
|
||||
if (schema['key']) {
|
||||
data['key'] = uid();
|
||||
}
|
||||
if (collectionName) {
|
||||
if (resourceName) {
|
||||
data['x-component-props'] = data['x-component-props'] || {};
|
||||
data['x-component-props']['collectionName'] = collectionName;
|
||||
data['x-component-props']['resourceName'] = resourceName;
|
||||
}
|
||||
if (isGridBlock(schema)) {
|
||||
path.pop();
|
||||
@ -595,8 +542,8 @@ AddNew.CardItem = observer((props: any) => {
|
||||
<Menu.Divider></Menu.Divider>
|
||||
<Menu.Item key={'addNewForm'}>新建数据表</Menu.Item>
|
||||
</Menu.SubMenu>
|
||||
<Menu.Item key={'Markdown'}>新建 Markdown</Menu.Item>
|
||||
<Menu.SubMenu key={'Ref'} title={'引用模板'}>
|
||||
<Menu.Item key={'Markdown'}>新建文本段</Menu.Item>
|
||||
<Menu.SubMenu disabled key={'Ref'} title={'引用模板'}>
|
||||
<Menu.ItemGroup key={'form-select'} title={'选择模板'}>
|
||||
<Menu.Item key={'Ref.name1'}>模板1</Menu.Item>
|
||||
</Menu.ItemGroup>
|
||||
@ -684,24 +631,67 @@ AddNew.BlockItem = observer((props: any) => {
|
||||
);
|
||||
});
|
||||
|
||||
function FieldSwitch({ field, onChange, defaultChecked }) {
|
||||
const [checked, setChecked] = useState(defaultChecked);
|
||||
const form = useForm();
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
}}
|
||||
onClick={(e) => {
|
||||
setChecked((value) => {
|
||||
onChange && onChange(!value);
|
||||
return !value;
|
||||
});
|
||||
console.log('FieldSwitch', form);
|
||||
}}
|
||||
>
|
||||
<span>{field?.uiSchema?.title || '未命名'}</span>
|
||||
<Switch
|
||||
onChange={(checked, e) => {
|
||||
e.stopPropagation();
|
||||
setChecked(checked);
|
||||
onChange && onChange(checked);
|
||||
}}
|
||||
size={'small'}
|
||||
checked={checked}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
AddNew.FormItem = observer((props: any) => {
|
||||
const { ghost, defaultAction } = props;
|
||||
const { schema, insertBefore, insertAfter, appendChild } = useDesignable();
|
||||
const path = useSchemaPath();
|
||||
const { collection = {}, refresh } = useFormContext();
|
||||
const { resource = {}, refresh } = useResourceContext();
|
||||
const [visible, setVisible] = useState(false);
|
||||
const { displayFields = [] } = useDisplayFieldsContext();
|
||||
console.log({ displayFields });
|
||||
return (
|
||||
<Dropdown
|
||||
trigger={['click']}
|
||||
visible={visible}
|
||||
onVisibleChange={setVisible}
|
||||
overlayStyle={{
|
||||
minWidth: 200,
|
||||
}}
|
||||
placement={'bottomCenter'}
|
||||
overlay={
|
||||
<Menu>
|
||||
<Menu.ItemGroup title={`选择「${collection.title}」里已有字段`}>
|
||||
{collection?.fields?.map((field) => (
|
||||
<Menu.Item
|
||||
key={field.key}
|
||||
onClick={async () => {
|
||||
<Menu.ItemGroup title={`要展示的字段`}>
|
||||
{resource?.fields?.map((field) => (
|
||||
<Menu.Item key={field.key}>
|
||||
<FieldSwitch
|
||||
field={field}
|
||||
defaultChecked={displayFields.includes(field.name)}
|
||||
onChange={async (checked) => {
|
||||
if (!checked) {
|
||||
return;
|
||||
}
|
||||
let data: ISchema = {
|
||||
key: uid(),
|
||||
type: 'void',
|
||||
@ -731,8 +721,7 @@ AddNew.FormItem = observer((props: any) => {
|
||||
await createSchema(s);
|
||||
}
|
||||
}}
|
||||
>
|
||||
{field?.uiSchema?.title || '未命名'}
|
||||
/>
|
||||
</Menu.Item>
|
||||
))}
|
||||
</Menu.ItemGroup>
|
||||
@ -745,6 +734,7 @@ AddNew.FormItem = observer((props: any) => {
|
||||
style={{ minWidth: 150 }}
|
||||
key={item.name}
|
||||
onClick={async () => {
|
||||
setVisible(false);
|
||||
const values = await FormDialog(`新增字段`, () => {
|
||||
return (
|
||||
<FormLayout layout={'vertical'}>
|
||||
@ -758,7 +748,7 @@ AddNew.FormItem = observer((props: any) => {
|
||||
name: `f_${uid()}`,
|
||||
},
|
||||
});
|
||||
await createCollectionField(collection.name, values);
|
||||
await createCollectionField(resource.name, values);
|
||||
await refresh();
|
||||
let data: ISchema = cloneDeep(values.uiSchema);
|
||||
data['name'] = values.name;
|
||||
@ -790,13 +780,13 @@ AddNew.FormItem = observer((props: any) => {
|
||||
</Menu.ItemGroup>
|
||||
))}
|
||||
</Menu.SubMenu>
|
||||
<Menu.Divider />
|
||||
{/* <Menu.Divider /> */}
|
||||
<Menu.Item
|
||||
onClick={async () => {
|
||||
let data: ISchema = {
|
||||
key: uid(),
|
||||
type: 'string',
|
||||
default: '这是一段演示文字',
|
||||
default: '这是一段演示文字,**支持使用 Markdown 语法**',
|
||||
'x-designable-bar': 'Markdown.FormItemDesignableBar',
|
||||
'x-decorator': 'FormItem',
|
||||
'x-read-pretty': true,
|
||||
@ -823,6 +813,7 @@ AddNew.FormItem = observer((props: any) => {
|
||||
}
|
||||
await createSchema(s);
|
||||
}
|
||||
setVisible(false);
|
||||
}}
|
||||
>
|
||||
添加说明文字
|
||||
|
@ -142,4 +142,8 @@ export const select: ISchema = {
|
||||
'x-component': 'Checkbox',
|
||||
},
|
||||
},
|
||||
operations: [
|
||||
{ label: '等于', value: 'eq' },
|
||||
{ label: '不等于', value: 'ne' },
|
||||
],
|
||||
};
|
||||
|
@ -51,4 +51,8 @@ export const string: ISchema = {
|
||||
'x-component': 'Checkbox',
|
||||
},
|
||||
},
|
||||
operations: [
|
||||
{ label: '等于', value: 'eq' },
|
||||
{ label: '不等于', value: 'ne' },
|
||||
],
|
||||
};
|
||||
|
@ -50,4 +50,8 @@ export const textarea: ISchema = {
|
||||
'x-component': 'Checkbox',
|
||||
},
|
||||
},
|
||||
operations: [
|
||||
{ label: '等于', value: 'eq' },
|
||||
{ label: '不等于', value: 'ne' },
|
||||
],
|
||||
};
|
||||
|
@ -18,6 +18,8 @@ import {
|
||||
useDesignable,
|
||||
removeSchema,
|
||||
useCollectionContext,
|
||||
useResourceContext,
|
||||
ResourceContextProvider,
|
||||
} from '../';
|
||||
import get from 'lodash/get';
|
||||
import { Button, Dropdown, Menu, Space } from 'antd';
|
||||
@ -37,23 +39,25 @@ import { FieldDesignableBar } from './Field.DesignableBar';
|
||||
import { createContext } from 'react';
|
||||
import { BlockItem } from '../block-item';
|
||||
|
||||
const [FormContextProvider, useFormContext] = constate(({ schema, form }) => {
|
||||
// const schema = useFieldSchema();
|
||||
const collectionName = schema['x-component-props']?.['collectionName'];
|
||||
const { data: collections = [], loading, refresh } = useCollectionContext();
|
||||
const collection = collectionName
|
||||
? collections.find((item) => item.name === collectionName)
|
||||
: {};
|
||||
console.log({ collection });
|
||||
return { form, schema, collection, refresh };
|
||||
const [DisplayFieldsContextProvider, useDisplayFieldsContext] = constate(() => {
|
||||
const [displayFields, setDisplayFields] = useState([]);
|
||||
|
||||
return {
|
||||
displayFields,
|
||||
setDisplayFields,
|
||||
addDisplayField(fieldName) {
|
||||
setDisplayFields(fields => fields.concat(fieldName));
|
||||
},
|
||||
}
|
||||
});
|
||||
|
||||
export { FormContextProvider, useFormContext };
|
||||
export { DisplayFieldsContextProvider, useDisplayFieldsContext }
|
||||
|
||||
export const Form: any = observer((props: any) => {
|
||||
const {
|
||||
useValues = () => ({}),
|
||||
showDefaultButtons = false,
|
||||
resourceName,
|
||||
...others
|
||||
} = props;
|
||||
const initialValues = useValues();
|
||||
@ -64,10 +68,8 @@ export const Form: any = observer((props: any) => {
|
||||
const { schema } = useDesignable();
|
||||
const path = useSchemaPath();
|
||||
const scope = useContext(SchemaExpressionScopeContext);
|
||||
return (
|
||||
const content = (
|
||||
<FormProvider form={form}>
|
||||
{/* @ts-ignore */}
|
||||
<FormContextProvider schema={schema} form={form}>
|
||||
{schema['x-decorator'] === 'Form' ? (
|
||||
<SchemaField
|
||||
scope={scope}
|
||||
@ -114,9 +116,18 @@ export const Form: any = observer((props: any) => {
|
||||
</Button>
|
||||
</Space>
|
||||
)}
|
||||
</FormContextProvider>
|
||||
</FormProvider>
|
||||
);
|
||||
return resourceName ? (
|
||||
// @ts-ignore
|
||||
<ResourceContextProvider resourceName={resourceName}>
|
||||
<DisplayFieldsContextProvider>
|
||||
{content}
|
||||
</DisplayFieldsContextProvider>
|
||||
</ResourceContextProvider>
|
||||
) : (
|
||||
content
|
||||
);
|
||||
});
|
||||
|
||||
export const FormFieldUIDContext = createContext(null);
|
||||
@ -126,11 +137,17 @@ Form.Field = observer((props: any) => {
|
||||
const { schema } = useDesignable();
|
||||
const path = getSchemaPath(schema);
|
||||
console.log('getSchemaPath', path);
|
||||
const { collection = {} } = useFormContext();
|
||||
const { addDisplayField } = useDisplayFieldsContext();
|
||||
const { resource = {} } = useResourceContext();
|
||||
useEffect(() => {
|
||||
if (fieldName) {
|
||||
addDisplayField(fieldName);
|
||||
}
|
||||
}, [fieldName]);
|
||||
if (!fieldName) {
|
||||
return null;
|
||||
}
|
||||
const field = collection?.fields?.find((item) => item.name === fieldName);
|
||||
const field = resource?.fields?.find((item) => item.name === fieldName);
|
||||
if (!field) {
|
||||
return null;
|
||||
}
|
||||
|
@ -129,3 +129,15 @@ const [SwithDesignableContextProvider, useSwithDesignableContext] = constate(()
|
||||
});
|
||||
|
||||
export { SwithDesignableContextProvider, useSwithDesignableContext };
|
||||
|
||||
const [ResourceContextProvider, useResourceContext] = constate(
|
||||
({ resourceName }) => {
|
||||
// const schema = useFieldSchema();
|
||||
const { data: collections = [], loading, refresh } = useCollectionContext();
|
||||
const resource = collections.find((item) => item.name === resourceName);
|
||||
console.log({ resource });
|
||||
return { resource, refresh };
|
||||
},
|
||||
);
|
||||
|
||||
export { ResourceContextProvider, useResourceContext };
|
||||
|
@ -105,9 +105,10 @@ Markdown.DesignableBar = observer((props) => {
|
||||
key={'update'}
|
||||
onClick={() => {
|
||||
field.readPretty = false;
|
||||
setVisible(false);
|
||||
}}
|
||||
>
|
||||
修改 Markdown
|
||||
修改文本段
|
||||
</Menu.Item>
|
||||
<Menu.Divider />
|
||||
<Menu.Item
|
||||
|
@ -360,6 +360,7 @@ Menu.AddNew = observer((props: any) => {
|
||||
className={'nb-menu-add-new'}
|
||||
title={
|
||||
<Dropdown
|
||||
// trigger={['click']}
|
||||
overlay={
|
||||
<AntdMenu
|
||||
onClick={async (info) => {
|
||||
|
@ -17,34 +17,41 @@ const schema: ISchema = {
|
||||
name: `table_${uid()}`,
|
||||
type: 'array',
|
||||
'x-component': 'Table',
|
||||
// default: [
|
||||
// { key: uid(), field1: uid(), field2: uid() },
|
||||
// { key: uid(), field1: uid(), field2: uid() },
|
||||
// { key: uid(), field1: uid(), field2: uid() },
|
||||
// { key: uid(), field1: uid(), field2: uid() },
|
||||
// { key: uid(), field1: uid(), field2: uid() },
|
||||
// { key: uid(), field1: uid(), field2: uid() },
|
||||
// { key: uid(), field1: uid(), field2: uid() },
|
||||
// { key: uid(), field1: uid(), field2: uid() },
|
||||
// { key: uid(), field1: uid(), field2: uid() },
|
||||
// { key: uid(), field1: uid(), field2: uid() },
|
||||
// { key: uid(), field1: uid(), field2: uid() },
|
||||
// { key: uid(), field1: uid(), field2: uid() },
|
||||
// ],
|
||||
default: [
|
||||
{ key: uid(), field1: uid(), field2: uid() },
|
||||
{ key: uid(), field1: uid(), field2: uid() },
|
||||
{ key: uid(), field1: uid(), field2: uid() },
|
||||
{ key: uid(), field1: uid(), field2: uid() },
|
||||
{ key: uid(), field1: uid(), field2: uid() },
|
||||
{ key: uid(), field1: uid(), field2: uid() },
|
||||
{ key: uid(), field1: uid(), field2: uid() },
|
||||
{ key: uid(), field1: uid(), field2: uid() },
|
||||
{ key: uid(), field1: uid(), field2: uid() },
|
||||
{ key: uid(), field1: uid(), field2: uid() },
|
||||
{ key: uid(), field1: uid(), field2: uid() },
|
||||
{ key: uid(), field1: uid(), field2: uid() },
|
||||
],
|
||||
'x-component-props': {
|
||||
rowKey: 'key',
|
||||
// isRemoteDataSource: true,
|
||||
dragSort: 'sort',
|
||||
showIndex: true,
|
||||
defaultFilter: {},
|
||||
defaultSort: [],
|
||||
pagination: {
|
||||
defaultPageSize: 50,
|
||||
},
|
||||
},
|
||||
properties: {
|
||||
[`action_bar_${uid()}`]: {
|
||||
type: 'void',
|
||||
'x-component': 'Table.ActionBar',
|
||||
'x-designable-bar': 'Table.ActionBar.DesignableBar',
|
||||
properties: {
|
||||
action1: {
|
||||
type: 'void',
|
||||
name: 'action1',
|
||||
title: '筛选',
|
||||
'x-component': 'Action',
|
||||
'x-designable-bar': 'Table.Filter.DesignableBar',
|
||||
properties: {
|
||||
popover1: {
|
||||
type: 'void',
|
||||
@ -104,7 +111,7 @@ const schema: ISchema = {
|
||||
name: 'action1',
|
||||
title: '新增',
|
||||
'x-component': 'Action',
|
||||
'x-designable-bar': 'Action.DesignableBar',
|
||||
'x-designable-bar': 'Table.Action.DesignableBar',
|
||||
properties: {
|
||||
drawer1: {
|
||||
type: 'void',
|
||||
@ -135,6 +142,7 @@ const schema: ISchema = {
|
||||
type: 'void',
|
||||
name: 'action1',
|
||||
title: '删除',
|
||||
'x-designable-bar': 'Table.Action.SimpleDesignableBar',
|
||||
'x-component': 'Action',
|
||||
'x-component-props': {
|
||||
useAction: '{{ Table.useTableDestroyAction }}',
|
||||
@ -157,175 +165,43 @@ const schema: ISchema = {
|
||||
},
|
||||
},
|
||||
},
|
||||
// [`column_${uid()}`]: {
|
||||
// type: 'void',
|
||||
// title: '排序',
|
||||
// 'x-component': 'Table.Column',
|
||||
// properties: {
|
||||
// sort: {
|
||||
// type: 'void',
|
||||
// 'x-component': 'Table.SortHandle',
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// [`column_${uid()}`]: {
|
||||
// type: 'void',
|
||||
// title: '序号',
|
||||
// 'x-component': 'Table.Column',
|
||||
// properties: {
|
||||
// index: {
|
||||
// type: 'void',
|
||||
// 'x-component': 'Table.Index',
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
[`column_${uid()}`]: {
|
||||
type: 'void',
|
||||
title: '排序',
|
||||
'x-component': 'Table.Column',
|
||||
properties: {
|
||||
sort: {
|
||||
type: 'void',
|
||||
'x-component': 'Table.SortHandle',
|
||||
},
|
||||
},
|
||||
},
|
||||
[`column_${uid()}`]: {
|
||||
type: 'void',
|
||||
title: '序号',
|
||||
'x-component': 'Table.Column',
|
||||
properties: {
|
||||
index: {
|
||||
type: 'void',
|
||||
'x-component': 'Table.Index',
|
||||
},
|
||||
},
|
||||
},
|
||||
[`column_${uid()}`]: {
|
||||
type: 'void',
|
||||
title: '字段1',
|
||||
'x-component': 'Table.Column',
|
||||
'x-component-props': {
|
||||
// title: 'z1',
|
||||
className: 'nb-table-operation',
|
||||
},
|
||||
'x-designable-bar': 'Table.Column.DesignableBar',
|
||||
properties: {
|
||||
field1: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
'x-read-pretty': true,
|
||||
'x-decorator-props': {
|
||||
feedbackLayout: 'popover',
|
||||
},
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Input',
|
||||
},
|
||||
},
|
||||
},
|
||||
[`column_${uid()}`]: {
|
||||
type: 'void',
|
||||
title: '字段2',
|
||||
'x-component': 'Table.Column',
|
||||
'x-designable-bar': 'Table.Column.DesignableBar',
|
||||
properties: {
|
||||
field2: {
|
||||
type: 'string',
|
||||
// title: '字段2',
|
||||
required: true,
|
||||
'x-read-pretty': true,
|
||||
'x-decorator-props': {
|
||||
feedbackLayout: 'popover',
|
||||
},
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Input',
|
||||
},
|
||||
},
|
||||
},
|
||||
[`column_${uid()}`]: {
|
||||
type: 'void',
|
||||
title: '操作',
|
||||
'x-component': 'Table.Column',
|
||||
properties: {
|
||||
[uid()]: {
|
||||
type: 'void',
|
||||
name: 'action1',
|
||||
title: '查看',
|
||||
'x-component': 'Action',
|
||||
'x-designable-bar': 'Table.Action.DesignableBar',
|
||||
properties: {
|
||||
drawer1: {
|
||||
type: 'void',
|
||||
title: '查看',
|
||||
'x-component': 'Action.Modal',
|
||||
'x-component-props': {},
|
||||
properties: {
|
||||
[uid()]: {
|
||||
type: 'void',
|
||||
'x-component': 'Tabs',
|
||||
properties: {
|
||||
tab1: {
|
||||
type: 'void',
|
||||
'x-component': 'Tabs.TabPane',
|
||||
'x-component-props': {
|
||||
tab: 'Tab1',
|
||||
},
|
||||
properties: {
|
||||
aaa: {
|
||||
type: 'string',
|
||||
title: 'AAA',
|
||||
'x-decorator': 'FormItem',
|
||||
required: true,
|
||||
'x-component': 'Input',
|
||||
},
|
||||
},
|
||||
},
|
||||
tab2: {
|
||||
type: 'void',
|
||||
'x-component': 'Tabs.TabPane',
|
||||
'x-component-props': {
|
||||
tab: 'Tab2',
|
||||
},
|
||||
properties: {
|
||||
bbb: {
|
||||
type: 'string',
|
||||
title: 'BBB',
|
||||
'x-decorator': 'FormItem',
|
||||
required: true,
|
||||
'x-component': 'Input',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
[uid()]: {
|
||||
type: 'void',
|
||||
name: 'action1',
|
||||
title: '修改',
|
||||
'x-component': 'Action',
|
||||
'x-designable-bar': 'Table.Action.DesignableBar',
|
||||
properties: {
|
||||
drawer1: {
|
||||
type: 'void',
|
||||
title: '编辑表单',
|
||||
"x-decorator": 'Form',
|
||||
'x-decorator-props': {
|
||||
useValues: '{{ Table.useTableRow }}',
|
||||
},
|
||||
'x-component': 'Action.Modal',
|
||||
'x-component-props': {
|
||||
useOkAction: '{{ Table.useTableUpdateAction }}',
|
||||
},
|
||||
properties: {
|
||||
field1: {
|
||||
type: 'string',
|
||||
title: '字段1',
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Input',
|
||||
},
|
||||
field2: {
|
||||
type: 'string',
|
||||
title: '字段2',
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Input',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
[uid()]: {
|
||||
type: 'void',
|
||||
title: '删除',
|
||||
'x-component': 'Action',
|
||||
'x-component-props': {
|
||||
useAction: '{{ Table.useTableDestroyAction }}',
|
||||
},
|
||||
},
|
||||
[uid()]: {
|
||||
type: 'void',
|
||||
title: '...',
|
||||
'x-component': 'Action.Dropdown',
|
||||
'x-component-props': {
|
||||
buttonProps: {
|
||||
icon: 'EllipsisOutlined',
|
||||
},
|
||||
},
|
||||
properties: {
|
||||
[uid()]: {
|
||||
type: 'void',
|
||||
@ -333,6 +209,9 @@ const schema: ISchema = {
|
||||
'x-component': 'Menu.Action',
|
||||
'x-component-props': {
|
||||
useAction,
|
||||
style: {
|
||||
minWidth: 150,
|
||||
},
|
||||
disabled: true,
|
||||
},
|
||||
},
|
||||
@ -410,7 +289,7 @@ const schema: ISchema = {
|
||||
drawer1: {
|
||||
type: 'void',
|
||||
title: '编辑表单',
|
||||
"x-decorator": 'Form',
|
||||
'x-decorator': 'Form',
|
||||
'x-decorator-props': {
|
||||
useValues: '{{ Table.useTableRow }}',
|
||||
},
|
||||
@ -447,6 +326,46 @@ const schema: ISchema = {
|
||||
},
|
||||
},
|
||||
},
|
||||
[`column_${uid()}`]: {
|
||||
type: 'void',
|
||||
title: '字段1',
|
||||
'x-component': 'Table.Column',
|
||||
'x-component-props': {
|
||||
// title: 'z1',
|
||||
},
|
||||
'x-designable-bar': 'Table.Column.DesignableBar',
|
||||
properties: {
|
||||
field1: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
'x-read-pretty': true,
|
||||
'x-decorator-props': {
|
||||
feedbackLayout: 'popover',
|
||||
},
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Input',
|
||||
},
|
||||
},
|
||||
},
|
||||
[`column_${uid()}`]: {
|
||||
type: 'void',
|
||||
title: '字段2',
|
||||
'x-component': 'Table.Column',
|
||||
'x-designable-bar': 'Table.Column.DesignableBar',
|
||||
properties: {
|
||||
field2: {
|
||||
type: 'string',
|
||||
// title: '字段2',
|
||||
required: true,
|
||||
'x-read-pretty': true,
|
||||
'x-decorator-props': {
|
||||
feedbackLayout: 'popover',
|
||||
},
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Input',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@ -457,7 +376,11 @@ const form = createForm({
|
||||
export default observer(() => {
|
||||
return (
|
||||
<div>
|
||||
<SchemaRenderer scope={{ Table, useTableCreateAction }} form={form} schema={schema} />
|
||||
<SchemaRenderer
|
||||
scope={{ Table, useTableCreateAction }}
|
||||
form={form}
|
||||
schema={schema}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
@ -19,24 +19,40 @@ import {
|
||||
Table as AntdTable,
|
||||
Dropdown,
|
||||
Menu,
|
||||
Select,
|
||||
Switch,
|
||||
} from 'antd';
|
||||
import { findIndex, get } from 'lodash';
|
||||
import { findIndex, get, set } from 'lodash';
|
||||
import constate from 'constate';
|
||||
import useRequest from '@ahooksjs/use-request';
|
||||
import { BaseResult } from '@ahooksjs/use-request/lib/types';
|
||||
import { uid, clone } from '@formily/shared';
|
||||
import { MenuOutlined, DragOutlined } from '@ant-design/icons';
|
||||
import {
|
||||
EllipsisOutlined,
|
||||
MenuOutlined,
|
||||
DragOutlined,
|
||||
PlusOutlined,
|
||||
} from '@ant-design/icons';
|
||||
import {
|
||||
SortableHandle,
|
||||
SortableContainer,
|
||||
SortableElement,
|
||||
} from 'react-sortable-hoc';
|
||||
import cls from 'classnames';
|
||||
import { getSchemaPath, removeSchema, useDesignable, useSchemaPath, VisibleContext } from '../';
|
||||
import {
|
||||
getSchemaPath,
|
||||
removeSchema,
|
||||
ResourceContextProvider,
|
||||
useCollectionContext,
|
||||
useDesignable,
|
||||
useResourceContext,
|
||||
useSchemaPath,
|
||||
VisibleContext,
|
||||
} from '../';
|
||||
import './style.less';
|
||||
import { DraggableBlockContext } from '../../components/drag-and-drop';
|
||||
import AddNew from '../add-new';
|
||||
import { isGridRowOrCol } from '../grid';
|
||||
import { options } from '../database-field/interfaces';
|
||||
|
||||
interface TableRowProps {
|
||||
index: number;
|
||||
@ -116,7 +132,7 @@ function useTableActionBars() {
|
||||
}
|
||||
|
||||
function useTableColumns(props?: any) {
|
||||
const { schema } = useDesignable();
|
||||
const { schema, designable } = useDesignable();
|
||||
// const schema = useFieldSchema();
|
||||
const { dataSource } = props || {};
|
||||
|
||||
@ -129,8 +145,9 @@ function useTableColumns(props?: any) {
|
||||
}, []);
|
||||
}
|
||||
|
||||
return findColumns(schema).map((item) => {
|
||||
const columns = findColumns(schema).map((item) => {
|
||||
const columnProps = item['x-component-props'] || {};
|
||||
console.log(item);
|
||||
return {
|
||||
title: <RecursionField name={item.name} schema={item} onlyRenderSelf />,
|
||||
dataIndex: item.name,
|
||||
@ -150,6 +167,83 @@ function useTableColumns(props?: any) {
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
// columns.unshift({
|
||||
// title: '',
|
||||
// className: 'nb-table-operation',
|
||||
// dataIndex: 'operation',
|
||||
// render(value, record, recordIndex) {
|
||||
// const index = dataSource.indexOf(record);
|
||||
// return (
|
||||
// <TableRowContext.Provider
|
||||
// value={{
|
||||
// index: index,
|
||||
// data: record,
|
||||
// }}
|
||||
// >
|
||||
// <Table.Operation />
|
||||
// </TableRowContext.Provider>
|
||||
// );
|
||||
// },
|
||||
// });
|
||||
|
||||
designable &&
|
||||
columns.push({
|
||||
title: <AddColumn />,
|
||||
dataIndex: 'addnew',
|
||||
});
|
||||
|
||||
return columns;
|
||||
}
|
||||
|
||||
function AddColumn() {
|
||||
const [visible, setVisible] = useState(false);
|
||||
const { resource = {}, refresh } = useResourceContext();
|
||||
return (
|
||||
<Dropdown
|
||||
trigger={['click']}
|
||||
visible={visible}
|
||||
onVisibleChange={setVisible}
|
||||
overlay={
|
||||
<Menu>
|
||||
<Menu.ItemGroup title={'要展示的字段'}>
|
||||
{resource?.fields?.map((field) => (
|
||||
<Menu.Item style={{ minWidth: 150 }}>
|
||||
<div
|
||||
style={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
}}
|
||||
>
|
||||
<span>{field.uiSchema.title}</span>
|
||||
<Switch size={'small'} defaultChecked />
|
||||
</div>
|
||||
</Menu.Item>
|
||||
))}
|
||||
</Menu.ItemGroup>
|
||||
<Menu.Divider />
|
||||
<Menu.SubMenu title={'新增字段'}>
|
||||
{options.map((option) => (
|
||||
<Menu.ItemGroup title={option.label}>
|
||||
{option.children.map((item) => (
|
||||
<Menu.Item
|
||||
style={{ minWidth: 150 }}
|
||||
key={item.name}
|
||||
onClick={async () => {}}
|
||||
>
|
||||
{item.title}
|
||||
</Menu.Item>
|
||||
))}
|
||||
</Menu.ItemGroup>
|
||||
))}
|
||||
</Menu.SubMenu>
|
||||
</Menu>
|
||||
}
|
||||
>
|
||||
<Button size={'small'} type={'dashed'} icon={<PlusOutlined />}></Button>
|
||||
</Dropdown>
|
||||
);
|
||||
}
|
||||
|
||||
export function useTableRow() {
|
||||
@ -245,8 +339,10 @@ const [TableContextProvider, useTableContext] = constate(() => {
|
||||
const field = useField<Formily.Core.Models.ArrayField>();
|
||||
const schema = useFieldSchema();
|
||||
const defaultSelectedRowKeys = useContext(SelectedRowKeysContext);
|
||||
const [selectedRowKeys, setSelectedRowKeys] = useState(defaultSelectedRowKeys || []);
|
||||
console.log({ defaultSelectedRowKeys })
|
||||
const [selectedRowKeys, setSelectedRowKeys] = useState(
|
||||
defaultSelectedRowKeys || [],
|
||||
);
|
||||
console.log({ defaultSelectedRowKeys });
|
||||
const pagination = usePaginationProps();
|
||||
const response = useRequest<{
|
||||
list: any[];
|
||||
@ -293,8 +389,9 @@ export { TableContextProvider, useTableContext };
|
||||
export const SelectedRowKeysContext = createContext([]);
|
||||
|
||||
const TableContainer = observer((props) => {
|
||||
const { schema } = useDesignable();
|
||||
const field = useField<Formily.Core.Models.ArrayField>();
|
||||
const schema = useFieldSchema();
|
||||
// const schema = useFieldSchema();
|
||||
const actionBars = useTableActionBars();
|
||||
const { loading, data, refresh, selectedRowKeys, setSelectedRowKeys } =
|
||||
useTableContext();
|
||||
@ -316,6 +413,8 @@ const TableContainer = observer((props) => {
|
||||
});
|
||||
}
|
||||
};
|
||||
const dragSort = schema?.['x-component-props']?.['dragSort'];
|
||||
const showIndex = schema?.['x-component-props']?.['showIndex'];
|
||||
return (
|
||||
<div ref={ref} className={'nb-table'}>
|
||||
{actionBars.top.map((actionBarSchema) => {
|
||||
@ -340,6 +439,26 @@ const TableContainer = observer((props) => {
|
||||
rowSelection={{
|
||||
type: 'checkbox',
|
||||
selectedRowKeys,
|
||||
renderCell: (checked, record, _, originNode) => {
|
||||
const index = dataSource.indexOf(record);
|
||||
return (
|
||||
<TableRowContext.Provider
|
||||
value={{
|
||||
index: index,
|
||||
data: record,
|
||||
}}
|
||||
>
|
||||
<div
|
||||
className={cls('nb-table-selection', { dragSort, showIndex })}
|
||||
>
|
||||
{dragSort && <Table.SortHandle />}
|
||||
{showIndex && <Table.Index />}
|
||||
{originNode}
|
||||
{/* <Table.Operation /> */}
|
||||
</div>
|
||||
</TableRowContext.Provider>
|
||||
);
|
||||
},
|
||||
onChange: (keys) => {
|
||||
console.log(keys);
|
||||
setSelectedRowKeys(keys);
|
||||
@ -384,13 +503,13 @@ const TableContainer = observer((props) => {
|
||||
if (!defaultAction) {
|
||||
return;
|
||||
}
|
||||
const el = (e.target as HTMLElement);
|
||||
if (
|
||||
!el.classList.contains('ant-table-cell')
|
||||
) {
|
||||
const el = e.target as HTMLElement;
|
||||
if (!el.classList.contains('ant-table-cell')) {
|
||||
return;
|
||||
}
|
||||
const btn = el.parentElement.querySelector<HTMLElement>(`.name-${defaultAction.name}`);
|
||||
const btn = el.parentElement.querySelector<HTMLElement>(
|
||||
`.name-${defaultAction.name}`,
|
||||
);
|
||||
btn && btn.click();
|
||||
},
|
||||
};
|
||||
@ -415,8 +534,16 @@ const TableContainer = observer((props) => {
|
||||
);
|
||||
});
|
||||
|
||||
export const Table: any = observer((props) => {
|
||||
return (
|
||||
export const Table: any = observer((props: any) => {
|
||||
const { resourceName } = props;
|
||||
return resourceName ? (
|
||||
// @ts-ignore
|
||||
<ResourceContextProvider resourceName={resourceName}>
|
||||
<TableContextProvider>
|
||||
<TableContainer />
|
||||
</TableContextProvider>
|
||||
</ResourceContextProvider>
|
||||
) : (
|
||||
<TableContextProvider>
|
||||
<TableContainer />
|
||||
</TableContextProvider>
|
||||
@ -477,17 +604,26 @@ Table.Column.DesignableBar = () => {
|
||||
}}
|
||||
overlay={
|
||||
<Menu>
|
||||
<Menu.Item onClick={(e) => {
|
||||
<Menu.Item
|
||||
onClick={(e) => {
|
||||
const title = uid();
|
||||
field.title = title;
|
||||
schema.title = title;
|
||||
setVisible(false);
|
||||
}}>点击修改按钮文案</Menu.Item>
|
||||
<Menu.Item onClick={() => {
|
||||
}}
|
||||
>
|
||||
点击修改按钮文案
|
||||
</Menu.Item>
|
||||
<Menu.Item
|
||||
onClick={() => {
|
||||
remove();
|
||||
console.log('Table.Column.DesignableBar', { schema });
|
||||
}}>删除列</Menu.Item>
|
||||
<Menu.Item onClick={() => {
|
||||
}}
|
||||
>
|
||||
删除列
|
||||
</Menu.Item>
|
||||
<Menu.Item
|
||||
onClick={() => {
|
||||
const name = uid();
|
||||
insertAfter({
|
||||
name: `column_${name}`,
|
||||
@ -510,8 +646,11 @@ Table.Column.DesignableBar = () => {
|
||||
'x-component': 'Input',
|
||||
},
|
||||
},
|
||||
})
|
||||
}}>插入列</Menu.Item>
|
||||
});
|
||||
}}
|
||||
>
|
||||
插入列
|
||||
</Menu.Item>
|
||||
</Menu>
|
||||
}
|
||||
>
|
||||
@ -522,10 +661,61 @@ Table.Column.DesignableBar = () => {
|
||||
);
|
||||
};
|
||||
|
||||
Table.ActionBar = observer((props) => {
|
||||
function AddActionButton() {
|
||||
const [visible, setVisible] = useState(false);
|
||||
return (
|
||||
<div className={'action-bar'}>
|
||||
<Space>{props.children}</Space>
|
||||
<Dropdown
|
||||
trigger={['click']}
|
||||
visible={visible}
|
||||
onVisibleChange={setVisible}
|
||||
overlay={
|
||||
<Menu>
|
||||
<Menu.ItemGroup title={'要展示的操作'}>
|
||||
{[
|
||||
{ title: '筛选', key: 'filter' },
|
||||
{ title: '导出', key: 'export' },
|
||||
{ title: '新增', key: 'create' },
|
||||
{ title: '删除', key: 'destroy' },
|
||||
].map((item) => (
|
||||
<Menu.Item style={{ minWidth: 150 }}>
|
||||
<div
|
||||
style={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
}}
|
||||
>
|
||||
<span>{item.title}</span>
|
||||
<Switch size={'small'} defaultChecked />
|
||||
</div>
|
||||
</Menu.Item>
|
||||
))}
|
||||
</Menu.ItemGroup>
|
||||
<Menu.Divider />
|
||||
<Menu.SubMenu title={'自定义'}>
|
||||
<Menu.Item style={{ minWidth: 120 }}>函数操作</Menu.Item>
|
||||
<Menu.Item>弹窗表单</Menu.Item>
|
||||
<Menu.Item>复杂弹窗</Menu.Item>
|
||||
</Menu.SubMenu>
|
||||
</Menu>
|
||||
}
|
||||
>
|
||||
<Button type={'dashed'} icon={<PlusOutlined />}></Button>
|
||||
</Dropdown>
|
||||
);
|
||||
}
|
||||
|
||||
Table.ActionBar = observer((props: any) => {
|
||||
const { align = 'top' } = props;
|
||||
const { schema, designable } = useDesignable();
|
||||
const designableBar = schema['x-designable-bar'];
|
||||
console.log('designableBar', designableBar);
|
||||
return (
|
||||
<div className={cls('nb-action-bar', `align-${align}`)}>
|
||||
<Space>
|
||||
{props.children}
|
||||
{designable && designableBar && <AddActionButton />}
|
||||
</Space>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
@ -533,7 +723,6 @@ Table.ActionBar = observer((props) => {
|
||||
Table.Pagination = observer((props) => {
|
||||
const { data, params, run } = useTableContext();
|
||||
return (
|
||||
data?.total > params?.pageSize && (
|
||||
<Pagination
|
||||
{...props}
|
||||
defaultCurrent={1}
|
||||
@ -545,7 +734,6 @@ Table.Pagination = observer((props) => {
|
||||
run({ page, pageSize });
|
||||
}}
|
||||
/>
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
@ -560,17 +748,16 @@ const SortHandle = SortableHandle((props: any) => {
|
||||
}) as any;
|
||||
|
||||
Table.SortHandle = observer((props) => {
|
||||
const field = useField<Formily.Core.Models.Field>();
|
||||
console.log('SortHandle', field.value);
|
||||
return <SortHandle {...props} />;
|
||||
});
|
||||
|
||||
Table.Operation = observer((props) => {
|
||||
return <EllipsisOutlined />;
|
||||
});
|
||||
|
||||
Table.Index = observer((props) => {
|
||||
const index = useTableIndex();
|
||||
const schema = useFieldSchema();
|
||||
const field = useField<Formily.Core.Models.Field>();
|
||||
const path = useSchemaPath();
|
||||
return <div>{index + 1}</div>;
|
||||
return <span className={'nb-table-index'}>{index + 1}</span>;
|
||||
});
|
||||
|
||||
Table.Addition = observer((props: any) => {
|
||||
@ -599,7 +786,7 @@ Table.Addition = observer((props: any) => {
|
||||
|
||||
Table.Action = () => null;
|
||||
|
||||
Table.Action.DesignableBar = () => {
|
||||
Table.Action.SimpleDesignableBar = () => {
|
||||
const field = useField();
|
||||
const path = useSchemaPath();
|
||||
const { schema, remove, refresh, insertAfter } = useDesignable();
|
||||
@ -621,10 +808,125 @@ Table.Action.DesignableBar = () => {
|
||||
}}
|
||||
overlay={
|
||||
<Menu>
|
||||
<Menu.Item onClick={(e) => {
|
||||
<Menu.Item
|
||||
onClick={(e) => {
|
||||
schema.title = uid();
|
||||
refresh();
|
||||
}}>点击修改按钮文案</Menu.Item>
|
||||
}}
|
||||
>
|
||||
修改名称和图标
|
||||
</Menu.Item>
|
||||
<Menu.Item>放置在右侧</Menu.Item>
|
||||
<Menu.Divider />
|
||||
<Menu.Item>删除</Menu.Item>
|
||||
</Menu>
|
||||
}
|
||||
>
|
||||
<MenuOutlined />
|
||||
</Dropdown>
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
Table.Filter = observer((props) => {
|
||||
return null;
|
||||
});
|
||||
|
||||
Table.Filter.DesignableBar = () => {
|
||||
const field = useField();
|
||||
const path = useSchemaPath();
|
||||
const { schema, remove, refresh, insertAfter } = useDesignable();
|
||||
const [visible, setVisible] = useState(false);
|
||||
// console.log('Table.Action.DesignableBar', path, field.address.entire, { schema, field });
|
||||
return (
|
||||
<div className={cls('designable-bar', { active: visible })}>
|
||||
<span
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
}}
|
||||
className={cls('designable-bar-actions', { active: visible })}
|
||||
>
|
||||
<Dropdown
|
||||
trigger={['click']}
|
||||
visible={visible}
|
||||
onVisibleChange={(visible) => {
|
||||
setVisible(visible);
|
||||
}}
|
||||
overlay={
|
||||
<Menu>
|
||||
<Menu.Item
|
||||
onClick={(e) => {
|
||||
schema.title = uid();
|
||||
refresh();
|
||||
}}
|
||||
>
|
||||
修改名称和图标
|
||||
</Menu.Item>
|
||||
<Menu.Item>自定义筛选字段</Menu.Item>
|
||||
<Menu.Item>放置在右侧</Menu.Item>
|
||||
<Menu.Divider />
|
||||
<Menu.Item>删除</Menu.Item>
|
||||
</Menu>
|
||||
}
|
||||
>
|
||||
<MenuOutlined />
|
||||
</Dropdown>
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
Table.Action.DesignableBar = () => {
|
||||
const field = useField();
|
||||
const path = useSchemaPath();
|
||||
const { schema, remove, refresh, insertAfter } = useDesignable();
|
||||
const [visible, setVisible] = useState(false);
|
||||
const isPopup = Object.keys(schema.properties || {}).length > 0;
|
||||
const inActionBar = schema.parent['x-component'] === 'Table.ActionBar';
|
||||
// console.log('Table.Action.DesignableBar', path, field.address.entire, { schema, field });
|
||||
return (
|
||||
<div className={cls('designable-bar', { active: visible })}>
|
||||
<span
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
}}
|
||||
className={cls('designable-bar-actions', { active: visible })}
|
||||
>
|
||||
<Dropdown
|
||||
trigger={['click']}
|
||||
visible={visible}
|
||||
onVisibleChange={(visible) => {
|
||||
setVisible(visible);
|
||||
}}
|
||||
overlay={
|
||||
<Menu>
|
||||
<Menu.Item
|
||||
onClick={(e) => {
|
||||
schema.title = uid();
|
||||
refresh();
|
||||
}}
|
||||
>
|
||||
修改名称和图标
|
||||
</Menu.Item>
|
||||
{isPopup && (
|
||||
<Menu.Item>
|
||||
在{' '}
|
||||
<Select
|
||||
bordered={false}
|
||||
size={'small'}
|
||||
defaultValue={'modal'}
|
||||
>
|
||||
<Select.Option value={'modal'}>对话框</Select.Option>
|
||||
<Select.Option value={'drawer'}>抽屉</Select.Option>
|
||||
<Select.Option value={'window'}>浏览器窗口</Select.Option>
|
||||
</Select>{' '}
|
||||
内打开
|
||||
</Menu.Item>
|
||||
)}
|
||||
{inActionBar && <Menu.Item>放置在右侧</Menu.Item>}
|
||||
<Menu.Divider />
|
||||
<Menu.Item>删除</Menu.Item>
|
||||
</Menu>
|
||||
}
|
||||
>
|
||||
@ -643,6 +945,8 @@ Table.DesignableBar = observer((props) => {
|
||||
if (!designable) {
|
||||
return null;
|
||||
}
|
||||
const defaultPageSize =
|
||||
schema['x-component-props']?.['pagination']?.['defaultPageSize'] || 20;
|
||||
return (
|
||||
<div className={cls('designable-bar', { active: visible })}>
|
||||
<span
|
||||
@ -663,12 +967,51 @@ Table.DesignableBar = observer((props) => {
|
||||
overlay={
|
||||
<Menu>
|
||||
<Menu.Item
|
||||
key={'update'}
|
||||
key={'showIndex'}
|
||||
onClick={() => {
|
||||
field.readPretty = false;
|
||||
const bool = !field.componentProps.showIndex;
|
||||
schema['x-component-props']['showIndex'] = bool;
|
||||
field.componentProps.showIndex = bool;
|
||||
}}
|
||||
>
|
||||
编辑Markdown
|
||||
{field.componentProps.showIndex ? '隐藏序号' : '显示序号'}
|
||||
</Menu.Item>
|
||||
<Menu.Item
|
||||
key={'dragSort'}
|
||||
onClick={() => {
|
||||
const dragSort = field.componentProps.dragSort
|
||||
? false
|
||||
: 'sort';
|
||||
schema['x-component-props']['dragSort'] = dragSort;
|
||||
field.componentProps.dragSort = dragSort;
|
||||
}}
|
||||
>
|
||||
{field.componentProps.dragSort
|
||||
? '禁用拖拽排序'
|
||||
: '启用拖拽排序'}
|
||||
</Menu.Item>
|
||||
{!field.componentProps.dragSort && (
|
||||
<Menu.Item key={'defaultSort'}>默认排序</Menu.Item>
|
||||
)}
|
||||
<Menu.Item key={'defaultFilter'}>筛选范围</Menu.Item>
|
||||
<Menu.Item key={'defaultPageSize'}>
|
||||
每页默认显示{' '}
|
||||
<Select
|
||||
bordered={false}
|
||||
size={'small'}
|
||||
onChange={(value) => {
|
||||
const componentProps = schema['x-component-props'] || {};
|
||||
set(componentProps, 'pagination.defaultPageSize', value);
|
||||
schema['x-component-props'] = componentProps;
|
||||
refresh();
|
||||
}}
|
||||
defaultValue={defaultPageSize}
|
||||
>
|
||||
<Select.Option value={20}>20</Select.Option>
|
||||
<Select.Option value={50}>50</Select.Option>
|
||||
<Select.Option value={100}>100</Select.Option>
|
||||
</Select>{' '}
|
||||
条
|
||||
</Menu.Item>
|
||||
<Menu.Divider />
|
||||
<Menu.Item
|
||||
|
@ -59,3 +59,162 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.nb-action-bar {
|
||||
&.align-top {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
&.align-bottom {
|
||||
margin-top: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
th.nb-table-operation,
|
||||
td.nb-table-operation {
|
||||
width: 24px;
|
||||
text-align: center;
|
||||
padding: 0 !important;
|
||||
&::before {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
td.nb-table-operation {
|
||||
.ant-btn {
|
||||
border: 0;
|
||||
box-shadow: none;
|
||||
padding: 6px;
|
||||
height: auto;
|
||||
line-height: 16px;
|
||||
background: none;
|
||||
&:hover {
|
||||
background: #f1f1f1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.nb-table-selection {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
&.dragSort {
|
||||
.nb-table-index {
|
||||
padding-left: 20px;
|
||||
min-width: 38px;
|
||||
}
|
||||
}
|
||||
.nb-table-sort-handle {
|
||||
margin-right: 8px;
|
||||
cursor: grab;
|
||||
}
|
||||
&.showIndex {
|
||||
.ant-checkbox-wrapper {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
display: none;
|
||||
// right: 8px;
|
||||
}
|
||||
.nb-table-sort-handle {
|
||||
display: inline-flex;
|
||||
align-items: baseline;
|
||||
position: absolute;
|
||||
// left: 8px;
|
||||
cursor: grab;
|
||||
margin-right: 8px;
|
||||
z-index: 3;
|
||||
}
|
||||
}
|
||||
.ant-checkbox-wrapper {
|
||||
// position: absolute;
|
||||
// right: 0;
|
||||
// display: none;
|
||||
// right: 8px;
|
||||
}
|
||||
.nb-table-index {
|
||||
// display: inline-flex;
|
||||
// align-items: baseline;
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
text-align: center;
|
||||
// padding-left: 20px;
|
||||
width: 100%;
|
||||
// min-width: 38px;
|
||||
// position: absolute;
|
||||
// right: 8px;
|
||||
// height: 16px;
|
||||
// line-height: 16px;
|
||||
// text-align: center;
|
||||
// background-color: #fff;
|
||||
// min-width: 16px;
|
||||
// width: 100%;
|
||||
// z-index: 2;
|
||||
}
|
||||
}
|
||||
|
||||
.ant-table-selection-column {
|
||||
text-align: right !important;
|
||||
&:hover {
|
||||
.nb-table-index {
|
||||
opacity: 0;
|
||||
}
|
||||
.ant-checkbox-wrapper {
|
||||
z-index: 4;
|
||||
display: inline-flex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.ant-table-row-selected {
|
||||
.nb-table-index {
|
||||
opacity: 0;
|
||||
}
|
||||
.ant-checkbox-wrapper {
|
||||
z-index: 4;
|
||||
display: inline-flex !important;
|
||||
}
|
||||
}
|
||||
|
||||
.ant-table-cell {
|
||||
.ant-formily-item-feedback-layout-popover {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.ant-formily-item-control .ant-formily-item-control-content .ant-formily-item-control-content-component {
|
||||
min-height: inherit;
|
||||
line-height: inherit;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.ant-dropdown-menu-item {
|
||||
&:hover {
|
||||
.designable-bar {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
.designable-bar {
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
border-radius: 0;
|
||||
border: 2px solid #1890ff;
|
||||
&.active {
|
||||
display: block;
|
||||
}
|
||||
.designable-bar-actions {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
line-height: 1rem;
|
||||
background-color: #1890ff;
|
||||
color: #fff;
|
||||
z-index: 10;
|
||||
padding: 0 3px;
|
||||
.anticon {
|
||||
font-size: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user