updates
This commit is contained in:
		
							parent
							
								
									e53a1edf7d
								
							
						
					
					
						commit
						708afa059c
					
				@ -1,7 +1,7 @@
 | 
			
		||||
export default {
 | 
			
		||||
  type: 'object',
 | 
			
		||||
  properties: {
 | 
			
		||||
    input: {
 | 
			
		||||
    email: {
 | 
			
		||||
      type: 'string',
 | 
			
		||||
      required: true,
 | 
			
		||||
      'x-decorator': 'FormItem',
 | 
			
		||||
@ -13,7 +13,7 @@ export default {
 | 
			
		||||
        },
 | 
			
		||||
      },
 | 
			
		||||
    },
 | 
			
		||||
    textarea: {
 | 
			
		||||
    password: {
 | 
			
		||||
      type: 'string',
 | 
			
		||||
      required: true,
 | 
			
		||||
      'x-decorator': 'FormItem',
 | 
			
		||||
@ -27,7 +27,6 @@ export default {
 | 
			
		||||
    },
 | 
			
		||||
    actions: {
 | 
			
		||||
      type: 'void',
 | 
			
		||||
      // 'x-decorator': 'Div',
 | 
			
		||||
      'x-component': 'Div',
 | 
			
		||||
      properties: {
 | 
			
		||||
        submit: {
 | 
			
		||||
 | 
			
		||||
@ -2,15 +2,18 @@ import { uid } from '@formily/shared';
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  type: 'void',
 | 
			
		||||
  name: `m_${uid()}`,
 | 
			
		||||
  name: `menu_${uid()}`,
 | 
			
		||||
  'x-component': 'Menu',
 | 
			
		||||
  'x-designable-bar': 'Menu.DesignableBar',
 | 
			
		||||
  'x-component-props': {
 | 
			
		||||
    mode: 'mix',
 | 
			
		||||
    theme: 'dark',
 | 
			
		||||
    defaultSelectedKeys: '{{ selectedKeys }}',
 | 
			
		||||
    sideMenuRef: '{{ sideMenuRef }}',
 | 
			
		||||
    onSelect: '{{ onSelect }}',
 | 
			
		||||
  },
 | 
			
		||||
  properties: {
 | 
			
		||||
    item2: {
 | 
			
		||||
    [uid()]: {
 | 
			
		||||
      type: 'void',
 | 
			
		||||
      title: `菜单2`,
 | 
			
		||||
      'x-component': 'Menu.Link',
 | 
			
		||||
@ -18,7 +21,7 @@ export default {
 | 
			
		||||
        icon: 'MailOutlined',
 | 
			
		||||
      },
 | 
			
		||||
    },
 | 
			
		||||
    item22: {
 | 
			
		||||
    [uid()]: {
 | 
			
		||||
      type: 'void',
 | 
			
		||||
      title: `菜单22`,
 | 
			
		||||
      'x-component': 'Menu.Link',
 | 
			
		||||
@ -27,15 +30,23 @@ export default {
 | 
			
		||||
        // url: 'https://www.google.com',
 | 
			
		||||
      },
 | 
			
		||||
    },
 | 
			
		||||
    item3: {
 | 
			
		||||
    [uid()]: {
 | 
			
		||||
      type: 'void',
 | 
			
		||||
      title: '菜单组',
 | 
			
		||||
      title: '菜单组1',
 | 
			
		||||
      'x-component': 'Menu.SubMenu',
 | 
			
		||||
      'x-component-props': {
 | 
			
		||||
        icon: 'SettingOutlined',
 | 
			
		||||
      },
 | 
			
		||||
    },
 | 
			
		||||
    [uid()]: {
 | 
			
		||||
      type: 'void',
 | 
			
		||||
      title: '菜单组2',
 | 
			
		||||
      'x-component': 'Menu.SubMenu',
 | 
			
		||||
      'x-component-props': {
 | 
			
		||||
        icon: 'SettingOutlined',
 | 
			
		||||
      },
 | 
			
		||||
      properties: {
 | 
			
		||||
        item6: {
 | 
			
		||||
        [uid()]: {
 | 
			
		||||
          type: 'void',
 | 
			
		||||
          title: '菜单6',
 | 
			
		||||
          'x-component': 'Menu.SubMenu',
 | 
			
		||||
@ -43,55 +54,48 @@ export default {
 | 
			
		||||
            icon: 'AppstoreOutlined',
 | 
			
		||||
          },
 | 
			
		||||
          properties: {
 | 
			
		||||
            item9: {
 | 
			
		||||
            [uid()]: {
 | 
			
		||||
              type: 'void',
 | 
			
		||||
              title: '菜单9',
 | 
			
		||||
              'x-component': 'Menu.SubMenu',
 | 
			
		||||
              properties: {
 | 
			
		||||
                item10: {
 | 
			
		||||
                [uid()]: {
 | 
			
		||||
                  type: 'void',
 | 
			
		||||
                  title: `子菜单10`,
 | 
			
		||||
                  'x-component': 'Menu.Link',
 | 
			
		||||
                  // properties: {
 | 
			
		||||
                  //   action1: {
 | 
			
		||||
                  //     type: 'void',
 | 
			
		||||
                  //     title: '页面标题2',
 | 
			
		||||
                  //     'x-component': 'Action.Page',
 | 
			
		||||
                  //   },
 | 
			
		||||
                  // },
 | 
			
		||||
                },
 | 
			
		||||
                item11: {
 | 
			
		||||
                [uid()]: {
 | 
			
		||||
                  type: 'void',
 | 
			
		||||
                  title: `子菜单11`,
 | 
			
		||||
                  'x-component': 'Menu.Link',
 | 
			
		||||
                },
 | 
			
		||||
              }
 | 
			
		||||
            },
 | 
			
		||||
            item7: {
 | 
			
		||||
            [uid()]: {
 | 
			
		||||
              type: 'void',
 | 
			
		||||
              title: `子菜单7`,
 | 
			
		||||
              'x-component': 'Menu.Link',
 | 
			
		||||
            },
 | 
			
		||||
            item8: {
 | 
			
		||||
            [uid()]: {
 | 
			
		||||
              type: 'void',
 | 
			
		||||
              title: `子菜单8`,
 | 
			
		||||
              'x-component': 'Menu.Link',
 | 
			
		||||
            },
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        item4: {
 | 
			
		||||
        [uid()]: {
 | 
			
		||||
          type: 'void',
 | 
			
		||||
          title: `子菜单1`,
 | 
			
		||||
          'x-component': 'Menu.Link',
 | 
			
		||||
        },
 | 
			
		||||
        item5: {
 | 
			
		||||
        [uid()]: {
 | 
			
		||||
          type: 'void',
 | 
			
		||||
          title: `子菜单2`,
 | 
			
		||||
          'x-component': 'Menu.Link',
 | 
			
		||||
        },
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    item1: {
 | 
			
		||||
    [uid()]: {
 | 
			
		||||
      type: 'void',
 | 
			
		||||
      title: `菜单1`,
 | 
			
		||||
      'x-component': 'Menu.Link',
 | 
			
		||||
 | 
			
		||||
@ -15,6 +15,7 @@ import {
 | 
			
		||||
  FormProvider,
 | 
			
		||||
  useField,
 | 
			
		||||
  useFieldSchema,
 | 
			
		||||
  useForm,
 | 
			
		||||
} from '@formily/react';
 | 
			
		||||
import { observable } from '@formily/reactive';
 | 
			
		||||
import { uid, clone } from '@formily/shared';
 | 
			
		||||
@ -304,8 +305,7 @@ export function useDesignable(path?: any) {
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function useSchemaPath() {
 | 
			
		||||
  const schema = useFieldSchema();
 | 
			
		||||
export function getSchemaPath(schema: Schema) {
 | 
			
		||||
  const path = [schema.name];
 | 
			
		||||
  let parent = schema.parent;
 | 
			
		||||
  while (parent) {
 | 
			
		||||
@ -315,7 +315,13 @@ export function useSchemaPath() {
 | 
			
		||||
    path.unshift(parent.name);
 | 
			
		||||
    parent = parent.parent;
 | 
			
		||||
  }
 | 
			
		||||
  console.log('useSchemaPath', path, schema);
 | 
			
		||||
  console.log('getSchemaPath', path, schema);
 | 
			
		||||
  return [...path];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function useSchemaPath() {
 | 
			
		||||
  const schema = useFieldSchema();
 | 
			
		||||
  const path = getSchemaPath(schema);
 | 
			
		||||
  return [...path];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -325,6 +331,7 @@ export const createDesignableSchemaField = (options) => {
 | 
			
		||||
  const SchemaField = createSchemaField(options);
 | 
			
		||||
 | 
			
		||||
  const DesignableSchemaField = (props) => {
 | 
			
		||||
 | 
			
		||||
    const schema = useMemo(() => new Schema(props.schema), [props.schema]);
 | 
			
		||||
    const [, refresh] = useState(0);
 | 
			
		||||
    if (props.designable === false) {
 | 
			
		||||
@ -340,8 +347,9 @@ export const createDesignableSchemaField = (options) => {
 | 
			
		||||
          },
 | 
			
		||||
        }}
 | 
			
		||||
      >
 | 
			
		||||
        <SchemaField schema={schema} />
 | 
			
		||||
        <SchemaField scope={props.scope} components={props.components} schema={schema} />
 | 
			
		||||
        <CodePreview schema={schema} />
 | 
			
		||||
        <FormValues />
 | 
			
		||||
      </DesignableContext.Provider>
 | 
			
		||||
    );
 | 
			
		||||
  };
 | 
			
		||||
@ -349,11 +357,34 @@ export const createDesignableSchemaField = (options) => {
 | 
			
		||||
  return DesignableSchemaField;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const CodePreview = ({ schema }) => {
 | 
			
		||||
const FormValues = () => {
 | 
			
		||||
  const form = useForm();
 | 
			
		||||
  const [visible, setVisible] = useState(false);
 | 
			
		||||
  return (
 | 
			
		||||
    <>
 | 
			
		||||
      <CodeOutlined onClick={() => setVisible(true)} />
 | 
			
		||||
      <Modal
 | 
			
		||||
        width={'50%'}
 | 
			
		||||
        onOk={() => setVisible(false)}
 | 
			
		||||
        onCancel={() => setVisible(false)}
 | 
			
		||||
        visible={visible}
 | 
			
		||||
      >
 | 
			
		||||
        <Editor
 | 
			
		||||
          height="60vh"
 | 
			
		||||
          defaultLanguage="json"
 | 
			
		||||
          value={JSON.stringify(form.values, null, 2)}
 | 
			
		||||
        />
 | 
			
		||||
        {/* <pre>{JSON.stringify(schema.toJSON(), null, 2)}</pre> */}
 | 
			
		||||
      </Modal>
 | 
			
		||||
    </>
 | 
			
		||||
  );
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const CodePreview = ({ schema }) => {
 | 
			
		||||
  const [visible, setVisible] = useState(false);
 | 
			
		||||
  return (
 | 
			
		||||
    <>
 | 
			
		||||
      <CodeOutlined style={{position: 'relative', zIndex: 100}} onClick={() => setVisible(true)} />
 | 
			
		||||
      <Modal
 | 
			
		||||
        width={'50%'}
 | 
			
		||||
        onOk={() => setVisible(false)}
 | 
			
		||||
@ -387,6 +418,8 @@ export interface SchemaRendererProps {
 | 
			
		||||
  designable?: boolean;
 | 
			
		||||
  onRefresh?: any;
 | 
			
		||||
  onlyRenderProperties?: boolean;
 | 
			
		||||
  scope?: any;
 | 
			
		||||
  components?: any;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const SchemaRenderer = (props: SchemaRendererProps) => {
 | 
			
		||||
@ -415,6 +448,8 @@ export const SchemaRenderer = (props: SchemaRendererProps) => {
 | 
			
		||||
  return (
 | 
			
		||||
    <FormProvider form={form}>
 | 
			
		||||
      <DesignableSchemaField
 | 
			
		||||
        scope={props.scope}
 | 
			
		||||
        components={props.components}
 | 
			
		||||
        onRefresh={props.onRefresh}
 | 
			
		||||
        designable={props.designable}
 | 
			
		||||
        schema={schema}
 | 
			
		||||
 | 
			
		||||
@ -13,11 +13,13 @@ group:
 | 
			
		||||
 | 
			
		||||
操作有三类:
 | 
			
		||||
 | 
			
		||||
- 常规操作
 | 
			
		||||
- 弹出层操作,弹出层有 Drawer、Modal、Popover
 | 
			
		||||
- 指定容器内操作 Container
 | 
			
		||||
- 下拉菜单,用于收纳多种操作
 | 
			
		||||
- 跳转操作
 | 
			
		||||
- 常规操作:Action
 | 
			
		||||
- 弹出层操作,弹出层可以是 Action.Drawer、Action.Modal、Action.Popover
 | 
			
		||||
- 指定容器内打开: Action.Container
 | 
			
		||||
- 下拉菜单:Action.Dropdown,用于收纳多种操作
 | 
			
		||||
- 跳转操作:Action.Link、Action.URL 和 Action.Route
 | 
			
		||||
 | 
			
		||||
Action.Drawer、Action.Modal、Action.Popover 和 Action.Container 需要和 Action 搭配使用
 | 
			
		||||
 | 
			
		||||
## Action - 常规操作
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -106,12 +106,18 @@ const [VisibleProvider, useVisibleContext] = constate((props: any = {}) => {
 | 
			
		||||
export { VisibleProvider, useVisibleContext };
 | 
			
		||||
 | 
			
		||||
const BaseAction = observer((props: any) => {
 | 
			
		||||
  const { useAction = useDefaultAction, ...others } = props;
 | 
			
		||||
  const {
 | 
			
		||||
    ButtonComponent = Button,
 | 
			
		||||
    className,
 | 
			
		||||
    useAction = useDefaultAction,
 | 
			
		||||
    ...others
 | 
			
		||||
  } = props;
 | 
			
		||||
  const field = useField();
 | 
			
		||||
  const { run } = useAction();
 | 
			
		||||
  const { DesignableBar } = useDesignableBar();
 | 
			
		||||
  const { setVisible } = useVisibleContext();
 | 
			
		||||
  const schema = useFieldSchema();
 | 
			
		||||
  // const schema = useFieldSchema();
 | 
			
		||||
  const { schema } = useDesignable();
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
    field.componentProps.setVisible = setVisible;
 | 
			
		||||
  }, []);
 | 
			
		||||
@ -119,17 +125,18 @@ const BaseAction = observer((props: any) => {
 | 
			
		||||
  console.log('BaseAction', { field, schema }, field.title);
 | 
			
		||||
 | 
			
		||||
  const renderButton = () => (
 | 
			
		||||
    <Button
 | 
			
		||||
    <ButtonComponent
 | 
			
		||||
      {...others}
 | 
			
		||||
      className={classNames(className, `name-${schema.name}`)}
 | 
			
		||||
      onClick={async (e) => {
 | 
			
		||||
        e.stopPropagation();
 | 
			
		||||
        e.stopPropagation && e.stopPropagation();
 | 
			
		||||
        setVisible && setVisible(true);
 | 
			
		||||
        await run();
 | 
			
		||||
      }}
 | 
			
		||||
    >
 | 
			
		||||
      {field.title}
 | 
			
		||||
      {schema.title}
 | 
			
		||||
      <DesignableBar />
 | 
			
		||||
    </Button>
 | 
			
		||||
    </ButtonComponent>
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
  const popover = schema.reduceProperties((items, current) => {
 | 
			
		||||
@ -268,6 +275,7 @@ Action.Dropdown = observer((props) => {
 | 
			
		||||
  // const { visible, setVisible } = useVisibleContext();
 | 
			
		||||
  const schema = useFieldSchema();
 | 
			
		||||
  return (
 | 
			
		||||
    <>
 | 
			
		||||
    <Popover
 | 
			
		||||
      // visible={visible}
 | 
			
		||||
      // onVisibleChange={(visible) => {
 | 
			
		||||
@ -281,13 +289,16 @@ Action.Dropdown = observer((props) => {
 | 
			
		||||
    >
 | 
			
		||||
      <Button>{schema.title}</Button>
 | 
			
		||||
    </Popover>
 | 
			
		||||
    {/* popover 的按钮初始化时并未渲染,暂时先这么处理 */}
 | 
			
		||||
    <div style={{display: 'none'}}>{props.children}</div>
 | 
			
		||||
    </>
 | 
			
		||||
  );
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
Action.DesignableBar = () => {
 | 
			
		||||
  const field = useField();
 | 
			
		||||
  const schema = useFieldSchema();
 | 
			
		||||
  const { insertAfter } = useDesignable();
 | 
			
		||||
  // const schema = useFieldSchema();
 | 
			
		||||
  const { schema, insertAfter } = useDesignable();
 | 
			
		||||
  const [visible, setVisible] = useState(false);
 | 
			
		||||
  return (
 | 
			
		||||
    <div className={classNames('designable-bar', { active: visible })}>
 | 
			
		||||
 | 
			
		||||
@ -186,10 +186,15 @@ import { MenuContainerContext } from './';
 | 
			
		||||
import { Layout } from 'antd';
 | 
			
		||||
 | 
			
		||||
export default () => {
 | 
			
		||||
  const ref = useRef();
 | 
			
		||||
  const sideMenuRef = useRef();
 | 
			
		||||
 | 
			
		||||
  const [activeKey, setActiveKey] = useState('item3');
 | 
			
		||||
 | 
			
		||||
  const onSelect = (info) => {
 | 
			
		||||
    setActiveKey(info.key);
 | 
			
		||||
    console.log({ info })
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const schema = {
 | 
			
		||||
    type: 'object',
 | 
			
		||||
    properties: {
 | 
			
		||||
@ -197,13 +202,11 @@ export default () => {
 | 
			
		||||
        type: 'void',
 | 
			
		||||
        'x-component': 'Menu',
 | 
			
		||||
        'x-component-props': {
 | 
			
		||||
          sideMenuRef: '{{ sideMenuRef }}',
 | 
			
		||||
          defaultSelectedKeys: [activeKey],
 | 
			
		||||
          mode: 'mix',
 | 
			
		||||
          theme: 'dark',
 | 
			
		||||
          onSelect(info) {
 | 
			
		||||
            setActiveKey(info.key);
 | 
			
		||||
            console.log({ info })
 | 
			
		||||
          },
 | 
			
		||||
          onSelect: '{{ onSelect }}',
 | 
			
		||||
        },
 | 
			
		||||
        properties: {
 | 
			
		||||
          item1: {
 | 
			
		||||
@ -271,14 +274,13 @@ export default () => {
 | 
			
		||||
    <div>
 | 
			
		||||
      <Layout>
 | 
			
		||||
        <Layout.Header>
 | 
			
		||||
          <MenuContainerContext.Provider value={{
 | 
			
		||||
            sideMenuRef: ref,
 | 
			
		||||
          }}>
 | 
			
		||||
            <SchemaRenderer schema={schema} />
 | 
			
		||||
          </MenuContainerContext.Provider>
 | 
			
		||||
          <SchemaRenderer 
 | 
			
		||||
            schema={schema}
 | 
			
		||||
            scope={{ onSelect, sideMenuRef }}
 | 
			
		||||
          />
 | 
			
		||||
        </Layout.Header>
 | 
			
		||||
        <Layout>
 | 
			
		||||
          <Layout.Sider ref={ref} theme={'light'} width={200}>
 | 
			
		||||
          <Layout.Sider ref={sideMenuRef} theme={'light'} width={200}>
 | 
			
		||||
          </Layout.Sider>
 | 
			
		||||
          <Layout.Content>
 | 
			
		||||
            {activeKey}
 | 
			
		||||
@ -299,10 +301,15 @@ import { MenuContainerContext } from './';
 | 
			
		||||
import { Layout } from 'antd';
 | 
			
		||||
 | 
			
		||||
export default () => {
 | 
			
		||||
  const ref = useRef();
 | 
			
		||||
  const sideMenuRef = useRef();
 | 
			
		||||
 | 
			
		||||
  const [activeKey, setActiveKey] = useState('item3');
 | 
			
		||||
 | 
			
		||||
  const onSelect = (info) => {
 | 
			
		||||
    setActiveKey(info.key);
 | 
			
		||||
    console.log({ info })
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const schema = {
 | 
			
		||||
    type: 'object',
 | 
			
		||||
    properties: {
 | 
			
		||||
@ -314,10 +321,8 @@ export default () => {
 | 
			
		||||
          defaultSelectedKeys: [activeKey],
 | 
			
		||||
          mode: 'mix',
 | 
			
		||||
          theme: 'dark',
 | 
			
		||||
          onSelect(info) {
 | 
			
		||||
            setActiveKey(info.key);
 | 
			
		||||
            console.log({ info })
 | 
			
		||||
          },
 | 
			
		||||
          sideMenuRef: '{{ sideMenuRef }}',
 | 
			
		||||
          onSelect: '{{ onSelect }}',
 | 
			
		||||
        },
 | 
			
		||||
        properties: {
 | 
			
		||||
          item1: {
 | 
			
		||||
@ -385,14 +390,17 @@ export default () => {
 | 
			
		||||
    <div>
 | 
			
		||||
      <Layout>
 | 
			
		||||
        <Layout.Header>
 | 
			
		||||
          <MenuContainerContext.Provider value={{
 | 
			
		||||
            sideMenuRef: ref,
 | 
			
		||||
          }}>
 | 
			
		||||
            <SchemaRenderer schema={schema} />
 | 
			
		||||
          </MenuContainerContext.Provider>
 | 
			
		||||
          <SchemaRenderer
 | 
			
		||||
            schema={schema}
 | 
			
		||||
            scope={{ onSelect, sideMenuRef }}
 | 
			
		||||
          />
 | 
			
		||||
        </Layout.Header>
 | 
			
		||||
        <Layout>
 | 
			
		||||
          <Layout.Sider ref={ref} theme={'light'} width={200}>
 | 
			
		||||
          <Layout.Sider 
 | 
			
		||||
            ref={sideMenuRef}
 | 
			
		||||
            theme={'light'}
 | 
			
		||||
            width={200}
 | 
			
		||||
          >
 | 
			
		||||
          </Layout.Sider>
 | 
			
		||||
          <Layout.Content>
 | 
			
		||||
            {activeKey}
 | 
			
		||||
@ -403,3 +411,82 @@ export default () => {
 | 
			
		||||
  )
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### Menu.Action
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
```tsx
 | 
			
		||||
/**
 | 
			
		||||
 * title: 横向菜单
 | 
			
		||||
 */
 | 
			
		||||
import React from 'react';
 | 
			
		||||
import { SchemaRenderer } from '../';
 | 
			
		||||
 | 
			
		||||
const schema = {
 | 
			
		||||
  type: 'object',
 | 
			
		||||
  properties: {
 | 
			
		||||
    menu1: {
 | 
			
		||||
      type: 'void',
 | 
			
		||||
      'x-component': 'Menu',
 | 
			
		||||
      'x-designable-bar': 'Menu.DesignableBar',
 | 
			
		||||
      'x-component-props': {
 | 
			
		||||
        mode: 'horizontal',
 | 
			
		||||
        theme: 'dark',
 | 
			
		||||
      },
 | 
			
		||||
      properties: {
 | 
			
		||||
        item1: {
 | 
			
		||||
          type: 'void',
 | 
			
		||||
          title: `菜单1`,
 | 
			
		||||
          'x-component': 'Menu.Item',
 | 
			
		||||
        },
 | 
			
		||||
        item2: {
 | 
			
		||||
          type: 'void',
 | 
			
		||||
          title: `菜单1`,
 | 
			
		||||
          'x-component': 'Menu.Action',
 | 
			
		||||
          properties: {
 | 
			
		||||
            drawer1: {
 | 
			
		||||
              type: 'void',
 | 
			
		||||
              title: '抽屉标题',
 | 
			
		||||
              'x-component': 'Action.Drawer',
 | 
			
		||||
              'x-component-props': {},
 | 
			
		||||
              properties: {
 | 
			
		||||
                input: {
 | 
			
		||||
                  type: 'string',
 | 
			
		||||
                  'x-decorator': 'FormItem',
 | 
			
		||||
                  'x-component': 'Input',
 | 
			
		||||
                },
 | 
			
		||||
                action2: {
 | 
			
		||||
                  type: 'void',
 | 
			
		||||
                  title: '打开二级抽屉',
 | 
			
		||||
                  // 'x-decorator': 'FormItem',
 | 
			
		||||
                  'x-component': 'Action',
 | 
			
		||||
                  properties: {
 | 
			
		||||
                    drawer1: {
 | 
			
		||||
                      type: 'void',
 | 
			
		||||
                      title: '二级抽屉标题',
 | 
			
		||||
                      'x-component': 'Action.Drawer',
 | 
			
		||||
                      'x-component-props': {},
 | 
			
		||||
                      properties: {
 | 
			
		||||
                        input: {
 | 
			
		||||
                          type: 'string',
 | 
			
		||||
                          'x-component': 'Input',
 | 
			
		||||
                        },
 | 
			
		||||
                      },
 | 
			
		||||
                    },
 | 
			
		||||
                  },
 | 
			
		||||
                }
 | 
			
		||||
              },
 | 
			
		||||
            },
 | 
			
		||||
          },
 | 
			
		||||
        },
 | 
			
		||||
      },
 | 
			
		||||
    },
 | 
			
		||||
  },
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default () => {
 | 
			
		||||
  return (
 | 
			
		||||
    <SchemaRenderer schema={schema} />
 | 
			
		||||
  );
 | 
			
		||||
};
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
@ -51,10 +51,10 @@ import cls from 'classnames';
 | 
			
		||||
import ReactDOM from 'react-dom';
 | 
			
		||||
import { useMount } from 'ahooks';
 | 
			
		||||
import { useDesignable, SchemaRenderer } from '..';
 | 
			
		||||
import { Router } from "react-router";
 | 
			
		||||
import { Router } from 'react-router';
 | 
			
		||||
 | 
			
		||||
import { useLifecycle } from 'beautiful-react-hooks';
 | 
			
		||||
import { useDefaultAction } from '../action';
 | 
			
		||||
import { Action, useDefaultAction } from '../action';
 | 
			
		||||
 | 
			
		||||
export type MenuType = React.FC<MenuProps & { hideSubMenu?: boolean }> & {
 | 
			
		||||
  Item?: React.FC<MenuItemProps>;
 | 
			
		||||
@ -63,6 +63,7 @@ export type MenuType = React.FC<MenuProps & { hideSubMenu?: boolean }> & {
 | 
			
		||||
  DesignableBar?: React.FC<any>;
 | 
			
		||||
  AddNew?: React.FC<any>;
 | 
			
		||||
  Link?: React.FC<MenuItemProps>;
 | 
			
		||||
  Action?: React.FC<MenuItemProps>;
 | 
			
		||||
  Url?: React.FC<MenuItemProps & { url: string }>;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@ -92,9 +93,9 @@ function useDesignableBar() {
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const Menu: MenuType = observer((props) => {
 | 
			
		||||
  const { onSelect, mode, defaultSelectedKeys, ...others } = props;
 | 
			
		||||
  const { sideMenuRef } = useContext(MenuContainerContext);
 | 
			
		||||
export const Menu: MenuType = observer((props: any) => {
 | 
			
		||||
  const { sideMenuRef, onSelect, mode, defaultSelectedKeys, ...others } = props;
 | 
			
		||||
  let defaultSelectedKey = defaultSelectedKeys ? defaultSelectedKeys[0] : null;
 | 
			
		||||
  const schema = useFieldSchema();
 | 
			
		||||
  const { schema: designableSchema, refresh } = useDesignable();
 | 
			
		||||
  const designableBar = schema['x-designable-bar'];
 | 
			
		||||
@ -109,33 +110,41 @@ export const Menu: MenuType = observer((props) => {
 | 
			
		||||
    if (!sideMenuRef || !sideMenuRef.current) {
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    const properties = schema.properties[selectedKey].properties;
 | 
			
		||||
    console.log({ selectedKey, properties });
 | 
			
		||||
    sideMenuRef.current.style.display = properties ? 'block' : 'none';
 | 
			
		||||
    const subSchema = schema.properties[selectedKey];
 | 
			
		||||
    if (!subSchema) {
 | 
			
		||||
      sideMenuRef.current.style.display = 'none';
 | 
			
		||||
      ReactDOM.render(null, sideMenuRef.current);
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    if (subSchema['x-component'] !== 'Menu.SubMenu') {
 | 
			
		||||
      sideMenuRef.current.style.display = 'none';
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    const properties = subSchema.properties || {};
 | 
			
		||||
    sideMenuRef.current.style.display = 'block';
 | 
			
		||||
    const newProps = {};
 | 
			
		||||
    Object.keys(properties || {}).forEach((name) => {
 | 
			
		||||
      newProps[name] = properties[name].toJSON();
 | 
			
		||||
    });
 | 
			
		||||
    ReactDOM.render(
 | 
			
		||||
      properties ? (
 | 
			
		||||
      <Router history={history}>
 | 
			
		||||
        <SchemaRenderer
 | 
			
		||||
          key={`${Math.random()}`}
 | 
			
		||||
          onRefresh={(subSchema: Schema) => {
 | 
			
		||||
            const selected = designableSchema.properties[selectedKey];
 | 
			
		||||
            const diff = subSchema.properties[`${schema.name}.${selectedKey}`];
 | 
			
		||||
            Object.keys(selected.properties).forEach((name) => {
 | 
			
		||||
            Object.keys(selected.properties || {}).forEach((name) => {
 | 
			
		||||
              selected.properties[name].parent.removeProperty(name);
 | 
			
		||||
            });
 | 
			
		||||
            Object.keys(diff.properties).forEach((name) => {
 | 
			
		||||
              if (name.endsWith('-add-new')) {
 | 
			
		||||
                return;
 | 
			
		||||
              }
 | 
			
		||||
              console.log('diff', name)
 | 
			
		||||
              console.log('diff', name);
 | 
			
		||||
              const current = diff.properties[name];
 | 
			
		||||
              selected.addProperty(current.name, current.toJSON());
 | 
			
		||||
            });
 | 
			
		||||
            console.log({selected })
 | 
			
		||||
            console.log({ selected });
 | 
			
		||||
            refresh();
 | 
			
		||||
          }}
 | 
			
		||||
          schema={{
 | 
			
		||||
@ -155,15 +164,13 @@ export const Menu: MenuType = observer((props) => {
 | 
			
		||||
              },
 | 
			
		||||
            },
 | 
			
		||||
          }}
 | 
			
		||||
        /></Router>
 | 
			
		||||
      ) : null,
 | 
			
		||||
        />
 | 
			
		||||
      </Router>,
 | 
			
		||||
      sideMenuRef.current,
 | 
			
		||||
    );
 | 
			
		||||
  };
 | 
			
		||||
  useMount(() => {
 | 
			
		||||
    const defaultSelectedKey = defaultSelectedKeys
 | 
			
		||||
      ? defaultSelectedKeys[0]
 | 
			
		||||
      : null;
 | 
			
		||||
    console.log({ defaultSelectedKey }, schema.properties);
 | 
			
		||||
    renderSideMenu(defaultSelectedKey);
 | 
			
		||||
  });
 | 
			
		||||
  return (
 | 
			
		||||
@ -197,13 +204,16 @@ const AddNewAction = () => {
 | 
			
		||||
      trigger={['click']}
 | 
			
		||||
      overlay={
 | 
			
		||||
        <AntdMenu>
 | 
			
		||||
          <AntdMenu.Item onClick={() => {
 | 
			
		||||
          <AntdMenu.Item
 | 
			
		||||
            onClick={() => {
 | 
			
		||||
              insertBefore({
 | 
			
		||||
                type: 'void',
 | 
			
		||||
                title: uid(),
 | 
			
		||||
              "x-component": 'Menu.Item',
 | 
			
		||||
            })
 | 
			
		||||
          }} style={{ minWidth: 150 }}>
 | 
			
		||||
                'x-component': 'Menu.Item',
 | 
			
		||||
              });
 | 
			
		||||
            }}
 | 
			
		||||
            style={{ minWidth: 150 }}
 | 
			
		||||
          >
 | 
			
		||||
            <MenuOutlined /> 新建菜单
 | 
			
		||||
          </AntdMenu.Item>
 | 
			
		||||
          <AntdMenu.Item>
 | 
			
		||||
@ -298,6 +308,25 @@ Menu.Item = observer((props: any) => {
 | 
			
		||||
  );
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
Menu.Action = observer((props: any) => {
 | 
			
		||||
  const { icon, ...others } = props;
 | 
			
		||||
  const schema = useFieldSchema();
 | 
			
		||||
  const { DesignableBar } = useDesignableBar();
 | 
			
		||||
  return (
 | 
			
		||||
    <Action
 | 
			
		||||
      // @ts-ignore
 | 
			
		||||
      eventKey={schema.name}
 | 
			
		||||
      key={schema.name}
 | 
			
		||||
      icon={icon ? <Icon type={icon as string} /> : undefined}
 | 
			
		||||
      ButtonComponent={AntdMenu.Item}
 | 
			
		||||
      {...others}
 | 
			
		||||
    />
 | 
			
		||||
    // <Action {...others}/>
 | 
			
		||||
    // <DesignableBar />
 | 
			
		||||
    // </AntdMenu.Item>
 | 
			
		||||
  );
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
Menu.SubMenu = observer((props) => {
 | 
			
		||||
  const { DesignableBar } = useDesignableBar();
 | 
			
		||||
  const schema = useFieldSchema();
 | 
			
		||||
@ -372,11 +401,13 @@ Menu.DesignableBar = (props) => {
 | 
			
		||||
                  const title = uid();
 | 
			
		||||
                  field.title = title;
 | 
			
		||||
                  field.componentProps['icon'] = 'DeleteOutlined';
 | 
			
		||||
                  schema['x-component-props'] = schema['x-component-props'] || {};
 | 
			
		||||
                  schema['x-component-props'] =
 | 
			
		||||
                    schema['x-component-props'] || {};
 | 
			
		||||
                  schema['x-component-props']['icon'] = 'DeleteOutlined';
 | 
			
		||||
                  schema.title = title;
 | 
			
		||||
                  fieldSchema.title = title;
 | 
			
		||||
                  fieldSchema['x-component-props'] = fieldSchema['x-component-props'] || {};
 | 
			
		||||
                  fieldSchema['x-component-props'] =
 | 
			
		||||
                    fieldSchema['x-component-props'] || {};
 | 
			
		||||
                  fieldSchema['x-component-props']['icon'] = 'DeleteOutlined';
 | 
			
		||||
                  refresh();
 | 
			
		||||
                }}
 | 
			
		||||
@ -396,6 +427,9 @@ Menu.DesignableBar = (props) => {
 | 
			
		||||
              >
 | 
			
		||||
                <DeleteOutlined /> 删除菜单
 | 
			
		||||
              </AntdMenu.Item>
 | 
			
		||||
              <AntdMenu.Item>
 | 
			
		||||
                <ModalButton />
 | 
			
		||||
              </AntdMenu.Item>
 | 
			
		||||
            </AntdMenu>
 | 
			
		||||
          }
 | 
			
		||||
        >
 | 
			
		||||
@ -406,4 +440,27 @@ Menu.DesignableBar = (props) => {
 | 
			
		||||
  );
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
function ModalButton() {
 | 
			
		||||
  const [visible, setVisible] = useState(false);
 | 
			
		||||
  return (
 | 
			
		||||
    <>
 | 
			
		||||
      <div
 | 
			
		||||
        onClick={() => {
 | 
			
		||||
          setVisible(true);
 | 
			
		||||
        }}
 | 
			
		||||
      >
 | 
			
		||||
        按钮
 | 
			
		||||
      </div>
 | 
			
		||||
      <Modal
 | 
			
		||||
        visible={visible}
 | 
			
		||||
        onCancel={() => {
 | 
			
		||||
          setVisible(false);
 | 
			
		||||
        }}
 | 
			
		||||
      >
 | 
			
		||||
        aaa
 | 
			
		||||
      </Modal>
 | 
			
		||||
    </>
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default Menu;
 | 
			
		||||
 | 
			
		||||
@ -35,10 +35,12 @@
 | 
			
		||||
    left: 0;
 | 
			
		||||
    bottom: 0;
 | 
			
		||||
    border: 2px solid #1890ff;
 | 
			
		||||
    pointer-events: none;
 | 
			
		||||
    &.active {
 | 
			
		||||
      display: block;
 | 
			
		||||
    }
 | 
			
		||||
    .designable-bar-actions {
 | 
			
		||||
      pointer-events: auto;
 | 
			
		||||
      position: absolute;
 | 
			
		||||
      right: 0;
 | 
			
		||||
      line-height: 1rem;
 | 
			
		||||
@ -61,3 +63,15 @@
 | 
			
		||||
    border: 2px solid #1890ff;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.ant-menu-title-content {
 | 
			
		||||
  .ant-btn {
 | 
			
		||||
    background: none;
 | 
			
		||||
    border: 0;
 | 
			
		||||
    border-radius: 0;
 | 
			
		||||
    color: inherit;
 | 
			
		||||
    padding: 0 20px;
 | 
			
		||||
    height: 100%;
 | 
			
		||||
    margin: 0 -20px;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@ -14,7 +14,7 @@ function useAction() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const schema = {
 | 
			
		||||
  name: `t_${uid()}`,
 | 
			
		||||
  name: `table_${uid()}`,
 | 
			
		||||
  type: 'array',
 | 
			
		||||
  'x-component': 'Table',
 | 
			
		||||
  // default: [
 | 
			
		||||
@ -36,7 +36,7 @@ const schema = {
 | 
			
		||||
    // isRemoteDataSource: true,
 | 
			
		||||
  },
 | 
			
		||||
  properties: {
 | 
			
		||||
    [`a_${uid()}`]: {
 | 
			
		||||
    [`action_bar_${uid()}`]: {
 | 
			
		||||
      type: 'void',
 | 
			
		||||
      'x-component': 'Table.ActionBar',
 | 
			
		||||
      properties: {
 | 
			
		||||
@ -132,22 +132,22 @@ const schema = {
 | 
			
		||||
        },
 | 
			
		||||
      },
 | 
			
		||||
    },
 | 
			
		||||
    [`a_${uid()}`]: {
 | 
			
		||||
      type: 'void',
 | 
			
		||||
      'x-component': 'Table.ActionBar',
 | 
			
		||||
      'x-component-props': {
 | 
			
		||||
        align: 'bottom',
 | 
			
		||||
      },
 | 
			
		||||
      properties: {
 | 
			
		||||
        pagination: {
 | 
			
		||||
          type: 'void',
 | 
			
		||||
          'x-component': 'Table.Pagination',
 | 
			
		||||
          'x-component-props': {
 | 
			
		||||
            defaultPageSize: 5,
 | 
			
		||||
          },
 | 
			
		||||
        },
 | 
			
		||||
      },
 | 
			
		||||
    },
 | 
			
		||||
    // [`a_${uid()}`]: {
 | 
			
		||||
    //   type: 'void',
 | 
			
		||||
    //   'x-component': 'Table.ActionBar',
 | 
			
		||||
    //   'x-component-props': {
 | 
			
		||||
    //     align: 'bottom',
 | 
			
		||||
    //   },
 | 
			
		||||
    //   properties: {
 | 
			
		||||
    //     pagination: {
 | 
			
		||||
    //       type: 'void',
 | 
			
		||||
    //       'x-component': 'Table.Pagination',
 | 
			
		||||
    //       'x-component-props': {
 | 
			
		||||
    //         defaultPageSize: 5,
 | 
			
		||||
    //       },
 | 
			
		||||
    //     },
 | 
			
		||||
    //   },
 | 
			
		||||
    // },
 | 
			
		||||
    [`a_${uid()}`]: {
 | 
			
		||||
      type: 'void',
 | 
			
		||||
      'x-component': 'Table.ActionBar',
 | 
			
		||||
@ -163,7 +163,7 @@ const schema = {
 | 
			
		||||
        },
 | 
			
		||||
      },
 | 
			
		||||
    },
 | 
			
		||||
    [`c_${uid()}`]: {
 | 
			
		||||
    [`column_${uid()}`]: {
 | 
			
		||||
      type: 'void',
 | 
			
		||||
      title: '排序',
 | 
			
		||||
      'x-component': 'Table.Column',
 | 
			
		||||
@ -174,7 +174,7 @@ const schema = {
 | 
			
		||||
        },
 | 
			
		||||
      },
 | 
			
		||||
    },
 | 
			
		||||
    [`c_${uid()}`]: {
 | 
			
		||||
    [`column_${uid()}`]: {
 | 
			
		||||
      type: 'void',
 | 
			
		||||
      title: '序号',
 | 
			
		||||
      'x-component': 'Table.Column',
 | 
			
		||||
@ -185,7 +185,7 @@ const schema = {
 | 
			
		||||
        },
 | 
			
		||||
      },
 | 
			
		||||
    },
 | 
			
		||||
    [`c_${uid()}`]: {
 | 
			
		||||
    [`column_${uid()}`]: {
 | 
			
		||||
      type: 'void',
 | 
			
		||||
      title: '字段1',
 | 
			
		||||
      'x-component': 'Table.Column',
 | 
			
		||||
@ -197,7 +197,7 @@ const schema = {
 | 
			
		||||
        field1: {
 | 
			
		||||
          type: 'string',
 | 
			
		||||
          required: true,
 | 
			
		||||
          // 'x-read-pretty': true,
 | 
			
		||||
          'x-read-pretty': true,
 | 
			
		||||
          'x-decorator-props': {
 | 
			
		||||
            feedbackLayout: 'popover',
 | 
			
		||||
          },
 | 
			
		||||
@ -206,16 +206,17 @@ const schema = {
 | 
			
		||||
        },
 | 
			
		||||
      },
 | 
			
		||||
    },
 | 
			
		||||
    [`c_${uid()}`]: {
 | 
			
		||||
    [`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-read-pretty': true,
 | 
			
		||||
          'x-decorator-props': {
 | 
			
		||||
            feedbackLayout: 'popover',
 | 
			
		||||
          },
 | 
			
		||||
@ -224,18 +225,18 @@ const schema = {
 | 
			
		||||
        },
 | 
			
		||||
      },
 | 
			
		||||
    },
 | 
			
		||||
    [`col_${uid()}`]: {
 | 
			
		||||
    [`column_${uid()}`]: {
 | 
			
		||||
      type: 'void',
 | 
			
		||||
      title: '操作',
 | 
			
		||||
      'x-component': 'Table.Column',
 | 
			
		||||
      properties: {
 | 
			
		||||
        action1: {
 | 
			
		||||
        [uid()]: {
 | 
			
		||||
          type: 'void',
 | 
			
		||||
          name: 'action1',
 | 
			
		||||
          title: '查看',
 | 
			
		||||
          
 | 
			
		||||
          'x-component': 'Action',
 | 
			
		||||
          'x-default-action': true,
 | 
			
		||||
          'x-designable-bar': 'Action.DesignableBar',
 | 
			
		||||
          'x-designable-bar': 'Table.Action.DesignableBar',
 | 
			
		||||
          properties: {
 | 
			
		||||
            drawer1: {
 | 
			
		||||
              type: 'void',
 | 
			
		||||
@ -285,13 +286,12 @@ const schema = {
 | 
			
		||||
            },
 | 
			
		||||
          },
 | 
			
		||||
        },
 | 
			
		||||
        action2: {
 | 
			
		||||
        [uid()]: {
 | 
			
		||||
          type: 'void',
 | 
			
		||||
          name: 'action1',
 | 
			
		||||
          title: '修改',
 | 
			
		||||
          'x-component': 'Action',
 | 
			
		||||
          'x-default-action': true,
 | 
			
		||||
          'x-designable-bar': 'Action.DesignableBar',
 | 
			
		||||
          'x-designable-bar': 'Table.Action.DesignableBar',
 | 
			
		||||
          properties: {
 | 
			
		||||
            drawer1: {
 | 
			
		||||
              type: 'void',
 | 
			
		||||
@ -333,7 +333,7 @@ const schema = {
 | 
			
		||||
            },
 | 
			
		||||
          },
 | 
			
		||||
        },
 | 
			
		||||
        action3: {
 | 
			
		||||
        [uid()]: {
 | 
			
		||||
          type: 'void',
 | 
			
		||||
          title: '删除',
 | 
			
		||||
          'x-component': 'Action',
 | 
			
		||||
@ -341,12 +341,12 @@ const schema = {
 | 
			
		||||
            useAction: '{{ useTableDestroyAction }}',
 | 
			
		||||
          },
 | 
			
		||||
        },
 | 
			
		||||
        action4: {
 | 
			
		||||
        [uid()]: {
 | 
			
		||||
          type: 'void',
 | 
			
		||||
          title: '...',
 | 
			
		||||
          'x-component': 'Action.Dropdown',
 | 
			
		||||
          properties: {
 | 
			
		||||
            action5: {
 | 
			
		||||
            [uid()]: {
 | 
			
		||||
              type: 'void',
 | 
			
		||||
              title: '操作 1',
 | 
			
		||||
              'x-component': 'Action',
 | 
			
		||||
@ -355,21 +355,22 @@ const schema = {
 | 
			
		||||
                disabled: true,
 | 
			
		||||
              },
 | 
			
		||||
            },
 | 
			
		||||
            action4: {
 | 
			
		||||
            [uid()]: {
 | 
			
		||||
              type: 'void',
 | 
			
		||||
              title: '操作 2',
 | 
			
		||||
              'x-component': 'Action',
 | 
			
		||||
              'x-default-action': true,
 | 
			
		||||
              'x-component-props': {
 | 
			
		||||
                useAction,
 | 
			
		||||
              },
 | 
			
		||||
            },
 | 
			
		||||
            action1: {
 | 
			
		||||
            [uid()]: {
 | 
			
		||||
              type: 'void',
 | 
			
		||||
              name: 'action1',
 | 
			
		||||
              title: '查看',
 | 
			
		||||
              'x-component': 'Action',
 | 
			
		||||
              // 'x-default-action': true,
 | 
			
		||||
              'x-designable-bar': 'Action.DesignableBar',
 | 
			
		||||
              'x-designable-bar': 'Table.Action.DesignableBar',
 | 
			
		||||
              properties: {
 | 
			
		||||
                drawer1: {
 | 
			
		||||
                  type: 'void',
 | 
			
		||||
@ -419,13 +420,12 @@ const schema = {
 | 
			
		||||
                },
 | 
			
		||||
              },
 | 
			
		||||
            },
 | 
			
		||||
            action2: {
 | 
			
		||||
            [uid()]: {
 | 
			
		||||
              type: 'void',
 | 
			
		||||
              name: 'action1',
 | 
			
		||||
              title: '修改',
 | 
			
		||||
              'x-component': 'Action',
 | 
			
		||||
              'x-default-action': true,
 | 
			
		||||
              'x-designable-bar': 'Action.DesignableBar',
 | 
			
		||||
              'x-designable-bar': 'Table.Action.DesignableBar',
 | 
			
		||||
              properties: {
 | 
			
		||||
                drawer1: {
 | 
			
		||||
                  type: 'void',
 | 
			
		||||
@ -467,7 +467,7 @@ const schema = {
 | 
			
		||||
                },
 | 
			
		||||
              },
 | 
			
		||||
            },
 | 
			
		||||
            action3: {
 | 
			
		||||
            [uid()]: {
 | 
			
		||||
              type: 'void',
 | 
			
		||||
              title: '删除',
 | 
			
		||||
              'x-component': 'Action',
 | 
			
		||||
@ -482,17 +482,14 @@ const schema = {
 | 
			
		||||
  },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const form = createForm();
 | 
			
		||||
const form = createForm({
 | 
			
		||||
  // designable: true,
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
export default observer(() => {
 | 
			
		||||
  return (
 | 
			
		||||
    <div>
 | 
			
		||||
      <SchemaRenderer form={form} schema={schema} />
 | 
			
		||||
      {/* <Editor
 | 
			
		||||
        height="200px"
 | 
			
		||||
        defaultLanguage="json"
 | 
			
		||||
        value={JSON.stringify(form.values, null, 2)}
 | 
			
		||||
      /> */}
 | 
			
		||||
    </div>
 | 
			
		||||
  );
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
@ -8,6 +8,7 @@ import {
 | 
			
		||||
  useForm,
 | 
			
		||||
  FormProvider,
 | 
			
		||||
  createSchemaField,
 | 
			
		||||
  SchemaOptionsContext,
 | 
			
		||||
} from '@formily/react';
 | 
			
		||||
import {
 | 
			
		||||
  Button,
 | 
			
		||||
@ -16,24 +17,32 @@ import {
 | 
			
		||||
  Space,
 | 
			
		||||
  Spin,
 | 
			
		||||
  Table as AntdTable,
 | 
			
		||||
  Dropdown,
 | 
			
		||||
  Menu,
 | 
			
		||||
} from 'antd';
 | 
			
		||||
import { findIndex } from 'lodash';
 | 
			
		||||
import { findIndex, get } 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 } from '@ant-design/icons';
 | 
			
		||||
import { useVisibleContext } from '../action';
 | 
			
		||||
import { SortableHandle, SortableContainer, SortableElement } from 'react-sortable-hoc'
 | 
			
		||||
import {
 | 
			
		||||
  SortableHandle,
 | 
			
		||||
  SortableContainer,
 | 
			
		||||
  SortableElement,
 | 
			
		||||
} from 'react-sortable-hoc';
 | 
			
		||||
import cls from 'classnames';
 | 
			
		||||
import { getSchemaPath, useDesignable, useSchemaPath } from '../DesignableSchemaField';
 | 
			
		||||
import './style.less';
 | 
			
		||||
 | 
			
		||||
interface TableRowProps {
 | 
			
		||||
  index: number;
 | 
			
		||||
  data: any;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const SortableRow = SortableElement((props: any) => <tr {...props} />)
 | 
			
		||||
const SortableBody = SortableContainer((props: any) => <tbody {...props} />)
 | 
			
		||||
const SortableRow = SortableElement((props: any) => <tr {...props} />);
 | 
			
		||||
const SortableBody = SortableContainer((props: any) => <tbody {...props} />);
 | 
			
		||||
 | 
			
		||||
const TableRowContext = createContext<TableRowProps>(null);
 | 
			
		||||
 | 
			
		||||
@ -105,7 +114,8 @@ function useTableActionBars() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function useTableColumns(props?: any) {
 | 
			
		||||
  const schema = useFieldSchema();
 | 
			
		||||
  const { schema } = useDesignable();
 | 
			
		||||
  // const schema = useFieldSchema();
 | 
			
		||||
  const { dataSource } = props || {};
 | 
			
		||||
 | 
			
		||||
  function findColumns(schema: Schema): Schema[] {
 | 
			
		||||
@ -120,7 +130,7 @@ function useTableColumns(props?: any) {
 | 
			
		||||
  return findColumns(schema).map((item) => {
 | 
			
		||||
    const columnProps = item['x-component-props'] || {};
 | 
			
		||||
    return {
 | 
			
		||||
      title: item.title,
 | 
			
		||||
      title: <RecursionField name={item.name} schema={item} onlyRenderSelf />,
 | 
			
		||||
      dataIndex: item.name,
 | 
			
		||||
      ...columnProps,
 | 
			
		||||
      render(value, record, recordIndex) {
 | 
			
		||||
@ -282,23 +292,22 @@ const TableContainer = observer((props) => {
 | 
			
		||||
    useTableContext();
 | 
			
		||||
  const rowKey = field.componentProps.rowKey || 'id';
 | 
			
		||||
  const defaultAction = useDefaultAction();
 | 
			
		||||
  console.log({ defaultAction });
 | 
			
		||||
  const dataSource = Array.isArray(field.value) ? field.value.slice() : [];
 | 
			
		||||
  const columns = useTableColumns({ dataSource });
 | 
			
		||||
  const ref = useRef<HTMLDivElement>()
 | 
			
		||||
  const ref = useRef<HTMLDivElement>();
 | 
			
		||||
  const addTdStyles = (node: HTMLElement) => {
 | 
			
		||||
    const helper = document.body.querySelector(`.nb-table-sort-helper`)
 | 
			
		||||
    const helper = document.body.querySelector(`.nb-table-sort-helper`);
 | 
			
		||||
    if (helper) {
 | 
			
		||||
      const tds = node.querySelectorAll('td')
 | 
			
		||||
      const tds = node.querySelectorAll('td');
 | 
			
		||||
      requestAnimationFrame(() => {
 | 
			
		||||
        helper.querySelectorAll('td').forEach((td, index) => {
 | 
			
		||||
          if (tds[index]) {
 | 
			
		||||
            td.style.width = getComputedStyle(tds[index]).width
 | 
			
		||||
          }
 | 
			
		||||
        })
 | 
			
		||||
      })
 | 
			
		||||
            td.style.width = getComputedStyle(tds[index]).width;
 | 
			
		||||
          }
 | 
			
		||||
        });
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
  return (
 | 
			
		||||
    <div ref={ref} className={'nb-table'}>
 | 
			
		||||
      {actionBars.top.map((actionBarSchema) => {
 | 
			
		||||
@ -339,10 +348,10 @@ const TableContainer = observer((props) => {
 | 
			
		||||
                // disableAutoscroll
 | 
			
		||||
                helperClass={`nb-table-sort-helper`}
 | 
			
		||||
                helperContainer={() => {
 | 
			
		||||
                  return ref.current?.querySelector('tbody')
 | 
			
		||||
                  return ref.current?.querySelector('tbody');
 | 
			
		||||
                }}
 | 
			
		||||
                onSortStart={({ node }) => {
 | 
			
		||||
                  addTdStyles(node)
 | 
			
		||||
                  addTdStyles(node);
 | 
			
		||||
                }}
 | 
			
		||||
                onSortEnd={({ oldIndex, newIndex }) => {
 | 
			
		||||
                  field.move(oldIndex, newIndex);
 | 
			
		||||
@ -352,13 +361,11 @@ const TableContainer = observer((props) => {
 | 
			
		||||
              />
 | 
			
		||||
            ),
 | 
			
		||||
            row: (props: any) => {
 | 
			
		||||
              const index = findIndex(field.value, item => item[rowKey] === props['data-row-key']);
 | 
			
		||||
              return (
 | 
			
		||||
                <SortableRow
 | 
			
		||||
                  index={index}
 | 
			
		||||
                  {...props}
 | 
			
		||||
                />
 | 
			
		||||
              )
 | 
			
		||||
              const index = findIndex(
 | 
			
		||||
                field.value,
 | 
			
		||||
                (item) => item[rowKey] === props['data-row-key'],
 | 
			
		||||
              );
 | 
			
		||||
              return <SortableRow index={index} {...props} />;
 | 
			
		||||
            },
 | 
			
		||||
          },
 | 
			
		||||
        }}
 | 
			
		||||
@ -366,20 +373,17 @@ const TableContainer = observer((props) => {
 | 
			
		||||
          const index = dataSource.indexOf(data);
 | 
			
		||||
          return {
 | 
			
		||||
            onClick(e) {
 | 
			
		||||
              console.log('onRow', (e.target as HTMLElement), (e.target as HTMLElement).classList.contains('ant-table-cell'));
 | 
			
		||||
              if (!(e.target as HTMLElement).classList.contains('ant-table-cell')) {
 | 
			
		||||
                return;
 | 
			
		||||
              }
 | 
			
		||||
              if (!defaultAction) {
 | 
			
		||||
                return;
 | 
			
		||||
              }
 | 
			
		||||
              // console.log('defaultAction');
 | 
			
		||||
              field
 | 
			
		||||
                .query(`.${schema.name}.${index}.${defaultAction.name}`)
 | 
			
		||||
                .take((f) => {
 | 
			
		||||
                  const setVisible = f.componentProps.setVisible;
 | 
			
		||||
                  setVisible && setVisible(true);
 | 
			
		||||
                });
 | 
			
		||||
              const el = (e.target as HTMLElement);
 | 
			
		||||
              if (
 | 
			
		||||
                !el.classList.contains('ant-table-cell')
 | 
			
		||||
              ) {
 | 
			
		||||
                return;
 | 
			
		||||
              }
 | 
			
		||||
              const btn = el.parentElement.querySelector<HTMLElement>(`.name-${defaultAction.name}`);
 | 
			
		||||
              btn && btn.click();
 | 
			
		||||
            },
 | 
			
		||||
          };
 | 
			
		||||
        }}
 | 
			
		||||
@ -411,7 +415,99 @@ export const Table: any = observer((props) => {
 | 
			
		||||
  );
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
Table.Column = () => null;
 | 
			
		||||
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.Column = observer((props) => {
 | 
			
		||||
  const schema = useFieldSchema();
 | 
			
		||||
  const field = useField();
 | 
			
		||||
  console.log('Table.Column', schema, field.title);
 | 
			
		||||
  const { DesignableBar } = useDesignableBar();
 | 
			
		||||
  return (
 | 
			
		||||
    <div className={'nb-table-column'}>
 | 
			
		||||
      {field.title}
 | 
			
		||||
      <DesignableBar />
 | 
			
		||||
    </div>
 | 
			
		||||
  );
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
Table.Column.DesignableBar = () => {
 | 
			
		||||
  const field = useField();
 | 
			
		||||
  // const fieldSchema = useFieldSchema();
 | 
			
		||||
  const { schema, remove, refresh, insertAfter } = useDesignable();
 | 
			
		||||
  const [visible, setVisible] = useState(false);
 | 
			
		||||
  console.log('Table.Column.DesignableBar', { schema });
 | 
			
		||||
  return (
 | 
			
		||||
    <div className={cls('designable-bar', { active: visible })}>
 | 
			
		||||
      <span
 | 
			
		||||
        onClick={(e) => {
 | 
			
		||||
          e.stopPropagation();
 | 
			
		||||
        }}
 | 
			
		||||
        className={cls('designable-bar-actions', { active: visible })}
 | 
			
		||||
      >
 | 
			
		||||
        <Dropdown
 | 
			
		||||
          trigger={['click']}
 | 
			
		||||
          visible={visible}
 | 
			
		||||
          onVisibleChange={(visible) => {
 | 
			
		||||
            setVisible(visible);
 | 
			
		||||
          }}
 | 
			
		||||
          overlay={
 | 
			
		||||
            <Menu>
 | 
			
		||||
              <Menu.Item onClick={(e) => {
 | 
			
		||||
                const title = uid();
 | 
			
		||||
                field.title = title;
 | 
			
		||||
                schema.title = title;
 | 
			
		||||
                setVisible(false);
 | 
			
		||||
              }}>点击修改按钮文案</Menu.Item>
 | 
			
		||||
              <Menu.Item onClick={() => {
 | 
			
		||||
                remove();
 | 
			
		||||
                console.log('Table.Column.DesignableBar', { schema });
 | 
			
		||||
              }}>删除列</Menu.Item>
 | 
			
		||||
              <Menu.Item onClick={() => {
 | 
			
		||||
                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',
 | 
			
		||||
                    },
 | 
			
		||||
                  },
 | 
			
		||||
                })
 | 
			
		||||
              }}>插入列</Menu.Item>
 | 
			
		||||
            </Menu>
 | 
			
		||||
          }
 | 
			
		||||
        >
 | 
			
		||||
          <MenuOutlined />
 | 
			
		||||
        </Dropdown>
 | 
			
		||||
      </span>
 | 
			
		||||
    </div>
 | 
			
		||||
  );
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
Table.ActionBar = observer((props) => {
 | 
			
		||||
  return (
 | 
			
		||||
@ -447,17 +543,20 @@ const SortHandle = SortableHandle((props: any) => {
 | 
			
		||||
      className={cls(`nb-table-sort-handle`, props.className)}
 | 
			
		||||
      style={{ ...props.style }}
 | 
			
		||||
    />
 | 
			
		||||
  )
 | 
			
		||||
}) as any
 | 
			
		||||
  );
 | 
			
		||||
}) as any;
 | 
			
		||||
 | 
			
		||||
Table.SortHandle = observer((props) => {
 | 
			
		||||
  const field = useField<Formily.Core.Models.Field>();
 | 
			
		||||
  console.log('SortHandle', field.value);
 | 
			
		||||
  return <SortHandle {...props}/>;
 | 
			
		||||
  return <SortHandle {...props} />;
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
Table.Index = observer((props) => {
 | 
			
		||||
  const index = useTableIndex();
 | 
			
		||||
  const schema = useFieldSchema();
 | 
			
		||||
  const field = useField<Formily.Core.Models.Field>();
 | 
			
		||||
  const path = useSchemaPath();
 | 
			
		||||
  return <div>#{index + 1}</div>;
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
@ -484,3 +583,41 @@ Table.Addition = observer((props: any) => {
 | 
			
		||||
    </Button>
 | 
			
		||||
  );
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
Table.Action = () => null;
 | 
			
		||||
 | 
			
		||||
Table.Action.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 (
 | 
			
		||||
    <div className={cls('designable-bar', { active: visible })}>
 | 
			
		||||
      <span
 | 
			
		||||
        onClick={(e) => {
 | 
			
		||||
          e.stopPropagation();
 | 
			
		||||
        }}
 | 
			
		||||
        className={cls('designable-bar-actions', { active: visible })}
 | 
			
		||||
      >
 | 
			
		||||
        <Dropdown
 | 
			
		||||
          trigger={['click']}
 | 
			
		||||
          visible={visible}
 | 
			
		||||
          onVisibleChange={(visible) => {
 | 
			
		||||
            setVisible(visible);
 | 
			
		||||
          }}
 | 
			
		||||
          overlay={
 | 
			
		||||
            <Menu>
 | 
			
		||||
              <Menu.Item onClick={(e) => {
 | 
			
		||||
                schema.title = uid();
 | 
			
		||||
                refresh();
 | 
			
		||||
              }}>点击修改按钮文案</Menu.Item>
 | 
			
		||||
            </Menu>
 | 
			
		||||
          }
 | 
			
		||||
        >
 | 
			
		||||
          <MenuOutlined />
 | 
			
		||||
        </Dropdown>
 | 
			
		||||
      </span>
 | 
			
		||||
    </div>
 | 
			
		||||
  );
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										61
									
								
								packages/client/src/schemas/table/style.less
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								packages/client/src/schemas/table/style.less
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,61 @@
 | 
			
		||||
.nb-table-column {
 | 
			
		||||
  &:hover {
 | 
			
		||||
    > .designable-bar {
 | 
			
		||||
      display: block;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  > .designable-bar {
 | 
			
		||||
    display: none;
 | 
			
		||||
    position: absolute;
 | 
			
		||||
    top: 0;
 | 
			
		||||
    right: 0;
 | 
			
		||||
    left: 0;
 | 
			
		||||
    bottom: 0;
 | 
			
		||||
    border-radius: 0;
 | 
			
		||||
    border: 2px solid #1890ff;
 | 
			
		||||
    &.active {
 | 
			
		||||
      display: block;
 | 
			
		||||
    }
 | 
			
		||||
    .designable-bar-actions {
 | 
			
		||||
      position: absolute;
 | 
			
		||||
      right: 0;
 | 
			
		||||
      line-height: 1rem;
 | 
			
		||||
      background-color: #1890ff;
 | 
			
		||||
      color: #fff;
 | 
			
		||||
      z-index: 10;
 | 
			
		||||
      padding: 0 3px;
 | 
			
		||||
      .anticon {
 | 
			
		||||
        font-size: 10px;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.ant-popover.nb-action-group {
 | 
			
		||||
  z-index: 1000;
 | 
			
		||||
  padding-top: 0;
 | 
			
		||||
  .ant-popover-arrow {
 | 
			
		||||
    display: none;
 | 
			
		||||
  }
 | 
			
		||||
  .ant-popover-inner-content {
 | 
			
		||||
    padding: 4px 0;
 | 
			
		||||
    .ant-btn {
 | 
			
		||||
      display: block;
 | 
			
		||||
      min-width: 100px;
 | 
			
		||||
      width: 100%;
 | 
			
		||||
      border: 0;
 | 
			
		||||
      border-radius: 0;
 | 
			
		||||
      text-align: left;
 | 
			
		||||
      padding: 5px 12px;
 | 
			
		||||
      color: #000;
 | 
			
		||||
      &:hover {
 | 
			
		||||
        background-color: #f5f5f5;
 | 
			
		||||
      }
 | 
			
		||||
      &[disabled] {
 | 
			
		||||
        color: #00000040;
 | 
			
		||||
        background-color:#fff;
 | 
			
		||||
        cursor:not-allowed;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@ -161,33 +161,36 @@ function Database() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function LayoutWithMenu({ schema }) {
 | 
			
		||||
  const match = useRouteMatch<any>();
 | 
			
		||||
  const location = useLocation();
 | 
			
		||||
  const ref = useRef();
 | 
			
		||||
  const [activeKey, setActiveKey] = useState('item3');
 | 
			
		||||
  schema['x-component-props']['defaultSelectedKeys'] = [activeKey];
 | 
			
		||||
  schema['x-component-props']['onSelect'] = (info) => {
 | 
			
		||||
    console.log('LayoutWithMenu', schema)
 | 
			
		||||
  const sideMenuRef = useRef();
 | 
			
		||||
  const [activeKey, setActiveKey] = useState(match.params.name);
 | 
			
		||||
  const onSelect = (info) => {
 | 
			
		||||
    console.log('LayoutWithMenu', schema);
 | 
			
		||||
    setActiveKey(info.key);
 | 
			
		||||
  }
 | 
			
		||||
  };
 | 
			
		||||
  console.log({ match });
 | 
			
		||||
  return (
 | 
			
		||||
    <Layout>
 | 
			
		||||
      <Layout.Header>
 | 
			
		||||
          <MenuContainerContext.Provider value={{
 | 
			
		||||
            sideMenuRef: ref,
 | 
			
		||||
          }}>
 | 
			
		||||
            <SchemaRenderer schema={schema} />
 | 
			
		||||
          </MenuContainerContext.Provider>
 | 
			
		||||
        <SchemaRenderer
 | 
			
		||||
          schema={schema}
 | 
			
		||||
          scope={{ sideMenuRef, onSelect, selectedKeys: [activeKey].filter(Boolean) }}
 | 
			
		||||
        />
 | 
			
		||||
      </Layout.Header>
 | 
			
		||||
      <Layout>
 | 
			
		||||
          <Layout.Sider ref={ref} theme={'light'} width={200}>
 | 
			
		||||
          </Layout.Sider>
 | 
			
		||||
        <Layout.Sider
 | 
			
		||||
          ref={sideMenuRef}
 | 
			
		||||
          theme={'light'}
 | 
			
		||||
          width={200}
 | 
			
		||||
        ></Layout.Sider>
 | 
			
		||||
        <Layout.Content>
 | 
			
		||||
          {location.pathname}
 | 
			
		||||
            <Content activeKey={activeKey}/>
 | 
			
		||||
          <Content activeKey={activeKey} />
 | 
			
		||||
        </Layout.Content>
 | 
			
		||||
      </Layout>
 | 
			
		||||
    </Layout>
 | 
			
		||||
  )
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function Content({ activeKey }) {
 | 
			
		||||
@ -207,7 +210,6 @@ function Content({ activeKey }) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function AdminLayout({ route, children }: any) {
 | 
			
		||||
  const match = useRouteMatch<any>();
 | 
			
		||||
 | 
			
		||||
  const { data = {}, loading } = useRequest(
 | 
			
		||||
    `/api/blocks:getSchema/${route.blockId}`,
 | 
			
		||||
@ -220,9 +222,7 @@ export function AdminLayout({ route, children }: any) {
 | 
			
		||||
    return <Spin />;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <LayoutWithMenu schema={data}/>
 | 
			
		||||
  );
 | 
			
		||||
  return <LayoutWithMenu schema={data} />;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default AdminLayout;
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user