updates...

This commit is contained in:
chenos 2021-07-07 22:50:40 +08:00
parent 14160761d3
commit ed4397e112
6 changed files with 582 additions and 472 deletions

View File

@ -40,7 +40,14 @@ import { Menu } from '../menu';
import { Password } from '../password'; import { Password } from '../password';
import { Radio } from '../radio'; import { Radio } from '../radio';
import { Select } from '../select'; import { Select } from '../select';
import { Table, useTableCreateAction, useTableDestroyAction } from '../table'; import {
Table,
useTableRow,
useTableCreateAction,
useTableUpdateAction,
useTableDestroyAction,
useTableFilterAction,
} from '../table';
import { Tabs } from '../tabs'; import { Tabs } from '../tabs';
import { TimePicker } from '../time-picker'; import { TimePicker } from '../time-picker';
import { Upload } from '../upload'; import { Upload } from '../upload';
@ -61,6 +68,9 @@ export const scope = {
useSubmit, useSubmit,
useTableCreateAction, useTableCreateAction,
useTableDestroyAction, useTableDestroyAction,
useTableFilterAction,
useTableRow,
useTableUpdateAction,
}; };
export const components = { export const components = {

View File

@ -1,4 +1,4 @@
import React, { createContext, useContext, useState } from 'react'; import React, { createContext, useContext, useEffect, useState } from 'react';
import { import {
useForm, useForm,
FormProvider, FormProvider,
@ -95,14 +95,12 @@ function useDesignableBar() {
}; };
} }
const [VisibleProvider, useVisibleContext] = constate( const [VisibleProvider, useVisibleContext] = constate((props: any = {}) => {
(props: any = {}) => { const { initialVisible = false, containerRef = null } = props;
const { initialVisible = false, containerRef = null } = props; const [visible, setVisible] = useState(initialVisible);
const [visible, setVisible] = useState(initialVisible);
return { containerRef, visible, setVisible }; return { containerRef, visible, setVisible };
}, });
);
export { VisibleProvider, useVisibleContext }; export { VisibleProvider, useVisibleContext };
@ -113,11 +111,17 @@ const BaseAction = observer((props: any) => {
const { DesignableBar } = useDesignableBar(); const { DesignableBar } = useDesignableBar();
const { setVisible } = useVisibleContext(); const { setVisible } = useVisibleContext();
const schema = useFieldSchema(); const schema = useFieldSchema();
useEffect(() => {
field.componentProps.setVisible = setVisible;
}, []);
console.log('BaseAction', { field, schema }, field.title)
const renderButton = () => ( const renderButton = () => (
<Button <Button
{...others} {...others}
onClick={async () => { onClick={async (e) => {
e.stopPropagation();
setVisible && setVisible(true); setVisible && setVisible(true);
await run(); await run();
}} }}
@ -164,7 +168,7 @@ export const Action: ActionType = observer((props: any) => {
const schema = useFieldSchema(); const schema = useFieldSchema();
if (schema.properties) { if (schema.properties) {
return ( return (
<VisibleProvider containerRef={props.containerRef}> <VisibleProvider initialVisible={props.initialVisible} containerRef={props.containerRef}>
<BaseAction {...props} /> <BaseAction {...props} />
</VisibleProvider> </VisibleProvider>
); );
@ -193,9 +197,17 @@ Action.Container = observer((props) => {
}); });
Action.Popover = observer((props) => { Action.Popover = observer((props) => {
const { visible, setVisible } = useVisibleContext();
const schema = useFieldSchema(); const schema = useFieldSchema();
return ( return (
<Popover {...props} content={props.children}> <Popover
visible={visible}
onVisibleChange={(visible) => {
setVisible(visible);
}}
{...props}
content={props.children}
>
{schema['x-button']} {schema['x-button']}
</Popover> </Popover>
); );
@ -206,11 +218,17 @@ Action.Drawer = observer((props) => {
const { visible, setVisible } = useVisibleContext(); const { visible, setVisible } = useVisibleContext();
return ( return (
<Drawer <Drawer
onClick={e => {
e.stopPropagation();
}}
title={field.title} title={field.title}
width={'50%'} width={'50%'}
{...props} {...props}
visible={visible} visible={visible}
onClose={() => setVisible(false)} onClose={(e) => {
e.stopPropagation();
setVisible(false)
}}
> >
{props.children} {props.children}
</Drawer> </Drawer>

View File

@ -1,6 +1,11 @@
import React, { useContext, useMemo, useRef, useState } from 'react'; import React, { useContext, useMemo, useRef, useState } from 'react';
import { createForm } from '@formily/core'; import { createForm } from '@formily/core';
import { SchemaOptionsContext, Schema, useFieldSchema } from '@formily/react'; import {
SchemaOptionsContext,
Schema,
useFieldSchema,
observer,
} from '@formily/react';
import { SchemaRenderer, useDesignable } from '../DesignableSchemaField'; import { SchemaRenderer, useDesignable } from '../DesignableSchemaField';
import get from 'lodash/get'; import get from 'lodash/get';
import { Dropdown, Menu } from 'antd'; import { Dropdown, Menu } from 'antd';
@ -14,6 +19,7 @@ import { useMouseEvents } from 'beautiful-react-hooks';
import cls from 'classnames'; import cls from 'classnames';
import './style.less'; import './style.less';
import { clone } from '@formily/shared';
function Blank() { function Blank() {
return null; return null;
@ -29,7 +35,20 @@ function useDesignableBar() {
}; };
} }
export const Form = (props) => { function useDefaultValues() {
return {};
}
export const Form: any = observer((props: any) => {
const { useValues = useDefaultValues } = props;
const values = useValues();
const form = useMemo(() => {
console.log('Form.useMemo', values);
return createForm({
values,
// values: clone(values),
});
}, [values]);
const schema = useFieldSchema(); const schema = useFieldSchema();
const { schema: designableSchema, refresh } = useDesignable(); const { schema: designableSchema, refresh } = useDesignable();
const { DesignableBar } = useDesignableBar(); const { DesignableBar } = useDesignableBar();
@ -44,9 +63,7 @@ export const Form = (props) => {
setActive(false); setActive(false);
}); });
onMouseMove((e: React.MouseEvent) => { onMouseMove((e: React.MouseEvent) => {});
});
return ( return (
<div ref={ref} className={'nb-form'}> <div ref={ref} className={'nb-form'}>
<SchemaRenderer <SchemaRenderer
@ -54,13 +71,14 @@ export const Form = (props) => {
designableSchema.properties = subSchema.properties; designableSchema.properties = subSchema.properties;
refresh(); refresh();
}} }}
form={form}
schema={schema.toJSON()} schema={schema.toJSON()}
onlyRenderProperties onlyRenderProperties
/> />
<DesignableBar active={active}/> <DesignableBar active={active} />
</div> </div>
); );
}; });
Form.DesignableBar = (props) => { Form.DesignableBar = (props) => {
const { active } = props; const { active } = props;

View File

@ -0,0 +1,283 @@
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: [
// { 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,
},
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: {
[uid()]: {
name: 'form',
type: 'object',
'x-component': 'Form',
properties: {
filter: {
type: 'string',
title: '字段1',
'x-decorator': 'FormItem',
'x-component': 'Input',
},
action: {
type: 'void',
title: '提交',
'x-component': 'Action',
'x-component-props': {
'useAction': '{{ useTableFilterAction }}'
},
}
}
},
},
},
},
},
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: {
[uid()]: {
name: 'form',
type: 'object',
'x-component': 'Form',
properties: {
field1: {
type: 'string',
title: '字段1',
'x-decorator': 'FormItem',
'x-component': 'Input',
},
field2: {
type: 'string',
title: '字段2',
'x-decorator': 'FormItem',
'x-component': 'Input',
},
action: {
type: 'void',
title: '提交',
'x-component': 'Action',
'x-component-props': {
'useAction': '{{ useTableCreateAction }}'
},
}
}
},
},
},
},
},
action3: {
type: 'void',
name: 'action1',
title: '删除',
'x-component': 'Action',
'x-component-props': {
'useAction': '{{ useTableDestroyAction }}'
},
},
},
},
[`a_${uid()}`]: {
type: 'void',
'x-component': 'Table.ActionBar',
'x-component-props': {
align: 'bottom',
},
properties: {
pagination: {
type: 'void',
'x-component': 'Table.Pagination',
'x-component-props': {
defaultPageSize: 5,
},
},
},
},
[`c_${uid()}`]: {
type: 'void',
title: '排序',
'x-component': 'Table.Column',
properties: {
sort: {
type: 'void',
'x-component': 'Table.SortHandle',
},
},
},
[`c_${uid()}`]: {
type: 'void',
title: '序号',
'x-component': 'Table.Column',
properties: {
index: {
type: 'void',
'x-component': 'Table.Index',
},
},
},
[`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-read-pretty': 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-read-pretty': true,
'x-decorator-props': {
feedbackLayout: 'popover',
},
'x-decorator': 'FormItem',
'x-component': 'Input',
},
},
},
[`col_${uid()}`]: {
type: 'void',
title: '操作',
'x-component': 'Table.Column',
properties: {
action3: {
type: 'void',
title: '删除',
'x-component': 'Action',
'x-component-props': {
'useAction': '{{ useTableDestroyAction }}'
},
},
action2: {
type: 'void',
name: 'action1',
title: '修改',
'x-component': 'Action',
'x-default-action': true,
'x-designable-bar': 'Action.DesignableBar',
properties: {
drawer1: {
type: 'void',
title: '编辑表单',
'x-component': 'Action.Drawer',
'x-component-props': {},
properties: {
[uid()]: {
name: 'form',
type: 'void',
'x-component': 'Form',
'x-component-props': {
'useValues': '{{ useTableRow }}',
},
properties: {
field1: {
type: 'string',
title: '字段1',
'x-decorator': 'FormItem',
'x-component': 'Input',
},
field2: {
type: 'string',
title: '字段2',
'x-decorator': 'FormItem',
'x-component': 'Input',
},
action: {
type: 'void',
title: '提交',
'x-component': 'Action',
'x-component-props': {
'useAction': '{{ useTableUpdateAction }}'
},
}
}
},
},
},
},
},
},
},
},
};
const form = createForm();
export default observer(() => {
return (
<div>
<SchemaRenderer form={form} schema={schema} />
<Editor
height="200px"
defaultLanguage="json"
value={JSON.stringify(form.values, null, 2)}
/>
</div>
)
});

View File

@ -9,317 +9,12 @@ group:
path: /client/components path: /client/components
--- ---
### Table.View # Table - 表格
只做数据展示,不能用作表单字段 - 远程数据、远程分页、远程过滤
- 远程数据、本地分页、远程过滤
- 远程数据、本地分页、本地过滤
- 本地数据、本地分页、本地过滤
```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 = { <code src="./demos/demo1.tsx"/>
name: `t_${uid()}`,
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()}`]: {
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: {
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 }}'
},
},
},
},
[`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 (
<div>
<SchemaRenderer form={form} schema={schema} />
<Editor
height="200px"
defaultLanguage="json"
value={JSON.stringify(form.values, null, 2)}
/>
</div>
)
});
```
### 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 (
<div>
<SchemaRenderer form={form} schema={schema} />
<Editor
height="200px"
defaultLanguage="json"
value={JSON.stringify(form.values, null, 2)}
/>
</div>
)
});
```

View File

@ -5,49 +5,54 @@ import {
observer, observer,
RecursionField, RecursionField,
useField, useField,
useForm,
FormProvider,
createSchemaField,
} from '@formily/react'; } from '@formily/react';
import { Button, Pagination, Space, Table as AntdTable } from 'antd'; import {
import { DesignableBar } from './DesignableBar'; Button,
import { ColumnDesignableBar } from './ColumnDesignableBar'; Pagination,
import { uid } from '@formily/shared'; PaginationProps,
import useRequest from '@ahooksjs/use-request'; Space,
Spin,
Table as AntdTable,
} from 'antd';
import { findIndex } from 'lodash';
import constate from 'constate'; import constate from 'constate';
import { SchemaRenderer } from '../'; import useRequest from '@ahooksjs/use-request';
import { BaseResult } from '@ahooksjs/use-request/lib/types';
import { uid, clone } from '@formily/shared';
import { MenuOutlined } from '@ant-design/icons';
import { useVisibleContext } from '../action'; import { useVisibleContext } from '../action';
function useTableColumns(props?: any) { interface TableRowProps {
const schema = useFieldSchema(); index: number;
const { dataSource } = props || {}; data: any;
}
function findColumns(schema: Schema): Schema[] { const TableRowContext = createContext<TableRowProps>(null);
function usePaginationProps() {
const schema = useFieldSchema();
function findPagination(schema: Schema): Schema[] {
return schema.reduceProperties((columns, current) => { return schema.reduceProperties((columns, current) => {
if (current['x-component'] === 'Table.Column') { if (current['x-component'] === 'Table.Pagination') {
return [...columns, current]; return [...columns, current];
} }
return [...columns, ...findColumns(current)]; return [...columns, ...findPagination(current)];
}, []); }, []);
} }
return findColumns(schema).map((item) => { const pagination = findPagination(schema).shift();
const columnProps = item['x-component-props'] || {};
return { if (pagination) {
title: item.title, // console.log({ pagination });
dataIndex: item.name, const props = pagination['x-component-props'] || {};
...columnProps, return { defaultCurrent: 1, defaultPageSize: 10, ...props };
render(value, record, index) { }
// console.log({ item });
// const index = dataSource.indexOf(record); return false;
item.mapProperties((s) => {
s['title'] = undefined;
s['x-read-pretty'] = true;
return s;
});
return (
<RecursionField schema={item} name={index} onlyRenderProperties />
);
},
};
});
} }
function useTableActionBars() { function useTableActionBars() {
@ -79,82 +84,177 @@ function useTableActionBars() {
return findActionBars(schema); return findActionBars(schema);
} }
function useTable() { function useTableColumns(props?: any) {
const field = useField<Formily.Core.Models.ArrayField>(); const schema = useFieldSchema();
const [selectedRowKeys, setSelectedRowKeys] = useState([]); const { dataSource } = props || {};
const response = useRequest<any>(
() => { function findColumns(schema: Schema): Schema[] {
return new Promise((resolve) => { return schema.reduceProperties((columns, current) => {
console.log('useRequest'); if (current['x-component'] === 'Table.Column') {
setTimeout(() => { return [...columns, current];
resolve([ }
{ key: uid(), field1: uid(), field2: uid() }, return [...columns, ...findColumns(current)];
{ key: uid(), field1: uid(), field2: uid() }, }, []);
]); }
}, 500);
}); return findColumns(schema).map((item) => {
}, const columnProps = item['x-component-props'] || {};
{ return {
onSuccess(data) { title: item.title,
field.setValue(data); dataIndex: item.name,
...columnProps,
render(value, record, recordIndex) {
const index = dataSource.indexOf(record);
return (
<TableRowContext.Provider
value={{
index: index,
data: record,
}}
>
<RecursionField schema={item} name={index} onlyRenderProperties />
</TableRowContext.Provider>
);
}, },
}, };
); });
return {
selectedRowKeys,
setSelectedRowKeys,
mutate: response.mutate,
response,
async create() {
response.refresh()
},
async update() {
response.refresh()
},
async destroy() {
response.refresh()
},
} as any;
} }
const [TableContextProvider, useTableContext] = constate(useTable); export function useTableRow() {
const ctx = useContext(TableRowContext);
console.log('useTableRow', ctx.data);
return ctx.data;
}
export function useTableCreateAction() { export function useTableIndex() {
const { visible, setVisible } = useVisibleContext() const { params: { page, pageSize } } = useTableContext();
const { create } = useTableContext(); const ctx = useContext(TableRowContext);
return { const field = useField();
run: async () => { if (!field.componentProps.isRemoteDataSource) {
setVisible(false); return ctx.index;
await create();
console.log({ visible })
},
} }
return pageSize ? ctx.index + (page - 1) * pageSize : ctx.index;
} }
export function useTableDestroyAction() { export function useTableDestroyAction() {
// const { setVisible } = useVisibleContext() const ctx = useContext(TableRowContext);
const { destroy } = useTableContext(); const { field, selectedRowKeys, setSelectedRowKeys, refresh } = useTableContext();
const rowKey = field.componentProps.rowKey || 'id';
return { return {
run: async () => { async run() {
// setVisible(false); if (ctx && typeof ctx.index !== 'undefined') {
await destroy(); field.remove(ctx.index);
}, refresh();
return;
}
if (!selectedRowKeys.length) {
return;
}
while (selectedRowKeys.length) {
const key = selectedRowKeys.shift();
const index = findIndex(
field.value,
(item) => item[rowKey] === key,
);
field.remove(index);
}
refresh();
setSelectedRowKeys([]);
}
}
}
export function useTableFilterAction() {
const { field, refresh, params } = useTableContext();
const { setVisible } = useVisibleContext();
const form = useForm();
return {
async run() {
setVisible && setVisible(false);
refresh();
}
} }
} }
const ArrayTable = (props) => { export function useTableCreateAction() {
const { field, run: exec, params } = useTableContext();
const { setVisible } = useVisibleContext();
const form = useForm();
return {
async run() {
setVisible && setVisible(false);
field.unshift(clone(form.values));
form.reset();
exec({...params, page: 1});
}
}
}
export function useTableUpdateAction() {
const { field, refresh, params } = useTableContext();
const { setVisible } = useVisibleContext();
const form = useForm();
return {
async run() {
setVisible && setVisible(false);
refresh();
}
}
}
const [TableContextProvider, useTableContext] = constate(() => {
const field = useField<Formily.Core.Models.ArrayField>(); const field = useField<Formily.Core.Models.ArrayField>();
// const dataSource = Array.isArray(field.value) ? field.value.slice() : []; const [selectedRowKeys, setSelectedRowKeys] = useState([]);
const columns = useTableColumns(); const pagination = usePaginationProps();
const response = useRequest<{
list: any[];
total: number;
}>((params = {}) => {
return new Promise((resolve) => {
const dataSource = Array.isArray(field.value) ? field.value.slice() : [];
if (pagination) {
const {
page = pagination.defaultCurrent,
pageSize = pagination.defaultPageSize,
} = params;
const startIndex = (page - 1) * pageSize;
const endIndex = startIndex + pageSize - 1;
resolve({
list: dataSource.slice(startIndex, endIndex + 1),
total: dataSource.length,
});
} else {
resolve({
list: dataSource,
total: dataSource.length,
});
}
});
});
const params = {
page: pagination.defaultCurrent,
pageSize: pagination.defaultPageSize,
...(response.params[0] || {}),
};
return { ...response, params, field, selectedRowKeys, setSelectedRowKeys };
});
export { TableContextProvider, useTableContext };
const TableContainer = observer((props) => {
const field = useField<Formily.Core.Models.ArrayField>();
const schema = useFieldSchema();
const actionBars = useTableActionBars(); const actionBars = useTableActionBars();
const { const { loading, data, refresh, selectedRowKeys, setSelectedRowKeys } =
selectedRowKeys, useTableContext();
setSelectedRowKeys, const rowKey = field.componentProps.rowKey || 'id';
response = {}, console.log({ actionBars });
create, const dataSource = Array.isArray(field.value) ? field.value.slice() : []
} = useTableContext(); const columns = useTableColumns({ dataSource });
console.log({ response });
const { data = [], loading, mutate } = response as any;
return ( return (
<div> <div>
{actionBars.top.map((actionBarSchema) => { {actionBars.top.map((actionBarSchema) => {
@ -172,33 +272,31 @@ const ArrayTable = (props) => {
/> />
); );
})} })}
<Button
onClick={() => {
create();
// field.unshift({ key: uid(), field1: uid(), field2: uid() });
// const dataSource = Array.isArray(field.value)
// ? field.value.slice()
// : [];
// mutate(dataSource);
// response.refresh();
// console.log({ selectedRowKeys })
}}
>
</Button>
<AntdTable <AntdTable
rowKey={'key'}
loading={loading}
pagination={false} pagination={false}
columns={columns} rowKey={rowKey}
dataSource={data} loading={loading}
rowSelection={{ rowSelection={{
type: 'checkbox', type: 'checkbox',
selectedRowKeys, selectedRowKeys,
onChange: (keys) => { onChange: (keys) => {
console.log(keys);
setSelectedRowKeys(keys); setSelectedRowKeys(keys);
}, },
}} }}
dataSource={data?.list}
columns={columns}
onRow={(data) => {
const index = dataSource.indexOf(data);
return {
onClick(e) {
field.query(`.${schema.name}.${index}.action2`).take((f) => {
const setVisible = f.componentProps.setVisible;
setVisible && setVisible(true);
});
},
};
}}
/> />
{actionBars.bottom.map((actionBarSchema) => { {actionBars.bottom.map((actionBarSchema) => {
return ( return (
@ -217,12 +315,12 @@ const ArrayTable = (props) => {
})} })}
</div> </div>
); );
}; });
export const Table: any = observer((props) => { export const Table: any = observer((props) => {
return ( return (
<TableContextProvider> <TableContextProvider>
<ArrayTable {...props} /> <TableContainer />
</TableContextProvider> </TableContextProvider>
); );
}); });
@ -238,41 +336,29 @@ Table.ActionBar = observer((props) => {
}); });
Table.Pagination = observer((props) => { Table.Pagination = observer((props) => {
const { response } = useTableContext(); const { data, params, run } = useTableContext();
return ( return data?.total > params?.pageSize && (
<Pagination <Pagination
{...props} {...props}
defaultCurrent={1}
defaultPageSize={5}
current={params?.page}
pageSize={params?.pageSize}
total={data?.total}
onChange={(page, pageSize) => { onChange={(page, pageSize) => {
response.refresh(); run({ page, pageSize });
// console.log('useRequest', { page, pageSize });
}} }}
/> />
); );
}); });
Table.View = observer(() => { Table.SortHandle = observer((props) => {
const schema = useFieldSchema(); const field = useField<Formily.Core.Models.Field>();
console.log('Table.View', schema); console.log('SortHandle', field.value);
return ( return <MenuOutlined />;
<SchemaRenderer
schema={{
type: 'object',
properties: {
[schema.name]: {
...schema.toJSON(),
type: 'array',
'x-component': 'Table.Field',
},
},
}}
/>
);
}); });
Table.Field = observer((props) => { Table.Index = observer((props) => {
return ( const index = useTableIndex();
<TableContextProvider> return <div>#{index + 1}</div>;
<ArrayTable {...props} />
</TableContextProvider>
);
}); });