{
setActive(true);
- console.log('e.onMouseEnter', new Date().toString());
+ // console.log('e.onMouseEnter', new Date().toString());
}}
onMouseMove={(event) => {
let dropElement = document.elementFromPoint(
@@ -65,11 +65,11 @@ const DraggableBlock = (props) => {
if (dropIds.length > 0) {
setActive(dropIds[0] === schema.name);
}
- console.log('e.onMouseMove', dropIds, schema.name);
+ // console.log('e.onMouseMove', dropIds, schema.name);
}}
onMouseLeave={(e) => {
setActive(false);
- console.log('e.onMouseLeave', new Date().toString());
+ // console.log('e.onMouseLeave', new Date().toString());
}}
ref={mergeRefs([previewRef, dropRef])}
className={cls('nb-grid-block', 'designable-form-item', {
diff --git a/packages/client/src/schemas/database-field/interfaces/select.ts b/packages/client/src/schemas/database-field/interfaces/select.ts
index ff28f3861..9d981e9b0 100644
--- a/packages/client/src/schemas/database-field/interfaces/select.ts
+++ b/packages/client/src/schemas/database-field/interfaces/select.ts
@@ -6,12 +6,15 @@ export const select: ISchema = {
title: '下拉选择',
group: 'choices',
default: {
+ interface: 'select',
dataType: 'string',
// name,
uiSchema: {
type: 'string',
// title,
'x-component': 'Select',
+ 'x-decorator': 'FormItem',
+ 'x-designable-bar': 'Markdown.DesignableBar',
enum: [],
} as ISchema,
},
diff --git a/packages/client/src/schemas/database-field/interfaces/string.ts b/packages/client/src/schemas/database-field/interfaces/string.ts
index c88e7649b..b8eea8c9e 100644
--- a/packages/client/src/schemas/database-field/interfaces/string.ts
+++ b/packages/client/src/schemas/database-field/interfaces/string.ts
@@ -6,12 +6,15 @@ export const string: ISchema = {
title: '单行文本',
group: 'basic',
default: {
+ interface: 'string',
dataType: 'string',
// name,
uiSchema: {
type: 'string',
// title,
'x-component': 'Input',
+ 'x-decorator': 'FormItem',
+ 'x-designable-bar': 'Input.DesignableBar',
} as ISchema,
},
properties: {
diff --git a/packages/client/src/schemas/database-field/interfaces/subTable.ts b/packages/client/src/schemas/database-field/interfaces/subTable.ts
index cfd624794..44a96eaca 100644
--- a/packages/client/src/schemas/database-field/interfaces/subTable.ts
+++ b/packages/client/src/schemas/database-field/interfaces/subTable.ts
@@ -6,11 +6,14 @@ export const subTable: ISchema = {
title: '子表格',
group: 'relation',
default: {
+ interface: 'subTable',
// name,
uiSchema: {
type: 'string',
// title,
- 'x-component': 'Select',
+ 'x-decorator': 'FormItem',
+ 'x-component': 'Table',
+ 'x-designable-bar': 'Markdown.DesignableBar',
enum: [],
} as ISchema,
},
diff --git a/packages/client/src/schemas/database-field/interfaces/textarea.ts b/packages/client/src/schemas/database-field/interfaces/textarea.ts
index 85742ebff..109a25b60 100644
--- a/packages/client/src/schemas/database-field/interfaces/textarea.ts
+++ b/packages/client/src/schemas/database-field/interfaces/textarea.ts
@@ -11,7 +11,9 @@ export const textarea: ISchema = {
uiSchema: {
type: 'string',
// title,
+ 'x-decorator': 'FormItem',
'x-component': 'Input.TextArea',
+ 'x-designable-bar': 'Markdown.DesignableBar',
} as ISchema,
},
properties: {
diff --git a/packages/client/src/schemas/form/DesignableBar.tsx b/packages/client/src/schemas/form/DesignableBar.tsx
new file mode 100644
index 000000000..a2bbd4e04
--- /dev/null
+++ b/packages/client/src/schemas/form/DesignableBar.tsx
@@ -0,0 +1,94 @@
+import React, { useContext, useMemo, useRef, useState } from 'react';
+import { createForm } from '@formily/core';
+import {
+ SchemaOptionsContext,
+ Schema,
+ useFieldSchema,
+ observer,
+ SchemaExpressionScopeContext,
+ FormProvider,
+ ISchema,
+ useField,
+ useForm,
+ RecursionField,
+} from '@formily/react';
+import {
+ useSchemaPath,
+ SchemaField,
+ useDesignable,
+ removeSchema,
+ useCollectionContext,
+} from '../';
+import get from 'lodash/get';
+import { Button, Dropdown, Menu, Space } from 'antd';
+import { MenuOutlined, DragOutlined } from '@ant-design/icons';
+import cls from 'classnames';
+import { FormLayout } from '@formily/antd';
+import './style.less';
+import AddNew from '../add-new';
+import { DraggableBlockContext } from '../../components/drag-and-drop';
+import { isGridRowOrCol } from '../grid';
+import constate from 'constate';
+import { useEffect } from 'react';
+import { uid } from '@formily/shared';
+import { getSchemaPath } from '../../components/schema-renderer';
+
+export const DesignableBar = observer((props) => {
+ const field = useField();
+ const { designable, schema, refresh, deepRemove } = useDesignable();
+ const [visible, setVisible] = useState(false);
+ const { dragRef } = useContext(DraggableBlockContext);
+ if (!designable) {
+ return null;
+ }
+ return (
+
+
{
+ e.stopPropagation();
+ }}
+ className={cls('designable-bar-actions', { active: visible })}
+ >
+
+
+ {dragRef && }
+ {
+ setVisible(visible);
+ }}
+ overlay={
+
+ }
+ >
+
+
+
+
+
+ );
+});
diff --git a/packages/client/src/schemas/form/Field.DesignableBar.tsx b/packages/client/src/schemas/form/Field.DesignableBar.tsx
new file mode 100644
index 000000000..3bd7edd3e
--- /dev/null
+++ b/packages/client/src/schemas/form/Field.DesignableBar.tsx
@@ -0,0 +1,114 @@
+import React, { useContext, useMemo, useRef, useState } from 'react';
+import { createForm } from '@formily/core';
+import {
+ SchemaOptionsContext,
+ Schema,
+ useFieldSchema,
+ observer,
+ SchemaExpressionScopeContext,
+ FormProvider,
+ ISchema,
+ useField,
+ useForm,
+ RecursionField,
+} from '@formily/react';
+import {
+ useSchemaPath,
+ SchemaField,
+ useDesignable,
+ removeSchema,
+ useCollectionContext,
+ updateSchema,
+} from '../';
+import get from 'lodash/get';
+import { Button, Dropdown, Menu, Space } from 'antd';
+import { MenuOutlined, DragOutlined } from '@ant-design/icons';
+import cls from 'classnames';
+import { FormLayout } from '@formily/antd';
+import './style.less';
+import AddNew from '../add-new';
+import { DraggableBlockContext } from '../../components/drag-and-drop';
+import { isGridRowOrCol } from '../grid';
+import constate from 'constate';
+import { useEffect } from 'react';
+import { uid } from '@formily/shared';
+import { getSchemaPath } from '../../components/schema-renderer';
+import { FormFieldUIDContext } from '.';
+
+export const FieldDesignableBar = observer((props) => {
+ const field = useField();
+ const fieldSchema = useFieldSchema();
+ const { designable, schema, deepRemove } = useDesignable();
+ const [visible, setVisible] = useState(false);
+ const { dragRef } = useContext(DraggableBlockContext);
+ const fieldUid = useContext(FormFieldUIDContext);
+ const fieldName = schema['x-component-props']?.['fieldName'];
+ if (!designable) {
+ return null;
+ }
+ return (
+
+
{
+ e.stopPropagation();
+ }}
+ className={cls('designable-bar-actions', { active: visible })}
+ >
+
+
+ {dragRef && }
+ {
+ setVisible(visible);
+ }}
+ overlay={
+
+ }
+ >
+
+
+
+
+
+ );
+});
diff --git a/packages/client/src/schemas/form/index.md b/packages/client/src/schemas/form/index.md
index 918f80273..d591f89c7 100644
--- a/packages/client/src/schemas/form/index.md
+++ b/packages/client/src/schemas/form/index.md
@@ -20,6 +20,13 @@ group:
// 添加其他节点
+
+
+
+
+
// Form 用作 decorator 时只用于创建独立的作用域
diff --git a/packages/client/src/schemas/form/index.tsx b/packages/client/src/schemas/form/index.tsx
index 402bfb9bf..49a35ebaa 100644
--- a/packages/client/src/schemas/form/index.tsx
+++ b/packages/client/src/schemas/form/index.tsx
@@ -9,10 +9,18 @@ import {
FormProvider,
ISchema,
useField,
+ useForm,
+ RecursionField,
} from '@formily/react';
-import { useSchemaPath, SchemaField, useDesignable, removeSchema } from '../';
+import {
+ useSchemaPath,
+ SchemaField,
+ useDesignable,
+ removeSchema,
+ useCollectionContext,
+} from '../';
import get from 'lodash/get';
-import { Dropdown, Menu, Space } from 'antd';
+import { Button, Dropdown, Menu, Space } from 'antd';
import { MenuOutlined, DragOutlined } from '@ant-design/icons';
import cls from 'classnames';
import { FormLayout } from '@formily/antd';
@@ -20,9 +28,34 @@ import './style.less';
import AddNew from '../add-new';
import { DraggableBlockContext } from '../../components/drag-and-drop';
import { isGridRowOrCol } from '../grid';
+import constate from 'constate';
+import { useEffect } from 'react';
+import { uid } from '@formily/shared';
+import { getSchemaPath } from '../../components/schema-renderer';
+import { DesignableBar } from './DesignableBar';
+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 };
+});
+
+export { FormContextProvider, useFormContext };
export const Form: any = observer((props: any) => {
- const { useValues = () => ({}), ...others } = props;
+ const {
+ useValues = () => ({}),
+ showDefaultButtons = false,
+ ...others
+ } = props;
const initialValues = useValues();
const form = useMemo(() => {
console.log('Form.useMemo', initialValues);
@@ -33,91 +66,105 @@ export const Form: any = observer((props: any) => {
const scope = useContext(SchemaExpressionScopeContext);
return (
- {schema['x-decorator'] === 'Form' ? (
-
- ) : (
-
+ {/* @ts-ignore */}
+
+ {schema['x-decorator'] === 'Form' ? (
-
- )}
+ ) : (
+
+
+
+ )}
+ {showDefaultButtons && (
+
+
+
+
+ )}
+
);
});
-Form.__Decorator = ({ children }) => children;
+export const FormFieldUIDContext = createContext(null);
-Form.DesignableBar = observer((props) => {
- const field = useField();
- const { schema, refresh, deepRemove } = useDesignable();
- const [visible, setVisible] = useState(false);
- const { dragRef } = useContext(DraggableBlockContext);
+Form.Field = observer((props: any) => {
+ const { fieldName } = props;
+ const { schema } = useDesignable();
+ const path = getSchemaPath(schema);
+ console.log('getSchemaPath', path);
+ const { collection = {} } = useFormContext();
+ if (!fieldName) {
+ return null;
+ }
+ const field = collection?.fields?.find((item) => item.name === fieldName);
+ if (!field) {
+ return null;
+ }
+ const name = useContext(FormFieldUIDContext);
+ const title = schema['title'] || field.uiSchema['title'];
return (
-
-
{
- e.stopPropagation();
- }}
- className={cls('designable-bar-actions', { active: visible })}
- >
-
-
- {dragRef && }
- {
- setVisible(visible);
- }}
- overlay={
-
- }
- >
-
-
-
-
-
+
);
});
+
+Form.Field.Item = observer((props) => {
+ const name = uid();
+ return (
+
+ {props.children}
+
+ );
+});
+
+Form.__Decorator = ({ children }) => children;
+Form.DesignableBar = DesignableBar;
+Form.Field.DesignableBar = FieldDesignableBar;
diff --git a/packages/client/src/schemas/grid/index.tsx b/packages/client/src/schemas/grid/index.tsx
index 0bf320e8a..3e8a7f3d0 100644
--- a/packages/client/src/schemas/grid/index.tsx
+++ b/packages/client/src/schemas/grid/index.tsx
@@ -89,6 +89,7 @@ export const Grid: any = observer((props: any) => {
// const schema = useFieldSchema();
const gridPath = useSchemaPath();
const {
+ designable,
schema,
schema: designableSchema,
insertAfter,
@@ -166,7 +167,7 @@ export const Grid: any = observer((props: any) => {
>
);
})}
- {AddNewComponent && }
+ {designable && AddNewComponent && }
);
@@ -187,7 +188,7 @@ Grid.Row = observer((props) => {
deepRemove,
} = useDesignable();
const len = Object.keys(designableSchema.properties || {}).length;
- console.log({ len, schema, designableSchema });
+ // console.log({ len, schema, designableSchema });
return (
{
- const field = useField()
+ const field = useField();
if (!isVoidField(field) && field?.pattern === 'readPretty') {
return React.createElement(component, {
...readPrettyProps,
...props,
- })
+ });
}
- return React.createElement(target, props)
+ return React.createElement(target, props);
},
{
forwardRef: true,
- }
- )
+ },
+ );
};
}
@@ -57,6 +57,13 @@ export async function createOrUpdateCollection(data: any) {
});
}
+export async function createCollectionField(collectionName: string, data: any) {
+ return await request(`collections/${collectionName}/fields:create`, {
+ method: 'post',
+ data,
+ });
+}
+
export async function deleteCollection(name) {
await request('collections:destroy', {
method: 'post',
@@ -109,3 +116,16 @@ const [CollectionContextProvider, useCollectionContext] = constate(() => {
});
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 };
diff --git a/packages/client/src/schemas/input/index.tsx b/packages/client/src/schemas/input/index.tsx
index 4a5762c16..35290da38 100644
--- a/packages/client/src/schemas/input/index.tsx
+++ b/packages/client/src/schemas/input/index.tsx
@@ -1,10 +1,19 @@
import React from 'react'
-import { connect, mapProps, mapReadPretty } from '@formily/react'
+import { connect, mapProps, mapReadPretty, observer, useField, useFieldSchema } from '@formily/react'
import { Input as AntdInput } from 'antd'
import { InputProps, TextAreaProps } from 'antd/lib/input'
-import { LoadingOutlined } from '@ant-design/icons'
import { Display } from '../display';
import { DesignableBar } from './DesignableBar';
+import { Dropdown, Menu, Space } from 'antd';
+import { LoadingOutlined, MenuOutlined, DragOutlined } from '@ant-design/icons';
+import { getSchemaPath, useDesignable } from '../../components/schema-renderer';
+import { useContext, useState } from 'react';
+import AddNew from '../add-new';
+import cls from 'classnames';
+import { DraggableBlockContext } from '../../components/drag-and-drop';
+import { uid } from '@formily/shared';
+import { removeSchema, updateSchema } from '..';
+import { isGridRowOrCol } from '../grid';
type ComposedInput = React.FC & {
TextArea?: React.FC
@@ -15,6 +24,7 @@ type ComposedInput = React.FC & {
export const Input: ComposedInput = connect(
AntdInput,
mapProps((props, field) => {
+ console.log('fieldfieldfieldfieldfield', field.address.entire);
return {
...props,
suffix: (
@@ -31,8 +41,65 @@ export const Input: ComposedInput = connect(
mapReadPretty(Display.Input)
)
-Input.DesignableBar = DesignableBar;
Input.TextArea = connect(AntdInput.TextArea, mapReadPretty(Display.TextArea))
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 [visible, setVisible] = useState(false);
+ const { dragRef } = useContext(DraggableBlockContext);
+ return (
+
+
{
+ e.stopPropagation();
+ }}
+ className={cls('designable-bar-actions', { active: visible })}
+ >
+
+
+ {dragRef && }
+ {
+ setVisible(visible);
+ }}
+ overlay={
+
+ }
+ >
+
+
+
+
+
+ );
+});
+
export default Input
diff --git a/packages/client/src/schemas/markdown/index.tsx b/packages/client/src/schemas/markdown/index.tsx
index 270fbb4e8..d385cca17 100644
--- a/packages/client/src/schemas/markdown/index.tsx
+++ b/packages/client/src/schemas/markdown/index.tsx
@@ -20,6 +20,7 @@ import { DraggableBlockContext } from '../../components/drag-and-drop';
import { uid } from '@formily/shared';
import { removeSchema, updateSchema } from '..';
import { isGridRowOrCol } from '../grid';
+import './style.less';
export const Markdown: any = connect(
(props) => {
@@ -67,7 +68,7 @@ export const Markdown: any = connect(
console.log('Markdown', props);
let text = props.value;
let value = (
-
+
);
return ;
}),
@@ -75,9 +76,12 @@ export const Markdown: any = connect(
Markdown.DesignableBar = observer((props) => {
const field = useField();
- const { schema, refresh, deepRemove } = useDesignable();
+ const { designable, schema, refresh, deepRemove } = useDesignable();
const [visible, setVisible] = useState(false);
const { dragRef } = useContext(DraggableBlockContext);
+ if (!designable) {
+ return null;
+ }
return (
{
}
}}
>
- 删除当前区块
+ 删除当前文本
+
+
+ }
+ >
+
+
+
+
+
+ );
+});
+
+Markdown.FormItemDesignableBar = observer((props) => {
+ const field = useField();
+ const { designable, schema, refresh, deepRemove } = useDesignable();
+ const [visible, setVisible] = useState(false);
+ const { dragRef } = useContext(DraggableBlockContext);
+ if (!designable) {
+ return null;
+ }
+ return (
+
+
{
+ e.stopPropagation();
+ }}
+ className={cls('designable-bar-actions', { active: visible })}
+ >
+
+
+ {dragRef && }
+ {
+ setVisible(visible);
+ }}
+ overlay={
+
}
diff --git a/packages/client/src/schemas/markdown/style.less b/packages/client/src/schemas/markdown/style.less
new file mode 100644
index 000000000..64bd143c9
--- /dev/null
+++ b/packages/client/src/schemas/markdown/style.less
@@ -0,0 +1,3 @@
+.nb-markdown > *:last-child {
+ margin-bottom: 0;
+}
\ No newline at end of file
diff --git a/packages/client/src/schemas/menu/index.tsx b/packages/client/src/schemas/menu/index.tsx
index d383f0c54..ab8c4309e 100644
--- a/packages/client/src/schemas/menu/index.tsx
+++ b/packages/client/src/schemas/menu/index.tsx
@@ -97,7 +97,7 @@ const SideMenu = (props: any) => {
export const Menu: any = observer((props: any) => {
const { mode, onSelect, sideMenuRef, ...others } = props;
- const { schema } = useDesignable();
+ const { designable, schema } = useDesignable();
const fieldSchema = useFieldSchema();
console.log('Menu.schema', schema, fieldSchema);
const [selectedKey, setSelectedKey] = useState(null);
@@ -275,8 +275,10 @@ Menu.SubMenu = observer((props: any) => {
});
Menu.AddNew = observer((props: any) => {
- const { appendChild } = useDesignable(props.path);
-
+ const { designable, appendChild } = useDesignable(props.path);
+ if (!designable) {
+ return null;
+ }
const schemas = {
'Menu.Link': {
icon: ,
@@ -516,11 +518,15 @@ Menu.DesignableBar = (props) => {
const field = useField();
const [visible, setVisible] = useState(false);
- const { schema, remove, refresh, insertAfter, insertBefore, appendChild } =
+ const { designable, schema, remove, refresh, insertAfter, insertBefore, appendChild } =
useDesignable();
const formConfig = schemas[schema['x-component']];
const isSubMenu = schema['x-component'] === 'Menu.SubMenu';
+ if (!designable) {
+ return null;
+ }
+
return (
{
const schema = useFieldSchema();
const field = useField();
- console.log('Table.Column', schema, field.title);
const { DesignableBar } = useDesignableBar();
return (
@@ -461,7 +461,6 @@ Table.Column.DesignableBar = () => {
// const fieldSchema = useFieldSchema();
const { schema, remove, refresh, insertAfter } = useDesignable();
const [visible, setVisible] = useState(false);
- console.log('Table.Column.DesignableBar', { schema });
return (
{
const schema = useFieldSchema();
const field = useField();
const path = useSchemaPath();
- return #{index + 1}
;
+ return {index + 1}
;
});
Table.Addition = observer((props: any) => {
@@ -605,7 +604,7 @@ Table.Action.DesignableBar = () => {
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 });
+ // console.log('Table.Action.DesignableBar', path, field.address.entire, { schema, field });
return (
{
Table.DesignableBar = observer((props) => {
const field = useField();
- const { schema, refresh, deepRemove } = useDesignable();
+ const { designable, schema, refresh, deepRemove } = useDesignable();
const [visible, setVisible] = useState(false);
const { dragRef } = useContext(DraggableBlockContext);
+ if (!designable) {
+ return null;
+ }
return (
{
{
- deepRemove();
+ onClick={async () => {
+ const removed = deepRemove();
+ // console.log({ removed })
+ const last = removed.pop();
+ if (isGridRowOrCol(last)) {
+ await removeSchema(last);
+ }
}}
>
删除当前区块