diff --git a/packages/client/src/blocks/DesignableSchemaField/index.tsx b/packages/client/src/blocks/DesignableSchemaField/index.tsx
index e5f7ff5bc..336c0cea4 100644
--- a/packages/client/src/blocks/DesignableSchemaField/index.tsx
+++ b/packages/client/src/blocks/DesignableSchemaField/index.tsx
@@ -40,7 +40,7 @@ import { Menu } from '../menu';
import { Password } from '../password';
import { Radio } from '../radio';
import { Select } from '../select';
-import { Table } from '../table';
+import { Table, useTableCreateAction, useTableDestroyAction } from '../table';
import { Tabs } from '../tabs';
import { TimePicker } from '../time-picker';
import { Upload } from '../upload';
@@ -59,6 +59,8 @@ export const scope = {
useLogin,
useRegister,
useSubmit,
+ useTableCreateAction,
+ useTableDestroyAction,
};
export const components = {
diff --git a/packages/client/src/blocks/action/index.md b/packages/client/src/blocks/action/index.md
index d5da98ebc..c3a29588c 100644
--- a/packages/client/src/blocks/action/index.md
+++ b/packages/client/src/blocks/action/index.md
@@ -29,7 +29,7 @@ group:
import React from 'react';
import { SchemaRenderer, registerScope } from '../';
-function useCustomAction() {
+function useAction() {
return {
run() {
alert('这是自定义的操作逻辑');
@@ -37,17 +37,13 @@ function useCustomAction() {
}
}
-registerScope({
- useCustomAction,
-});
-
const schema = {
type: 'void',
name: 'action1',
title: '按钮',
'x-component': 'Action',
'x-component-props': {
- useAction: '{{ useCustomAction }}'
+ useAction,
},
};
@@ -188,6 +184,17 @@ export default () => {
```tsx
import React from 'react';
import { SchemaRenderer } from '../';
+import { useVisibleContext } from './';
+
+function useAction() {
+ const { visible, setVisible } = useVisibleContext();
+ return {
+ async run() {
+ console.log({ visible })
+ setVisible(false);
+ }
+ }
+}
const schema = {
type: 'void',
@@ -200,88 +207,21 @@ const schema = {
title: '弹窗标题',
'x-component': 'Action.Modal',
'x-component-props': {},
- properties: {
- },
- },
- },
-};
-
-export default () => {
- return
-}
-```
-
-## Action.Container - 指定容器内打开
-
-```tsx
-import React, { useRef } from 'react';
-import { SchemaRenderer } from '../';
-import { ActionContext } from './';
-
-const schema = {
- type: 'void',
- name: 'action1',
- title: '按钮',
- 'x-component': 'Action',
- properties: {
- container1: {
- type: 'void',
- title: '页面标题',
- 'x-component': 'Action.Container',
- properties: {
- input: {
- type: 'string',
- title: '字段',
- 'x-designable-bar': 'FormItem.DesignableBar',
- 'x-decorator': 'FormItem',
- 'x-component': 'Input',
- }
- },
- },
- },
-};
-
-export default () => {
- const ref = useRef();
- console.log('containerRef2222', ref)
- return (
-
- )
-}
-```
-
-## Action.DesignableBar - 按钮配置操作栏
-
-```tsx
-import React from 'react';
-import { SchemaRenderer } from '../';
-
-const schema = {
- type: 'void',
- name: 'action1',
- title: '按钮',
- 'x-component': 'Action',
- 'x-designable-bar': 'Action.DesignableBar',
- properties: {
- drawer1: {
- type: 'void',
- title: '抽屉标题',
- 'x-component': 'Action.Drawer',
- 'x-component-props': {},
properties: {
input: {
type: 'string',
'x-decorator': 'FormItem',
'x-component': 'Input',
},
+ close: {
+ type: 'void',
+ name: 'action1',
+ title: '关闭',
+ 'x-component': 'Action',
+ 'x-component-props': {
+ useAction,
+ },
+ },
action2: {
type: 'void',
title: '打开二级抽屉',
@@ -291,7 +231,7 @@ const schema = {
drawer1: {
type: 'void',
title: '二级抽屉标题',
- 'x-component': 'Action.Drawer',
+ 'x-component': 'Action.Modal',
'x-component-props': {},
properties: {
input: {
@@ -311,3 +251,45 @@ export default () => {
return
}
```
+
+## Action.Container - 指定容器内打开
+
+```tsx
+import React, { useRef } from 'react';
+import { SchemaRenderer } from '../';
+import { ActionContext } from './';
+
+export default () => {
+ const containerRef = useRef();
+ const schema = {
+ type: 'void',
+ name: 'action1',
+ title: '按钮',
+ 'x-component': 'Action',
+ 'x-component-props': {
+ containerRef
+ },
+ properties: {
+ container1: {
+ type: 'void',
+ title: '页面标题',
+ 'x-component': 'Action.Container',
+ properties: {
+ input: {
+ type: 'string',
+ title: '字段',
+ 'x-designable-bar': 'FormItem.DesignableBar',
+ 'x-decorator': 'FormItem',
+ 'x-component': 'Input',
+ }
+ },
+ },
+ },
+ };
+ return (
+
+
+
+ )
+}
+```
diff --git a/packages/client/src/blocks/action/index.tsx b/packages/client/src/blocks/action/index.tsx
index 5e18ff0de..0f71d58d7 100644
--- a/packages/client/src/blocks/action/index.tsx
+++ b/packages/client/src/blocks/action/index.tsx
@@ -10,9 +10,8 @@ import {
Schema,
useField,
} from '@formily/react';
-import { Button, Dropdown, Menu, Popover, Space } from 'antd';
+import { Button, Dropdown, Menu, Popover, Space, Drawer, Modal } from 'antd';
import { Link, useHistory, LinkProps } from 'react-router-dom';
-import Drawer from '../../components/Drawer';
import { SchemaRenderer, useDesignable } from '../';
import ReactDOM from 'react-dom';
import get from 'lodash/get';
@@ -22,6 +21,7 @@ import { useMount } from 'ahooks';
import { uid } from '@formily/shared';
import './style.less';
+import constate from 'constate';
export function useDefaultAction() {
return {
@@ -95,92 +95,81 @@ function useDesignableBar() {
};
}
-export const ActionContext = createContext({ containerRef: null });
+const [VisibleProvider, useVisibleContext] = constate(
+ (props: any = {}) => {
+ const { initialVisible = false, containerRef = null } = props;
+ const [visible, setVisible] = useState(initialVisible);
-export const Action: ActionType = observer((props) => {
+ return { containerRef, visible, setVisible };
+ },
+);
+
+export { VisibleProvider, useVisibleContext };
+
+const BaseAction = observer((props: any) => {
const { useAction = useDefaultAction, ...others } = props;
- const { containerRef } = useContext(ActionContext);
const field = useField();
- const schema = useFieldSchema();
const { run } = useAction();
const { DesignableBar } = useDesignableBar();
+ const { setVisible } = useVisibleContext();
+ const schema = useFieldSchema();
- const renderContainer = () => {
- let childSchema = null;
- if (schema.properties) {
- const key = Object.keys(schema.properties).shift();
- const current = schema.properties[key];
- childSchema = current;
- }
- if (childSchema && childSchema['x-component'] === 'Action.Container') {
- containerRef &&
- ReactDOM.render(
-
-
-
,
- containerRef.current,
- );
- }
- };
-
- useMount(() => {
- renderContainer();
- });
-
- let childSchema = null;
-
- if (schema.properties) {
- const key = Object.keys(schema.properties).shift();
- const current = schema.properties[key];
- childSchema = current;
- }
- console.log({ schema });
- if (childSchema && childSchema['x-component'] === 'Action.Popover') {
- return (
-
-
-
- }
- >
-
-
- );
- }
-
- return (
+ const renderButton = () => (
);
+
+ const popover = schema.reduceProperties((items, current) => {
+ if (current['x-component'] === 'Action.Popover') {
+ return current;
+ }
+ return null;
+ }, null);
+
+ if (popover) {
+ return (
+
+ );
+ }
+
+ return (
+ <>
+ {renderButton()}
+ {props.children}
+ >
+ );
+});
+
+export const Action: ActionType = observer((props: any) => {
+ const schema = useFieldSchema();
+ if (schema.properties) {
+ return (
+
+
+
+ );
+ }
+ return ;
});
Action.Link = observer((props) => {
@@ -198,21 +187,51 @@ Action.URL = observer((props) => {
);
});
-Action.Container = ({ children }) => {
- return children;
-};
+Action.Container = observer((props) => {
+ const { visible, setVisible } = useVisibleContext();
+ return visible && {props.children}
;
+});
-Action.Popover = ({ children }) => {
- return children;
-};
+Action.Popover = observer((props) => {
+ const schema = useFieldSchema();
+ return (
+
+ {schema['x-button']}
+
+ );
+});
-Action.Drawer = ({ children }) => {
- return children;
-};
+Action.Drawer = observer((props) => {
+ const field = useField();
+ const { visible, setVisible } = useVisibleContext();
+ return (
+ setVisible(false)}
+ >
+ {props.children}
+
+ );
+});
-Action.Modal = ({ children }) => {
- return children;
-};
+Action.Modal = observer((props) => {
+ const field = useField();
+ const { visible, setVisible } = useVisibleContext();
+ return (
+ setVisible(false)}
+ >
+ {props.children}
+
+ );
+});
Action.DesignableBar = () => {
const field = useField();
diff --git a/packages/client/src/blocks/database-field/index.md b/packages/client/src/blocks/database-field/index.md
index 94da656ca..211c487dd 100644
--- a/packages/client/src/blocks/database-field/index.md
+++ b/packages/client/src/blocks/database-field/index.md
@@ -16,6 +16,7 @@ import React from 'react';
import { createForm } from '@formily/core';
import { SchemaRenderer } from '../';
import { observer, connect, useField } from '@formily/react';
+import Editor from '@monaco-editor/react';
const schema = {
type: 'object',
@@ -50,73 +51,13 @@ const form = createForm();
export default observer(() => {
return (
- {JSON.stringify(form.values, null, 2)}
+
)
})
```
-
-```tsx
-import React from 'react';
-import { SchemaRenderer } from '../';
-
-const schema = {
- type: 'object',
- properties: {
- array: {
- type: 'array',
- // title: '数据表字段',
- 'x-component': 'ArrayCollapse',
- 'x-component-props': {
- accordion: true,
- },
- // maxItems: 3,
- 'x-decorator': 'FormItem',
- items: {
- type: 'object',
- 'x-component': 'ArrayCollapse.CollapsePanel',
- 'x-component-props': {
- header: '字段',
- },
- properties: {
- index: {
- type: 'void',
- 'x-component': 'ArrayCollapse.Index',
- },
- input: {
- type: 'string',
- 'x-decorator': 'FormItem',
- title: 'Input',
- required: true,
- 'x-component': 'Input',
- },
- remove: {
- type: 'void',
- 'x-component': 'ArrayCollapse.Remove',
- },
- moveUp: {
- type: 'void',
- 'x-component': 'ArrayCollapse.MoveUp',
- },
- moveDown: {
- type: 'void',
- 'x-component': 'ArrayCollapse.MoveDown',
- },
- },
- },
- properties: {
- addition: {
- type: 'void',
- title: '添加字段',
- 'x-component': 'ArrayCollapse.Addition',
- },
- },
- },
- }
-};
-
-export default () => {
- return
-}
-```
diff --git a/packages/client/src/blocks/database-field/index.tsx b/packages/client/src/blocks/database-field/index.tsx
index 4ed82d9dd..906cb29d3 100644
--- a/packages/client/src/blocks/database-field/index.tsx
+++ b/packages/client/src/blocks/database-field/index.tsx
@@ -11,13 +11,7 @@ import {
import { ArrayCollapse } from '@formily/antd';
import { uid } from '@formily/shared';
import '@formily/antd/lib/form-tab/style';
-import { Collapse, Button } from 'antd';
-
-const text = `
- A dog is a type of domesticated animal.
- Known for its loyalty and faithfulness,
- it can be found as a welcome guest in many households across the world.
-`;
+import { Collapse, Button, Dropdown, Menu } from 'antd';
const interfaces = new Map();
@@ -33,6 +27,21 @@ interfaces.set('string', {
} as ISchema,
},
properties: {
+ 'ui.title': {
+ type: 'string',
+ title: '字段名称',
+ required: true,
+ 'x-decorator': 'FormItem',
+ 'x-component': 'Input',
+ },
+ name: {
+ type: 'string',
+ title: '字段标识',
+ required: true,
+ 'x-disabled': true,
+ 'x-decorator': 'FormItem',
+ 'x-component': 'Input',
+ },
type: {
type: 'string',
title: '数据类型',
@@ -44,20 +53,6 @@ interfaces.set('string', {
{ label: 'Text', value: 'text' },
],
},
- name: {
- type: 'string',
- title: '字段标识',
- required: true,
- 'x-decorator': 'FormItem',
- 'x-component': 'Input',
- },
- 'ui.title': {
- type: 'string',
- title: '字段名称',
- required: true,
- 'x-decorator': 'FormItem',
- 'x-component': 'Input',
- },
'ui.required': {
type: 'string',
title: '必填',
@@ -79,6 +74,21 @@ interfaces.set('textarea', {
} as ISchema,
},
properties: {
+ 'ui.title': {
+ type: 'string',
+ required: true,
+ title: '字段名称',
+ 'x-decorator': 'FormItem',
+ 'x-component': 'Input',
+ },
+ name: {
+ type: 'string',
+ required: true,
+ title: '字段标识',
+ 'x-disabled': true,
+ 'x-decorator': 'FormItem',
+ 'x-component': 'Input',
+ },
type: {
type: 'string',
title: '数据类型',
@@ -90,13 +100,28 @@ interfaces.set('textarea', {
{ label: 'Text', value: 'text' },
],
},
- name: {
+ 'ui.required': {
type: 'string',
- required: true,
- title: '字段标识',
+ title: '必填',
'x-decorator': 'FormItem',
- 'x-component': 'Input.TextArea',
+ 'x-component': 'Checkbox',
},
+ },
+});
+
+interfaces.set('subTable', {
+ type: 'object',
+ default: {
+ type: 'string',
+ // name,
+ ui: {
+ type: 'string',
+ // title,
+ 'x-component': 'Select',
+ enum: [],
+ } as ISchema,
+ },
+ properties: {
'ui.title': {
type: 'string',
required: true,
@@ -104,6 +129,170 @@ interfaces.set('textarea', {
'x-decorator': 'FormItem',
'x-component': 'Input',
},
+ name: {
+ type: 'string',
+ required: true,
+ title: '字段标识',
+ 'x-disabled': true,
+ 'x-decorator': 'FormItem',
+ 'x-component': 'Input',
+ },
+ type: {
+ type: 'string',
+ title: '数据类型',
+ required: true,
+ 'x-decorator': 'FormItem',
+ 'x-component': 'Select',
+ enum: [
+ { label: 'String', value: 'string' },
+ { label: 'Text', value: 'text' },
+ { label: 'HasMany', value: 'hasMany' },
+ ],
+ },
+ 'children': {
+ type: 'array',
+ title: '子表格字段',
+ 'x-decorator': 'FormItem',
+ 'x-component': 'DatabaseField',
+ },
+ // 'ui.required': {
+ // type: 'string',
+ // title: '必填',
+ // 'x-decorator': 'FormItem',
+ // 'x-component': 'Checkbox',
+ // },
+ },
+});
+
+interfaces.set('select', {
+ type: 'object',
+ default: {
+ type: 'string',
+ // name,
+ ui: {
+ type: 'string',
+ // title,
+ 'x-component': 'Select',
+ enum: [],
+ } as ISchema,
+ },
+ properties: {
+ 'ui.title': {
+ type: 'string',
+ required: true,
+ title: '字段名称',
+ 'x-decorator': 'FormItem',
+ 'x-component': 'Input',
+ },
+ name: {
+ type: 'string',
+ required: true,
+ title: '字段标识',
+ 'x-disabled': true,
+ 'x-decorator': 'FormItem',
+ 'x-component': 'Input',
+ },
+ type: {
+ type: 'string',
+ title: '数据类型',
+ required: true,
+ 'x-decorator': 'FormItem',
+ 'x-component': 'Select',
+ enum: [
+ { label: 'String', value: 'string' },
+ { label: 'Text', value: 'text' },
+ ],
+ },
+ 'ui.enum': {
+ type: 'array',
+ title: '可选项',
+ 'x-decorator': 'FormItem',
+ 'x-component': 'ArrayTable',
+ 'x-component-props': {
+ pagination: false,
+ // scroll: { x: '100%' },
+ },
+ items: {
+ type: 'object',
+ properties: {
+ column1: {
+ type: 'void',
+ 'x-component': 'ArrayTable.Column',
+ 'x-component-props': { width: 50, title: '', align: 'center' },
+ properties: {
+ sort: {
+ type: 'void',
+ 'x-component': 'ArrayTable.SortHandle',
+ },
+ },
+ },
+ column2: {
+ type: 'void',
+ 'x-component': 'ArrayTable.Column',
+ 'x-component-props': { title: '选项值' },
+ properties: {
+ value: {
+ type: 'string',
+ 'x-decorator': 'FormItem',
+ 'x-component': 'Input',
+ },
+ },
+ },
+ column3: {
+ type: 'void',
+ 'x-component': 'ArrayTable.Column',
+ 'x-component-props': { title: '选项' },
+ properties: {
+ label: {
+ type: 'string',
+ 'x-decorator': 'FormItem',
+ 'x-component': 'Input',
+ },
+ },
+ },
+ column4: {
+ type: 'void',
+ 'x-component': 'ArrayTable.Column',
+ 'x-component-props': { title: '颜色' },
+ properties: {
+ color: {
+ type: 'string',
+ 'x-decorator': 'FormItem',
+ 'x-component': 'ColorSelect',
+ },
+ },
+ },
+ column5: {
+ type: 'void',
+ 'x-component': 'ArrayTable.Column',
+ 'x-component-props': {
+ title: '',
+ dataIndex: 'operations',
+ fixed: 'right',
+ },
+ properties: {
+ item: {
+ type: 'void',
+ 'x-component': 'FormItem',
+ properties: {
+ remove: {
+ type: 'void',
+ 'x-component': 'ArrayTable.Remove',
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ properties: {
+ add: {
+ type: 'void',
+ 'x-component': 'ArrayTable.Addition',
+ title: '添加可选项',
+ },
+ },
+ },
'ui.required': {
type: 'string',
title: '必填',
@@ -116,65 +305,101 @@ interfaces.set('textarea', {
export const DatabaseField: any = observer((props) => {
const field = useField();
console.log('DatabaseField', field.componentProps);
+ const [activeKey, setActiveKey] = useState(null);
return (
- {
- field.setComponentProps({
- activeKey: key,
- });
- }}
- accordion
- >
+ {
+ setActiveKey(key);
+ }} accordion>
{field.value?.map((item, index) => {
const schema = interfaces.get(item.interface);
console.log({ schema });
return (
field.moveUp(index)}>Up,
- ,
- ]}
- header={item.name}
+ // extra={[
+ // ,
+ // ,
+ // ]}
+ header={
+ <>
+ {item.ui && item.ui.title}
+ {' '}
+ {item.name}
+ >
+ }
key={item.id}
>
);
})}
-
+
+
);
});
diff --git a/packages/client/src/blocks/table/index.md b/packages/client/src/blocks/table/index.md
index d211c08aa..27f8b9a53 100644
--- a/packages/client/src/blocks/table/index.md
+++ b/packages/client/src/blocks/table/index.md
@@ -9,18 +9,26 @@ group:
path: /client/components
---
-# Table - 表格
+### Table.View
+
+只做数据展示,不能用作表单字段
```tsx
import React from 'react';
import { SchemaRenderer } from '../';
import { uid } from '@formily/shared';
+import Editor from '@monaco-editor/react';
+import { createForm } from '@formily/core';
+import { observer } from '@formily/react';
const schema = {
name: `t_${uid()}`,
- type: 'array',
- 'x-component': 'Table',
- default: [{ field1: 'a1', field2: 'b1' }, { field1: 'a2', field2: 'b2' }],
+ type: 'void',
+ 'x-component': 'Table.View',
+ // default: [
+ // { key: uid(), field1: 'a1', field2: 'b1' },
+ // { key: uid(), field1: 'a2', field2: 'b2' },
+ // ],
'x-component-props': {},
properties: {
[`a_${uid()}`]: {
@@ -28,17 +36,64 @@ const schema = {
'x-component': 'Table.ActionBar',
properties: {
action1: {
- type: 'object',
- title: '按钮1',
- 'x-component': 'Table.BulkAction.Popover',
- 'x-component-props': {},
- properties: {},
+ type: 'void',
+ name: 'action1',
+ title: '筛选',
+ 'x-component': 'Action',
+ properties: {
+ popover1: {
+ type: 'void',
+ title: '弹窗标题',
+ 'x-component': 'Action.Popover',
+ 'x-component-props': {},
+ properties: {
+ input: {
+ type: 'string',
+ 'x-component': 'Input',
+ }
+ },
+ },
+ },
},
action2: {
type: 'void',
- title: '按钮2',
- 'x-component': 'Table.BulkAction',
- 'x-component-props': {},
+ name: 'action1',
+ title: '新增',
+ 'x-component': 'Action',
+ 'x-designable-bar': 'Action.DesignableBar',
+ properties: {
+ drawer1: {
+ type: 'void',
+ title: '抽屉标题',
+ 'x-component': 'Action.Drawer',
+ 'x-component-props': {},
+ properties: {
+ input: {
+ type: 'string',
+ 'x-decorator': 'FormItem',
+ 'x-component': 'Input',
+ },
+ action2: {
+ type: 'void',
+ name: 'action1',
+ title: '提交',
+ 'x-component': 'Action',
+ 'x-component-props': {
+ 'useAction': '{{ useTableCreateAction }}'
+ },
+ }
+ },
+ },
+ },
+ },
+ action3: {
+ type: 'void',
+ name: 'action1',
+ title: '删除',
+ 'x-component': 'Action',
+ 'x-component-props': {
+ 'useAction': '{{ useTableDestroyAction }}'
+ },
},
},
},
@@ -65,8 +120,6 @@ const schema = {
'x-component': 'Table.Column',
'x-component-props': {
title: 'z1',
- width: 100,
- // DesignableBar: 'Table.Column.DesignableBar',
},
'x-designable-bar': 'Table.Column.DesignableBar',
properties: {
@@ -101,9 +154,172 @@ const schema = {
},
};
-export default () => {
+const form = createForm();
+
+export default observer(() => {
return (
-
- );
+
+
+
+
+ )
+});
+```
+
+### Table.Field
+
+可用作表单字段
+
+```tsx
+import React from 'react';
+import { SchemaRenderer } from '../';
+import { uid } from '@formily/shared';
+import Editor from '@monaco-editor/react';
+import { createForm } from '@formily/core';
+import { observer } from '@formily/react';
+
+const schema = {
+ name: `t_${uid()}`,
+ type: 'array',
+ 'x-component': 'Table.Field',
+ // default: [
+ // { key: uid(), field1: 'a1', field2: 'b1' },
+ // { key: uid(), field1: 'a2', field2: 'b2' },
+ // ],
+ 'x-component-props': {},
+ properties: {
+ [`a_${uid()}`]: {
+ type: 'void',
+ 'x-component': 'Table.ActionBar',
+ properties: {
+ action1: {
+ type: 'void',
+ name: 'action1',
+ title: '筛选',
+ 'x-component': 'Action',
+ properties: {
+ popover1: {
+ type: 'void',
+ title: '弹窗标题',
+ 'x-component': 'Action.Popover',
+ 'x-component-props': {},
+ properties: {
+ input: {
+ type: 'string',
+ 'x-component': 'Input',
+ }
+ },
+ },
+ },
+ },
+ action2: {
+ type: 'void',
+ name: 'action1',
+ title: '新增',
+ 'x-component': 'Action',
+ 'x-designable-bar': 'Action.DesignableBar',
+ properties: {
+ drawer1: {
+ type: 'void',
+ title: '抽屉标题',
+ 'x-component': 'Action.Drawer',
+ 'x-component-props': {},
+ properties: {
+ action2: {
+ type: 'void',
+ name: 'action1',
+ title: '提交',
+ 'x-component': 'Action',
+ 'x-component-props': {
+ },
+ }
+ },
+ },
+ },
+ },
+ action3: {
+ type: 'void',
+ name: 'action1',
+ title: '删除',
+ 'x-component': 'Action',
+ 'x-component-props': {
+ },
+ },
+ },
+ },
+ [`a_${uid()}`]: {
+ type: 'void',
+ 'x-component': 'Table.ActionBar',
+ 'x-component-props': {
+ align: 'bottom',
+ },
+ properties: {
+ pagination: {
+ type: 'void',
+ 'x-component': 'Table.Pagination',
+ 'x-component-props': {
+ defaultCurrent: 1,
+ total: 50,
+ },
+ },
+ },
+ },
+ [`c_${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-decorator-props': {
+ feedbackLayout: 'popover',
+ },
+ 'x-decorator': 'FormItem',
+ 'x-component': 'Input',
+ },
+ },
+ },
+ [`c_${uid()}`]: {
+ type: 'void',
+ title: '字段2',
+ 'x-component': 'Table.Column',
+ properties: {
+ field2: {
+ type: 'string',
+ title: '字段2',
+ required: true,
+ 'x-decorator-props': {
+ feedbackLayout: 'popover',
+ },
+ 'x-decorator': 'FormItem',
+ 'x-component': 'Input',
+ },
+ },
+ },
+ },
};
+
+const form = createForm();
+
+export default observer(() => {
+ return (
+
+
+
+
+ )
+});
```
\ No newline at end of file
diff --git a/packages/client/src/blocks/table/index.tsx b/packages/client/src/blocks/table/index.tsx
index c70822ffd..2173c804b 100644
--- a/packages/client/src/blocks/table/index.tsx
+++ b/packages/client/src/blocks/table/index.tsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import React, { createContext, useContext, useState } from 'react';
import {
useFieldSchema,
Schema,
@@ -6,13 +6,18 @@ import {
RecursionField,
useField,
} from '@formily/react';
-import { Table as AntdTable } from 'antd';
+import { Button, Pagination, Space, Table as AntdTable } from 'antd';
import { DesignableBar } from './DesignableBar';
import { ColumnDesignableBar } from './ColumnDesignableBar';
+import { uid } from '@formily/shared';
+import useRequest from '@ahooksjs/use-request';
+import constate from 'constate';
+import { SchemaRenderer } from '../';
+import { useVisibleContext } from '../action';
-function useTableColumns(props) {
+function useTableColumns(props?: any) {
const schema = useFieldSchema();
- const { dataSource } = props;
+ const { dataSource } = props || {};
function findColumns(schema: Schema): Schema[] {
return schema.reduceProperties((columns, current) => {
@@ -29,14 +34,14 @@ function useTableColumns(props) {
title: item.title,
dataIndex: item.name,
...columnProps,
- render(value, record) {
- console.log({ item });
- const index = dataSource.indexOf(record);
+ render(value, record, index) {
+ // console.log({ item });
+ // const index = dataSource.indexOf(record);
item.mapProperties((s) => {
s['title'] = undefined;
s['x-read-pretty'] = true;
return s;
- })
+ });
return (
);
@@ -74,35 +79,200 @@ function useTableActionBars() {
return findActionBars(schema);
}
-function useTableDetails() {
- const schema = useFieldSchema();
-
- function findDetails(schema: Schema) {
- return schema.reduceProperties((items, current) => {
- if (current['x-component'] === 'Table.Details') {
- return [...items, current];
- }
- return [...items, ...findDetails(current)];
- }, []);
- }
-
- return findDetails(schema);
+function useTable() {
+ const field = useField();
+ const [selectedRowKeys, setSelectedRowKeys] = useState([]);
+ const response = useRequest(
+ () => {
+ return new Promise((resolve) => {
+ console.log('useRequest');
+ setTimeout(() => {
+ resolve([
+ { key: uid(), field1: uid(), field2: uid() },
+ { key: uid(), field1: uid(), field2: uid() },
+ ]);
+ }, 500);
+ });
+ },
+ {
+ onSuccess(data) {
+ field.setValue(data);
+ },
+ },
+ );
+ return {
+ selectedRowKeys,
+ setSelectedRowKeys,
+ mutate: response.mutate,
+ response,
+ async create() {
+ response.refresh()
+ },
+ async update() {
+ response.refresh()
+ },
+ async destroy() {
+ response.refresh()
+ },
+ } as any;
}
-export const Table: any = observer((props) => {
+const [TableContextProvider, useTableContext] = constate(useTable);
+
+export function useTableCreateAction() {
+ const { visible, setVisible } = useVisibleContext()
+ const { create } = useTableContext();
+ return {
+ run: async () => {
+ setVisible(false);
+ await create();
+ console.log({ visible })
+ },
+ }
+}
+
+export function useTableDestroyAction() {
+ // const { setVisible } = useVisibleContext()
+ const { destroy } = useTableContext();
+ return {
+ run: async () => {
+ // setVisible(false);
+ await destroy();
+ },
+ }
+}
+
+const ArrayTable = (props) => {
const field = useField();
- const dataSource = field.value;
- const columns = useTableColumns({ dataSource });
+ // const dataSource = Array.isArray(field.value) ? field.value.slice() : [];
+ const columns = useTableColumns();
const actionBars = useTableActionBars();
- const details = useTableDetails();
- console.log({ columns, actionBars, details });
+ const {
+ selectedRowKeys,
+ setSelectedRowKeys,
+ response = {},
+ create,
+ } = useTableContext();
+ console.log({ response });
+ const { data = [], loading, mutate } = response as any;
return (
- <>
-
- >
+
+ {actionBars.top.map((actionBarSchema) => {
+ return (
+
+ );
+ })}
+
+
{
+ setSelectedRowKeys(keys);
+ },
+ }}
+ />
+ {actionBars.bottom.map((actionBarSchema) => {
+ return (
+
+ );
+ })}
+
+ );
+};
+
+export const Table: any = observer((props) => {
+ return (
+
+
+
);
});
Table.Column = () => null;
-Table.Column.DesignableBar = ColumnDesignableBar;
-Table.DesignableBar = DesignableBar;
+
+Table.ActionBar = observer((props) => {
+ return (
+
+ {props.children}
+
+ );
+});
+
+Table.Pagination = observer((props) => {
+ const { response } = useTableContext();
+ return (
+ {
+ response.refresh();
+ // console.log('useRequest', { page, pageSize });
+ }}
+ />
+ );
+});
+
+Table.View = observer(() => {
+ const schema = useFieldSchema();
+ console.log('Table.View', schema);
+ return (
+
+ );
+});
+
+Table.Field = observer((props) => {
+ return (
+
+
+
+ );
+});