diff --git a/packages/client/src/schemas/DesignableSchemaField/index.tsx b/packages/client/src/schemas/DesignableSchemaField/index.tsx index 7b01164a9..2281a490c 100644 --- a/packages/client/src/schemas/DesignableSchemaField/index.tsx +++ b/packages/client/src/schemas/DesignableSchemaField/index.tsx @@ -16,6 +16,7 @@ import { useField, useFieldSchema, useForm, + SchemaOptionsContext, } from '@formily/react'; import { observable } from '@formily/reactive'; import { uid, clone } from '@formily/shared'; @@ -58,6 +59,7 @@ import { DragAndDrop } from '../drag-and-drop'; import { CodeOutlined } from '@ant-design/icons'; import Editor from '@monaco-editor/react'; +import { get } from 'lodash'; export const BlockContext = createContext({ dragRef: null }); @@ -187,10 +189,13 @@ export function addPropertyAfter(target: Schema, data: ISchema) { export function useDesignable(path?: any) { const { schema, refresh } = useContext(DesignableContext); const schemaPath = path || useSchemaPath(); - const currentSchema = findPropertyByPath(schema, schemaPath); + const currentSchema = findPropertyByPath(schema, schemaPath) || ({} as Schema); console.log('useDesignable', { schema, schemaPath, currentSchema }); + const options = useContext(SchemaOptionsContext); + const DesignableBar = get(options.components, currentSchema['x-designable-bar']) || (() => null); return { - schema: currentSchema || ({} as Schema), + DesignableBar, + schema: currentSchema, refresh, prepend: (property: ISchema, targetPath?: any): Schema => { let target = currentSchema; diff --git a/packages/client/src/schemas/action/index.md b/packages/client/src/schemas/action/index.md index 1ba59d48b..703e20227 100644 --- a/packages/client/src/schemas/action/index.md +++ b/packages/client/src/schemas/action/index.md @@ -17,7 +17,7 @@ group: - 弹出层操作,弹出层可以是 Action.Drawer、Action.Modal、Action.Popover - 指定容器内打开: Action.Container - 下拉菜单:Action.Dropdown,用于收纳多种操作 -- 跳转操作:Action.Link、Action.URL 和 Action.Route +- 跳转操作:Action.Link、Action.URL Action.Drawer、Action.Modal、Action.Popover 和 Action.Container 需要和 Action 搭配使用 diff --git a/packages/client/src/schemas/block-item/index.tsx b/packages/client/src/schemas/block-item/index.tsx index 1ccef6a39..0817d7c13 100644 --- a/packages/client/src/schemas/block-item/index.tsx +++ b/packages/client/src/schemas/block-item/index.tsx @@ -27,23 +27,9 @@ import { } from '../../components/drag-and-drop'; import cls from 'classnames'; -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, - }; -} - const DraggableBlock = (props) => { const { children, ...others } = props; - const { DesignableBar } = useDesignableBar(); + const { DesignableBar } = useDesignable(); const { isDragging, dragRef, previewRef, isOver, onTopHalf, dropRef } = useBlockDragAndDrop(); const schema = useFieldSchema(); @@ -102,9 +88,22 @@ const DraggableBlock = (props) => { }; const Block = (props) => { + const { DesignableBar } = useDesignable(); + const [active, setActive] = useState(false); return ( -
+
{ + setActive(true); + console.log('e.onMouseEnter', new Date().toString()); + }} + onMouseLeave={(e) => { + setActive(false); + console.log('e.onMouseLeave', new Date().toString()); + }} + className={cls('nb-grid-block', 'designable-form-item', { active })} + > {props.children} +
); }; diff --git a/packages/client/src/schemas/database-field/index.md b/packages/client/src/schemas/database-field/index.md index 72f1379fc..ba833f6a5 100644 --- a/packages/client/src/schemas/database-field/index.md +++ b/packages/client/src/schemas/database-field/index.md @@ -28,14 +28,20 @@ const schema = { { id: 1, interface: 'string', - type: 'string', + dataType: 'string', name: 'title', + ui: { + title: '标题', + }, }, { id: 2, - type: 'text', + dataType: 'text', interface: 'textarea', name: 'content', + ui: { + title: '内容', + }, }, ], }, diff --git a/packages/client/src/schemas/database-field/index.tsx b/packages/client/src/schemas/database-field/index.tsx index 906cb29d3..9c6f4673f 100644 --- a/packages/client/src/schemas/database-field/index.tsx +++ b/packages/client/src/schemas/database-field/index.tsx @@ -11,296 +11,9 @@ import { import { ArrayCollapse } from '@formily/antd'; import { uid } from '@formily/shared'; import '@formily/antd/lib/form-tab/style'; -import { Collapse, Button, Dropdown, Menu } from 'antd'; - -const interfaces = new Map(); - -interfaces.set('string', { - type: 'object', - default: { - type: 'string', - // name, - ui: { - type: 'string', - // title, - 'x-component': 'Input', - } as ISchema, - }, - properties: { - 'ui.title': { - type: 'string', - title: '字段名称', - required: true, - 'x-decorator': 'FormItem', - 'x-component': 'Input', - }, - name: { - type: 'string', - title: '字段标识', - required: true, - 'x-disabled': true, - 'x-decorator': 'FormItem', - 'x-component': 'Input', - }, - type: { - type: 'string', - title: '数据类型', - required: true, - 'x-decorator': 'FormItem', - 'x-component': 'Select', - enum: [ - { label: 'String', value: 'string' }, - { label: 'Text', value: 'text' }, - ], - }, - 'ui.required': { - type: 'string', - title: '必填', - 'x-decorator': 'FormItem', - 'x-component': 'Checkbox', - }, - }, -}); - -interfaces.set('textarea', { - type: 'object', - default: { - type: 'text', - // name, - ui: { - type: 'string', - // title, - 'x-component': 'Input.TextArea', - } as ISchema, - }, - properties: { - 'ui.title': { - type: 'string', - required: true, - title: '字段名称', - 'x-decorator': 'FormItem', - 'x-component': 'Input', - }, - name: { - type: 'string', - required: true, - title: '字段标识', - 'x-disabled': true, - 'x-decorator': 'FormItem', - 'x-component': 'Input', - }, - type: { - type: 'string', - title: '数据类型', - required: true, - 'x-decorator': 'FormItem', - 'x-component': 'Select', - enum: [ - { label: 'String', value: 'string' }, - { label: 'Text', value: 'text' }, - ], - }, - 'ui.required': { - type: 'string', - title: '必填', - 'x-decorator': 'FormItem', - 'x-component': 'Checkbox', - }, - }, -}); - -interfaces.set('subTable', { - type: 'object', - default: { - type: 'string', - // name, - ui: { - type: 'string', - // title, - 'x-component': 'Select', - enum: [], - } as ISchema, - }, - properties: { - 'ui.title': { - type: 'string', - required: true, - title: '字段名称', - 'x-decorator': 'FormItem', - 'x-component': 'Input', - }, - name: { - type: 'string', - required: true, - title: '字段标识', - 'x-disabled': true, - 'x-decorator': 'FormItem', - 'x-component': 'Input', - }, - type: { - type: 'string', - title: '数据类型', - required: true, - 'x-decorator': 'FormItem', - 'x-component': 'Select', - enum: [ - { label: 'String', value: 'string' }, - { label: 'Text', value: 'text' }, - { label: 'HasMany', value: 'hasMany' }, - ], - }, - 'children': { - type: 'array', - title: '子表格字段', - 'x-decorator': 'FormItem', - 'x-component': 'DatabaseField', - }, - // 'ui.required': { - // type: 'string', - // title: '必填', - // 'x-decorator': 'FormItem', - // 'x-component': 'Checkbox', - // }, - }, -}); - -interfaces.set('select', { - type: 'object', - default: { - type: 'string', - // name, - ui: { - type: 'string', - // title, - 'x-component': 'Select', - enum: [], - } as ISchema, - }, - properties: { - 'ui.title': { - type: 'string', - required: true, - title: '字段名称', - 'x-decorator': 'FormItem', - 'x-component': 'Input', - }, - name: { - type: 'string', - required: true, - title: '字段标识', - 'x-disabled': true, - 'x-decorator': 'FormItem', - 'x-component': 'Input', - }, - type: { - type: 'string', - title: '数据类型', - required: true, - 'x-decorator': 'FormItem', - 'x-component': 'Select', - enum: [ - { label: 'String', value: 'string' }, - { label: 'Text', value: 'text' }, - ], - }, - 'ui.enum': { - type: 'array', - title: '可选项', - 'x-decorator': 'FormItem', - 'x-component': 'ArrayTable', - 'x-component-props': { - pagination: false, - // scroll: { x: '100%' }, - }, - items: { - type: 'object', - properties: { - column1: { - type: 'void', - 'x-component': 'ArrayTable.Column', - 'x-component-props': { width: 50, title: '', align: 'center' }, - properties: { - sort: { - type: 'void', - 'x-component': 'ArrayTable.SortHandle', - }, - }, - }, - column2: { - type: 'void', - 'x-component': 'ArrayTable.Column', - 'x-component-props': { title: '选项值' }, - properties: { - value: { - type: 'string', - 'x-decorator': 'FormItem', - 'x-component': 'Input', - }, - }, - }, - column3: { - type: 'void', - 'x-component': 'ArrayTable.Column', - 'x-component-props': { title: '选项' }, - properties: { - label: { - type: 'string', - 'x-decorator': 'FormItem', - 'x-component': 'Input', - }, - }, - }, - column4: { - type: 'void', - 'x-component': 'ArrayTable.Column', - 'x-component-props': { title: '颜色' }, - properties: { - color: { - type: 'string', - 'x-decorator': 'FormItem', - 'x-component': 'ColorSelect', - }, - }, - }, - column5: { - type: 'void', - 'x-component': 'ArrayTable.Column', - 'x-component-props': { - title: '', - dataIndex: 'operations', - fixed: 'right', - }, - properties: { - item: { - type: 'void', - 'x-component': 'FormItem', - properties: { - remove: { - type: 'void', - 'x-component': 'ArrayTable.Remove', - }, - }, - }, - }, - }, - }, - }, - properties: { - add: { - type: 'void', - 'x-component': 'ArrayTable.Addition', - title: '添加可选项', - }, - }, - }, - 'ui.required': { - type: 'string', - title: '必填', - 'x-decorator': 'FormItem', - 'x-component': 'Checkbox', - }, - }, -}); +import { Collapse, Button, Dropdown, Menu, Tag } from 'antd'; +import { interfaces } from './interfaces'; +import { DeleteOutlined } from '@ant-design/icons'; export const DatabaseField: any = observer((props) => { const field = useField(); @@ -308,9 +21,13 @@ export const DatabaseField: any = observer((props) => { const [activeKey, setActiveKey] = useState(null); return (
- { - setActiveKey(key); - }} accordion> + { + setActiveKey(key); + }} + accordion + > {field.value?.map((item, index) => { const schema = interfaces.get(item.interface); console.log({ schema }); @@ -332,31 +49,39 @@ export const DatabaseField: any = observer((props) => { // ]} header={ <> - {item.ui && item.ui.title} - {' '} - {item.name} + {(item.ui && item.ui.title) || 未命名}{' '} + {schema.title} } + extra={[ + { + field.remove(index); + }} + />, + ]} key={item.id} > ); @@ -369,7 +94,7 @@ export const DatabaseField: any = observer((props) => { }} overlay={ { + onClick={(info) => { const schema = interfaces.get(info.key); if (!schema) { return; @@ -378,25 +103,20 @@ export const DatabaseField: any = observer((props) => { id: uid(), name: uid(), interface: info.key, - ...schema.default + ...schema.default, }; field.push(data); setActiveKey(data.id); console.log('info.key', info.key, schema); }} > - 单行文本 - 多行文本 - 下拉选择 - 子表格 + {Array.from(interfaces).map(([key, schema]) => ( + {schema.title} + ))} } > - diff --git a/packages/client/src/schemas/database-field/interfaces/index.ts b/packages/client/src/schemas/database-field/interfaces/index.ts new file mode 100644 index 000000000..cea53e09f --- /dev/null +++ b/packages/client/src/schemas/database-field/interfaces/index.ts @@ -0,0 +1,13 @@ +import { ISchema } from '@formily/react'; + +import { select } from './select'; +import { string } from './string'; +import { subTable } from './subTable'; +import { textarea } from './textarea'; + +export const interfaces = new Map(); + +interfaces.set('select', select); +interfaces.set('string', string); +interfaces.set('subTable', subTable); +interfaces.set('textarea', textarea); diff --git a/packages/client/src/schemas/database-field/interfaces/select.ts b/packages/client/src/schemas/database-field/interfaces/select.ts new file mode 100644 index 000000000..1061c10ba --- /dev/null +++ b/packages/client/src/schemas/database-field/interfaces/select.ts @@ -0,0 +1,140 @@ +import { ISchema } from '@formily/react'; + +export const select: ISchema = { + type: 'object', + title: '下拉选择', + default: { + dataType: 'string', + // name, + ui: { + type: 'string', + // title, + 'x-component': 'Select', + enum: [], + } as ISchema, + }, + properties: { + 'ui.title': { + type: 'string', + required: true, + title: '字段名称', + 'x-decorator': 'FormItem', + 'x-component': 'Input', + }, + name: { + type: 'string', + required: true, + title: '字段标识', + 'x-disabled': true, + 'x-decorator': 'FormItem', + 'x-component': 'Input', + }, + dataType: { + type: 'string', + title: '数据类型', + required: true, + 'x-decorator': 'FormItem', + 'x-component': 'Select', + enum: [ + { label: 'String', value: 'string' }, + { label: 'Text', value: 'text' }, + ], + }, + 'ui.enum': { + type: 'array', + title: '可选项', + 'x-decorator': 'FormItem', + 'x-component': 'ArrayTable', + 'x-component-props': { + pagination: false, + // scroll: { x: '100%' }, + }, + items: { + type: 'object', + properties: { + column1: { + type: 'void', + 'x-component': 'ArrayTable.Column', + 'x-component-props': { width: 50, title: '', align: 'center' }, + properties: { + sort: { + type: 'void', + 'x-component': 'ArrayTable.SortHandle', + }, + }, + }, + column2: { + type: 'void', + 'x-component': 'ArrayTable.Column', + 'x-component-props': { title: '选项值' }, + properties: { + value: { + type: 'string', + 'x-decorator': 'FormItem', + 'x-component': 'Input', + }, + }, + }, + column3: { + type: 'void', + 'x-component': 'ArrayTable.Column', + 'x-component-props': { title: '选项' }, + properties: { + label: { + type: 'string', + 'x-decorator': 'FormItem', + 'x-component': 'Input', + }, + }, + }, + column4: { + type: 'void', + 'x-component': 'ArrayTable.Column', + 'x-component-props': { title: '颜色' }, + properties: { + color: { + type: 'string', + 'x-decorator': 'FormItem', + 'x-component': 'ColorSelect', + }, + }, + }, + column5: { + type: 'void', + 'x-component': 'ArrayTable.Column', + 'x-component-props': { + title: '', + dataIndex: 'operations', + fixed: 'right', + }, + properties: { + item: { + type: 'void', + 'x-component': 'FormItem', + properties: { + remove: { + type: 'void', + 'x-component': 'ArrayTable.Remove', + }, + }, + }, + }, + }, + }, + }, + properties: { + add: { + type: 'void', + 'x-component': 'ArrayTable.Addition', + title: '添加可选项', + }, + }, + }, + 'ui.required': { + type: 'string', + title: '必填', + 'x-decorator': 'FormItem', + 'x-component': 'Checkbox', + }, + }, +}; diff --git a/packages/client/src/schemas/database-field/interfaces/string.ts b/packages/client/src/schemas/database-field/interfaces/string.ts new file mode 100644 index 000000000..9914fd119 --- /dev/null +++ b/packages/client/src/schemas/database-field/interfaces/string.ts @@ -0,0 +1,49 @@ +import { ISchema } from '@formily/react'; + +export const string: ISchema = { + type: 'object', + title: '单行文本', + default: { + dataType: 'string', + // name, + ui: { + type: 'string', + // title, + 'x-component': 'Input', + } as ISchema, + }, + properties: { + 'ui.title': { + type: 'string', + title: '字段名称', + required: true, + 'x-decorator': 'FormItem', + 'x-component': 'Input', + }, + name: { + type: 'string', + title: '字段标识', + required: true, + 'x-disabled': true, + 'x-decorator': 'FormItem', + 'x-component': 'Input', + }, + dataType: { + type: 'string', + title: '数据类型', + required: true, + 'x-decorator': 'FormItem', + 'x-component': 'Select', + enum: [ + { label: 'String', value: 'string' }, + { label: 'Text', value: 'text' }, + ], + }, + 'ui.required': { + type: 'string', + title: '必填', + 'x-decorator': 'FormItem', + 'x-component': 'Checkbox', + }, + }, +}; diff --git a/packages/client/src/schemas/database-field/interfaces/subTable.ts b/packages/client/src/schemas/database-field/interfaces/subTable.ts new file mode 100644 index 000000000..7ed2f5985 --- /dev/null +++ b/packages/client/src/schemas/database-field/interfaces/subTable.ts @@ -0,0 +1,50 @@ +import { ISchema } from '@formily/react'; + +export const subTable: ISchema = { + type: 'object', + title: '子表格', + default: { + // name, + ui: { + type: 'string', + // title, + 'x-component': 'Select', + enum: [], + } as ISchema, + }, + properties: { + 'ui.title': { + type: 'string', + required: true, + title: '字段名称', + 'x-decorator': 'FormItem', + 'x-component': 'Input', + }, + name: { + type: 'string', + required: true, + title: '字段标识', + 'x-disabled': true, + 'x-decorator': 'FormItem', + 'x-component': 'Input', + }, + dataType: { + type: 'string', + title: '数据类型', + required: true, + 'x-decorator': 'FormItem', + 'x-component': 'Select', + enum: [ + { label: 'String', value: 'string' }, + { label: 'Text', value: 'text' }, + { label: 'HasMany', value: 'hasMany' }, + ], + }, + 'children': { + type: 'array', + title: '子表格字段', + 'x-decorator': 'FormItem', + 'x-component': 'DatabaseField', + }, + }, +}; diff --git a/packages/client/src/schemas/database-field/interfaces/textarea.ts b/packages/client/src/schemas/database-field/interfaces/textarea.ts new file mode 100644 index 000000000..ad5fda3c2 --- /dev/null +++ b/packages/client/src/schemas/database-field/interfaces/textarea.ts @@ -0,0 +1,49 @@ +import { ISchema } from '@formily/react'; + +export const textarea: ISchema = { + type: 'object', + title: '多行文本', + default: { + dataType: 'text', + // name, + ui: { + type: 'string', + // title, + 'x-component': 'Input.TextArea', + } as ISchema, + }, + properties: { + 'ui.title': { + type: 'string', + required: true, + title: '字段名称', + 'x-decorator': 'FormItem', + 'x-component': 'Input', + }, + name: { + type: 'string', + required: true, + title: '字段标识', + 'x-disabled': true, + 'x-decorator': 'FormItem', + 'x-component': 'Input', + }, + dataType: { + type: 'string', + title: '数据类型', + required: true, + 'x-decorator': 'FormItem', + 'x-component': 'Select', + enum: [ + { label: 'String', value: 'string' }, + { label: 'Text', value: 'text' }, + ], + }, + 'ui.required': { + type: 'string', + title: '必填', + 'x-decorator': 'FormItem', + 'x-component': 'Checkbox', + }, + }, +};