diff --git a/packages/client/src/schemas/action/index.tsx b/packages/client/src/schemas/action/index.tsx index e454e68a6..b78364240 100644 --- a/packages/client/src/schemas/action/index.tsx +++ b/packages/client/src/schemas/action/index.tsx @@ -20,6 +20,7 @@ import cls from 'classnames'; import { MenuOutlined } from '@ant-design/icons'; import { FormLayout } from '@formily/antd'; import IconPicker from '../../components/icon-picker'; +import { useSchemaComponent } from '../../components/schema-renderer'; export const Action: any = observer((props: any) => { const { useAction = useDefaultAction, icon, ...others } = props; @@ -188,6 +189,7 @@ Action.Dropdown = observer((props: any) => { const { buttonProps = {}, ...others } = props; const { schema } = useDesignable(); const componentProps = schema.parent['x-component-props'] || {}; + const icon = buttonProps.icon || componentProps['icon']; return ( { } > - + ); }); @@ -212,6 +220,10 @@ Action.Popover = observer((props) => { console.log('Action.Popover', schema, fieldSchema); const componentProps = (schema.parent && schema.parent['x-component-props']) || {}; + const designableBarComponent = schema.parent + ? schema.parent['x-designable-bar'] + : null; + const DesignableBar = useSchemaComponent(designableBarComponent); return ( { } > - + ); }); diff --git a/packages/client/src/schemas/add-new/index.tsx b/packages/client/src/schemas/add-new/index.tsx index aa5865ccf..7f463ec1c 100644 --- a/packages/client/src/schemas/add-new/index.tsx +++ b/packages/client/src/schemas/add-new/index.tsx @@ -16,6 +16,7 @@ import { RecursionField, Schema, ISchema, + useForm, } from '@formily/react'; import { Menu, @@ -58,9 +59,10 @@ import { import { uid } from '@formily/shared'; import { useRequest } from 'ahooks'; import { SchemaField } from '../../components/schema-renderer'; -import { useFormContext } from '../form'; +import { useResourceContext } from '../'; import { cloneDeep } from 'lodash'; import { options } from '../database-field/interfaces'; +import { useDisplayFieldsContext } from '../form'; const generateGridBlock = (schema: ISchema) => { const name = schema.name || uid(); @@ -126,73 +128,154 @@ function generateCardItemSchema(component) { { key: uid(), field1: uid(), field2: uid() }, { key: uid(), field1: uid(), field2: uid() }, { key: uid(), field1: uid(), field2: uid() }, - { key: uid(), field1: uid(), field2: uid() }, - { key: uid(), field1: uid(), field2: uid() }, - { key: uid(), field1: uid(), field2: uid() }, - { key: uid(), field1: uid(), field2: uid() }, ], 'x-component-props': { rowKey: 'key', + dragSort: true, + showIndex: true, }, properties: { - [`action_bar_${uid()}`]: { + [uid()]: { type: 'void', 'x-component': 'Table.ActionBar', + 'x-designable-bar': 'Table.ActionBar.DesignableBar', properties: { - action1: { + [uid()]: { + type: 'void', + 'x-component': 'Table.Filter', + 'x-designable-bar': 'Table.Filter.DesignableBar', + 'x-component-props': { + fieldNames: [], + }, + }, + [uid()]: { type: 'void', name: 'action1', - title: '筛选', + title: '新增', 'x-component': 'Action', + 'x-designable-bar': 'Table.Action.DesignableBar', properties: { - popover1: { + modal: { type: 'void', - title: '弹窗标题', + title: '新增数据', 'x-decorator': 'Form', - 'x-component': 'Action.Popover', - 'x-component-props': {}, + 'x-component': 'Action.Modal', + 'x-component-props': { + useOkAction: '{{ Table.useTableCreateAction }}', + }, properties: { - filter: { - name: 'filter', - type: 'object', - 'x-component': 'Filter', + [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 }}', + }, + }, + }, + }, + [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', + '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': { + style: { + minWidth: 150, + }, + disabled: true, + }, + }, + [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: { - column1: { + [uid()]: { type: 'void', - title: '字段1', - 'x-component': 'Filter.Column', - 'x-component-props': { - operations: [ - { label: '等于', value: 'eq' }, - { label: '不等于', value: 'ne' }, - ], - }, + 'x-component': 'Tabs', 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, + 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', + }, }, - ], - }, - properties: { - field1: { - type: 'number', - 'x-component': 'InputNumber', }, }, }, @@ -200,88 +283,54 @@ function generateCardItemSchema(component) { }, }, }, - }, - }, - action2: { - type: 'void', - name: 'action1', - title: '新增', - 'x-component': 'Action', - 'x-designable-bar': 'Action.DesignableBar', - properties: { - drawer1: { + [uid()]: { type: 'void', - title: '抽屉标题', - 'x-decorator': 'Form', - 'x-component': 'Action.Modal', - 'x-component-props': { - useOkAction: '{{ Table.useTableCreateAction }}', - }, + name: 'action1', + title: '修改', + 'x-component': 'Menu.Action', + 'x-designable-bar': 'Table.Action.DesignableBar', properties: { - field1: { - type: 'string', - title: '字段1', - 'x-decorator': 'FormItem', - 'x-component': 'Input', - }, - field2: { - type: 'string', - title: '字段2', - 'x-decorator': 'FormItem', - 'x-component': 'Input', + 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 }}', + }, + }, }, }, - action3: { - type: 'void', - name: 'action1', - title: '删除', - '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', - 'x-component': 'Table.Pagination', - '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()}`]: { + [uid()]: { type: 'void', title: '字段1', 'x-component': 'Table.Column', @@ -302,15 +351,17 @@ function generateCardItemSchema(component) { }, }, }, - [`column_${uid()}`]: { + [uid()]: { type: 'void', title: '字段2', 'x-component': 'Table.Column', + 'x-component-props': { + // title: 'z1', + }, 'x-designable-bar': 'Table.Column.DesignableBar', properties: { field2: { type: 'string', - // title: '字段2', required: true, 'x-read-pretty': true, 'x-decorator-props': { @@ -321,111 +372,6 @@ function generateCardItemSchema(component) { }, }, }, - [`column_${uid()}`]: { - type: 'void', - title: '操作', - 'x-component': 'Table.Column', - properties: { - [uid()]: { - type: 'void', - name: 'action1', - title: '查看', - 'x-component': 'Action', - 'x-designable-bar': 'Table.Action.DesignableBar', - properties: { - drawer1: { - type: 'void', - title: '查看', - 'x-component': 'Action.Modal', - 'x-component-props': {}, - properties: { - [uid()]: { - type: 'void', - 'x-component': 'Tabs', - properties: { - tab1: { - type: 'void', - 'x-component': 'Tabs.TabPane', - 'x-component-props': { - tab: 'Tab1', - }, - properties: { - aaa: { - type: 'string', - title: 'AAA', - 'x-decorator': 'FormItem', - required: true, - 'x-component': 'Input', - }, - }, - }, - tab2: { - type: 'void', - 'x-component': 'Tabs.TabPane', - 'x-component-props': { - tab: 'Tab2', - }, - properties: { - bbb: { - type: 'string', - title: 'BBB', - 'x-decorator': 'FormItem', - required: true, - 'x-component': 'Input', - }, - }, - }, - }, - }, - }, - }, - }, - }, - [uid()]: { - type: 'void', - name: 'action1', - title: '修改', - 'x-component': 'Action', - 'x-designable-bar': 'Table.Action.DesignableBar', - properties: { - drawer1: { - type: 'void', - title: '编辑表单', - 'x-decorator': 'Form', - 'x-decorator-props': { - useValues: '{{ Table.useTableRow }}', - }, - 'x-component': 'Action.Modal', - 'x-component-props': { - useOkAction: '{{ Table.useTableUpdateAction }}', - }, - properties: { - field1: { - type: 'string', - title: '字段1', - 'x-decorator': 'FormItem', - 'x-component': 'Input', - }, - field2: { - type: 'string', - title: '字段2', - 'x-decorator': 'FormItem', - 'x-component': 'Input', - }, - }, - }, - }, - }, - [uid()]: { - type: 'void', - title: '删除', - 'x-component': 'Action', - 'x-component-props': { - useAction: '{{ Table.useTableDestroyAction }}', - }, - }, - }, - }, }, }, Form: { @@ -509,6 +455,7 @@ AddNew.CardItem = observer((props: any) => { console.log({ collections }); return ( { { let data: ISchema; - let collectionName = null; + let resourceName = null; if (['addNewTable', 'addNewForm'].includes(info.key)) { const values = await FormDialog(`新建数据表`, () => { return ( @@ -539,12 +486,12 @@ AddNew.CardItem = observer((props: any) => { data = generateCardItemSchema( info.key === 'addNewTable' ? 'Table' : 'Form', ); - collectionName = values.name; + resourceName = values.name; } else if (info.key !== 'Markdown') { const keys = info.key.split('.'); const component = keys.shift(); const tableName = keys.join('.'); - collectionName = tableName; + resourceName = tableName; data = generateCardItemSchema(component); console.log('info.keyPath', component, tableName); } else { @@ -553,9 +500,9 @@ AddNew.CardItem = observer((props: any) => { if (schema['key']) { data['key'] = uid(); } - if (collectionName) { + if (resourceName) { data['x-component-props'] = data['x-component-props'] || {}; - data['x-component-props']['collectionName'] = collectionName; + data['x-component-props']['resourceName'] = resourceName; } if (isGridBlock(schema)) { path.pop(); @@ -595,8 +542,8 @@ AddNew.CardItem = observer((props: any) => { 新建数据表 - 新建 Markdown - + 新建文本段 + 模板1 @@ -684,55 +631,97 @@ AddNew.BlockItem = observer((props: any) => { ); }); +function FieldSwitch({ field, onChange, defaultChecked }) { + const [checked, setChecked] = useState(defaultChecked); + const form = useForm(); + return ( +
{ + setChecked((value) => { + onChange && onChange(!value); + return !value; + }); + console.log('FieldSwitch', form); + }} + > + {field?.uiSchema?.title || '未命名'} + { + e.stopPropagation(); + setChecked(checked); + onChange && onChange(checked); + }} + size={'small'} + checked={checked} + /> +
+ ); +} + AddNew.FormItem = observer((props: any) => { const { ghost, defaultAction } = props; const { schema, insertBefore, insertAfter, appendChild } = useDesignable(); const path = useSchemaPath(); - const { collection = {}, refresh } = useFormContext(); + const { resource = {}, refresh } = useResourceContext(); + const [visible, setVisible] = useState(false); + const { displayFields = [] } = useDisplayFieldsContext(); + console.log({ displayFields }); return ( - - {collection?.fields?.map((field) => ( - { - let data: ISchema = { - key: uid(), - type: 'void', - 'x-decorator': 'Form.Field.Item', - 'x-designable-bar': 'Form.Field.DesignableBar', - 'x-component': 'Form.Field', - 'x-component-props': { - fieldName: field.name, - }, - }; - if (isGridBlock(schema)) { - path.pop(); - path.pop(); - data = generateGridBlock(data); - } else if (isGrid(schema)) { - data = generateGridBlock(data); - } - if (data) { - let s; - if (isGrid(schema)) { - s = appendChild(data, [...path]); - } else if (defaultAction === 'insertAfter') { - s = insertAfter(data, [...path]); - } else { - s = insertBefore(data, [...path]); + + {resource?.fields?.map((field) => ( + + { + if (!checked) { + return; } - await createSchema(s); - } - }} - > - {field?.uiSchema?.title || '未命名'} + let data: ISchema = { + key: uid(), + type: 'void', + 'x-decorator': 'Form.Field.Item', + 'x-designable-bar': 'Form.Field.DesignableBar', + 'x-component': 'Form.Field', + 'x-component-props': { + fieldName: field.name, + }, + }; + if (isGridBlock(schema)) { + path.pop(); + path.pop(); + data = generateGridBlock(data); + } else if (isGrid(schema)) { + data = generateGridBlock(data); + } + if (data) { + let s; + if (isGrid(schema)) { + s = appendChild(data, [...path]); + } else if (defaultAction === 'insertAfter') { + s = insertAfter(data, [...path]); + } else { + s = insertBefore(data, [...path]); + } + await createSchema(s); + } + }} + /> ))} @@ -745,6 +734,7 @@ AddNew.FormItem = observer((props: any) => { style={{ minWidth: 150 }} key={item.name} onClick={async () => { + setVisible(false); const values = await FormDialog(`新增字段`, () => { return ( @@ -758,7 +748,7 @@ AddNew.FormItem = observer((props: any) => { name: `f_${uid()}`, }, }); - await createCollectionField(collection.name, values); + await createCollectionField(resource.name, values); await refresh(); let data: ISchema = cloneDeep(values.uiSchema); data['name'] = values.name; @@ -790,13 +780,13 @@ AddNew.FormItem = observer((props: any) => { ))}
- + {/* */} { let data: ISchema = { key: uid(), type: 'string', - default: '这是一段演示文字', + default: '这是一段演示文字,**支持使用 Markdown 语法**', 'x-designable-bar': 'Markdown.FormItemDesignableBar', 'x-decorator': 'FormItem', 'x-read-pretty': true, @@ -823,6 +813,7 @@ AddNew.FormItem = observer((props: any) => { } await createSchema(s); } + setVisible(false); }} > 添加说明文字 diff --git a/packages/client/src/schemas/database-field/interfaces/select.ts b/packages/client/src/schemas/database-field/interfaces/select.ts index 9d981e9b0..3a3bbcc14 100644 --- a/packages/client/src/schemas/database-field/interfaces/select.ts +++ b/packages/client/src/schemas/database-field/interfaces/select.ts @@ -142,4 +142,8 @@ export const select: ISchema = { 'x-component': 'Checkbox', }, }, + operations: [ + { label: '等于', value: 'eq' }, + { label: '不等于', value: 'ne' }, + ], }; diff --git a/packages/client/src/schemas/database-field/interfaces/string.ts b/packages/client/src/schemas/database-field/interfaces/string.ts index b8eea8c9e..b833297d3 100644 --- a/packages/client/src/schemas/database-field/interfaces/string.ts +++ b/packages/client/src/schemas/database-field/interfaces/string.ts @@ -51,4 +51,8 @@ export const string: ISchema = { 'x-component': 'Checkbox', }, }, + operations: [ + { label: '等于', value: 'eq' }, + { label: '不等于', value: 'ne' }, + ], }; diff --git a/packages/client/src/schemas/database-field/interfaces/textarea.ts b/packages/client/src/schemas/database-field/interfaces/textarea.ts index 109a25b60..bdfa5bf8a 100644 --- a/packages/client/src/schemas/database-field/interfaces/textarea.ts +++ b/packages/client/src/schemas/database-field/interfaces/textarea.ts @@ -50,4 +50,8 @@ export const textarea: ISchema = { 'x-component': 'Checkbox', }, }, + operations: [ + { label: '等于', value: 'eq' }, + { label: '不等于', value: 'ne' }, + ], }; diff --git a/packages/client/src/schemas/form/index.tsx b/packages/client/src/schemas/form/index.tsx index 49a35ebaa..5ac584c45 100644 --- a/packages/client/src/schemas/form/index.tsx +++ b/packages/client/src/schemas/form/index.tsx @@ -18,6 +18,8 @@ import { useDesignable, removeSchema, useCollectionContext, + useResourceContext, + ResourceContextProvider, } from '../'; import get from 'lodash/get'; import { Button, Dropdown, Menu, Space } from 'antd'; @@ -37,23 +39,25 @@ import { FieldDesignableBar } from './Field.DesignableBar'; import { createContext } from 'react'; import { BlockItem } from '../block-item'; -const [FormContextProvider, useFormContext] = constate(({ schema, form }) => { - // const schema = useFieldSchema(); - const collectionName = schema['x-component-props']?.['collectionName']; - const { data: collections = [], loading, refresh } = useCollectionContext(); - const collection = collectionName - ? collections.find((item) => item.name === collectionName) - : {}; - console.log({ collection }); - return { form, schema, collection, refresh }; +const [DisplayFieldsContextProvider, useDisplayFieldsContext] = constate(() => { + const [displayFields, setDisplayFields] = useState([]); + + return { + displayFields, + setDisplayFields, + addDisplayField(fieldName) { + setDisplayFields(fields => fields.concat(fieldName)); + }, + } }); -export { FormContextProvider, useFormContext }; +export { DisplayFieldsContextProvider, useDisplayFieldsContext } export const Form: any = observer((props: any) => { const { useValues = () => ({}), showDefaultButtons = false, + resourceName, ...others } = props; const initialValues = useValues(); @@ -64,59 +68,66 @@ export const Form: any = observer((props: any) => { const { schema } = useDesignable(); const path = useSchemaPath(); const scope = useContext(SchemaExpressionScopeContext); - return ( + const content = ( - {/* @ts-ignore */} - - {schema['x-decorator'] === 'Form' ? ( + {schema['x-decorator'] === 'Form' ? ( + + ) : ( + - ) : ( - - - - )} - {showDefaultButtons && ( - - - - - )} - + + )} + {showDefaultButtons && ( + + + + + )} ); + return resourceName ? ( + // @ts-ignore + + + {content} + + + ) : ( + content + ); }); export const FormFieldUIDContext = createContext(null); @@ -126,11 +137,17 @@ Form.Field = observer((props: any) => { const { schema } = useDesignable(); const path = getSchemaPath(schema); console.log('getSchemaPath', path); - const { collection = {} } = useFormContext(); + const { addDisplayField } = useDisplayFieldsContext(); + const { resource = {} } = useResourceContext(); + useEffect(() => { + if (fieldName) { + addDisplayField(fieldName); + } + }, [fieldName]); if (!fieldName) { return null; } - const field = collection?.fields?.find((item) => item.name === fieldName); + const field = resource?.fields?.find((item) => item.name === fieldName); if (!field) { return null; } diff --git a/packages/client/src/schemas/index.tsx b/packages/client/src/schemas/index.tsx index 5c713432e..b5c127750 100644 --- a/packages/client/src/schemas/index.tsx +++ b/packages/client/src/schemas/index.tsx @@ -129,3 +129,15 @@ const [SwithDesignableContextProvider, useSwithDesignableContext] = constate(() }); export { SwithDesignableContextProvider, useSwithDesignableContext }; + +const [ResourceContextProvider, useResourceContext] = constate( + ({ resourceName }) => { + // const schema = useFieldSchema(); + const { data: collections = [], loading, refresh } = useCollectionContext(); + const resource = collections.find((item) => item.name === resourceName); + console.log({ resource }); + return { resource, refresh }; + }, +); + +export { ResourceContextProvider, useResourceContext }; diff --git a/packages/client/src/schemas/markdown/index.tsx b/packages/client/src/schemas/markdown/index.tsx index d385cca17..98d4d887f 100644 --- a/packages/client/src/schemas/markdown/index.tsx +++ b/packages/client/src/schemas/markdown/index.tsx @@ -105,9 +105,10 @@ Markdown.DesignableBar = observer((props) => { key={'update'} onClick={() => { field.readPretty = false; + setVisible(false); }} > - 修改 Markdown + 修改文本段 { className={'nb-menu-add-new'} title={ { diff --git a/packages/client/src/schemas/table/demos/demo1.tsx b/packages/client/src/schemas/table/demos/demo1.tsx index 7245b7b8b..3fc92e41f 100644 --- a/packages/client/src/schemas/table/demos/demo1.tsx +++ b/packages/client/src/schemas/table/demos/demo1.tsx @@ -17,34 +17,41 @@ const schema: ISchema = { name: `table_${uid()}`, type: 'array', 'x-component': 'Table', - // default: [ - // { key: uid(), field1: uid(), field2: uid() }, - // { key: uid(), field1: uid(), field2: uid() }, - // { key: uid(), field1: uid(), field2: uid() }, - // { key: uid(), field1: uid(), field2: uid() }, - // { key: uid(), field1: uid(), field2: uid() }, - // { key: uid(), field1: uid(), field2: uid() }, - // { key: uid(), field1: uid(), field2: uid() }, - // { key: uid(), field1: uid(), field2: uid() }, - // { key: uid(), field1: uid(), field2: uid() }, - // { key: uid(), field1: uid(), field2: uid() }, - // { key: uid(), field1: uid(), field2: uid() }, - // { key: uid(), field1: uid(), field2: uid() }, - // ], + default: [ + { key: uid(), field1: uid(), field2: uid() }, + { key: uid(), field1: uid(), field2: uid() }, + { key: uid(), field1: uid(), field2: uid() }, + { key: uid(), field1: uid(), field2: uid() }, + { key: uid(), field1: uid(), field2: uid() }, + { key: uid(), field1: uid(), field2: uid() }, + { key: uid(), field1: uid(), field2: uid() }, + { key: uid(), field1: uid(), field2: uid() }, + { key: uid(), field1: uid(), field2: uid() }, + { key: uid(), field1: uid(), field2: uid() }, + { key: uid(), field1: uid(), field2: uid() }, + { key: uid(), field1: uid(), field2: uid() }, + ], 'x-component-props': { rowKey: 'key', - // isRemoteDataSource: true, + dragSort: 'sort', + showIndex: true, + defaultFilter: {}, + defaultSort: [], + pagination: { + defaultPageSize: 50, + }, }, properties: { [`action_bar_${uid()}`]: { type: 'void', 'x-component': 'Table.ActionBar', + 'x-designable-bar': 'Table.ActionBar.DesignableBar', properties: { action1: { type: 'void', - name: 'action1', title: '筛选', 'x-component': 'Action', + 'x-designable-bar': 'Table.Filter.DesignableBar', properties: { popover1: { type: 'void', @@ -104,7 +111,7 @@ const schema: ISchema = { name: 'action1', title: '新增', 'x-component': 'Action', - 'x-designable-bar': 'Action.DesignableBar', + 'x-designable-bar': 'Table.Action.DesignableBar', properties: { drawer1: { type: 'void', @@ -135,6 +142,7 @@ const schema: ISchema = { type: 'void', name: 'action1', title: '删除', + 'x-designable-bar': 'Table.Action.SimpleDesignableBar', 'x-component': 'Action', 'x-component-props': { useAction: '{{ Table.useTableDestroyAction }}', @@ -157,175 +165,43 @@ const schema: ISchema = { }, }, }, + // [`column_${uid()}`]: { + // type: 'void', + // title: '排序', + // 'x-component': 'Table.Column', + // properties: { + // sort: { + // type: 'void', + // 'x-component': 'Table.SortHandle', + // }, + // }, + // }, + // [`column_${uid()}`]: { + // type: 'void', + // title: '序号', + // 'x-component': 'Table.Column', + // properties: { + // index: { + // type: 'void', + // 'x-component': 'Table.Index', + // }, + // }, + // }, [`column_${uid()}`]: { type: 'void', - title: '排序', - 'x-component': 'Table.Column', - properties: { - sort: { - type: 'void', - 'x-component': 'Table.SortHandle', - }, - }, - }, - [`column_${uid()}`]: { - type: 'void', - title: '序号', - 'x-component': 'Table.Column', - properties: { - index: { - type: 'void', - 'x-component': 'Table.Index', - }, - }, - }, - [`column_${uid()}`]: { - type: 'void', - title: '字段1', 'x-component': 'Table.Column', 'x-component-props': { - // title: 'z1', + className: 'nb-table-operation', }, - 'x-designable-bar': 'Table.Column.DesignableBar', - properties: { - field1: { - type: 'string', - required: true, - 'x-read-pretty': true, - 'x-decorator-props': { - feedbackLayout: 'popover', - }, - 'x-decorator': 'FormItem', - 'x-component': 'Input', - }, - }, - }, - [`column_${uid()}`]: { - type: 'void', - title: '字段2', - 'x-component': 'Table.Column', - 'x-designable-bar': 'Table.Column.DesignableBar', - properties: { - field2: { - type: 'string', - // title: '字段2', - required: true, - 'x-read-pretty': true, - 'x-decorator-props': { - feedbackLayout: 'popover', - }, - 'x-decorator': 'FormItem', - 'x-component': 'Input', - }, - }, - }, - [`column_${uid()}`]: { - type: 'void', - title: '操作', - 'x-component': 'Table.Column', properties: { [uid()]: { type: 'void', - name: 'action1', - title: '查看', - 'x-component': 'Action', - 'x-designable-bar': 'Table.Action.DesignableBar', - properties: { - drawer1: { - type: 'void', - title: '查看', - 'x-component': 'Action.Modal', - 'x-component-props': {}, - properties: { - [uid()]: { - type: 'void', - 'x-component': 'Tabs', - properties: { - tab1: { - type: 'void', - 'x-component': 'Tabs.TabPane', - 'x-component-props': { - tab: 'Tab1', - }, - properties: { - aaa: { - type: 'string', - title: 'AAA', - 'x-decorator': 'FormItem', - required: true, - 'x-component': 'Input', - }, - }, - }, - tab2: { - type: 'void', - 'x-component': 'Tabs.TabPane', - 'x-component-props': { - tab: 'Tab2', - }, - properties: { - bbb: { - type: 'string', - title: 'BBB', - 'x-decorator': 'FormItem', - required: true, - 'x-component': 'Input', - }, - }, - }, - }, - }, - }, - }, - }, - }, - [uid()]: { - type: 'void', - name: 'action1', - title: '修改', - 'x-component': 'Action', - 'x-designable-bar': 'Table.Action.DesignableBar', - properties: { - drawer1: { - type: 'void', - title: '编辑表单', - "x-decorator": 'Form', - 'x-decorator-props': { - useValues: '{{ Table.useTableRow }}', - }, - 'x-component': 'Action.Modal', - 'x-component-props': { - useOkAction: '{{ Table.useTableUpdateAction }}', - }, - properties: { - field1: { - type: 'string', - title: '字段1', - 'x-decorator': 'FormItem', - 'x-component': 'Input', - }, - field2: { - type: 'string', - title: '字段2', - 'x-decorator': 'FormItem', - 'x-component': 'Input', - }, - }, - }, - }, - }, - [uid()]: { - type: 'void', - title: '删除', - 'x-component': 'Action', - 'x-component-props': { - useAction: '{{ Table.useTableDestroyAction }}', - }, - }, - [uid()]: { - type: 'void', - title: '...', 'x-component': 'Action.Dropdown', + 'x-component-props': { + buttonProps: { + icon: 'EllipsisOutlined', + }, + }, properties: { [uid()]: { type: 'void', @@ -333,6 +209,9 @@ const schema: ISchema = { 'x-component': 'Menu.Action', 'x-component-props': { useAction, + style: { + minWidth: 150, + }, disabled: true, }, }, @@ -410,7 +289,7 @@ const schema: ISchema = { drawer1: { type: 'void', title: '编辑表单', - "x-decorator": 'Form', + 'x-decorator': 'Form', 'x-decorator-props': { useValues: '{{ Table.useTableRow }}', }, @@ -447,6 +326,46 @@ const schema: ISchema = { }, }, }, + [`column_${uid()}`]: { + type: 'void', + title: '字段1', + 'x-component': 'Table.Column', + 'x-component-props': { + // title: 'z1', + }, + 'x-designable-bar': 'Table.Column.DesignableBar', + properties: { + field1: { + type: 'string', + required: true, + 'x-read-pretty': true, + 'x-decorator-props': { + feedbackLayout: 'popover', + }, + 'x-decorator': 'FormItem', + 'x-component': 'Input', + }, + }, + }, + [`column_${uid()}`]: { + type: 'void', + title: '字段2', + 'x-component': 'Table.Column', + 'x-designable-bar': 'Table.Column.DesignableBar', + properties: { + field2: { + type: 'string', + // title: '字段2', + required: true, + 'x-read-pretty': true, + 'x-decorator-props': { + feedbackLayout: 'popover', + }, + 'x-decorator': 'FormItem', + 'x-component': 'Input', + }, + }, + }, }, }; @@ -457,7 +376,11 @@ const form = createForm({ export default observer(() => { return (
- +
); }); diff --git a/packages/client/src/schemas/table/index.tsx b/packages/client/src/schemas/table/index.tsx index 09c2b7225..da8abe8ca 100644 --- a/packages/client/src/schemas/table/index.tsx +++ b/packages/client/src/schemas/table/index.tsx @@ -19,24 +19,40 @@ import { Table as AntdTable, Dropdown, Menu, + Select, + Switch, } from 'antd'; -import { findIndex, get } from 'lodash'; +import { findIndex, get, set } from 'lodash'; import constate from 'constate'; import useRequest from '@ahooksjs/use-request'; -import { BaseResult } from '@ahooksjs/use-request/lib/types'; import { uid, clone } from '@formily/shared'; -import { MenuOutlined, DragOutlined } from '@ant-design/icons'; +import { + EllipsisOutlined, + MenuOutlined, + DragOutlined, + PlusOutlined, +} from '@ant-design/icons'; import { SortableHandle, SortableContainer, SortableElement, } from 'react-sortable-hoc'; import cls from 'classnames'; -import { getSchemaPath, removeSchema, useDesignable, useSchemaPath, VisibleContext } from '../'; +import { + getSchemaPath, + removeSchema, + ResourceContextProvider, + useCollectionContext, + useDesignable, + useResourceContext, + useSchemaPath, + VisibleContext, +} from '../'; import './style.less'; import { DraggableBlockContext } from '../../components/drag-and-drop'; import AddNew from '../add-new'; import { isGridRowOrCol } from '../grid'; +import { options } from '../database-field/interfaces'; interface TableRowProps { index: number; @@ -116,7 +132,7 @@ function useTableActionBars() { } function useTableColumns(props?: any) { - const { schema } = useDesignable(); + const { schema, designable } = useDesignable(); // const schema = useFieldSchema(); const { dataSource } = props || {}; @@ -129,8 +145,9 @@ function useTableColumns(props?: any) { }, []); } - return findColumns(schema).map((item) => { + const columns = findColumns(schema).map((item) => { const columnProps = item['x-component-props'] || {}; + console.log(item); return { title: , dataIndex: item.name, @@ -150,6 +167,83 @@ function useTableColumns(props?: any) { }, }; }); + + // columns.unshift({ + // title: '', + // className: 'nb-table-operation', + // dataIndex: 'operation', + // render(value, record, recordIndex) { + // const index = dataSource.indexOf(record); + // return ( + // + // + // + // ); + // }, + // }); + + designable && + columns.push({ + title: , + dataIndex: 'addnew', + }); + + return columns; +} + +function AddColumn() { + const [visible, setVisible] = useState(false); + const { resource = {}, refresh } = useResourceContext(); + return ( + + + {resource?.fields?.map((field) => ( + +
+ {field.uiSchema.title} + +
+
+ ))} +
+ + + {options.map((option) => ( + + {option.children.map((item) => ( + {}} + > + {item.title} + + ))} + + ))} + +
+ } + > + +
+ ); } export function useTableRow() { @@ -200,7 +294,7 @@ export function useTableDestroyAction() { export function useTableFilterAction() { const { field, refresh, params } = useTableContext(); - const [,setVisible] = useContext(VisibleContext); + const [, setVisible] = useContext(VisibleContext); const form = useForm(); return { async run() { @@ -212,7 +306,7 @@ export function useTableFilterAction() { export function useTableCreateAction() { const { field, run: exec, params } = useTableContext(); - const [,setVisible] = useContext(VisibleContext); + const [, setVisible] = useContext(VisibleContext); const form = useForm(); return { async run() { @@ -229,7 +323,7 @@ export function useTableCreateAction() { export function useTableUpdateAction() { const { field, refresh, params } = useTableContext(); - const [,setVisible] = useContext(VisibleContext); + const [, setVisible] = useContext(VisibleContext); const ctx = useContext(TableRowContext); const form = useForm(); return { @@ -245,8 +339,10 @@ const [TableContextProvider, useTableContext] = constate(() => { const field = useField(); const schema = useFieldSchema(); const defaultSelectedRowKeys = useContext(SelectedRowKeysContext); - const [selectedRowKeys, setSelectedRowKeys] = useState(defaultSelectedRowKeys || []); - console.log({ defaultSelectedRowKeys }) + const [selectedRowKeys, setSelectedRowKeys] = useState( + defaultSelectedRowKeys || [], + ); + console.log({ defaultSelectedRowKeys }); const pagination = usePaginationProps(); const response = useRequest<{ list: any[]; @@ -293,8 +389,9 @@ export { TableContextProvider, useTableContext }; export const SelectedRowKeysContext = createContext([]); const TableContainer = observer((props) => { + const { schema } = useDesignable(); const field = useField(); - const schema = useFieldSchema(); + // const schema = useFieldSchema(); const actionBars = useTableActionBars(); const { loading, data, refresh, selectedRowKeys, setSelectedRowKeys } = useTableContext(); @@ -316,6 +413,8 @@ const TableContainer = observer((props) => { }); } }; + const dragSort = schema?.['x-component-props']?.['dragSort']; + const showIndex = schema?.['x-component-props']?.['showIndex']; return (
{actionBars.top.map((actionBarSchema) => { @@ -340,6 +439,26 @@ const TableContainer = observer((props) => { rowSelection={{ type: 'checkbox', selectedRowKeys, + renderCell: (checked, record, _, originNode) => { + const index = dataSource.indexOf(record); + return ( + +
+ {dragSort && } + {showIndex && } + {originNode} + {/* */} +
+
+ ); + }, onChange: (keys) => { console.log(keys); setSelectedRowKeys(keys); @@ -384,13 +503,13 @@ const TableContainer = observer((props) => { if (!defaultAction) { return; } - const el = (e.target as HTMLElement); - if ( - !el.classList.contains('ant-table-cell') - ) { + const el = e.target as HTMLElement; + if (!el.classList.contains('ant-table-cell')) { return; } - const btn = el.parentElement.querySelector(`.name-${defaultAction.name}`); + const btn = el.parentElement.querySelector( + `.name-${defaultAction.name}`, + ); btn && btn.click(); }, }; @@ -415,8 +534,16 @@ const TableContainer = observer((props) => { ); }); -export const Table: any = observer((props) => { - return ( +export const Table: any = observer((props: any) => { + const { resourceName } = props; + return resourceName ? ( + // @ts-ignore + + + + + + ) : ( @@ -477,41 +604,53 @@ Table.Column.DesignableBar = () => { }} overlay={ - { - const title = uid(); - field.title = title; - schema.title = title; - setVisible(false); - }}>点击修改按钮文案 - { - remove(); - console.log('Table.Column.DesignableBar', { schema }); - }}>删除列 - { - const name = uid(); - insertAfter({ - name: `column_${name}`, - type: 'void', - title: `字段 ${name}`, - 'x-component': 'Table.Column', - 'x-component-props': { - // title: 'z1', - }, - 'x-designable-bar': 'Table.Column.DesignableBar', - properties: { - [name]: { - type: 'string', - required: true, - // 'x-read-pretty': true, - 'x-decorator-props': { - feedbackLayout: 'popover', - }, - 'x-decorator': 'FormItem', - 'x-component': 'Input', + { + const title = uid(); + field.title = title; + schema.title = title; + setVisible(false); + }} + > + 点击修改按钮文案 + + { + remove(); + console.log('Table.Column.DesignableBar', { schema }); + }} + > + 删除列 + + { + const name = uid(); + insertAfter({ + name: `column_${name}`, + type: 'void', + title: `字段 ${name}`, + 'x-component': 'Table.Column', + 'x-component-props': { + // title: 'z1', }, - }, - }) - }}>插入列 + 'x-designable-bar': 'Table.Column.DesignableBar', + properties: { + [name]: { + type: 'string', + required: true, + // 'x-read-pretty': true, + 'x-decorator-props': { + feedbackLayout: 'popover', + }, + 'x-decorator': 'FormItem', + 'x-component': 'Input', + }, + }, + }); + }} + > + 插入列 + } > @@ -522,10 +661,61 @@ Table.Column.DesignableBar = () => { ); }; -Table.ActionBar = observer((props) => { +function AddActionButton() { + const [visible, setVisible] = useState(false); return ( -
- {props.children} + + + {[ + { title: '筛选', key: 'filter' }, + { title: '导出', key: 'export' }, + { title: '新增', key: 'create' }, + { title: '删除', key: 'destroy' }, + ].map((item) => ( + +
+ {item.title} + +
+
+ ))} +
+ + + 函数操作 + 弹窗表单 + 复杂弹窗 + + + } + > + +
+ ); +} + +Table.ActionBar = observer((props: any) => { + const { align = 'top' } = props; + const { schema, designable } = useDesignable(); + const designableBar = schema['x-designable-bar']; + console.log('designableBar', designableBar); + return ( +
+ + {props.children} + {designable && designableBar && } +
); }); @@ -533,19 +723,17 @@ Table.ActionBar = observer((props) => { Table.Pagination = observer((props) => { const { data, params, run } = useTableContext(); return ( - data?.total > params?.pageSize && ( - { - run({ page, pageSize }); - }} - /> - ) + { + run({ page, pageSize }); + }} + /> ); }); @@ -560,17 +748,16 @@ const SortHandle = SortableHandle((props: any) => { }) as any; Table.SortHandle = observer((props) => { - const field = useField(); - console.log('SortHandle', field.value); return ; }); +Table.Operation = observer((props) => { + return ; +}); + Table.Index = observer((props) => { const index = useTableIndex(); - const schema = useFieldSchema(); - const field = useField(); - const path = useSchemaPath(); - return
{index + 1}
; + return {index + 1}; }); Table.Addition = observer((props: any) => { @@ -599,7 +786,7 @@ Table.Addition = observer((props: any) => { Table.Action = () => null; -Table.Action.DesignableBar = () => { +Table.Action.SimpleDesignableBar = () => { const field = useField(); const path = useSchemaPath(); const { schema, remove, refresh, insertAfter } = useDesignable(); @@ -621,10 +808,125 @@ Table.Action.DesignableBar = () => { }} overlay={ - { - schema.title = uid(); - refresh(); - }}>点击修改按钮文案 + { + 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 ( +
+ { + e.stopPropagation(); + }} + className={cls('designable-bar-actions', { active: visible })} + > + { + setVisible(visible); + }} + overlay={ + + { + schema.title = uid(); + refresh(); + }} + > + 修改名称和图标 + + {isPopup && ( + + 在{' '} + {' '} + 内打开 + + )} + {inActionBar && 放置在右侧} + + 删除 } > @@ -643,6 +945,8 @@ Table.DesignableBar = observer((props) => { if (!designable) { return null; } + const defaultPageSize = + schema['x-component-props']?.['pagination']?.['defaultPageSize'] || 20; return (
{ overlay={ { - field.readPretty = false; + const bool = !field.componentProps.showIndex; + schema['x-component-props']['showIndex'] = bool; + field.componentProps.showIndex = bool; }} > - 编辑Markdown + {field.componentProps.showIndex ? '隐藏序号' : '显示序号'} + + { + const dragSort = field.componentProps.dragSort + ? false + : 'sort'; + schema['x-component-props']['dragSort'] = dragSort; + field.componentProps.dragSort = dragSort; + }} + > + {field.componentProps.dragSort + ? '禁用拖拽排序' + : '启用拖拽排序'} + + {!field.componentProps.dragSort && ( + 默认排序 + )} + 筛选范围 + + 每页默认显示{' '} + {' '} + 条