diff --git a/packages/client/src/schemas/form/DesignableBar.tsx b/packages/client/src/schemas/form/DesignableBar.tsx
index a2bbd4e04..7e4e1e901 100644
--- a/packages/client/src/schemas/form/DesignableBar.tsx
+++ b/packages/client/src/schemas/form/DesignableBar.tsx
@@ -17,7 +17,6 @@ import {
SchemaField,
useDesignable,
removeSchema,
- useCollectionContext,
} from '../';
import get from 'lodash/get';
import { Button, Dropdown, Menu, Space } from 'antd';
diff --git a/packages/client/src/schemas/form/Field.DesignableBar.tsx b/packages/client/src/schemas/form/Field.DesignableBar.tsx
index 65a674214..72624a33e 100644
--- a/packages/client/src/schemas/form/Field.DesignableBar.tsx
+++ b/packages/client/src/schemas/form/Field.DesignableBar.tsx
@@ -17,7 +17,6 @@ import {
SchemaField,
useDesignable,
removeSchema,
- useCollectionContext,
updateSchema,
} from '../';
import get from 'lodash/get';
@@ -33,7 +32,8 @@ import constate from 'constate';
import { useEffect } from 'react';
import { uid } from '@formily/shared';
import { getSchemaPath } from '../../components/schema-renderer';
-import { FormFieldUIDContext, useDisplayFieldsContext } from '.';
+import { RandomNameContext } from '.';
+import { useDisplayedMapContext } from '../../constate';
export const FieldDesignableBar = observer((props) => {
const field = useField();
@@ -41,8 +41,8 @@ export const FieldDesignableBar = observer((props) => {
const { designable, schema, deepRemove } = useDesignable();
const [visible, setVisible] = useState(false);
const { dragRef } = useContext(DraggableBlockContext);
- const fieldUid = useContext(FormFieldUIDContext);
- const { removeDisplayField } = useDisplayFieldsContext();
+ const randomName = useContext(RandomNameContext);
+ const displayed = useDisplayedMapContext();
const fieldName = schema['x-component-props']?.['fieldName'];
if (!designable) {
return null;
@@ -71,13 +71,13 @@ export const FieldDesignableBar = observer((props) => {
onClick={async () => {
const title = uid();
field
- .query(field.address.concat(fieldUid, fieldName))
+ .query(field.address.concat(randomName, fieldName))
.take((f) => {
f.title = title;
});
console.log(
'fieldfieldfieldfieldfield',
- field.address.concat(fieldUid, fieldName).entire,
+ field.address.concat(randomName, fieldName).entire,
schema,
);
schema['title'] = title;
@@ -98,7 +98,7 @@ export const FieldDesignableBar = observer((props) => {
schema['x-component-props']?.['fieldName'];
console.log({ schema, removed, fieldName });
const last = removed.pop();
- removeDisplayField(fieldName);
+ displayed.remove(fieldName);
if (isGridRowOrCol(last)) {
await removeSchema(last);
}
diff --git a/packages/client/src/schemas/form/index.tsx b/packages/client/src/schemas/form/index.tsx
index 5bfdd5eee..82450787f 100644
--- a/packages/client/src/schemas/form/index.tsx
+++ b/packages/client/src/schemas/form/index.tsx
@@ -12,15 +12,7 @@ import {
useForm,
RecursionField,
} from '@formily/react';
-import {
- useSchemaPath,
- SchemaField,
- useDesignable,
- removeSchema,
- useCollectionContext,
- useResourceContext,
- ResourceContextProvider,
-} from '../';
+import { useSchemaPath, SchemaField, useDesignable, removeSchema } from '../';
import get from 'lodash/get';
import { Button, Dropdown, Menu, message, Space } from 'antd';
import { MenuOutlined, DragOutlined } from '@ant-design/icons';
@@ -39,48 +31,30 @@ import { FieldDesignableBar } from './Field.DesignableBar';
import { createContext } from 'react';
import { BlockItem } from '../block-item';
import { Resource } from '../../resource';
-import { useMap } from 'ahooks';
-
-const [DisplayFieldsContextProvider, useDisplayFieldsContext] = constate(() => {
- const [displayFields, { set, remove, get }] = useMap([]);
-
- return {
- displayFields,
- hasDisplayField(fieldName) {
- return !!get(fieldName);
- },
- addDisplayField(fieldName, schema) {
- set(fieldName, schema);
- },
- getDisplayField(fieldName) {
- return get(fieldName);
- },
- removeDisplayField(fieldName) {
- remove(fieldName);
- },
- };
-});
-
-export { DisplayFieldsContextProvider, useDisplayFieldsContext };
+import {
+ CollectionProvider,
+ useCollectionContext,
+ DisplayedMapProvider,
+ useDisplayedMapContext,
+} from '../../constate';
export const Form: any = observer((props: any) => {
const {
useValues = () => ({}),
showDefaultButtons = false,
- resourceName,
...others
} = props;
const { schema } = useDesignable();
const initialValues = useValues();
const form = useMemo(() => {
- console.log('Form.useMemo', initialValues);
- return createForm({
- initialValues,
+ return createForm({
+ initialValues,
readPretty: schema['x-read-pretty'],
});
}, []);
const path = useSchemaPath();
const scope = useContext(SchemaExpressionScopeContext);
+ const { collection } = useCollectionContext();
const content = (
{schema['x-decorator'] === 'Form' ? (
@@ -115,7 +89,7 @@ export const Form: any = observer((props: any) => {
onClick={async () => {
const values = await form.submit();
console.log({ values });
- await Resource.make(resourceName).save(values);
+ await Resource.make(props.resource).save(values);
message.success('保存成功');
await form.reset();
}}
@@ -134,49 +108,47 @@ export const Form: any = observer((props: any) => {
)}
);
- return resourceName ? (
- // @ts-ignore
-
- {content}
-
- ) : (
-
{content}
+ return (
+
+ {content}
+
);
});
-export const FormFieldUIDContext = createContext(null);
+export const RandomNameContext = createContext(null);
Form.Field = observer((props: any) => {
const { fieldName } = props;
const { schema } = useDesignable();
const path = getSchemaPath(schema);
- console.log('getSchemaPath', path);
- const { addDisplayField } = useDisplayFieldsContext();
- const { resource = {} } = useResourceContext();
+ const { getField } = useCollectionContext();
+ const displayed = useDisplayedMapContext();
useEffect(() => {
if (fieldName) {
- addDisplayField && addDisplayField(fieldName, schema);
+ displayed.set(fieldName, schema);
}
}, [fieldName, schema]);
if (!fieldName) {
return null;
}
- const field = resource?.fields?.find((item) => item.name === fieldName);
- if (!field) {
+ const collectionField = getField(fieldName);
+ if (!collectionField) {
return null;
}
- const name = useContext(FormFieldUIDContext);
- const title = schema['title'] || field.uiSchema['title'];
+ const randomName = useContext(RandomNameContext);
+ const title = schema['title'] || collectionField?.uiSchema?.title;
return (
{
});
Form.Field.Item = observer((props) => {
- const name = uid();
return (
-
+
{props.children}
-
+
);
});
diff --git a/packages/client/src/schemas/index.tsx b/packages/client/src/schemas/index.tsx
index 962679290..78f0fed40 100644
--- a/packages/client/src/schemas/index.tsx
+++ b/packages/client/src/schemas/index.tsx
@@ -10,51 +10,6 @@ import { useCookieState, useRequest } from 'ahooks';
export * from '../components/schema-renderer';
-export function mapReadPretty(component: any, readPrettyProps?: any) {
- return function (target) {
- return observer(
- (props) => {
- const field = useField();
- // if (!isVoidField(field) && field?.pattern === 'readPretty') {
- if (field?.pattern === 'readPretty') {
- return React.createElement(component, {
- ...readPrettyProps,
- ...props,
- });
- }
- return React.createElement(target, props);
- },
- {
- forwardRef: true,
- },
- );
- };
-}
-
-export const VisibleContext = createContext(null);
-
-export function useVisible(name, defaultValue = false) {
- const [visible, setVisible] = useState(defaultValue);
- return { visible, setVisible };
- // const [visible, setVisible] = useCookieState(`${name}-visible`, {
- // defaultValue: defaultValue ? 'true' : null,
- // });
- // return {
- // visible: visible === 'true' ? true : false,
- // setVisible: (value) => {
- // setVisible(value ? 'true' : null);
- // },
- // }
-}
-
-export const DesignableBarContext = createContext(null);
-
-const [PageTitleContextProvider, usePageTitleContext] = constate(({ defaultPageTitle }) => {
- return useState(defaultPageTitle);
-});
-
-export { PageTitleContextProvider, usePageTitleContext };
-
export function useDefaultAction() {
return {
async run() {},
@@ -93,6 +48,9 @@ export async function deleteCollection(name) {
}
export async function createSchema(schema: ISchema) {
+ if (!schema) {
+ return;
+ }
if (!schema['key']) {
return;
}
@@ -125,36 +83,3 @@ export async function removeSchema(schema: ISchema) {
},
});
}
-
-const [CollectionContextProvider, useCollectionContext] = constate(() => {
- return useRequest('collections:findAll', {
- formatResult: (result) => result?.data,
- });
-});
-
-export { CollectionContextProvider, useCollectionContext };
-
-const [SwithDesignableContextProvider, useSwithDesignableContext] = constate(() => {
- const [active, setActive] = useCookieState('useCookieDesignable');
-
- return {
- designable: active === 'true',
- setDesignable(value) {
- setActive(value ? 'true' : 'false');
- }
- }
-});
-
-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 };
diff --git a/packages/client/src/schemas/input/index.tsx b/packages/client/src/schemas/input/index.tsx
index 3eb9ced77..96ccfda89 100644
--- a/packages/client/src/schemas/input/index.tsx
+++ b/packages/client/src/schemas/input/index.tsx
@@ -46,7 +46,7 @@ Input.URL = connect(AntdInput, mapReadPretty(Display.URL))
Input.DesignableBar = observer((props) => {
const field = useField();
const fieldSchema = useFieldSchema();
- const { root, currentSchema, schema, refresh, deepRemove } = useDesignable();
+ const { root, currentSchema, schema, refresh, deepRemove, remove } = useDesignable();
const [visible, setVisible] = useState(false);
const { dragRef } = useContext(DraggableBlockContext);
return (
@@ -71,6 +71,10 @@ Input.DesignableBar = observer((props) => {
{
+ const title = uid();
+ schema['title'] = title;
+ field.title = title;
+ refresh();
console.log({ root, currentSchema, schema, fieldSchema }, getSchemaPath(fieldSchema));
}}
>
@@ -80,12 +84,13 @@ Input.DesignableBar = observer((props) => {
{
- const removed = deepRemove();
- // console.log({ removed })
- const last = removed.pop();
- if (isGridRowOrCol(last)) {
- await removeSchema(last);
- }
+ remove();
+ // const removed = deepRemove();
+ // // console.log({ removed })
+ // const last = removed.pop();
+ // if (isGridRowOrCol(last)) {
+ // await removeSchema(last);
+ // }
}}
>
删除当前区块
diff --git a/packages/client/src/schemas/menu/index.tsx b/packages/client/src/schemas/menu/index.tsx
index b8171c43d..011bc3245 100644
--- a/packages/client/src/schemas/menu/index.tsx
+++ b/packages/client/src/schemas/menu/index.tsx
@@ -50,24 +50,16 @@ import {
DragOutlined,
} from '@ant-design/icons';
import { IconPicker } from '../../components/icon-picker';
-import {
- createSchema,
- removeSchema,
- updateSchema,
- useDefaultAction,
- useVisible,
- VisibleContext,
-} from '..';
+import { createSchema, removeSchema, updateSchema, useDefaultAction } from '..';
import { useMount } from 'ahooks';
import './style.less';
-import { Link } from 'react-router-dom';
import { findPropertyByPath, getSchemaPath, useSchemaPath } from '../../';
-import { request } from '../';
import { generateDefaultSchema } from './defaultSchemas';
import _, { cloneDeep, get, isNull } from 'lodash';
import { FormDialog, FormItem, FormLayout, Input } from '@formily/antd';
import deepmerge from 'deepmerge';
import { onFieldChange } from '@formily/core';
+import { VisibleContext } from '../../context';
export const MenuModeContext = createContext(null);
@@ -101,11 +93,19 @@ const SideMenu = (props: any) => {
};
export const Menu: any = observer((props: any) => {
- const { mode, onSelect, sideMenuRef, defaultSelectedKeys = [], ...others } = props;
+ const {
+ mode,
+ onSelect,
+ sideMenuRef,
+ defaultSelectedKeys = [],
+ ...others
+ } = props;
const { designable, schema } = useDesignable();
const fieldSchema = useFieldSchema();
console.log('Menu.schema', schema, fieldSchema);
- const [selectedKey, setSelectedKey] = useState(defaultSelectedKeys[0]||null);
+ const [selectedKey, setSelectedKey] = useState(
+ defaultSelectedKeys[0] || null,
+ );
const ref = useRef();
const path = useSchemaPath();
const child = schema.properties && schema.properties[selectedKey];
@@ -170,7 +170,7 @@ export const Menu: any = observer((props: any) => {
onSelect &&
onSelect({ ...info, keyPath, schema: selectedSchema });
}}
- defaultSelectedKeys={defaultSelectedKeys||[]}
+ defaultSelectedKeys={defaultSelectedKeys || []}
selectedKey={selectedKey}
sideMenuRef={sideMenuRef}
/>
@@ -237,7 +237,7 @@ Menu.Action = observer((props: any) => {
const { icon, useAction = useDefaultAction, ...others } = props;
const { schema, DesignableBar } = useDesignable();
const field = useField();
- const { visible, setVisible } = useVisible(field.address.entire);
+ const [visible, setVisible] = useState(false);
const { run } = useAction();
return (
diff --git a/packages/client/src/schemas/page/index.tsx b/packages/client/src/schemas/page/index.tsx
index caa109575..b482a0198 100644
--- a/packages/client/src/schemas/page/index.tsx
+++ b/packages/client/src/schemas/page/index.tsx
@@ -1,7 +1,7 @@
import React from 'react';
import { PageHeader as AntdPageHeader } from 'antd';
import { observer } from '@formily/react';
-import { usePageTitleContext } from '..';
+import { usePageTitleContext } from '../../constate/PageTitle';
export const Page = observer((props) => {
const { children, ...others } = props;
diff --git a/packages/client/src/schemas/table/ColumnDesignableBar.tsx b/packages/client/src/schemas/table/ColumnDesignableBar.tsx
deleted file mode 100644
index 5502460fb..000000000
--- a/packages/client/src/schemas/table/ColumnDesignableBar.tsx
+++ /dev/null
@@ -1,43 +0,0 @@
-import React, { useState } from 'react';
-import classNames from 'classnames';
-import { useField, observer, RecursionField, Schema } from '@formily/react';
-import { Dropdown, Menu } from 'antd';
-import {
- MenuOutlined,
- ArrowUpOutlined,
- ArrowDownOutlined,
- DeleteOutlined,
-} from '@ant-design/icons';
-
-export const ColumnDesignableBar = (props) => {
- const [active, setActive] = useState(false);
- return (
- <>
- {
- setActive(false);
- }}
- icon={}
- >
- 在上方插入区块
-
- {
- setActive(false);
- }}
- icon={}
- >
- 在下方插入区块
-
-
- {
- setActive(false);
- }}
- icon={}
- >
- 删除区块
-
- >
- );
-};
diff --git a/packages/client/src/schemas/table/DesignableBar.tsx b/packages/client/src/schemas/table/DesignableBar.tsx
deleted file mode 100644
index 9cf72c589..000000000
--- a/packages/client/src/schemas/table/DesignableBar.tsx
+++ /dev/null
@@ -1,43 +0,0 @@
-import React, { useState } from 'react';
-import classNames from 'classnames';
-import { useField, observer, RecursionField, Schema } from '@formily/react';
-import { Dropdown, Menu } from 'antd';
-import {
- MenuOutlined,
- ArrowUpOutlined,
- ArrowDownOutlined,
- DeleteOutlined,
-} from '@ant-design/icons';
-
-export const DesignableBar = (props) => {
- const [active, setActive] = useState(false);
- return (
- <>
- {
- setActive(false);
- }}
- icon={}
- >
- 在上方插入区块
-
- {
- setActive(false);
- }}
- icon={}
- >
- 在下方插入区块
-
-
- {
- setActive(false);
- }}
- icon={}
- >
- 删除区块
-
- >
- );
-};
diff --git a/packages/client/src/schemas/table/demos/demo1.tsx b/packages/client/src/schemas/table/demos/demo1.tsx
deleted file mode 100644
index 3fc92e41f..000000000
--- a/packages/client/src/schemas/table/demos/demo1.tsx
+++ /dev/null
@@ -1,386 +0,0 @@
-import React from 'react';
-import { SchemaRenderer } from '../..';
-import { Table, useTableCreateAction } from '../';
-import { uid } from '@formily/shared';
-import { createForm } from '@formily/core';
-import { ISchema, observer } from '@formily/react';
-
-function useAction() {
- return {
- async run() {
- alert('自定义');
- },
- };
-}
-
-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() },
- ],
- 'x-component-props': {
- rowKey: 'key',
- 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',
- title: '筛选',
- 'x-component': 'Action',
- 'x-designable-bar': 'Table.Filter.DesignableBar',
- 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-props': {
- operations: [
- { label: '等于', value: 'eq' },
- { label: '不等于', value: 'ne' },
- ],
- },
- properties: {
- field1: {
- type: 'string',
- 'x-component': 'Input',
- },
- },
- },
- 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: {
- type: 'void',
- name: 'action1',
- title: '新增',
- 'x-component': 'Action',
- 'x-designable-bar': 'Table.Action.DesignableBar',
- properties: {
- drawer1: {
- type: 'void',
- 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',
- },
- },
- },
- },
- },
- action3: {
- type: 'void',
- name: 'action1',
- title: '删除',
- 'x-designable-bar': 'Table.Action.SimpleDesignableBar',
- 'x-component': 'Action',
- 'x-component-props': {
- useAction: '{{ Table.useTableDestroyAction }}',
- },
- },
- },
- },
- [`a_${uid()}`]: {
- type: 'void',
- 'x-component': 'Table.ActionBar',
- 'x-component-props': {
- align: 'bottom',
- },
- properties: {
- pagination: {
- type: 'void',
- title: '新增',
- 'x-component': 'Table.Addition',
- 'x-component-props': {},
- },
- },
- },
- // [`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',
- 'x-component': 'Table.Column',
- 'x-component-props': {
- className: 'nb-table-operation',
- },
- properties: {
- [uid()]: {
- type: 'void',
- 'x-component': 'Action.Dropdown',
- 'x-component-props': {
- buttonProps: {
- icon: 'EllipsisOutlined',
- },
- },
- properties: {
- [uid()]: {
- type: 'void',
- title: '操作 1',
- 'x-component': 'Menu.Action',
- 'x-component-props': {
- useAction,
- style: {
- minWidth: 150,
- },
- disabled: true,
- },
- },
- [uid()]: {
- type: 'void',
- title: '操作 2',
- 'x-component': 'Menu.Action',
- 'x-default-action': true,
- 'x-component-props': {
- useAction,
- },
- },
- [uid()]: {
- type: 'void',
- name: 'action1',
- title: '查看',
- 'x-component': 'Menu.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': 'Menu.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': 'Menu.Action',
- 'x-component-props': {
- useAction: '{{ Table.useTableDestroyAction }}',
- },
- },
- },
- },
- },
- },
- [`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',
- },
- },
- },
- },
-};
-
-const form = createForm({
- // designable: true,
-});
-
-export default observer(() => {
- return (
-
-
-
- );
-});
diff --git a/packages/client/src/schemas/table/demos/demo3.tsx b/packages/client/src/schemas/table/demos/demo3.tsx
new file mode 100644
index 000000000..db5eeb0c5
--- /dev/null
+++ b/packages/client/src/schemas/table/demos/demo3.tsx
@@ -0,0 +1,261 @@
+import React from 'react';
+import { range } from 'lodash';
+import { ISchema } from '@formily/react';
+import { SchemaRenderer } from '../..';
+import { uid } from '@formily/shared';
+
+const loadDataSource = (params?: any): Promise => {
+ const { page, pageSize = 50 } = params || {};
+ console.log({ pageSize });
+ return new Promise((resolve) => {
+ setTimeout(() => {
+ resolve({
+ list: range(50 || pageSize).map(() => {
+ return { id: uid(), title: uid() };
+ }),
+ total: 50,
+ });
+ }, 1000);
+ });
+};
+
+const schema: ISchema = {
+ type: 'array',
+ name: 'arr',
+ 'x-component': 'Table',
+ 'x-component-props': {
+ dragSort: true,
+ showIndex: true,
+ refreshRequestOnChange: false,
+ clientSidePagination: true,
+ dataRequest: '{{ loadDataSource }}',
+ pagination: {
+ pageSize: 2,
+ },
+ },
+ // default: range(50).map(() => {
+ // return { id: uid(), title: uid() };
+ // }),
+ properties: {
+ [uid()]: {
+ type: 'void',
+ 'x-component': 'Table.ActionBar',
+ 'x-designable-bar': 'Table.ActionBar.DesignableBar',
+ properties: {
+ [uid()]: {
+ type: 'void',
+ 'x-component': 'Table.Filter',
+ 'x-designable-bar': 'Table.Filter.DesignableBar',
+ 'x-component-props': {
+ fieldNames: [],
+ },
+ },
+ [uid()]: {
+ type: 'void',
+ name: 'action1',
+ title: '新增',
+ 'x-component': 'Action',
+ 'x-designable-bar': 'Table.Action.DesignableBar',
+ properties: {
+ modal: {
+ type: 'void',
+ title: '新增数据',
+ 'x-decorator': 'Form',
+ 'x-component': 'Action.Modal',
+ 'x-component-props': {
+ useOkAction: '{{ Table.useTableCreateAction }}',
+ },
+ properties: {
+ [uid()]: {
+ type: 'void',
+ 'x-component': 'Grid',
+ 'x-component-props': {
+ addNewComponent: 'AddNew.FormItem',
+ },
+ },
+ },
+ },
+ },
+ },
+ [uid()]: {
+ type: 'void',
+ name: 'action1',
+ title: '删除',
+ 'x-component': 'Action',
+ 'x-designable-bar': 'Table.Action.DesignableBar',
+ 'x-component-props': {
+ useAction: '{{ Table.useTableDestroyAction }}',
+ },
+ },
+ },
+ },
+ column2: {
+ type: 'void',
+ title: '操作',
+ 'x-component': 'Table.Column',
+ 'x-component-props': {
+ className: 'nb-table-operation',
+ },
+ properties: {
+ action1: {
+ type: 'void',
+ name: 'dropdown1',
+ 'x-component': 'Action.Dropdown',
+ 'x-designable-bar': 'Action.DesignableBar',
+ 'x-component-props': {
+ buttonProps: {
+ icon: 'EllipsisOutlined',
+ },
+ },
+ properties: {
+ [uid()]: {
+ type: 'void',
+ title: '操作 1',
+ 'x-component': 'Menu.Action',
+ 'x-component-props': {
+ style: {
+ minWidth: 150,
+ },
+ disabled: true,
+ },
+ },
+ [uid()]: {
+ type: 'void',
+ name: 'action1',
+ title: '查看',
+ 'x-component': 'Menu.Action',
+ 'x-designable-bar': 'Table.Action.DesignableBar',
+ properties: {
+ [uid()]: {
+ type: 'void',
+ title: '查看',
+ 'x-component': 'Action.Modal',
+ 'x-component-props': {
+ bodyStyle: {
+ background: '#f0f2f5',
+ paddingTop: 0,
+ },
+ },
+ properties: {
+ [uid()]: {
+ type: 'void',
+ 'x-component': 'Tabs',
+ properties: {
+ [uid()]: {
+ type: 'void',
+ 'x-component': 'Tabs.TabPane',
+ 'x-component-props': {
+ tab: 'Tab1',
+ },
+ properties: {
+ [uid()]: {
+ type: 'void',
+ 'x-component': 'Grid',
+ 'x-component-props': {
+ addNewComponent: 'AddNew.PaneItem',
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ [uid()]: {
+ type: 'void',
+ title: '编辑',
+ 'x-component': 'Menu.Action',
+ 'x-designable-bar': 'Table.Action.DesignableBar',
+ properties: {
+ [uid()]: {
+ type: 'void',
+ title: '编辑数据',
+ 'x-decorator': 'Form',
+ 'x-decorator-props': {
+ useValues: '{{ Table.useTableRowRecord }}',
+ },
+ 'x-component': 'Action.Modal',
+ 'x-component-props': {
+ useOkAction: '{{ Table.useTableUpdateAction }}',
+ },
+ properties: {
+ [uid()]: {
+ type: 'void',
+ 'x-component': 'Grid',
+ 'x-component-props': {
+ addNewComponent: 'AddNew.FormItem',
+ },
+ properties: {
+ [uid()]: {
+ type: 'void',
+ 'x-component': 'Grid.Row',
+ properties: {
+ [uid()]: {
+ type: 'void',
+ 'x-component': 'Grid.Col',
+ properties: {
+ title: {
+ title: '标题',
+ type: 'string',
+ 'x-component': 'Input',
+ 'x-decorator': 'FormItem',
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ [uid()]: {
+ type: 'void',
+ title: '删除',
+ 'x-component': 'Menu.Action',
+ 'x-component-props': {
+ useAction: '{{ Table.useTableDestroyAction }}',
+ },
+ },
+ },
+ },
+ },
+ },
+ column0: {
+ type: 'void',
+ title: 'ID',
+ 'x-component': 'Table.Column',
+ 'x-designable-bar': 'Table.Column.DesignableBar',
+ properties: {
+ id: {
+ type: 'string',
+ 'x-component': 'Input',
+ 'x-read-pretty': true,
+ },
+ },
+ },
+ column1: {
+ type: 'void',
+ title: 'Title',
+ 'x-component': 'Table.Column',
+ properties: {
+ title: {
+ type: 'string',
+ 'x-component': 'Input',
+ 'x-read-pretty': true,
+ },
+ },
+ },
+ },
+};
+
+export default () => {
+ return (
+
+
+
+ );
+};
diff --git a/packages/client/src/schemas/table/index.md b/packages/client/src/schemas/table/index.md
index 5a6be619b..b7940d4d1 100644
--- a/packages/client/src/schemas/table/index.md
+++ b/packages/client/src/schemas/table/index.md
@@ -60,4 +60,15 @@ group:
## Examples
-
+
+
+## API
+
+表格的几个重要概念
+
+- collection 当前表格的数据表配置信息(主要是字段)
+- resource 当前资源,用于处理 create、update、list、destroy
+- service 当前表格的 resource.list 实例
+- field 当前表格的 ArrayField 对象
+- schema 当前表格的 json schema
+- props 当前表格的参数
diff --git a/packages/client/src/schemas/table/index.tsx b/packages/client/src/schemas/table/index.tsx
index c65edca24..836b666dd 100644
--- a/packages/client/src/schemas/table/index.tsx
+++ b/packages/client/src/schemas/table/index.tsx
@@ -1,227 +1,295 @@
-import React, {
- createContext,
- useContext,
- useEffect,
- useRef,
- useState,
-} from 'react';
import {
- useFieldSchema,
- Schema,
observer,
RecursionField,
+ Schema,
useField,
useForm,
- FormProvider,
- createSchemaField,
- SchemaOptionsContext,
} from '@formily/react';
-import {
- Button,
- Pagination,
- PaginationProps,
- Space,
- Spin,
- Table as AntdTable,
- Dropdown,
- Menu,
- Select,
- Switch,
-} from 'antd';
-import { cloneDeep, findIndex, get, set } from 'lodash';
-import constate from 'constate';
+import { Pagination, Table as AntdTable } from 'antd';
+import { findIndex, forIn, range, set } from 'lodash';
+import React, { Fragment, useEffect, useState } from 'react';
+import { useContext } from 'react';
+import { createContext } from 'react';
+import { useDesignable, updateSchema, removeSchema, createSchema } from '..';
+import { uid } from '@formily/shared';
import useRequest from '@ahooksjs/use-request';
-import { uid, clone } from '@formily/shared';
-import {
- EllipsisOutlined,
- MenuOutlined,
- DragOutlined,
- PlusOutlined,
-} from '@ant-design/icons';
-import {
- SortableHandle,
- SortableContainer,
- SortableElement,
-} from 'react-sortable-hoc';
+import { BaseResult } from '@ahooksjs/use-request/lib/types';
import cls from 'classnames';
-import {
- createSchema,
- getSchemaPath,
- removeSchema,
- ResourceContextProvider,
- updateSchema,
- useCollectionContext,
- useDesignable,
- useResourceContext,
- useSchemaPath,
- VisibleContext,
-} from '../';
+import { MenuOutlined, DragOutlined } from '@ant-design/icons';
+import { DndContext } from '@dnd-kit/core';
+import { SortableContext, useSortable } from '@dnd-kit/sortable';
+import { CSS } from '@dnd-kit/utilities';
+import { Select, Dropdown, Menu, Switch, Button, Space } from 'antd';
+import { PlusOutlined } from '@ant-design/icons';
import './style.less';
+import { getSchemaPath } from '../../components/schema-renderer';
+import { options } from '../database-field/interfaces';
import { DraggableBlockContext } from '../../components/drag-and-drop';
import AddNew from '../add-new';
import { isGridRowOrCol } from '../grid';
-import { options } from '../database-field/interfaces';
import { Resource } from '../../resource';
-import { DisplayFieldsContextProvider, useDisplayFieldsContext } from '../form';
+import {
+ CollectionProvider,
+ DisplayedMapProvider,
+ useCollectionContext,
+ useDisplayedMapContext,
+} from '../../constate';
-interface TableRowProps {
+const SyntheticListenerMapContext = createContext(null);
+
+function DragableBodyRow(props: any) {
+ const {
+ className,
+ style: prevStyle,
+ ['data-row-key']: dataRowKey,
+ ...others
+ } = props;
+ const {
+ attributes,
+ listeners,
+ setNodeRef,
+ overIndex,
+ transform,
+ transition,
+ } = useSortable({ id: dataRowKey });
+
+ const style = {
+ ...prevStyle,
+ transform: CSS.Transform.toString(transform),
+ transition,
+ };
+
+ return (
+
+
+ {props.children}
+
+
+ );
+}
+
+export interface ITableContext {
+ props: any;
+ field: Formily.Core.Models.ArrayField;
+ schema: Schema;
+ service: BaseResult;
+ selectedRowKeys?: any;
+ setSelectedRowKeys?: any;
+ pagination?: any;
+ setPagination?: any;
+ refresh?: any;
+ resource?: Resource;
+}
+
+export interface ITableRowContext {
index: number;
- data: any;
+ record: any;
}
-const SortableRow = SortableElement((props: any) =>
);
-const SortableBody = SortableContainer((props: any) => );
+const TableConetxt = createContext(null);
+const TableRowContext = createContext(null);
+const CollectionFieldContext = createContext(null);
-const TableRowContext = createContext(null);
+const useTable = () => {
+ return useContext(TableConetxt);
+};
-function usePaginationProps() {
- const schema = useFieldSchema();
+const useTableRow = () => {
+ return useContext(TableRowContext);
+};
- function findPagination(schema: Schema): Schema[] {
- return schema.reduceProperties((columns, current) => {
- if (current['x-component'] === 'Table.Pagination') {
- return [...columns, current];
+function useTableFilterAction() {
+ const {
+ field,
+ service,
+ refresh,
+ props: { refreshRequestOnChange },
+ } = useTable();
+ return {
+ async run() {
+ if (refreshRequestOnChange) {
+ return service.refresh();
}
- return [...columns, ...findPagination(current)];
- }, []);
- }
-
- const pagination = findPagination(schema).shift();
-
- if (pagination) {
- // console.log({ pagination });
- const props = pagination['x-component-props'] || {};
- return { defaultCurrent: 1, defaultPageSize: 10, ...props };
- }
-
- return false;
+ },
+ };
}
-function useDefaultAction() {
- const schema = useFieldSchema();
-
- function findDefaultAction(schema: Schema): Schema[] {
- return schema.reduceProperties((columns, current) => {
- if (current['x-default-action']) {
- return [...columns, current];
+function useTableCreateAction() {
+ const {
+ field,
+ service,
+ resource,
+ refresh,
+ props: { refreshRequestOnChange },
+ } = useTable();
+ const form = useForm();
+ return {
+ async run() {
+ if (refreshRequestOnChange) {
+ await resource.create(form.values);
+ await form.reset();
+ return service.refresh();
}
- return [...columns, ...findDefaultAction(current)];
- }, []);
- }
-
- return findDefaultAction(schema).shift();
+ field.unshift(form.values);
+ },
+ };
}
-function useTableActionBars() {
- const schema = useFieldSchema();
+const useTableUpdateAction = () => {
+ const {
+ resource,
+ field,
+ service,
+ refresh,
+ props: { refreshRequestOnChange, rowKey },
+ } = useTable();
+ const ctx = useContext(TableRowContext);
+ const form = useForm();
- function findActionBars(schema: Schema) {
- const actionBars = {
- top: [],
- bottom: [],
- };
- return schema.reduceProperties((bars, current) => {
- if (current['x-component'] === 'Table.ActionBar') {
- const align = current['x-component-props']?.['align'] || 'top';
- bars[align].push(current);
-
- return bars;
+ return {
+ async run() {
+ if (refreshRequestOnChange) {
+ await resource.save(form.values, {
+ resourceKey: ctx.record[rowKey],
+ });
+ return service.refresh();
}
+ field.value[ctx.index] = form.values;
+ // refresh();
+ },
+ };
+};
- const nested = findActionBars(current);
-
- Object.keys(nested).forEach((align) => {
- bars[align].push(...nested[align]);
- });
-
- return bars;
- }, actionBars);
- }
-
- return findActionBars(schema);
-}
-
-const ResourceFieldContext = createContext(null);
-
-function useTableColumns(props?: any) {
- const { schema, designable } = useDesignable();
- // const schema = useFieldSchema();
- const { dataSource, rowKey = 'id' } = props || {};
- const { resource = {} } = useResourceContext();
-
- function findColumns(schema: Schema): Schema[] {
- return schema.reduceProperties((columns, current) => {
- if (current['x-component'] === 'Table.Column') {
- return [...columns, current];
+const useTableDestroyAction = () => {
+ const {
+ resource,
+ field,
+ service,
+ selectedRowKeys,
+ setSelectedRowKeys,
+ refresh,
+ props: { refreshRequestOnChange, rowKey },
+ } = useTable();
+ const ctx = useContext(TableRowContext);
+ return {
+ async run() {
+ if (refreshRequestOnChange) {
+ const rowKeys = selectedRowKeys || [];
+ if (ctx) {
+ rowKeys.push(ctx.record[rowKey]);
+ }
+ await resource.destroy({
+ [`${rowKey}.in`]: rowKeys,
+ });
+ setSelectedRowKeys([]);
+ return service.refresh();
}
- return [...columns, ...findColumns(current)];
- }, []);
+ if (ctx) {
+ console.log('ctx.index', ctx.index);
+ field.remove(ctx.index);
+ refresh();
+ }
+ const rowKeys = [...selectedRowKeys];
+ while (rowKeys.length) {
+ const key = rowKeys.shift();
+ const index = findIndex(field.value, (item) => item[rowKey] === key);
+ field.remove(index);
+ }
+ setSelectedRowKeys([]);
+ refresh();
+ return;
+ },
+ };
+};
+
+const useTableRowRecord = () => {
+ const ctx = useContext(TableRowContext);
+ return ctx.record;
+};
+
+const useTableIndex = () => {
+ const { pagination, props } = useTable();
+ const ctx = useContext(TableRowContext);
+ if (pagination && !props.clientSidePagination) {
+ const { pageSize, page } = pagination;
+ return ctx.index + (page - 1) * pageSize;
}
+ return ctx.index;
+};
- const columns = findColumns(schema).map((item) => {
- const columnProps = item['x-component-props'] || {};
- console.log(item);
- const resourceField = columnProps.fieldName
- ? resource?.fields?.find((item) => item.name === columnProps.fieldName)
- : null;
+const useTableActionBars = () => {
+ const {
+ field,
+ schema,
+ props: { rowKey },
+ } = useTable();
- return {
- title: (
-
-
-
- ),
- dataIndex: item.name,
- ...columnProps,
- render(value, record, recordIndex) {
- const index = findIndex(
- dataSource,
- (item) => item[rowKey] === record[rowKey],
- );
- console.log({ dataSource, record, index });
- return (
-
-
-
-
-
- );
+ const bars = schema.reduceProperties((bars, current) => {
+ if (current['x-component'] === 'Table.ActionBar') {
+ return [...bars, current];
+ }
+ return [...bars];
+ }, []);
+
+ return bars;
+};
+
+const useTableColumns = () => {
+ const {
+ field,
+ schema,
+ props: { rowKey },
+ } = useTable();
+
+ const { getField } = useCollectionContext();
+
+ const columns = schema.reduceProperties((columns, current) => {
+ if (current['x-component'] === 'Table.Column') {
+ return [...columns, current];
+ }
+ return [...columns];
+ }, []);
+
+ return columns
+ .map((column: Schema) => {
+ const columnProps = column['x-component-props'] || {};
+ const collectionField = getField(columnProps.fieldName);
+ return {
+ title: (
+
+
+
+ ),
+ dataIndex: column.name,
+ ...columnProps,
+ render: (_: any, record: any) => {
+ const index = findIndex(
+ field.value,
+ (item) => item[rowKey] === record[rowKey],
+ );
+ return (
+
+
+
+
+
+ );
+ },
+ };
+ })
+ .concat([
+ {
+ title: ,
+ dataIndex: 'addnew',
},
- };
- });
-
- // columns.unshift({
- // title: '',
- // className: 'nb-table-operation',
- // dataIndex: 'operation',
- // render(value, record, recordIndex) {
- // const index = dataSource.indexOf(record);
- // return (
- //
- //
- //
- // );
- // },
- // });
-
- designable &&
- columns.push({
- title: ,
- dataIndex: 'addnew',
- });
-
- return columns;
-}
+ ]);
+};
function SwitchField(props) {
const { field, onChange } = props;
@@ -252,9 +320,8 @@ function SwitchField(props) {
function AddColumn() {
const [visible, setVisible] = useState(false);
const { appendChild, remove } = useDesignable();
- const { resource = {}, refresh } = useResourceContext();
- const { hasDisplayField, removeDisplayField, getDisplayField } =
- useDisplayFieldsContext();
+ const { fields } = useCollectionContext();
+ const displayed = useDisplayedMapContext();
return (
- {resource?.fields?.map((field) => (
+ {fields.map((field) => (
{
if (checked) {
@@ -281,11 +348,11 @@ function AddColumn() {
});
await createSchema(data);
} else {
- const s: any = getDisplayField(field.name);
+ const s: any = displayed.get(field.name);
const p = getSchemaPath(s);
const removed = remove(p);
await removeSchema(removed);
- removeDisplayField(field.name);
+ displayed.remove(field.name);
}
}}
/>
@@ -319,505 +386,225 @@ function AddColumn() {
);
}
-export function useTableRow() {
- const ctx = useContext(TableRowContext);
- console.log('useTableRow', ctx.data);
- return ctx.data;
-}
-
-export function useTableIndex() {
+const useDataSource = () => {
const {
- params: { page, pageSize },
- } = useTableContext();
- const ctx = useContext(TableRowContext);
- const field = useField();
- if (!field.componentProps.isRemoteDataSource) {
- return ctx.index;
- }
- return pageSize ? ctx.index + (page - 1) * pageSize : ctx.index;
-}
-
-export function useTableDestroyAction() {
- const ctx = useContext(TableRowContext);
- const { resource, field, selectedRowKeys, setSelectedRowKeys, refresh } =
- useTableContext();
- const rowKey = field.componentProps.rowKey || 'id';
-
- return {
- async run() {
- if (ctx && typeof ctx.index !== 'undefined') {
- // field.remove(ctx.index);
- await resource.destroy({
- [rowKey]: ctx.data[rowKey],
- });
- await refresh();
- return;
- }
- if (!selectedRowKeys.length) {
- return;
- }
- await resource.destroy({
- [`${rowKey}.in`]: selectedRowKeys,
- });
- // 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] = useContext(VisibleContext);
- const form = useForm();
- return {
- async run() {
- setVisible && setVisible(false);
- refresh();
- },
- };
-}
-
-export function useTableCreateAction() {
- const { resource, field, run: exec, params, refresh } = useTableContext();
- const [, setVisible] = useContext(VisibleContext);
- const form = useForm();
- return {
- async run() {
- setVisible && setVisible(false);
- await resource.save(form.values);
- // await refresh();
- // field.push({
- // key: uid(),
- // ...clone(form.values),
- // });
- form.reset();
- exec({ ...params, page: 1 });
- },
- };
-}
-
-export function useTableUpdateAction() {
- const { resource, field, refresh, params } = useTableContext();
- const [, setVisible] = useContext(VisibleContext);
- const ctx = useContext(TableRowContext);
- const form = useForm();
- return {
- async run() {
- setVisible && setVisible(false);
- await resource.save(form.values, {
- resourceKey: form.values[field.componentProps.rowKey || 'id'],
- });
- refresh();
- },
- };
-}
-
-const [TableContextProvider, useTableContext] = constate(() => {
- const field = useField();
- const schema = useFieldSchema();
- const defaultSelectedRowKeys = useContext(SelectedRowKeysContext);
- const [selectedRowKeys, setSelectedRowKeys] = useState(
- defaultSelectedRowKeys || [],
- );
- const resource = Resource.make(field.componentProps.resourceName);
- console.log({ defaultSelectedRowKeys });
- const pagination = usePaginationProps();
- const response = useRequest<{
- list: any[];
- total: number;
- }>((params = {}) => {
- return new Promise((resolve) => {
- resource.list({}).then((res) => {
- field.setValue(res?.data || []);
- resolve({
- list: res?.data || [],
- total: res?.meta?.count || res?.data?.length,
- });
- console.log(
- 'field.componentProps.resourceName',
- field.componentProps.resourceName,
- res,
- );
- });
-
- return;
-
- 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 {
- resource,
- ...response,
- params,
+ pagination,
field,
- schema,
+ props: { clientSidePagination, dataRequest },
+ } = useTable();
+ let dataSource = field.value;
+ if (pagination && (clientSidePagination || !dataRequest)) {
+ const { page = 1, pageSize } = pagination;
+ const startIndex = (page - 1) * pageSize;
+ const endIndex = startIndex + pageSize - 1;
+ dataSource = field.value?.slice(startIndex, endIndex + 1);
+ }
+ return dataSource;
+};
+
+const TableMain = () => {
+ const {
selectedRowKeys,
setSelectedRowKeys,
- };
-});
-
-export { TableContextProvider, useTableContext };
-
-export const SelectedRowKeysContext = createContext([]);
-
-const TableContainer = observer((props) => {
- const { schema } = useDesignable();
- const field = useField();
- // const schema = useFieldSchema();
+ service,
+ field,
+ props: { rowKey, dragSort, showIndex },
+ } = useTable();
+ const columns = useTableColumns();
+ const dataSource = useDataSource();
const actionBars = useTableActionBars();
- const { loading, data, refresh, selectedRowKeys, setSelectedRowKeys } =
- useTableContext();
- const rowKey = field.componentProps.rowKey || 'id';
- const defaultAction = useDefaultAction();
- const dataSource = Array.isArray(field.value) ? field.value.slice() : [];
- const columns = useTableColumns({ dataSource });
- const ref = useRef();
- const addTdStyles = (node: HTMLElement) => {
- const helper = document.body.querySelector(`.nb-table-sort-helper`);
- if (helper) {
- const tds = node.querySelectorAll('td');
- requestAnimationFrame(() => {
- helper.querySelectorAll('td').forEach((td, index) => {
- if (tds[index]) {
- td.style.width = getComputedStyle(tds[index]).width;
- }
- });
- });
- }
- };
- const dragSort = schema?.['x-component-props']?.['dragSort'];
- const showIndex = schema?.['x-component-props']?.['showIndex'];
return (
-
- {actionBars.top.map((actionBarSchema) => {
- return (
-
- );
- })}
-
{
- const index = findIndex(
- dataSource,
- (item) => item[rowKey] === record[rowKey],
- );
- return (
-
-
- {dragSort &&
}
- {showIndex &&
}
- {originNode}
- {/*
*/}
-
-
- );
- },
- onChange: (keys) => {
- console.log(keys);
- setSelectedRowKeys(keys);
- },
+
+ {
+ console.log({ event });
}}
- dataSource={data?.list}
- columns={columns}
- components={{
- body: {
- wrapper: (props: any) => (
- {
- return ref.current?.querySelector('tbody');
- }}
- onSortStart={({ node }) => {
- addTdStyles(node);
- }}
- onSortEnd={({ oldIndex, newIndex }) => {
- field.move(oldIndex, newIndex);
- refresh();
- }}
- {...props}
- />
- ),
- row: (props: any) => {
- const index = findIndex(
- field.value,
- (item) => item[rowKey] === props['data-row-key'],
- );
- return ;
- },
- },
- }}
- onRow={(data) => {
- const index = dataSource.indexOf(data);
- return {
- onClick(e) {
- if (!defaultAction) {
- return;
- }
- const el = e.target as HTMLElement;
- if (!el.classList.contains('ant-table-cell')) {
- return;
- }
- const btn = el.parentElement.querySelector(
- `.name-${defaultAction.name}`,
- );
- btn && btn.click();
- },
- };
- }}
- />
- {actionBars.bottom.map((actionBarSchema) => {
- return (
-
- );
- })}
-
- );
-});
-
-export const Table: any = observer((props: any) => {
- const { resourceName } = props;
- return resourceName ? (
- // @ts-ignore
-
-
-
-
-
-
-
- ) : (
-
-
-
-
-
- );
-});
-
-Table.useTableRow = useTableRow;
-Table.useTableIndex = useTableIndex;
-Table.useTableDestroyAction = useTableDestroyAction;
-Table.useTableFilterAction = useTableFilterAction;
-Table.useTableCreateAction = useTableCreateAction;
-Table.useTableUpdateAction = useTableUpdateAction;
-
-function Blank() {
- return null;
-}
-
-function useDesignableBar() {
- const schema = useFieldSchema();
- const options = useContext(SchemaOptionsContext);
- const DesignableBar = get(options.components, schema['x-designable-bar']);
-
- return {
- DesignableBar: DesignableBar || Blank,
- };
-}
-
-Table.Cell = observer((props: any) => {
- const ctx = useContext(TableRowContext);
- const schema = props.schema;
- const resourceField = useContext(ResourceFieldContext);
- return (
-
- );
- // const { fieldName } = props;
- // const { schema } = useDesignable();
- // const path = getSchemaPath(schema);
- // const { addDisplayField } = useDisplayFieldsContext();
- // const { resource = {} } = useResourceContext();
- // useEffect(() => {
- // if (fieldName) {
- // addDisplayField && addDisplayField(fieldName);
- // }
- // }, [fieldName]);
- // if (!fieldName) {
- // return null;
- // }
- // const field = resource?.fields?.find((item) => item.name === fieldName);
- // if (!field) {
- // return null;
- // }
- // const name = useContext(FormFieldUIDContext);
- // const title = schema['title'] || field.uiSchema['title'];
- // return (
- //
- // );
-});
-
-Table.Column = observer((props: any) => {
- const resourceField = useContext(ResourceFieldContext);
- const { schema, DesignableBar } = useDesignable();
- const { addDisplayField } = useDisplayFieldsContext();
- useEffect(() => {
- if (resourceField?.name) {
- addDisplayField(resourceField.name, schema);
- }
- }, [resourceField, schema]);
- return (
-
- {schema.title || resourceField?.uiSchema?.title}
-
-
- );
-});
-
-Table.Column.DesignableBar = () => {
- const field = useField();
- // const fieldSchema = useFieldSchema();
- const { schema, remove, refresh, insertAfter } = useDesignable();
- const [visible, setVisible] = useState(false);
- const { removeDisplayField } = useDisplayFieldsContext();
- return (
-
-
{
- e.stopPropagation();
- }}
- className={cls('designable-bar-actions', { active: visible })}
>
- {
- setVisible(visible);
- }}
- overlay={
-
- }
- >
-
-
-
+ {actionBars.map((actionBar) => (
+
+ ))}
+
+ {}}
+ loading={service?.loading}
+ rowKey={rowKey}
+ dataSource={dataSource}
+ columns={columns}
+ components={{
+ body: {
+ row: DragableBodyRow,
+ },
+ }}
+ rowSelection={{
+ type: 'checkbox',
+ selectedRowKeys,
+ onChange: (rowKeys) => {
+ setSelectedRowKeys(rowKeys);
+ },
+ renderCell: (checked, record, _, originNode) => {
+ const index = findIndex(
+ field.value,
+ (item) => item[rowKey] === record[rowKey],
+ );
+ return (
+
+
+ {dragSort &&
}
+ {showIndex &&
}
+ {originNode}
+
+
+ );
+ },
+ }}
+ />
+
+
+
);
};
+const usePagination = (paginationProps?: any) => {
+ return useState(() => {
+ if (!paginationProps) {
+ return false;
+ }
+ return { page: 1, pageSize: 10, ...paginationProps };
+ });
+};
+
+export const Table: any = observer((props: any) => {
+ const { rowKey = 'id', dataRequest, ...others } = props;
+ const { schema } = useDesignable();
+ const field = useField();
+ const [pagination, setPagination] = usePagination(props.pagination);
+ const [selectedRowKeys, setSelectedRowKeys] = useState([]);
+ const [, refresh] = useState(uid());
+ const resource = Resource.make(props.resource);
+ const service = useRequest(
+ (params?: any) => {
+ if (!resource) {
+ return Promise.resolve({
+ list: field.value,
+ total: field?.value?.length,
+ });
+ }
+ return resource.list(params).then((res) => {
+ return {
+ list: res?.data || [],
+ total: res?.meta?.count || res?.data?.length,
+ };
+ });
+ },
+ {
+ onSuccess(data: any) {
+ field.setValue(data?.list || []);
+ },
+ defaultParams: [{ ...pagination }],
+ },
+ );
+ console.log('refresh', { pagination });
+ return (
+ {
+ const { page = 1, pageSize } = pagination;
+ const total = props.clientSidePagination
+ ? field?.value?.length
+ : service?.data?.total;
+ const maxPage = Math.ceil(total / pageSize);
+ if (page > maxPage) {
+ setPagination((prev) => ({ ...prev, page: maxPage }));
+ } else {
+ refresh(uid());
+ }
+ },
+ selectedRowKeys,
+ setSelectedRowKeys,
+ pagination,
+ setPagination,
+ service,
+ field,
+ schema,
+ props: { ...others, rowKey, dataRequest },
+ }}
+ >
+
+
+
+
+
+
+ );
+});
+
+const useTotal = () => {
+ const {
+ field,
+ service,
+ props: { clientSidePagination },
+ } = useTable();
+ return clientSidePagination ? field?.value?.length : service?.data?.total;
+};
+
+Table.Pagination = observer(() => {
+ const { field, service, pagination, setPagination, props } = useTable();
+ if (!pagination || Object.keys(pagination).length === 0) {
+ return null;
+ }
+ const { clientSidePagination } = props;
+ const total = useTotal();
+ const { page = 1 } = pagination;
+ return (
+
+
{
+ const page = pagination.pageSize !== pageSize ? 1 : current;
+ setPagination((prev) => ({
+ ...prev,
+ page,
+ pageSize,
+ }));
+ if (clientSidePagination) {
+ return;
+ }
+ service.run({
+ ...service.params,
+ page,
+ pageSize,
+ });
+ }}
+ />
+
+ );
+});
+
function AddActionButton() {
const [visible, setVisible] = useState(false);
return (
@@ -857,7 +644,9 @@ function AddActionButton() {
}
>
- }>
+ }>
+ 配置操作
+
);
}
@@ -866,7 +655,7 @@ Table.ActionBar = observer((props: any) => {
const { align = 'top' } = props;
const { schema, designable } = useDesignable();
const designableBar = schema['x-designable-bar'];
- console.log('designableBar', designableBar);
+ console.log('Table.ActionBar', schema);
return (
@@ -877,171 +666,14 @@ Table.ActionBar = observer((props: any) => {
);
});
-Table.Pagination = observer((props) => {
- const { data, params, run } = useTableContext();
- return (
- {
- run({ page, pageSize });
- }}
- />
- );
-});
-
-const SortHandle = SortableHandle((props: any) => {
- return (
-
- );
-}) as any;
-
-Table.SortHandle = observer((props) => {
- return ;
-});
-
-Table.Operation = observer((props) => {
- return ;
-});
-
-Table.Index = observer((props) => {
- const index = useTableIndex();
- return {index + 1};
-});
-
-Table.Addition = observer((props: any) => {
- const { field, refresh } = useTableContext();
- const current = useField();
- return (
-
- );
-});
-
Table.Action = () => null;
-Table.Action.SimpleDesignableBar = () => {
- 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 (
-
- {
- e.stopPropagation();
- }}
- className={cls('designable-bar-actions', { active: visible })}
- >
- {
- setVisible(visible);
- }}
- overlay={
-
- }
- >
-
-
-
-
- );
-};
-
-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 (
-
- {
- e.stopPropagation();
- }}
- className={cls('designable-bar-actions', { active: visible })}
- >
- {
- setVisible(visible);
- }}
- overlay={
-
- }
- >
-
-
-
-
- );
-};
-
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 (
{
);
};
+Table.Cell = observer((props: any) => {
+ const ctx = useContext(TableRowContext);
+ const schema = props.schema;
+ const collectionField = useContext(CollectionFieldContext);
+ return (
+
+ );
+});
+
+Table.Column = observer((props: any) => {
+ const collectionField = useContext(CollectionFieldContext);
+ const { schema, DesignableBar } = useDesignable();
+ const displayed = useDisplayedMapContext();
+ useEffect(() => {
+ if (collectionField?.name) {
+ displayed.set(collectionField.name, schema);
+ }
+ }, [collectionField, schema]);
+ return (
+
+ {schema.title || collectionField?.uiSchema?.title}
+
+
+ );
+});
+
+Table.Column.DesignableBar = () => {
+ const field = useField();
+ // const fieldSchema = useFieldSchema();
+ const { schema, remove, refresh, insertAfter } = useDesignable();
+ const [visible, setVisible] = useState(false);
+ const displayed = useDisplayedMapContext();
+ return (
+
+ {
+ e.stopPropagation();
+ }}
+ className={cls('designable-bar-actions', { active: visible })}
+ >
+ {
+ setVisible(visible);
+ }}
+ overlay={
+
+ }
+ >
+
+
+
+
+ );
+};
+
+Table.Index = observer(() => {
+ const index = useTableIndex();
+ return {index + 1};
+});
+
+Table.SortHandle = observer((props: any) => {
+ const listeners = useContext(SyntheticListenerMapContext);
+ const { className, ...others } = props;
+
+ return (
+
+ );
+});
+
Table.DesignableBar = observer((props) => {
const field = useField();
const { designable, schema, refresh, deepRemove } = useDesignable();
@@ -1202,3 +956,10 @@ Table.DesignableBar = observer((props) => {
);
});
+
+Table.useTableFilterAction = useTableFilterAction;
+Table.useTableCreateAction = useTableCreateAction;
+Table.useTableUpdateAction = useTableUpdateAction;
+Table.useTableDestroyAction = useTableDestroyAction;
+Table.useTableIndex = useTableIndex;
+Table.useTableRowRecord = useTableRowRecord;
diff --git a/packages/client/src/schemas/table/style.less b/packages/client/src/schemas/table/style.less
index 7aaa31980..48987094c 100644
--- a/packages/client/src/schemas/table/style.less
+++ b/packages/client/src/schemas/table/style.less
@@ -71,8 +71,8 @@
th.nb-table-operation,
td.nb-table-operation {
- width: 24px;
- text-align: center;
+ width: 50px;
+ text-align: center !important;
padding: 0 !important;
&::before {
display: none;
diff --git a/yarn.lock b/yarn.lock
index 1c4ff0118..b099f901b 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1755,6 +1755,37 @@
resolved "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-3.4.0.tgz#c3c5ae543c897caa9c2a68630bed355be5f9990f"
integrity sha512-JZButFdZ1+/xAfpguQHoabIXkcqRRKpMrWKBkpEZZyxfY9C1DpADFB8PEqGSTeFr135SaTRfKqGKx5xSCLI7ZQ==
+"@dnd-kit/accessibility@^3.0.0":
+ version "3.0.0"
+ resolved "https://registry.npmjs.org/@dnd-kit/accessibility/-/accessibility-3.0.0.tgz#b56e3750414fd907b7d6972b3116aa8f96d07fde"
+ integrity sha512-QwaQ1IJHQHMMuAGOOYHQSx7h7vMZPfO97aDts8t5N/MY7n2QTDSnW+kF7uRQ1tVBkr6vJ+BqHWG5dlgGvwVjow==
+ dependencies:
+ tslib "^2.0.0"
+
+"@dnd-kit/core@^3.1.1":
+ version "3.1.1"
+ resolved "https://registry.npmjs.org/@dnd-kit/core/-/core-3.1.1.tgz#c5ad6665931f5a51e74226220e58ac7514f3faf0"
+ integrity sha512-18YY5+1lTqJbGSg6JBSa/fjAOTUYAysFrQ5Ti8oppEPHFacQbC+owM51y2z2KN0LkDHBfGZKw2sFT7++ttwfpA==
+ dependencies:
+ "@dnd-kit/accessibility" "^3.0.0"
+ "@dnd-kit/utilities" "^2.0.0"
+ tslib "^2.0.0"
+
+"@dnd-kit/sortable@^4.0.0":
+ version "4.0.0"
+ resolved "https://registry.npmjs.org/@dnd-kit/sortable/-/sortable-4.0.0.tgz#81dd2b014a16527cf89602dc40060d9ee4dad352"
+ integrity sha512-teYVFy6mQG/u6F6CaGxAkzPfiNJvguFzWfJ/zonYQRxfANHX6QJ6GziMG9KON/Ae9Q2ODJP8vib+guWJrDXeGg==
+ dependencies:
+ "@dnd-kit/utilities" "^2.0.0"
+ tslib "^2.0.0"
+
+"@dnd-kit/utilities@^2.0.0":
+ version "2.0.0"
+ resolved "https://registry.npmjs.org/@dnd-kit/utilities/-/utilities-2.0.0.tgz#a8462dff65c6f606ecbe95273c7e263b14a1ab97"
+ integrity sha512-bjs49yMNzMM+BYRsBUhTqhTk6HEvhuY3leFt6Em6NaYGgygaMbtGbbXof/UXBv7rqyyi0OkmBBnrCCcxqS2t/g==
+ dependencies:
+ tslib "^2.0.0"
+
"@eslint/eslintrc@^0.4.2":
version "0.4.2"
resolved "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.2.tgz#f63d0ef06f5c0c57d76c4ab5f63d3835c51b0179"