From 27b61bd5719dec2c0544c504840255d271b226fc Mon Sep 17 00:00:00 2001 From: chenos Date: Fri, 30 Jul 2021 00:03:10 +0800 Subject: [PATCH] refactor code --- packages/client/package.json | 2 + .../src/components/admin-layout/datatable.tsx | 6 +- .../src/components/admin-layout/index.tsx | 45 +- .../src/components/schema-renderer/index.tsx | 6 +- packages/client/src/constate/Collections.ts | 44 + .../client/src/constate/DesignableSwitch.ts | 15 + packages/client/src/constate/DisplayedMap.ts | 9 + packages/client/src/constate/PageTitle.ts | 12 + packages/client/src/constate/index.tsx | 4 + packages/client/src/context.ts | 3 + packages/client/src/resource.ts | 16 +- packages/client/src/schemas/action/index.md | 12 +- packages/client/src/schemas/action/index.tsx | 18 +- packages/client/src/schemas/add-new/index.tsx | 172 +- .../src/schemas/database-field/index.tsx | 24 +- .../client/src/schemas/form/DesignableBar.tsx | 1 - .../src/schemas/form/Field.DesignableBar.tsx | 14 +- packages/client/src/schemas/form/index.tsx | 89 +- packages/client/src/schemas/index.tsx | 81 +- packages/client/src/schemas/input/index.tsx | 19 +- packages/client/src/schemas/menu/index.tsx | 28 +- packages/client/src/schemas/page/index.tsx | 2 +- .../src/schemas/table/ColumnDesignableBar.tsx | 43 - .../src/schemas/table/DesignableBar.tsx | 43 - .../client/src/schemas/table/demos/demo1.tsx | 386 ----- .../client/src/schemas/table/demos/demo3.tsx | 261 +++ packages/client/src/schemas/table/index.md | 13 +- packages/client/src/schemas/table/index.tsx | 1449 +++++++---------- packages/client/src/schemas/table/style.less | 4 +- yarn.lock | 31 + 30 files changed, 1180 insertions(+), 1672 deletions(-) create mode 100644 packages/client/src/constate/Collections.ts create mode 100644 packages/client/src/constate/DesignableSwitch.ts create mode 100644 packages/client/src/constate/DisplayedMap.ts create mode 100644 packages/client/src/constate/PageTitle.ts create mode 100644 packages/client/src/constate/index.tsx create mode 100644 packages/client/src/context.ts delete mode 100644 packages/client/src/schemas/table/ColumnDesignableBar.tsx delete mode 100644 packages/client/src/schemas/table/DesignableBar.tsx delete mode 100644 packages/client/src/schemas/table/demos/demo1.tsx create mode 100644 packages/client/src/schemas/table/demos/demo3.tsx diff --git a/packages/client/package.json b/packages/client/package.json index 3d3808064..183167a4b 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -19,6 +19,8 @@ "gitHead": "f0b335ac30f29f25c95d7d137655fa64d8d67f1e", "dependencies": { "@antv/g2plot": "^2.3.27", + "@dnd-kit/core": "^3.1.1", + "@dnd-kit/sortable": "^4.0.0", "@formily/antd": "^2.0.0-beta.72", "@formily/core": "^2.0.0-beta.72", "@formily/react": "^2.0.0-beta.72", diff --git a/packages/client/src/components/admin-layout/datatable.tsx b/packages/client/src/components/admin-layout/datatable.tsx index fa1fae5fd..0caaaf746 100644 --- a/packages/client/src/components/admin-layout/datatable.tsx +++ b/packages/client/src/components/admin-layout/datatable.tsx @@ -1,8 +1,8 @@ import { SchemaRenderer } from '../../'; import React from 'react'; import { FormItem } from '@formily/antd'; -import { useCollectionContext } from '../../schemas'; import { action } from '@formily/reactive'; +import { useCollectionsContext } from '../../constate/Collections'; const useAsyncDataSource = (service: any) => (field: any) => { field.loading = true; @@ -15,10 +15,10 @@ const useAsyncDataSource = (service: any) => (field: any) => { }; export default () => { - const { data, loading } = useCollectionContext(); + const { collections = [], loading } = useCollectionsContext(); const loadCollections = async (field: any) => { - return data.map((item: any) => ({ + return collections.map((item: any) => ({ label: item.title, value: item.name, })); diff --git a/packages/client/src/components/admin-layout/index.tsx b/packages/client/src/components/admin-layout/index.tsx index 896cee3e2..504292b22 100644 --- a/packages/client/src/components/admin-layout/index.tsx +++ b/packages/client/src/components/admin-layout/index.tsx @@ -17,26 +17,24 @@ import { useHistory, Redirect, } from 'react-router-dom'; -import { - CollectionContextProvider, - PageTitleContextProvider, - SchemaRenderer, - SwithDesignableContextProvider, - usePageTitleContext, - useSwithDesignableContext, -} from '../../schemas'; +import { SchemaRenderer } from '../../schemas'; import { useRequest } from 'ahooks'; import './style.less'; -import { uid } from '@formily/shared'; import { ISchema, Schema } from '@formily/react'; import Database from './datatable'; import { HighlightOutlined } from '@ant-design/icons'; -import { useCookieState } from 'ahooks'; import cls from 'classnames'; +import { + DesignableSwitchProvider, + useDesignableSwitchContext, + PageTitleProvider, + usePageTitleContext, + CollectionsProvider, +} from '../../constate'; function DesignableToggle() { - const { designable, setDesignable } = useSwithDesignableContext(); + const { designable, setDesignable } = useDesignableSwitchContext(); return ( ); diff --git a/packages/client/src/schemas/add-new/index.tsx b/packages/client/src/schemas/add-new/index.tsx index b662b305a..0c67413d1 100644 --- a/packages/client/src/schemas/add-new/index.tsx +++ b/packages/client/src/schemas/add-new/index.tsx @@ -52,23 +52,23 @@ import { createOrUpdateCollection, createSchema, removeSchema, - request, - useCollectionContext, useDesignable, useSchemaPath, } from '../'; import { uid } from '@formily/shared'; -import { useRequest } from 'ahooks'; import { getSchemaPath, SchemaField } from '../../components/schema-renderer'; -import { useResourceContext } from '../'; import { cloneDeep } from 'lodash'; import { options } from '../database-field/interfaces'; -import { useDisplayFieldsContext } from '../form'; import './style.less'; import IconPicker from '../../components/icon-picker'; import { barChartConfig, columnChartConfig } from './chart'; import { isGridRowOrCol } from '../grid'; +import { + useCollectionContext, + useCollectionsContext, + useDisplayedMapContext, +} from '../../constate'; const generateGridBlock = (schema: ISchema) => { const name = schema.name || uid(); @@ -136,6 +136,10 @@ function generateCardItemSchema(component) { rowKey: 'id', dragSort: true, showIndex: true, + refreshRequestOnChange: true, + pagination: { + pageSize: 10, + }, }, properties: { [uid()]: { @@ -192,20 +196,7 @@ function generateCardItemSchema(component) { }, [uid()]: { type: 'void', - 'x-component': 'Table.ActionBar', - 'x-component-props': { - align: 'bottom', - }, - properties: { - [uid()]: { - type: 'void', - 'x-component': 'Table.Pagination', - 'x-component-props': {}, - }, - }, - }, - [uid()]: { - type: 'void', + title: '操作', 'x-component': 'Table.Column', 'x-component-props': { className: 'nb-table-operation', @@ -286,7 +277,7 @@ function generateCardItemSchema(component) { title: '编辑数据', 'x-decorator': 'Form', 'x-decorator-props': { - useValues: '{{ Table.useTableRow }}', + useValues: '{{ Table.useTableRowRecord }}', }, 'x-component': 'Action.Modal', 'x-component-props': { @@ -406,15 +397,7 @@ AddNew.CardItem = observer((props: any) => { const { ghost, defaultAction } = props; const { schema, insertBefore, insertAfter, appendChild } = useDesignable(); const path = useSchemaPath(); - // const { - // data: collections = [], - // loading, - // run, - // } = useRequest('collections:findAll', { - // formatResult: (result) => result?.data, - // }); - const { data: collections = [], loading, refresh } = useCollectionContext(); - console.log({ collections }); + const { collections = [], loading, refresh } = useCollectionsContext(); return ( { onVisibleChange={(visible) => { console.log('onVisibleChange', visible); }} - placement={'bottomCenter'} overlay={ { let data: ISchema; - let resourceName = null; + let collectionName = null; if (['addNewTable', 'addNewForm'].includes(info.key)) { const values = await FormDialog(`新建数据表`, () => { return ( @@ -448,12 +430,12 @@ AddNew.CardItem = observer((props: any) => { data = generateCardItemSchema( info.key === 'addNewTable' ? 'Table' : 'Form', ); - resourceName = values.name; + collectionName = values.name; } else if (info.key.startsWith('collection.')) { const keys = info.key.split('.'); const component = keys.pop(); const tableName = keys.pop(); - resourceName = tableName; + collectionName = tableName; data = generateCardItemSchema(component); console.log('info.keyPath', component, tableName); } else { @@ -463,9 +445,10 @@ AddNew.CardItem = observer((props: any) => { if (schema['key']) { data['key'] = uid(); } - if (resourceName) { + if (collectionName) { data['x-component-props'] = data['x-component-props'] || {}; - data['x-component-props']['resourceName'] = resourceName; + data['x-component-props']['resource'] = collectionName; + data['x-component-props']['collectionName'] = collectionName; } if (isGridBlock(schema)) { path.pop(); @@ -511,7 +494,7 @@ AddNew.CardItem = observer((props: any) => { title={view.title} > - {collections.map((item) => ( + {collections?.map((item) => ( { {ghost ? ( ) : ( - - )} - - ); -}); - -AddNew.BlockItem = observer((props: any) => { - const { ghost, defaultAction } = props; - const { schema, insertBefore, insertAfter } = useDesignable(); - const path = useSchemaPath(); - return ( - - - - 数据表1 - - - 新增数据表 - - - - 数据表1 - - - 新增数据表 - - { - let data: ISchema = { - type: 'void', - title: uid(), - 'x-designable-bar': 'BlockItem.DesignableBar', - 'x-decorator': 'CardItem', - 'x-component': 'Markdown.Void', - }; - if (schema['key']) { - data['key'] = uid(); - } - console.log('isGridBlock(schema)', isGridBlock(schema)); - if (isGridBlock(schema)) { - path.pop(); - path.pop(); - data = generateGridBlock(data); - } - if (data) { - let s; - if (defaultAction === 'insertAfter') { - s = insertAfter(data, [...path]); - } else { - s = insertBefore(data, [...path]); - } - await createSchema(s); - } - }} - > - 新建 Markdown - - - } - > - {ghost ? ( - - ) : ( - + )} ); @@ -692,15 +608,9 @@ AddNew.FormItem = observer((props: any) => { const { schema, insertBefore, insertAfter, appendChild, deepRemove } = useDesignable(); const path = useSchemaPath(); - const { resource = {}, refresh } = useResourceContext(); + const { collection, fields, refresh } = useCollectionContext(); const [visible, setVisible] = useState(false); - const { - displayFields, - hasDisplayField, - getDisplayField, - removeDisplayField, - } = useDisplayFieldsContext(); - console.log({ displayFields }); + const displayed = useDisplayedMapContext(); return ( { overlayStyle={{ minWidth: 200, }} - placement={'bottomCenter'} overlay={ - {resource?.fields?.map((field) => ( + {fields?.map((field) => ( { if (!checked) { - const s: any = getDisplayField(field.name); + const s: any = displayed.get(field.name); const p = getSchemaPath(s); const removed = deepRemove(p); if (!removed) { @@ -728,7 +637,7 @@ AddNew.FormItem = observer((props: any) => { return; } const last = removed.pop(); - removeDisplayField(field.name); + displayed.remove(field.name); if (isGridRowOrCol(last)) { await removeSchema(last); } @@ -797,7 +706,7 @@ AddNew.FormItem = observer((props: any) => { name: `f_${uid()}`, }, }); - await createCollectionField(resource.name, values); + await createCollectionField(collection?.name, values); await refresh(); let data: ISchema = cloneDeep(values.uiSchema); data['name'] = values.name; @@ -834,7 +743,6 @@ AddNew.FormItem = observer((props: any) => { { let data: ISchema = { - key: uid(), type: 'void', default: '这是一段演示文字,**支持使用 Markdown 语法**', 'x-designable-bar': 'Markdown.Void.DesignableBar', @@ -842,6 +750,9 @@ AddNew.FormItem = observer((props: any) => { 'x-read-pretty': true, 'x-component': 'Markdown.Void', }; + if (schema['key']) { + data['key'] = uid(); + } if (isGridBlock(schema)) { path.pop(); path.pop(); @@ -858,6 +769,7 @@ AddNew.FormItem = observer((props: any) => { } else { s = insertBefore(data, [...path]); } + console.log('ISchema', schema, data, path); await createSchema(s); } setVisible(false); @@ -871,7 +783,9 @@ AddNew.FormItem = observer((props: any) => { {ghost ? ( ) : ( - + )} ); @@ -881,10 +795,8 @@ AddNew.PaneItem = observer((props: any) => { const { ghost, defaultAction } = props; const { schema, insertBefore, insertAfter, appendChild } = useDesignable(); const path = useSchemaPath(); - const { resource = {}, refresh } = useResourceContext(); const [visible, setVisible] = useState(false); - const { displayFields } = useDisplayFieldsContext(); - console.log({ displayFields }); + return ( { overlayStyle={{ minWidth: 200, }} - placement={'bottomCenter'} + // placement={'bottomCenter'} overlay={ @@ -907,7 +819,7 @@ AddNew.PaneItem = observer((props: any) => { 'x-component': 'Form', 'x-read-pretty': true, 'x-component-props': { - useValues: '{{ Table.useTableRow }}', + useValues: '{{ Table.useTableRowRecord }}', }, 'x-designable-bar': 'Form.DesignableBar', properties: { @@ -953,7 +865,7 @@ AddNew.PaneItem = observer((props: any) => { 'x-decorator': 'CardItem', 'x-component': 'Form', 'x-component-props': { - useValues: '{{ Table.useTableRow }}', + useValues: '{{ Table.useTableRowRecord }}', showDefaultButtons: true, }, 'x-designable-bar': 'Form.DesignableBar', @@ -1045,7 +957,9 @@ AddNew.PaneItem = observer((props: any) => { {ghost ? ( ) : ( - + )} ); diff --git a/packages/client/src/schemas/database-field/index.tsx b/packages/client/src/schemas/database-field/index.tsx index 6970077ed..1bc103a28 100644 --- a/packages/client/src/schemas/database-field/index.tsx +++ b/packages/client/src/schemas/database-field/index.tsx @@ -39,11 +39,8 @@ import Modal from 'antd/lib/modal/Modal'; import { clone, cloneDeep, get } from 'lodash'; import { useEffect } from 'react'; import { useRequest } from 'ahooks'; -import { - createOrUpdateCollection, - deleteCollection, - useCollectionContext, -} from '..'; +import { createOrUpdateCollection, deleteCollection } from '..'; +import { useCollectionsContext } from '../../constate/Collections'; export const DatabaseCollection = observer((props) => { const field = useField(); @@ -53,21 +50,12 @@ export const DatabaseCollection = observer((props) => { const [activeIndex, setActiveIndex] = useState(0); const form = useForm(); const [newValue, setNewValue] = useState(''); - const { loading, refresh, data } = useCollectionContext(); + const { loading, refresh, collections = [] } = useCollectionsContext(); useEffect(() => { - field.setValue(data); - console.log('onSuccess', data); - }, [data]); - - // const { run, loading } = useRequest('collections:findAll', { - // formatResult: (result) => result?.data, - // onSuccess(data) { - // // field.setValue(data); - // // console.log('onSuccess', data); - // }, - // manual: true, - // }); + field.setValue(collections); + console.log('onSuccess', collections); + }, [collections]); return (
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={ - - { - const title = uid(); - field.title = title; - schema.title = title; - refresh(); - await updateSchema({ - key: schema['key'], - title: title, - }); - setVisible(false); - }} - > - 编辑列 - - { - const s = remove(); - const fieldName = schema['x-component-props']?.['fieldName']; - removeDisplayField(fieldName); - await removeSchema(s); - }} - > - 删除列 - - - } - > - - - + {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={ - - { - schema.title = uid(); - refresh(); - }} - > - 修改名称和图标 - - 放置在右侧 - - 删除 - - } - > - - - -
- ); -}; - -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={ - - { - schema.title = uid(); - refresh(); - }} - > - 修改名称和图标 - - 自定义筛选字段 - 放置在右侧 - - 删除 - - } - > - - - -
- ); -}; - 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={ + + { + const title = uid(); + field.title = title; + schema.title = title; + refresh(); + await updateSchema({ + key: schema['key'], + title: title, + }); + setVisible(false); + }} + > + 编辑列 + + { + const s = remove(); + const fieldName = schema['x-component-props']?.['fieldName']; + displayed.remove(fieldName); + await removeSchema(s); + }} + > + 删除列 + + + } + > + + + +
+ ); +}; + +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"