update docs
This commit is contained in:
parent
e50267d64c
commit
03da153052
@ -1,27 +0,0 @@
|
|||||||
---
|
|
||||||
title: API - 接口
|
|
||||||
nav:
|
|
||||||
title: 组件
|
|
||||||
path: /client
|
|
||||||
order: 99
|
|
||||||
group:
|
|
||||||
order: 3
|
|
||||||
title: 其他
|
|
||||||
path: /client/others
|
|
||||||
---
|
|
||||||
|
|
||||||
# API - 接口
|
|
||||||
|
|
||||||
## setGlobalState
|
|
||||||
|
|
||||||
## setGlobalActionState
|
|
||||||
|
|
||||||
## useGlobalState
|
|
||||||
|
|
||||||
## useGlobalAction
|
|
||||||
|
|
||||||
## refreshGlobalAction
|
|
||||||
|
|
||||||
## useAction
|
|
||||||
|
|
||||||
## doAction
|
|
@ -1,110 +0,0 @@
|
|||||||
---
|
|
||||||
title: Drawer - 抽屉
|
|
||||||
nav:
|
|
||||||
title: 组件
|
|
||||||
path: /client
|
|
||||||
group:
|
|
||||||
order: 3
|
|
||||||
title: 其他
|
|
||||||
path: /client/others
|
|
||||||
---
|
|
||||||
|
|
||||||
# Drawer - 抽屉
|
|
||||||
|
|
||||||
通过 `Drawer.open(props)` 方法打开抽屉,无需预渲染,可在触发事件中使用。
|
|
||||||
|
|
||||||
### 基础抽屉
|
|
||||||
|
|
||||||
```tsx
|
|
||||||
/**
|
|
||||||
* title: 基础抽屉
|
|
||||||
*/
|
|
||||||
import React from 'react';
|
|
||||||
import { Button } from 'antd';
|
|
||||||
import Drawer from './index.tsx';
|
|
||||||
|
|
||||||
export default () => (
|
|
||||||
<Button onClick={() => {
|
|
||||||
Drawer.open({
|
|
||||||
title: 'Basic Drawer',
|
|
||||||
content: () => {
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<p>Some contents...</p>
|
|
||||||
<p>Some contents...</p>
|
|
||||||
<p>Some contents...</p>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}}>Open Drawer</Button>
|
|
||||||
);
|
|
||||||
```
|
|
||||||
|
|
||||||
### 多层抽屉
|
|
||||||
|
|
||||||
```tsx
|
|
||||||
/**
|
|
||||||
* title: 多层抽屉
|
|
||||||
* desc: 有多少层就执行多少个 `Drawer.open(props)`
|
|
||||||
*/
|
|
||||||
import React from 'react';
|
|
||||||
import { Button } from 'antd';
|
|
||||||
import Drawer from './index.tsx';
|
|
||||||
|
|
||||||
export default () => (
|
|
||||||
<Button onClick={() => {
|
|
||||||
Drawer.open({
|
|
||||||
title: 'Multi-level drawer',
|
|
||||||
content: () => {
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<Button onClick={() => {
|
|
||||||
Drawer.open({
|
|
||||||
title: 'Two-level Drawer',
|
|
||||||
content: () => {
|
|
||||||
return (
|
|
||||||
<div>This is two-level drawer</div>
|
|
||||||
)
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}}>Two-level Drawer</Button>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}}>Open drawer</Button>
|
|
||||||
);
|
|
||||||
```
|
|
||||||
|
|
||||||
### 关闭时提示
|
|
||||||
|
|
||||||
```tsx
|
|
||||||
/**
|
|
||||||
* title: 关闭时提示
|
|
||||||
* desc: 通过 `closeWithConfirm(props)` 方法触发,更多参数请参考 `Modal.confirm`
|
|
||||||
*/
|
|
||||||
import React from 'react';
|
|
||||||
import { Button } from 'antd';
|
|
||||||
import Drawer from './index.tsx';
|
|
||||||
|
|
||||||
export default () => (
|
|
||||||
<Button onClick={() => {
|
|
||||||
Drawer.open({
|
|
||||||
title: 'Basic Drawer',
|
|
||||||
content: ({ closeWithConfirm }) => {
|
|
||||||
closeWithConfirm({
|
|
||||||
title: '您确定关闭抽屉吗?'
|
|
||||||
});
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<p>Some contents...</p>
|
|
||||||
<p>Some contents...</p>
|
|
||||||
<p>Some contents...</p>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}}>Open Drawer</Button>
|
|
||||||
);
|
|
||||||
```
|
|
@ -1,206 +0,0 @@
|
|||||||
import React, { Fragment, useLayoutEffect, useRef, useState } from 'react';
|
|
||||||
import ReactDOM, { createPortal } from 'react-dom';
|
|
||||||
import { Modal, Drawer as AntdDrawer } from 'antd';
|
|
||||||
import { DrawerProps } from 'antd/lib/drawer';
|
|
||||||
import { useContext } from 'react';
|
|
||||||
import { ConfigProvider } from 'antd';
|
|
||||||
import zhCN from 'antd/lib/locale/zh_CN';
|
|
||||||
import { ModalFuncProps } from 'antd/lib/modal/Modal'
|
|
||||||
import isNum from 'lodash/isNumber';
|
|
||||||
import isBool from 'lodash/isBoolean';
|
|
||||||
import isStr from 'lodash/isString';
|
|
||||||
import './style.less';
|
|
||||||
|
|
||||||
export const usePrefixCls = (
|
|
||||||
tag?: string,
|
|
||||||
props?: {
|
|
||||||
prefixCls?: string;
|
|
||||||
},
|
|
||||||
) => {
|
|
||||||
const { getPrefixCls } = useContext(ConfigProvider.ConfigContext);
|
|
||||||
return getPrefixCls(tag, props?.prefixCls);
|
|
||||||
};
|
|
||||||
|
|
||||||
type DrawerTitle = string | number | React.ReactElement;
|
|
||||||
|
|
||||||
const isDrawerTitle = (props: any): props is DrawerTitle => {
|
|
||||||
return (
|
|
||||||
isNum(props) || isStr(props) || isBool(props) || React.isValidElement(props)
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const getDrawerProps = (props: any): DrawerProps => {
|
|
||||||
if (isDrawerTitle(props)) {
|
|
||||||
return {
|
|
||||||
title: props,
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
return props;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const createElement = (content, props?: any) => {
|
|
||||||
if (!content) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
if (typeof content === 'string') {
|
|
||||||
return content;
|
|
||||||
}
|
|
||||||
if (React.isValidElement(content)) {
|
|
||||||
return content;
|
|
||||||
}
|
|
||||||
return React.createElement(content, props);
|
|
||||||
};
|
|
||||||
|
|
||||||
export interface IDrawer {
|
|
||||||
open(props?: any): void;
|
|
||||||
close(): void;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function Drawer(title: DrawerProps, content: any): IDrawer;
|
|
||||||
export function Drawer(title: DrawerTitle, content: any): IDrawer;
|
|
||||||
export function Drawer(title: any, content: any): IDrawer {
|
|
||||||
document.querySelectorAll('.env-root').forEach((el) => {
|
|
||||||
el.className = 'env-root env-root-push';
|
|
||||||
});
|
|
||||||
const env = {
|
|
||||||
root: document.createElement('div'),
|
|
||||||
promise: null,
|
|
||||||
};
|
|
||||||
env.root.className = 'env-root';
|
|
||||||
const props = getDrawerProps(title);
|
|
||||||
const drawerProps = {
|
|
||||||
width: '75%',
|
|
||||||
...props,
|
|
||||||
onClose: (e: any) => {
|
|
||||||
props?.onClose?.(e);
|
|
||||||
drawer.close();
|
|
||||||
},
|
|
||||||
afterVisibleChange: (visible: boolean) => {
|
|
||||||
props?.afterVisibleChange?.(visible);
|
|
||||||
if (visible) return;
|
|
||||||
ReactDOM.unmountComponentAtNode(env.root);
|
|
||||||
env.root?.parentNode?.removeChild(env.root);
|
|
||||||
env.root = undefined;
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const drawer: any = {
|
|
||||||
open: (props: any) => {
|
|
||||||
render(
|
|
||||||
false,
|
|
||||||
() => {
|
|
||||||
drawer.closeWithConfirm = null;
|
|
||||||
drawer.close();
|
|
||||||
},
|
|
||||||
() => {
|
|
||||||
drawer.close();
|
|
||||||
},
|
|
||||||
);
|
|
||||||
setTimeout(() => {
|
|
||||||
render(
|
|
||||||
true,
|
|
||||||
() => {
|
|
||||||
drawer.closeWithConfirm = null;
|
|
||||||
drawer.close();
|
|
||||||
},
|
|
||||||
() => {
|
|
||||||
drawer.close();
|
|
||||||
},
|
|
||||||
);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
close: () => {
|
|
||||||
if (!env.root) return;
|
|
||||||
if (drawer.closeWithConfirm) {
|
|
||||||
Modal.confirm({
|
|
||||||
okText: '确定',
|
|
||||||
cancelText: '取消',
|
|
||||||
...drawer.closeWithConfirm,
|
|
||||||
onOk() {
|
|
||||||
drawer.closeWithConfirm = null;
|
|
||||||
const els = document.querySelectorAll('.env-root-push');
|
|
||||||
if (els.length) {
|
|
||||||
const last = els[els.length - 1];
|
|
||||||
last.className = 'env-root';
|
|
||||||
}
|
|
||||||
render(false);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
const els = document.querySelectorAll('.env-root-push');
|
|
||||||
if (els.length) {
|
|
||||||
const last = els[els.length - 1];
|
|
||||||
last.className = 'env-root';
|
|
||||||
}
|
|
||||||
render(false);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
closeWithConfirm: null,
|
|
||||||
};
|
|
||||||
|
|
||||||
const closeWithConfirm = (props) => {
|
|
||||||
drawer.closeWithConfirm = props;
|
|
||||||
};
|
|
||||||
|
|
||||||
const render = (visible = true, resolve?: () => any, reject?: () => any) => {
|
|
||||||
ReactDOM.render(
|
|
||||||
<ConfigProvider locale={zhCN}>
|
|
||||||
<AntdDrawer {...drawerProps} className={'nb-drawer'} visible={visible}>
|
|
||||||
{createElement(content, {
|
|
||||||
resolve,
|
|
||||||
reject,
|
|
||||||
closeWithConfirm,
|
|
||||||
})}
|
|
||||||
</AntdDrawer>
|
|
||||||
</ConfigProvider>,
|
|
||||||
env.root,
|
|
||||||
);
|
|
||||||
};
|
|
||||||
document.body.appendChild(env.root);
|
|
||||||
|
|
||||||
return drawer;
|
|
||||||
}
|
|
||||||
|
|
||||||
const DrawerFooter: React.FC = (props) => {
|
|
||||||
const ref = useRef<HTMLDivElement>();
|
|
||||||
const [footer, setFooter] = useState<HTMLDivElement>();
|
|
||||||
const footerRef = useRef<HTMLDivElement>();
|
|
||||||
const prefixCls = usePrefixCls('drawer');
|
|
||||||
useLayoutEffect(() => {
|
|
||||||
const content = ref.current?.closest(`.${prefixCls}-wrapper-body`);
|
|
||||||
if (content) {
|
|
||||||
if (!footerRef.current) {
|
|
||||||
footerRef.current = content.querySelector(`.${prefixCls}-footer`);
|
|
||||||
if (!footerRef.current) {
|
|
||||||
footerRef.current = document.createElement('div');
|
|
||||||
footerRef.current.classList.add(`${prefixCls}-footer`);
|
|
||||||
content.appendChild(footerRef.current);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
setFooter(footerRef.current);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
footerRef.current = footer;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div ref={ref} style={{ display: 'none' }}>
|
|
||||||
{footer && createPortal(props.children, footer)}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
interface ContentPorps {
|
|
||||||
resolve?: () => any;
|
|
||||||
closeWithConfirm?: (props: ModalFuncProps) => any;
|
|
||||||
}
|
|
||||||
|
|
||||||
Drawer.open = (props: DrawerProps & { content: (contentPorps?: ContentPorps) => any }) => {
|
|
||||||
const { content, visible, ...others } = props;
|
|
||||||
return Drawer(others, content).open({ visible });
|
|
||||||
};
|
|
||||||
|
|
||||||
Drawer.Footer = DrawerFooter;
|
|
||||||
|
|
||||||
export default Drawer;
|
|
@ -1,18 +0,0 @@
|
|||||||
.env-root-push + style + div > div {
|
|
||||||
transform: translateX(-10%);
|
|
||||||
}
|
|
||||||
.env-root-push + div > div {
|
|
||||||
transform: translateX(-10%);
|
|
||||||
}
|
|
||||||
.ant-drawer.nb-drawer .ant-drawer-content-wrapper {
|
|
||||||
width: 75%;
|
|
||||||
max-width: 1000px;
|
|
||||||
}
|
|
||||||
@media only screen and (max-width: 800px) {
|
|
||||||
.ant-drawer.nb-drawer .ant-drawer-content-wrapper {
|
|
||||||
width: 100% !important;
|
|
||||||
}
|
|
||||||
.ant-drawer.noco-drawer .ant-drawer-content-wrapper {
|
|
||||||
width: 100% !important;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,14 +0,0 @@
|
|||||||
---
|
|
||||||
title: AdminLayout - 后台布局
|
|
||||||
nav:
|
|
||||||
title: 组件
|
|
||||||
path: /client
|
|
||||||
group:
|
|
||||||
order: 2
|
|
||||||
title: Templates
|
|
||||||
path: /client/templates
|
|
||||||
---
|
|
||||||
|
|
||||||
# AdminLayout - 后台布局
|
|
||||||
|
|
||||||
内置的后台布局模板,提供了基础的菜单和路由切换。
|
|
@ -1,14 +0,0 @@
|
|||||||
---
|
|
||||||
title: AuthLayout - 登录布局
|
|
||||||
nav:
|
|
||||||
title: 组件
|
|
||||||
path: /client
|
|
||||||
group:
|
|
||||||
order: 2
|
|
||||||
title: Templates
|
|
||||||
path: /client/templates
|
|
||||||
---
|
|
||||||
|
|
||||||
# AuthLayout - 登录布局
|
|
||||||
|
|
||||||
内置的登录、注册页布局
|
|
14
packages/client/src/demo.md
Normal file
14
packages/client/src/demo.md
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
---
|
||||||
|
title: 全站演示
|
||||||
|
nav:
|
||||||
|
title: 组件
|
||||||
|
path: /client
|
||||||
|
toc: menu
|
||||||
|
group:
|
||||||
|
order: 0
|
||||||
|
title: 概念
|
||||||
|
path: /client
|
||||||
|
---
|
||||||
|
|
||||||
|
<code src="./demos/demo1.tsx"/>
|
||||||
|
|
@ -1,14 +1,14 @@
|
|||||||
---
|
---
|
||||||
title: 全站演示
|
title: 介绍
|
||||||
nav:
|
nav:
|
||||||
title: 组件
|
title: 组件
|
||||||
path: /client
|
path: /client
|
||||||
toc: menu
|
toc: menu
|
||||||
group:
|
group:
|
||||||
order: 0
|
order: 0
|
||||||
title: 全站演示
|
title: 概念
|
||||||
path: /client
|
path: /client
|
||||||
---
|
---
|
||||||
|
|
||||||
<code src="./demos/demo1.tsx"/>
|
# 介绍
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ import { uid, clone } from '@formily/shared';
|
|||||||
import { ArrayCollapse, ArrayTable, FormLayout } from '@formily/antd';
|
import { ArrayCollapse, ArrayTable, FormLayout } from '@formily/antd';
|
||||||
|
|
||||||
import { Space, Card, Modal, Spin } from 'antd';
|
import { Space, Card, Modal, Spin } from 'antd';
|
||||||
import { Action, useLogin, useRegister, useSubmit } from '../action';
|
import { Action, useLogin, useRegister, useSubmit, useDesignableValues } from '../action';
|
||||||
import { AddNew } from '../add-new';
|
import { AddNew } from '../add-new';
|
||||||
import { Cascader } from '../cascader';
|
import { Cascader } from '../cascader';
|
||||||
import { Checkbox } from '../checkbox';
|
import { Checkbox } from '../checkbox';
|
||||||
@ -73,6 +73,7 @@ export const scope = {
|
|||||||
useTableFilterAction,
|
useTableFilterAction,
|
||||||
useTableRow,
|
useTableRow,
|
||||||
useTableUpdateAction,
|
useTableUpdateAction,
|
||||||
|
useDesignableValues,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const components = {
|
export const components = {
|
||||||
@ -363,8 +364,8 @@ export const createDesignableSchemaField = (options) => {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<SchemaField scope={props.scope} components={props.components} schema={schema} />
|
<SchemaField scope={props.scope} components={props.components} schema={schema} />
|
||||||
<CodePreview schema={schema} />
|
{props.debug && <CodePreview schema={schema} />}
|
||||||
<FormValues />
|
{props.debug && <FormValues />}
|
||||||
</DesignableContext.Provider>
|
</DesignableContext.Provider>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@ -435,6 +436,7 @@ export interface SchemaRendererProps {
|
|||||||
onlyRenderProperties?: boolean;
|
onlyRenderProperties?: boolean;
|
||||||
scope?: any;
|
scope?: any;
|
||||||
components?: any;
|
components?: any;
|
||||||
|
debug?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const SchemaRenderer = (props: SchemaRendererProps) => {
|
export const SchemaRenderer = (props: SchemaRendererProps) => {
|
||||||
@ -463,6 +465,7 @@ export const SchemaRenderer = (props: SchemaRendererProps) => {
|
|||||||
return (
|
return (
|
||||||
<FormProvider form={form}>
|
<FormProvider form={form}>
|
||||||
<DesignableSchemaField
|
<DesignableSchemaField
|
||||||
|
debug={props.debug}
|
||||||
scope={props.scope}
|
scope={props.scope}
|
||||||
components={props.components}
|
components={props.components}
|
||||||
onRefresh={props.onRefresh}
|
onRefresh={props.onRefresh}
|
||||||
|
61
packages/client/src/schemas/action/designableBar.tsx
Normal file
61
packages/client/src/schemas/action/designableBar.tsx
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
import { ISchema } from '@formily/react';
|
||||||
|
import {
|
||||||
|
useDesignableValues,
|
||||||
|
useDesignableUpdate,
|
||||||
|
useDesignableSchemaRemove,
|
||||||
|
} from '.';
|
||||||
|
|
||||||
|
export const DesignableBar: { [key: string]: ISchema } = {};
|
||||||
|
|
||||||
|
DesignableBar.Action = {
|
||||||
|
name: 'bar',
|
||||||
|
type: 'void',
|
||||||
|
// title: '操作栏2',
|
||||||
|
'x-component': 'Action.Dropdown',
|
||||||
|
'x-component-props': {
|
||||||
|
icon: 'MenuOutlined',
|
||||||
|
},
|
||||||
|
properties: {
|
||||||
|
edit: {
|
||||||
|
type: 'void',
|
||||||
|
title: '编辑按钮',
|
||||||
|
'x-component': 'Action',
|
||||||
|
'x-component-props': {
|
||||||
|
// icon,
|
||||||
|
},
|
||||||
|
properties: {
|
||||||
|
modal: {
|
||||||
|
type: 'void',
|
||||||
|
title: '修改按钮配置',
|
||||||
|
'x-decorator': 'Form',
|
||||||
|
'x-decorator-props': {
|
||||||
|
useValues: useDesignableValues,
|
||||||
|
},
|
||||||
|
'x-component': 'Action.Modal',
|
||||||
|
'x-component-props': {
|
||||||
|
width: '500px',
|
||||||
|
useAction: useDesignableUpdate,
|
||||||
|
},
|
||||||
|
properties: {
|
||||||
|
title: {
|
||||||
|
type: 'string',
|
||||||
|
title: '按钮标题',
|
||||||
|
required: true,
|
||||||
|
'x-component': 'Input',
|
||||||
|
'x-decorator': 'FormItem',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
remove: {
|
||||||
|
type: 'void',
|
||||||
|
title: '删除按钮',
|
||||||
|
'x-component': 'Action',
|
||||||
|
'x-component-props': {
|
||||||
|
useAction: useDesignableSchemaRemove,
|
||||||
|
// icon,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
@ -11,8 +11,7 @@ group:
|
|||||||
|
|
||||||
# Action - 操作
|
# Action - 操作
|
||||||
|
|
||||||
|
## Node Tree
|
||||||
## 组件节点树
|
|
||||||
|
|
||||||
<pre lang="tsx">
|
<pre lang="tsx">
|
||||||
////////// 单节点 //////////
|
////////// 单节点 //////////
|
||||||
@ -67,17 +66,16 @@ group:
|
|||||||
</Action.Dropdown>
|
</Action.Dropdown>
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
操作有三类:
|
## Designable Bar
|
||||||
|
|
||||||
- 常规操作:Action
|
- Action.DesignableBar
|
||||||
- 弹出层操作,弹出层可以是 Action.Drawer、Action.Modal、Action.Popover
|
- Action.Modal.DesignableBar
|
||||||
- 指定容器内打开: Action.Container
|
- Action.Drawer.DesignableBar
|
||||||
- 下拉菜单:Action.Dropdown,用于收纳多种操作
|
- Action.Popover.DesignableBar
|
||||||
- 跳转操作:Action.Link、Action.URL
|
|
||||||
|
|
||||||
Action.Drawer、Action.Modal、Action.Popover 和 Action.Container 需要和 Action 搭配使用
|
## Examples
|
||||||
|
|
||||||
## Action - 常规操作
|
### Action - 常规操作
|
||||||
|
|
||||||
```tsx
|
```tsx
|
||||||
/**
|
/**
|
||||||
@ -100,17 +98,18 @@ const schema = {
|
|||||||
name: 'action1',
|
name: 'action1',
|
||||||
title: '按钮',
|
title: '按钮',
|
||||||
'x-component': 'Action',
|
'x-component': 'Action',
|
||||||
|
'x-designable-bar': 'Action.DesignableBar',
|
||||||
'x-component-props': {
|
'x-component-props': {
|
||||||
useAction,
|
useAction: '{{ useAction }}',
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export default () => {
|
export default () => {
|
||||||
return <SchemaRenderer schema={schema} />
|
return <SchemaRenderer debug={true} scope={{ useAction }} schema={schema} />
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## Action.Link - 内链跳转
|
### Action.Link - 内链跳转
|
||||||
|
|
||||||
```tsx
|
```tsx
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
@ -131,7 +130,7 @@ export default () => {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## Action.URL - 外链跳转
|
### Action.URL - 外链跳转
|
||||||
|
|
||||||
```tsx
|
```tsx
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
@ -152,7 +151,7 @@ export default () => {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## Action.Dropdown - 下拉操作
|
### Action.Dropdown - 下拉操作
|
||||||
|
|
||||||
```tsx
|
```tsx
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
@ -253,7 +252,7 @@ export default () => {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## Action.Popover - 打开气泡
|
### Action.Popover - 打开气泡
|
||||||
|
|
||||||
```tsx
|
```tsx
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
@ -285,7 +284,7 @@ export default () => {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## Action.Drawer - 打开抽屉
|
### Action.Drawer - 打开抽屉
|
||||||
|
|
||||||
```tsx
|
```tsx
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
@ -338,10 +337,13 @@ export default () => {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## Action.Modal - 打开对话框
|
### Action.Modal - 打开对话框
|
||||||
|
|
||||||
|
`x-decorator='Form'` 时,Model 为 Form,并自带按钮
|
||||||
|
|
||||||
```tsx
|
```tsx
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { Space } from 'antd';
|
||||||
import { SchemaRenderer } from '../';
|
import { SchemaRenderer } from '../';
|
||||||
import { useVisibleContext } from './';
|
import { useVisibleContext } from './';
|
||||||
|
|
||||||
@ -406,12 +408,40 @@ const schema = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const schema2 = {
|
||||||
|
type: 'void',
|
||||||
|
name: 'action1',
|
||||||
|
title: 'x-decorator=Form',
|
||||||
|
'x-component': 'Action',
|
||||||
|
properties: {
|
||||||
|
drawer1: {
|
||||||
|
type: 'void',
|
||||||
|
title: '弹窗标题',
|
||||||
|
'x-component': 'Action.Modal',
|
||||||
|
'x-component-props': {},
|
||||||
|
'x-decorator': 'Form',
|
||||||
|
properties: {
|
||||||
|
input: {
|
||||||
|
type: 'string',
|
||||||
|
'x-decorator': 'FormItem',
|
||||||
|
'x-component': 'Input',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
export default () => {
|
export default () => {
|
||||||
return <SchemaRenderer schema={schema} />
|
return (
|
||||||
|
<Space>
|
||||||
|
<SchemaRenderer schema={schema} />
|
||||||
|
<SchemaRenderer schema={schema2} />
|
||||||
|
</Space>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## Action.Container - 指定容器内打开
|
### Action.Container - 指定容器内打开
|
||||||
|
|
||||||
```tsx
|
```tsx
|
||||||
import React, { useRef } from 'react';
|
import React, { useRef } from 'react';
|
||||||
|
@ -9,6 +9,7 @@ import {
|
|||||||
SchemaOptionsContext,
|
SchemaOptionsContext,
|
||||||
Schema,
|
Schema,
|
||||||
useField,
|
useField,
|
||||||
|
SchemaExpressionScopeContext,
|
||||||
} from '@formily/react';
|
} from '@formily/react';
|
||||||
import { Button, Dropdown, Menu, Popover, Space, Drawer, Modal } from 'antd';
|
import { Button, Dropdown, Menu, Popover, Space, Drawer, Modal } from 'antd';
|
||||||
import { Link, useHistory, LinkProps } from 'react-router-dom';
|
import { Link, useHistory, LinkProps } from 'react-router-dom';
|
||||||
@ -22,6 +23,9 @@ import { uid } from '@formily/shared';
|
|||||||
|
|
||||||
import './style.less';
|
import './style.less';
|
||||||
import constate from 'constate';
|
import constate from 'constate';
|
||||||
|
import { Icon } from '../icon-picker';
|
||||||
|
import { useMemo } from 'react';
|
||||||
|
import { createForm } from '@formily/core';
|
||||||
|
|
||||||
export function useDefaultAction() {
|
export function useDefaultAction() {
|
||||||
return {
|
return {
|
||||||
@ -109,6 +113,7 @@ const BaseAction = observer((props: any) => {
|
|||||||
const {
|
const {
|
||||||
ButtonComponent = Button,
|
ButtonComponent = Button,
|
||||||
className,
|
className,
|
||||||
|
icon,
|
||||||
useAction = useDefaultAction,
|
useAction = useDefaultAction,
|
||||||
...others
|
...others
|
||||||
} = props;
|
} = props;
|
||||||
@ -122,11 +127,10 @@ const BaseAction = observer((props: any) => {
|
|||||||
field.componentProps.setVisible = setVisible;
|
field.componentProps.setVisible = setVisible;
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
console.log('BaseAction', { field, schema, fieldSchema }, field.title);
|
|
||||||
|
|
||||||
const renderButton = () => (
|
const renderButton = () => (
|
||||||
<ButtonComponent
|
<ButtonComponent
|
||||||
{...others}
|
{...others}
|
||||||
|
icon={<Icon type={icon} />}
|
||||||
className={classNames(className, `name-${schema.name}`)}
|
className={classNames(className, `name-${schema.name}`)}
|
||||||
onClick={async (e) => {
|
onClick={async (e) => {
|
||||||
e.stopPropagation && e.stopPropagation();
|
e.stopPropagation && e.stopPropagation();
|
||||||
@ -227,7 +231,24 @@ Action.Popover = observer((props) => {
|
|||||||
|
|
||||||
Action.Drawer = observer((props) => {
|
Action.Drawer = observer((props) => {
|
||||||
const field = useField();
|
const field = useField();
|
||||||
|
// const { visible, setVisible } = useVisibleContext();
|
||||||
|
const { useAction = () => ({ async run() {} }), ...others } = props;
|
||||||
|
const { schema } = useDesignable();
|
||||||
const { visible, setVisible } = useVisibleContext();
|
const { visible, setVisible } = useVisibleContext();
|
||||||
|
const { run } = useAction();
|
||||||
|
const form = useForm();
|
||||||
|
console.log(`schema['x-decorator']`, schema['x-decorator'])
|
||||||
|
if (schema['x-decorator'] === 'Form.Decorator') {
|
||||||
|
Object.assign(others, {
|
||||||
|
footer: (
|
||||||
|
<Space>
|
||||||
|
<Button type={'primary'}>Ok</Button>
|
||||||
|
<Button>Cancel</Button>
|
||||||
|
</Space>
|
||||||
|
),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Drawer
|
<Drawer
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
@ -235,7 +256,7 @@ Action.Drawer = observer((props) => {
|
|||||||
}}
|
}}
|
||||||
title={field.title}
|
title={field.title}
|
||||||
width={'50%'}
|
width={'50%'}
|
||||||
{...props}
|
{...others}
|
||||||
visible={visible}
|
visible={visible}
|
||||||
onClose={(e) => {
|
onClose={(e) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
@ -247,103 +268,142 @@ Action.Drawer = observer((props) => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const [DesignableContextProvider, useDesignableContext] = constate(() => {
|
||||||
|
return useDesignable();
|
||||||
|
});
|
||||||
|
|
||||||
|
import { DesignableBar } from './designableBar';
|
||||||
|
import { cloneDeep } from 'lodash';
|
||||||
|
import { clone } from '@formily/shared';
|
||||||
|
|
||||||
|
export function useDesignableValues() {
|
||||||
|
const { schema } = useDesignableContext();
|
||||||
|
return schema
|
||||||
|
? {
|
||||||
|
title: schema.title,
|
||||||
|
}
|
||||||
|
: {};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useDesignableUpdate() {
|
||||||
|
const { schema, refresh } = useDesignableContext();
|
||||||
|
const form = useForm();
|
||||||
|
return {
|
||||||
|
async run() {
|
||||||
|
schema.title = form.values.title;
|
||||||
|
refresh();
|
||||||
|
console.log('useDesignableUpdate', schema, form.values);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useDesignableSchemaRemove() {
|
||||||
|
const { schema, refresh, remove } = useDesignableContext();
|
||||||
|
return {
|
||||||
|
async run() {
|
||||||
|
remove();
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
Action.Modal = observer((props) => {
|
Action.Modal = observer((props) => {
|
||||||
const field = useField();
|
const { useAction = () => ({ async run() {} }), ...others } = props;
|
||||||
|
const { schema } = useDesignable();
|
||||||
|
const { setVisible: setDropdownVisible } = useDropdownVisibleContext();
|
||||||
const { visible, setVisible } = useVisibleContext();
|
const { visible, setVisible } = useVisibleContext();
|
||||||
|
const { run } = useAction();
|
||||||
|
const form = useForm();
|
||||||
|
if (schema['x-decorator'] !== 'Form.Decorator') {
|
||||||
|
Object.assign(others, { footer: null });
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
// onClick={e => {
|
title={schema.title}
|
||||||
// e.stopPropagation();
|
|
||||||
// }}
|
|
||||||
title={field.title}
|
|
||||||
width={'50%'}
|
width={'50%'}
|
||||||
{...props}
|
{...others}
|
||||||
visible={visible}
|
visible={visible}
|
||||||
closable
|
closable
|
||||||
maskClosable
|
maskClosable
|
||||||
onCancel={(e) => {
|
destroyOnClose
|
||||||
|
onCancel={async (e) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
setVisible(false);
|
setVisible(false);
|
||||||
|
setDropdownVisible && setDropdownVisible(false);
|
||||||
|
}}
|
||||||
|
onOk={async (e) => {
|
||||||
|
console.log('onOk', form.values);
|
||||||
|
// await form.submit();
|
||||||
|
await run();
|
||||||
|
// e.stopPropagation();
|
||||||
|
setVisible(false);
|
||||||
|
setDropdownVisible && setDropdownVisible(false);
|
||||||
}}
|
}}
|
||||||
footer={null}
|
|
||||||
>
|
>
|
||||||
<div onClick={(e) => e.stopPropagation()}>{props.children}</div>
|
<div
|
||||||
|
//onClick={(e) => e.stopPropagation()}
|
||||||
|
>
|
||||||
|
{props.children}
|
||||||
|
</div>
|
||||||
</Modal>
|
</Modal>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
Action.Dropdown = observer((props) => {
|
const [DropdownVisibleProvider, useDropdownVisibleContext] = constate((props: any = {}) => {
|
||||||
// const { visible, setVisible } = useVisibleContext();
|
const { initialVisible = false } = props;
|
||||||
|
const [visible, setVisible] = useState(initialVisible);
|
||||||
|
|
||||||
|
return { visible, setVisible };
|
||||||
|
});
|
||||||
|
|
||||||
|
const ActionDropdown = observer((props: any) => {
|
||||||
|
const { icon, ...others } = props;
|
||||||
const schema = useFieldSchema();
|
const schema = useFieldSchema();
|
||||||
|
const { visible, setVisible } = useDropdownVisibleContext();
|
||||||
return (
|
return (
|
||||||
<>
|
|
||||||
<Popover
|
<Popover
|
||||||
// visible={visible}
|
visible={visible}
|
||||||
// onVisibleChange={(visible) => {
|
onVisibleChange={(visible) => {
|
||||||
// setVisible(visible);
|
setVisible(visible);
|
||||||
// }}
|
}}
|
||||||
{...props}
|
// {...props}
|
||||||
overlayClassName={'nb-action-group'}
|
overlayClassName={'nb-action-group'}
|
||||||
// trigger={'click'}
|
// trigger={'click'}
|
||||||
content={props.children}
|
content={props.children}
|
||||||
placement={'bottomLeft'}
|
placement={'bottomLeft'}
|
||||||
>
|
>
|
||||||
<Button>{schema.title}</Button>
|
<Button icon={<Icon type={icon} />} {...others}>
|
||||||
|
{schema.title}
|
||||||
|
</Button>
|
||||||
</Popover>
|
</Popover>
|
||||||
{/* popover 的按钮初始化时并未渲染,暂时先这么处理 */}
|
);
|
||||||
<div style={{display: 'none'}}>{props.children}</div>
|
});
|
||||||
</>
|
|
||||||
|
Action.Dropdown = observer((props) => {
|
||||||
|
return (
|
||||||
|
<DropdownVisibleProvider>
|
||||||
|
<ActionDropdown {...props} />
|
||||||
|
<div style={{ display: 'none' }}>{props.children}</div>
|
||||||
|
</DropdownVisibleProvider>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
Action.DesignableBar = () => {
|
Action.DesignableBar = () => {
|
||||||
const field = useField();
|
const field = useField();
|
||||||
// const schema = useFieldSchema();
|
// const schema = useFieldSchema();
|
||||||
const { schema, insertAfter } = useDesignable();
|
const { schema, insertAfter, refresh } = useDesignable();
|
||||||
const [visible, setVisible] = useState(false);
|
const [visible, setVisible] = useState(false);
|
||||||
return (
|
return (
|
||||||
<div className={classNames('designable-bar', { active: visible })}>
|
<DesignableContextProvider>
|
||||||
<span
|
<div className={classNames('designable-bar', { active: visible })}>
|
||||||
onClick={(e) => {
|
<span
|
||||||
e.stopPropagation();
|
onClick={(e) => {
|
||||||
}}
|
e.stopPropagation();
|
||||||
className={classNames('designable-bar-actions', { active: visible })}
|
|
||||||
>
|
|
||||||
<Dropdown
|
|
||||||
trigger={['click']}
|
|
||||||
visible={visible}
|
|
||||||
onVisibleChange={(visible) => {
|
|
||||||
setVisible(visible);
|
|
||||||
}}
|
}}
|
||||||
overlay={
|
className={classNames('designable-bar-actions', { active: visible })}
|
||||||
<Menu>
|
|
||||||
<Menu.Item
|
|
||||||
onClick={(e) => {
|
|
||||||
console.log({ field, schema });
|
|
||||||
schema.title = '按钮文案被修改了';
|
|
||||||
field.setTitle('按钮文案被修改了');
|
|
||||||
schema.properties.drawer1.title = '抽屉标题文案被修改了';
|
|
||||||
setVisible(false);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
点击修改按钮文案
|
|
||||||
</Menu.Item>
|
|
||||||
<Menu.Item
|
|
||||||
onClick={() => {
|
|
||||||
insertAfter({
|
|
||||||
name: uid(),
|
|
||||||
'x-component': 'Input',
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
insertAfter
|
|
||||||
</Menu.Item>
|
|
||||||
</Menu>
|
|
||||||
}
|
|
||||||
>
|
>
|
||||||
<MenuOutlined />
|
<SchemaRenderer schema={DesignableBar.Action} />
|
||||||
</Dropdown>
|
</span>
|
||||||
</span>
|
</div>
|
||||||
</div>
|
</DesignableContextProvider>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -80,3 +80,16 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.designable-bar-actions {
|
||||||
|
.ant-btn {
|
||||||
|
border: 0;
|
||||||
|
padding: 0;
|
||||||
|
background: none;
|
||||||
|
height: auto;
|
||||||
|
line-height: 1em;
|
||||||
|
width: auto;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
}
|
@ -11,7 +11,7 @@ group:
|
|||||||
|
|
||||||
# AddNew - 新增
|
# AddNew - 新增
|
||||||
|
|
||||||
## 组件节点树
|
## Node Tree
|
||||||
|
|
||||||
<pre lang="tsx">
|
<pre lang="tsx">
|
||||||
// 简单场景,只支持上下拖拽布局
|
// 简单场景,只支持上下拖拽布局
|
||||||
@ -24,7 +24,7 @@ group:
|
|||||||
|
|
||||||
// 栅格布局,支持行列等复杂的拖拽操作
|
// 栅格布局,支持行列等复杂的拖拽操作
|
||||||
<Grid>
|
<Grid>
|
||||||
<Grid.Row>
|
<Grid.Row locked>
|
||||||
<Grid.Col>
|
<Grid.Col>
|
||||||
// 常规区块
|
// 常规区块
|
||||||
<AddNew.BlockItem/>
|
<AddNew.BlockItem/>
|
||||||
@ -35,7 +35,11 @@ group:
|
|||||||
</Grid>
|
</Grid>
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
## 代码演示
|
## Designable Bar
|
||||||
|
|
||||||
|
暂无
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
### AddNew.BlockItem
|
### AddNew.BlockItem
|
||||||
|
|
||||||
|
26
packages/client/src/schemas/block-item/index.md
Normal file
26
packages/client/src/schemas/block-item/index.md
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
---
|
||||||
|
title: BlockItem - 区块项
|
||||||
|
nav:
|
||||||
|
title: 组件
|
||||||
|
path: /client
|
||||||
|
group:
|
||||||
|
order: 1
|
||||||
|
title: Schemas
|
||||||
|
path: /client/schemas
|
||||||
|
---
|
||||||
|
|
||||||
|
# BlockItem - 区块项
|
||||||
|
|
||||||
|
## Node Tree
|
||||||
|
|
||||||
|
通常 BlockItem 并不单独占用一个节点,而是节点的 x-decorator
|
||||||
|
|
||||||
|
<pre lang="tsx">
|
||||||
|
<Table x-decorator={'BlockItem'}/>
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
BlockItem 的作用主要用于处理 DesignableBar,如:
|
||||||
|
|
||||||
|
<pre lang="tsx">
|
||||||
|
<Table x-decorator={'BlockItem'} x-designable-bar={'Table.DesignableBar'}/>
|
||||||
|
</pre>
|
@ -11,13 +11,17 @@ group:
|
|||||||
|
|
||||||
# Cascader - 级联选择
|
# Cascader - 级联选择
|
||||||
|
|
||||||
## 组件节点树
|
## Node Tree
|
||||||
|
|
||||||
<pre lang="tsx">
|
<pre lang="tsx">
|
||||||
<Cascader/>
|
<Cascader/>
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
## 代码演示
|
## Designable Bar
|
||||||
|
|
||||||
|
- Cascader.DesignableBar
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
### 省市区级联
|
### 省市区级联
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ group:
|
|||||||
|
|
||||||
# Checkbox - 多选框
|
# Checkbox - 多选框
|
||||||
|
|
||||||
## 组件节点树
|
## Node Tree
|
||||||
|
|
||||||
<pre lang="tsx">
|
<pre lang="tsx">
|
||||||
// 勾选
|
// 勾选
|
||||||
@ -20,7 +20,11 @@ group:
|
|||||||
<Checkbox.Group/>
|
<Checkbox.Group/>
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
## 代码演示
|
## Designable Bar
|
||||||
|
|
||||||
|
- Checkbox.DesignableBar
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
### 勾选
|
### 勾选
|
||||||
|
|
||||||
|
@ -11,13 +11,17 @@ group:
|
|||||||
|
|
||||||
# ColorSelect - 颜色选择器
|
# ColorSelect - 颜色选择器
|
||||||
|
|
||||||
## 组件节点树
|
## Node Tree
|
||||||
|
|
||||||
<pre lang="tsx">
|
<pre lang="tsx">
|
||||||
<ColorSelect/>
|
<ColorSelect/>
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
## 代码演示
|
## Designable Bar
|
||||||
|
|
||||||
|
- ColorSelect.DesignableBar
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
### 颜色选择器
|
### 颜色选择器
|
||||||
|
|
||||||
|
@ -11,20 +11,23 @@ group:
|
|||||||
|
|
||||||
# DatabaseField - 数据表字段
|
# DatabaseField - 数据表字段
|
||||||
|
|
||||||
## 组件节点树
|
## Node Tree
|
||||||
|
|
||||||
<pre lang="tsx">
|
<pre lang="tsx">
|
||||||
<DatabaseField/>
|
<DatabaseField/>
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
## 代码演示
|
## Designable Bar
|
||||||
|
|
||||||
|
暂无
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
```tsx
|
```tsx
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { createForm } from '@formily/core';
|
import { createForm } from '@formily/core';
|
||||||
import { SchemaRenderer } from '../';
|
import { SchemaRenderer } from '../';
|
||||||
import { observer, connect, useField } from '@formily/react';
|
import { observer, connect, useField } from '@formily/react';
|
||||||
import Editor from '@monaco-editor/react';
|
|
||||||
|
|
||||||
const schema = {
|
const schema = {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
@ -66,11 +69,6 @@ export default observer(() => {
|
|||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<SchemaRenderer form={form} schema={schema} />
|
<SchemaRenderer form={form} schema={schema} />
|
||||||
<Editor
|
|
||||||
height="200px"
|
|
||||||
defaultLanguage="json"
|
|
||||||
value={JSON.stringify(form.values, null, 2)}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
@ -11,13 +11,17 @@ group:
|
|||||||
|
|
||||||
# DatePicker - 日期选择器
|
# DatePicker - 日期选择器
|
||||||
|
|
||||||
## 组件节点树
|
## Node Tree
|
||||||
|
|
||||||
<pre lang="tsx">
|
<pre lang="tsx">
|
||||||
<DatePicker/>
|
<DatePicker/>
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
## 代码演示
|
## Designable Bar
|
||||||
|
|
||||||
|
- DatePicker.DesignableBar
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
### 日期选择器
|
### 日期选择器
|
||||||
|
|
||||||
|
25
packages/client/src/schemas/designable-bar/index.md
Normal file
25
packages/client/src/schemas/designable-bar/index.md
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
---
|
||||||
|
title: DesignableBar - 配置操作栏
|
||||||
|
nav:
|
||||||
|
title: 组件
|
||||||
|
path: /client
|
||||||
|
group:
|
||||||
|
order: 1
|
||||||
|
title: Schemas
|
||||||
|
path: /client/schemas
|
||||||
|
---
|
||||||
|
|
||||||
|
# DesignableBar - 配置操作栏
|
||||||
|
|
||||||
|
用于修改节点的参数配置,DesignableBar 是所有配置操作栏的统称,不是固定的,可以根据不同节点定义不同的 `**.DesignableBar`。
|
||||||
|
|
||||||
|
## Node Tree
|
||||||
|
|
||||||
|
通常 DesignableBar 并不单独占用一个节点,而是节点的 x-designable-bar
|
||||||
|
|
||||||
|
<pre lang="tsx">
|
||||||
|
<Table x-decorator={'BlockItem'} x-designable-bar={'Table.DesignableBar'}/>
|
||||||
|
<Action x-designable-bar={'Action.DesignableBar'}/>
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
数据组件的 DesignableBar 通常与 FormItem 搭配使用,非数据组件的 DesignableBar 通常与 BlockItem 搭配使用,也有少量如 Action、Menu 无需 BlockItem
|
@ -11,7 +11,7 @@ group:
|
|||||||
|
|
||||||
# Filter - 筛选器
|
# Filter - 筛选器
|
||||||
|
|
||||||
## 组件节点树
|
## Node Tree
|
||||||
|
|
||||||
<pre lang="tsx">
|
<pre lang="tsx">
|
||||||
<Filter>
|
<Filter>
|
||||||
@ -24,16 +24,11 @@ group:
|
|||||||
</Filter>
|
</Filter>
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
## 代码演示
|
## Designable Bar
|
||||||
|
|
||||||
<!-- <Filter>
|
- Filter.DesignableBar
|
||||||
<Filter.Column title={'字段1'} operations={[]}>
|
|
||||||
<Input/>
|
## Examples
|
||||||
</Filter.Column>
|
|
||||||
<Filter.Column title={'字段2'}>
|
|
||||||
<Input/>
|
|
||||||
</Filter.Column>
|
|
||||||
</Filter> -->
|
|
||||||
|
|
||||||
```tsx
|
```tsx
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
26
packages/client/src/schemas/form-item/index.md
Normal file
26
packages/client/src/schemas/form-item/index.md
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
---
|
||||||
|
title: FormItem - 表单项
|
||||||
|
nav:
|
||||||
|
title: 组件
|
||||||
|
path: /client
|
||||||
|
group:
|
||||||
|
order: 1
|
||||||
|
title: Schemas
|
||||||
|
path: /client/schemas
|
||||||
|
---
|
||||||
|
|
||||||
|
# FormItem - 表单项
|
||||||
|
|
||||||
|
## Node Tree
|
||||||
|
|
||||||
|
通常 FormItem 并不单独占用一个节点,而是节点的 x-decorator
|
||||||
|
|
||||||
|
<pre lang="tsx">
|
||||||
|
<Input x-decorator={'FormItem'}/>
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
FormItem 的作用主要用于处理表单项(控件)的校验、布局等
|
||||||
|
|
||||||
|
<pre lang="tsx">
|
||||||
|
<Input x-decorator={'FormItem'} x-designable-bar={'Input.DesignableBar'}/>
|
||||||
|
</pre>
|
@ -11,7 +11,7 @@ group:
|
|||||||
|
|
||||||
# Form - 表单
|
# Form - 表单
|
||||||
|
|
||||||
## 组件节点树
|
## Node Tree
|
||||||
|
|
||||||
<pre lang="tsx">
|
<pre lang="tsx">
|
||||||
<Form>
|
<Form>
|
||||||
@ -19,9 +19,15 @@ group:
|
|||||||
<Select/>
|
<Select/>
|
||||||
// 添加其他节点
|
// 添加其他节点
|
||||||
</Form>
|
</Form>
|
||||||
|
|
||||||
|
<Table x-decorator={'Form'}/>
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
## 代码演示
|
## Designable Bar
|
||||||
|
|
||||||
|
- Form.DesignableBar
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
### 常规表单
|
### 常规表单
|
||||||
|
|
||||||
@ -161,7 +167,7 @@ import { uid } from '@formily/shared';
|
|||||||
const schema = {
|
const schema = {
|
||||||
type: 'void',
|
type: 'void',
|
||||||
name: uid(),
|
name: uid(),
|
||||||
'x-decorator': 'Card',
|
'x-decorator': 'BlockItem',
|
||||||
'x-component': 'Form',
|
'x-component': 'Form',
|
||||||
'x-designable-bar': 'Form.DesignableBar',
|
'x-designable-bar': 'Form.DesignableBar',
|
||||||
properties: {
|
properties: {
|
||||||
|
@ -6,6 +6,8 @@ import {
|
|||||||
useFieldSchema,
|
useFieldSchema,
|
||||||
observer,
|
observer,
|
||||||
SchemaExpressionScopeContext,
|
SchemaExpressionScopeContext,
|
||||||
|
FormProvider,
|
||||||
|
ISchema,
|
||||||
} from '@formily/react';
|
} from '@formily/react';
|
||||||
import { SchemaRenderer, useDesignable } from '../DesignableSchemaField';
|
import { SchemaRenderer, useDesignable } from '../DesignableSchemaField';
|
||||||
import get from 'lodash/get';
|
import get from 'lodash/get';
|
||||||
@ -42,7 +44,6 @@ function useDefaultValues() {
|
|||||||
|
|
||||||
export const Form: any = observer((props: any) => {
|
export const Form: any = observer((props: any) => {
|
||||||
const scope = useContext(SchemaExpressionScopeContext);
|
const scope = useContext(SchemaExpressionScopeContext);
|
||||||
|
|
||||||
const { useValues = useDefaultValues } = props;
|
const { useValues = useDefaultValues } = props;
|
||||||
const values = useValues();
|
const values = useValues();
|
||||||
const form = useMemo(() => {
|
const form = useMemo(() => {
|
||||||
@ -54,37 +55,37 @@ export const Form: any = observer((props: any) => {
|
|||||||
}, [values]);
|
}, [values]);
|
||||||
const schema = useFieldSchema();
|
const schema = useFieldSchema();
|
||||||
const { schema: designableSchema, refresh } = useDesignable();
|
const { schema: designableSchema, refresh } = useDesignable();
|
||||||
const { DesignableBar } = useDesignableBar();
|
const formSchema: ISchema = schema['x-decorator'] === 'Form' ? {
|
||||||
const ref = useRef();
|
type: 'void',
|
||||||
const [active, setActive] = useState(false);
|
"x-component": 'Blank',
|
||||||
const { onMouseEnter, onMouseLeave, onMouseMove } = useMouseEvents(ref);
|
properties: {
|
||||||
onMouseEnter((e: React.MouseEvent) => {
|
[schema.name]: {
|
||||||
setActive(true);
|
...schema.toJSON(),
|
||||||
});
|
"x-decorator": 'Form.Decorator',
|
||||||
|
}
|
||||||
onMouseLeave((e: React.MouseEvent) => {
|
}
|
||||||
setActive(false);
|
} : {
|
||||||
});
|
...schema.toJSON(),
|
||||||
|
'x-component': 'Form.Blank',
|
||||||
onMouseMove((e: React.MouseEvent) => {});
|
'x-component-props': {},
|
||||||
|
};
|
||||||
return (
|
return (
|
||||||
<div ref={ref} className={'nb-form'}>
|
<SchemaRenderer
|
||||||
<SchemaRenderer
|
scope={scope}
|
||||||
scope={scope}
|
// components={options.components}
|
||||||
// components={options.components}
|
onRefresh={(subSchema: Schema) => {
|
||||||
onRefresh={(subSchema: Schema) => {
|
designableSchema.properties = subSchema.properties;
|
||||||
designableSchema.properties = subSchema.properties;
|
refresh();
|
||||||
refresh();
|
}}
|
||||||
}}
|
form={form}
|
||||||
form={form}
|
schema={formSchema}
|
||||||
schema={schema.toJSON()}
|
onlyRenderProperties
|
||||||
onlyRenderProperties
|
/>
|
||||||
/>
|
|
||||||
<DesignableBar active={active} />
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Form.Decorator = ({children}) => children;
|
||||||
|
|
||||||
Form.DesignableBar = (props) => {
|
Form.DesignableBar = (props) => {
|
||||||
const { active } = props;
|
const { active } = props;
|
||||||
return (
|
return (
|
||||||
|
@ -13,21 +13,6 @@ group:
|
|||||||
|
|
||||||
基于行(Row)和列(Col)来定义区块(Block)的外部框架。
|
基于行(Row)和列(Col)来定义区块(Block)的外部框架。
|
||||||
|
|
||||||
## 组件节点树
|
|
||||||
|
|
||||||
<pre lang="tsx">
|
|
||||||
<Grid>
|
|
||||||
<Grid.Row>
|
|
||||||
<Grid.Col>
|
|
||||||
// 添加其他节点
|
|
||||||
</Grid.Col>
|
|
||||||
<Grid.Col>
|
|
||||||
// 添加其他节点
|
|
||||||
</Grid.Col>
|
|
||||||
</Grid.Row>
|
|
||||||
</Grid>
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
## 列宽说明
|
## 列宽说明
|
||||||
|
|
||||||
最大支持四列,如果要支持越多列,需要处理的比例也越多。
|
最大支持四列,如果要支持越多列,需要处理的比例也越多。
|
||||||
@ -88,4 +73,26 @@ group:
|
|||||||
|
|
||||||
- 100%
|
- 100%
|
||||||
|
|
||||||
|
|
||||||
|
## Node Tree
|
||||||
|
|
||||||
|
<pre lang="tsx">
|
||||||
|
<Grid>
|
||||||
|
<Grid.Row>
|
||||||
|
<Grid.Col>
|
||||||
|
// 添加其他节点
|
||||||
|
</Grid.Col>
|
||||||
|
<Grid.Col>
|
||||||
|
// 添加其他节点
|
||||||
|
</Grid.Col>
|
||||||
|
</Grid.Row>
|
||||||
|
</Grid>
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
## Designable Bar
|
||||||
|
|
||||||
|
暂无
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
<code src="./demos/demo1.tsx"/>
|
<code src="./demos/demo1.tsx"/>
|
||||||
|
@ -11,13 +11,17 @@ group:
|
|||||||
|
|
||||||
# IconPicker - 图标选择器
|
# IconPicker - 图标选择器
|
||||||
|
|
||||||
## 节点树
|
## Node Tree
|
||||||
|
|
||||||
<pre lang="tsx">
|
<pre lang="tsx">
|
||||||
<IconPicker/>
|
<IconPicker/>
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
## 代码演示
|
## Designable Bar
|
||||||
|
|
||||||
|
- IconPicker.DesignableBar
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
```tsx
|
```tsx
|
||||||
/**
|
/**
|
||||||
|
@ -11,13 +11,17 @@ group:
|
|||||||
|
|
||||||
# InputNumber - 数字框
|
# InputNumber - 数字框
|
||||||
|
|
||||||
## 节点树
|
## Node Tree
|
||||||
|
|
||||||
<pre lang="tsx">
|
<pre lang="tsx">
|
||||||
<InputNumber/>
|
<InputNumber/>
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
## 代码演示
|
## Designable Bar
|
||||||
|
|
||||||
|
- InputNumber.DesignableBar
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
### 数字框
|
### 数字框
|
||||||
|
|
||||||
|
@ -13,14 +13,19 @@ group:
|
|||||||
|
|
||||||
输入框是非常常用的控件,参数可以组合成许多字段,如单行文本、多行文本、手机号、邮箱、网址等。
|
输入框是非常常用的控件,参数可以组合成许多字段,如单行文本、多行文本、手机号、邮箱、网址等。
|
||||||
|
|
||||||
## 节点树
|
## Node Tree
|
||||||
|
|
||||||
<pre lang="tsx">
|
<pre lang="tsx">
|
||||||
<Input/>
|
<Input/>
|
||||||
<Input.TextArea/>
|
<Input.TextArea/>
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
## 代码演示
|
## Designable Bar
|
||||||
|
|
||||||
|
- Input.DesignableBar
|
||||||
|
- Input.TextArea.DesignableBar
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
### 单行文本
|
### 单行文本
|
||||||
|
|
||||||
|
@ -11,13 +11,17 @@ group:
|
|||||||
|
|
||||||
# Markdown 编辑器
|
# Markdown 编辑器
|
||||||
|
|
||||||
## 节点树
|
## Node Tree
|
||||||
|
|
||||||
<pre lang="tsx">
|
<pre lang="tsx">
|
||||||
<Markdown/>
|
<Markdown/>
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
## 代码演示
|
## Designable Bar
|
||||||
|
|
||||||
|
- Markdown.DesignableBar
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
### Markdown 编辑器
|
### Markdown 编辑器
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ group:
|
|||||||
|
|
||||||
需要 antd v4.16+ 支持,在此之前的 Menu.Item 不支持 Fragment 包裹。
|
需要 antd v4.16+ 支持,在此之前的 Menu.Item 不支持 Fragment 包裹。
|
||||||
|
|
||||||
## 组件树
|
## Node Tree
|
||||||
|
|
||||||
<pre lang="tsx">
|
<pre lang="tsx">
|
||||||
<Menu>
|
<Menu>
|
||||||
@ -43,7 +43,11 @@ group:
|
|||||||
</Menu>
|
</Menu>
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
## 代码演示
|
## Designable Bar
|
||||||
|
|
||||||
|
- Menu.DesignableBar
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
### 横向菜单
|
### 横向菜单
|
||||||
|
|
||||||
|
@ -11,14 +11,18 @@ group:
|
|||||||
|
|
||||||
# Password - 密码
|
# Password - 密码
|
||||||
|
|
||||||
## 节点树
|
## Node Tree
|
||||||
|
|
||||||
<pre lang="tsx">
|
<pre lang="tsx">
|
||||||
// 单选框
|
// 单选框
|
||||||
<Password/>
|
<Password/>
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
## 代码演示
|
## Designable Bar
|
||||||
|
|
||||||
|
- Password.DesignableBar
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
### 密码框
|
### 密码框
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ group:
|
|||||||
|
|
||||||
# Radio - 单选框
|
# Radio - 单选框
|
||||||
|
|
||||||
## 节点树
|
## Node Tree
|
||||||
|
|
||||||
<pre lang="tsx">
|
<pre lang="tsx">
|
||||||
// 单选框
|
// 单选框
|
||||||
@ -20,7 +20,11 @@ group:
|
|||||||
<Radio.Group/>
|
<Radio.Group/>
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
## 代码演示
|
## Designable Bar
|
||||||
|
|
||||||
|
- Radio.DesignableBar
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
### 单选框
|
### 单选框
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ group:
|
|||||||
|
|
||||||
# Select - 选择器
|
# Select - 选择器
|
||||||
|
|
||||||
## 节点树
|
## Node Tree
|
||||||
|
|
||||||
<pre lang="tsx">
|
<pre lang="tsx">
|
||||||
// 常规选择器
|
// 常规选择器
|
||||||
@ -37,7 +37,14 @@ group:
|
|||||||
</Select.Drawer>
|
</Select.Drawer>
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
## Select
|
## Designable Bar
|
||||||
|
|
||||||
|
- Select.DesignableBar
|
||||||
|
- Select.Drawer.DesignableBar
|
||||||
|
- Select.Options.DesignableBar
|
||||||
|
- Select.OptionTag.DesignableBar
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
### 单选
|
### 单选
|
||||||
|
|
||||||
@ -62,13 +69,11 @@ const schema = {
|
|||||||
type: 'object',
|
type: 'object',
|
||||||
properties: {
|
properties: {
|
||||||
input: {
|
input: {
|
||||||
interface: 'string',
|
type: 'number',
|
||||||
type: 'string',
|
|
||||||
title: `编辑模式`,
|
title: `编辑模式`,
|
||||||
name: 'name1',
|
|
||||||
enum: options,
|
enum: options,
|
||||||
'x-decorator': 'FormItem',
|
'x-decorator': 'FormItem',
|
||||||
'x-component': 'Select',
|
'x-component': 'Select.Object',
|
||||||
'x-reactions': {
|
'x-reactions': {
|
||||||
target: 'read',
|
target: 'read',
|
||||||
fulfill: {
|
fulfill: {
|
||||||
@ -79,14 +84,12 @@ const schema = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
read: {
|
read: {
|
||||||
interface: 'string',
|
type: 'number',
|
||||||
type: 'string',
|
|
||||||
title: `阅读模式`,
|
title: `阅读模式`,
|
||||||
enum: options,
|
enum: options,
|
||||||
name: 'name2',
|
|
||||||
'x-read-pretty': true,
|
|
||||||
'x-decorator': 'FormItem',
|
'x-decorator': 'FormItem',
|
||||||
'x-component': 'Select',
|
'x-component': 'Select.Object',
|
||||||
|
'x-read-pretty': true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -257,8 +260,7 @@ const schema = {
|
|||||||
type: 'object',
|
type: 'object',
|
||||||
properties: {
|
properties: {
|
||||||
input: {
|
input: {
|
||||||
interface: 'select',
|
type: 'object',
|
||||||
type: 'string',
|
|
||||||
title: `编辑模式`,
|
title: `编辑模式`,
|
||||||
enum: dataSource,
|
enum: dataSource,
|
||||||
'x-decorator': 'FormItem',
|
'x-decorator': 'FormItem',
|
||||||
@ -281,8 +283,7 @@ const schema = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
read: {
|
read: {
|
||||||
interface: 'select',
|
type: 'object',
|
||||||
type: 'string',
|
|
||||||
title: `阅读模式`,
|
title: `阅读模式`,
|
||||||
enum: dataSource,
|
enum: dataSource,
|
||||||
'x-read-pretty': true,
|
'x-read-pretty': true,
|
||||||
@ -332,8 +333,7 @@ const schema = {
|
|||||||
type: 'object',
|
type: 'object',
|
||||||
properties: {
|
properties: {
|
||||||
input: {
|
input: {
|
||||||
interface: 'select',
|
type: 'array',
|
||||||
type: 'string',
|
|
||||||
title: `编辑模式`,
|
title: `编辑模式`,
|
||||||
enum: dataSource,
|
enum: dataSource,
|
||||||
'x-decorator': 'FormItem',
|
'x-decorator': 'FormItem',
|
||||||
@ -356,8 +356,7 @@ const schema = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
read: {
|
read: {
|
||||||
interface: 'select',
|
type: 'array',
|
||||||
type: 'string',
|
|
||||||
title: `阅读模式`,
|
title: `阅读模式`,
|
||||||
enum: dataSource,
|
enum: dataSource,
|
||||||
'x-read-pretty': true,
|
'x-read-pretty': true,
|
||||||
@ -571,22 +570,44 @@ export default () => {
|
|||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
<!--
|
## Schema API
|
||||||
<Select />
|
|
||||||
<Select.Object />
|
|
||||||
<Select.Drawer>
|
|
||||||
<Select.Options>
|
|
||||||
<Table />
|
|
||||||
<Action />
|
|
||||||
<Select.Options>
|
|
||||||
<Select.ItemDetails>
|
|
||||||
<Form/>
|
|
||||||
</Select.ItemDetails>
|
|
||||||
<Select.Drawer>
|
|
||||||
|
|
||||||
<Action />
|
### Select
|
||||||
|
|
||||||
<Action>
|
type 支持 string、number、object 和 array,array 元素可以是 string、number 或 object。如:
|
||||||
<Drawer />
|
|
||||||
</Action>
|
```ts
|
||||||
-->
|
{
|
||||||
|
properties: {
|
||||||
|
select: {
|
||||||
|
type: 'string', // 也可以是 number、object、array
|
||||||
|
'x-component': 'Select',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
可以配置 dataSource(enum)的 fieldNames,如:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
{
|
||||||
|
properties: {
|
||||||
|
select: {
|
||||||
|
type: 'string', // 也可以是 number、object、array
|
||||||
|
'x-component': 'Select',
|
||||||
|
'x-component-props': {
|
||||||
|
fieldNames: {
|
||||||
|
label: 'label', // 标签文案
|
||||||
|
value: 'value',
|
||||||
|
color: 'color', // 标签颜色
|
||||||
|
children: 'children', // 选项分组时,选项字段对应的 key
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Select.Drawer
|
||||||
|
|
||||||
|
type 支持 object 和 array,Select.Drawer 的可选项是以抽屉方式展开,提供了 Select.Options 和 Select.OptionTag 用于配置可选项界面和选中项详情界面。
|
||||||
|
@ -18,6 +18,8 @@ import { useDesignable } from '../DesignableSchemaField';
|
|||||||
import { createContext } from 'react';
|
import { createContext } from 'react';
|
||||||
import { useContext } from 'react';
|
import { useContext } from 'react';
|
||||||
import { SelectedRowKeysContext, useTableContext } from '../table';
|
import { SelectedRowKeysContext, useTableContext } from '../table';
|
||||||
|
import { isEmpty } from 'lodash';
|
||||||
|
import { isField } from '@formily/core';
|
||||||
|
|
||||||
export const Select: any = connect(
|
export const Select: any = connect(
|
||||||
(props) => {
|
(props) => {
|
||||||
@ -189,10 +191,13 @@ Select.Object = connect(
|
|||||||
),
|
),
|
||||||
mapReadPretty(
|
mapReadPretty(
|
||||||
observer((props: any) => {
|
observer((props: any) => {
|
||||||
const { value, fieldNames = { label: 'label' }, ...others } = props;
|
const { value, fieldNames = { label: 'label', color: 'color' }, ...others } = props;
|
||||||
if (!value) {
|
if (!value) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
if (isEmpty(value)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
const values = toArr(value);
|
const values = toArr(value);
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
|
@ -11,7 +11,7 @@ group:
|
|||||||
|
|
||||||
# Table - 表格
|
# Table - 表格
|
||||||
|
|
||||||
## 组件节点树
|
## Node Tree
|
||||||
|
|
||||||
<pre lang="tsx">
|
<pre lang="tsx">
|
||||||
<Table>
|
<Table>
|
||||||
@ -53,6 +53,11 @@ group:
|
|||||||
</Table>
|
</Table>
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
## 代码演示
|
## Designable Bar
|
||||||
|
|
||||||
|
- Table.DesignableBar
|
||||||
|
- Table.Column.DesignableBar
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
<code src="./demos/demo1.tsx"/>
|
<code src="./demos/demo1.tsx"/>
|
||||||
|
@ -11,7 +11,7 @@ group:
|
|||||||
|
|
||||||
# Tabs - 标签页
|
# Tabs - 标签页
|
||||||
|
|
||||||
## 组件节点树
|
## Node
|
||||||
|
|
||||||
<pre lang="tsx">
|
<pre lang="tsx">
|
||||||
<Tabs>
|
<Tabs>
|
||||||
@ -24,7 +24,11 @@ group:
|
|||||||
</Tabs>
|
</Tabs>
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
## 代码演示
|
## Designable Bar
|
||||||
|
|
||||||
|
- Tabs.DesignableBar
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
### 基本使用
|
### 基本使用
|
||||||
|
|
||||||
|
@ -11,13 +11,17 @@ group:
|
|||||||
|
|
||||||
# TimePicker - 时间选择器
|
# TimePicker - 时间选择器
|
||||||
|
|
||||||
## 节点树
|
## Node Tree
|
||||||
|
|
||||||
<pre lang="tsx">
|
<pre lang="tsx">
|
||||||
<TimePicker/>
|
<TimePicker/>
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
## 代码演示
|
## Designable Bar
|
||||||
|
|
||||||
|
- TimePicker.DesignableBar
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
### 日期选择器
|
### 日期选择器
|
||||||
|
|
||||||
|
@ -11,13 +11,17 @@ group:
|
|||||||
|
|
||||||
# Upload - 上传
|
# Upload - 上传
|
||||||
|
|
||||||
## 节点树
|
## Node Tree
|
||||||
|
|
||||||
<pre lang="tsx">
|
<pre lang="tsx">
|
||||||
<Upload/>
|
<Upload/>
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
## 代码演示
|
## Designable Bar
|
||||||
|
|
||||||
|
- Upload.DesignableBar
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
### 上传
|
### 上传
|
||||||
|
|
||||||
|
@ -1,14 +0,0 @@
|
|||||||
---
|
|
||||||
title: AdminLayout - 后台布局
|
|
||||||
nav:
|
|
||||||
title: 组件
|
|
||||||
path: /client
|
|
||||||
group:
|
|
||||||
order: 2
|
|
||||||
title: Templates
|
|
||||||
path: /client/templates
|
|
||||||
---
|
|
||||||
|
|
||||||
# AdminLayout - 后台布局
|
|
||||||
|
|
||||||
内置的后台布局模板,提供了基础的菜单和路由切换。
|
|
@ -1,229 +0,0 @@
|
|||||||
import React, { useContext, useEffect, useRef, useState } from 'react';
|
|
||||||
import {
|
|
||||||
Button,
|
|
||||||
Spin,
|
|
||||||
Layout,
|
|
||||||
PageHeader,
|
|
||||||
Modal,
|
|
||||||
Menu,
|
|
||||||
Collapse,
|
|
||||||
Dropdown,
|
|
||||||
} from 'antd';
|
|
||||||
import isEmpty from 'lodash/isEmpty';
|
|
||||||
import {
|
|
||||||
Link,
|
|
||||||
useLocation,
|
|
||||||
useRouteMatch,
|
|
||||||
useHistory,
|
|
||||||
Redirect,
|
|
||||||
} from 'react-router-dom';
|
|
||||||
import {
|
|
||||||
useGlobalAction,
|
|
||||||
refreshGlobalAction,
|
|
||||||
RouteComponentContext,
|
|
||||||
} from '../../';
|
|
||||||
import { SchemaRenderer } from '../../schemas';
|
|
||||||
import { useRequest } from 'ahooks';
|
|
||||||
import {
|
|
||||||
DatabaseOutlined,
|
|
||||||
PlusOutlined,
|
|
||||||
DownOutlined,
|
|
||||||
} from '@ant-design/icons';
|
|
||||||
import { Tabs } from 'antd';
|
|
||||||
import '@formily/antd/esm/array-collapse/style';
|
|
||||||
import './style.less';
|
|
||||||
import { MenuContainerContext } from '../../schemas/menu';
|
|
||||||
|
|
||||||
function LogoutButton() {
|
|
||||||
const history = useHistory();
|
|
||||||
return (
|
|
||||||
<Button
|
|
||||||
onClick={async () => {
|
|
||||||
history.push('/login');
|
|
||||||
await refreshGlobalAction('routes:getAccessible');
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
注销
|
|
||||||
</Button>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function Database() {
|
|
||||||
const [visible, setVisible] = useState(false);
|
|
||||||
|
|
||||||
const schema = {
|
|
||||||
type: 'object',
|
|
||||||
properties: {
|
|
||||||
layout: {
|
|
||||||
type: 'void',
|
|
||||||
'x-component': 'FormLayout',
|
|
||||||
'x-component-props': {
|
|
||||||
layout: 'vertical',
|
|
||||||
},
|
|
||||||
properties: {
|
|
||||||
input: {
|
|
||||||
type: 'string',
|
|
||||||
title: '数据表名称',
|
|
||||||
required: true,
|
|
||||||
'x-decorator': 'FormItem',
|
|
||||||
'x-component': 'Input',
|
|
||||||
},
|
|
||||||
array: {
|
|
||||||
type: 'array',
|
|
||||||
title: '数据表字段',
|
|
||||||
'x-component': 'ArrayCollapse',
|
|
||||||
'x-component-props': {
|
|
||||||
accordion: true,
|
|
||||||
},
|
|
||||||
// maxItems: 3,
|
|
||||||
'x-decorator': 'FormItem',
|
|
||||||
items: {
|
|
||||||
type: 'object',
|
|
||||||
'x-component': 'ArrayCollapse.CollapsePanel',
|
|
||||||
'x-component-props': {
|
|
||||||
header: '字段',
|
|
||||||
},
|
|
||||||
properties: {
|
|
||||||
index: {
|
|
||||||
type: 'void',
|
|
||||||
'x-component': 'ArrayCollapse.Index',
|
|
||||||
},
|
|
||||||
input: {
|
|
||||||
type: 'string',
|
|
||||||
'x-decorator': 'FormItem',
|
|
||||||
title: 'Input',
|
|
||||||
required: true,
|
|
||||||
'x-component': 'Input',
|
|
||||||
},
|
|
||||||
remove: {
|
|
||||||
type: 'void',
|
|
||||||
'x-component': 'ArrayCollapse.Remove',
|
|
||||||
},
|
|
||||||
moveUp: {
|
|
||||||
type: 'void',
|
|
||||||
'x-component': 'ArrayCollapse.MoveUp',
|
|
||||||
},
|
|
||||||
moveDown: {
|
|
||||||
type: 'void',
|
|
||||||
'x-component': 'ArrayCollapse.MoveDown',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
properties: {
|
|
||||||
addition: {
|
|
||||||
type: 'void',
|
|
||||||
title: '添加字段',
|
|
||||||
'x-component': 'ArrayCollapse.Addition',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Modal
|
|
||||||
title={
|
|
||||||
<Dropdown
|
|
||||||
overlay={
|
|
||||||
<Menu>
|
|
||||||
<Menu.Item key={'1'}>数据表1</Menu.Item>
|
|
||||||
<Menu.Item key={'2'}>数据表2</Menu.Item>
|
|
||||||
<Menu.Item key={'3'}>数据表3</Menu.Item>
|
|
||||||
<Menu.Item key={'4'}>数据表4</Menu.Item>
|
|
||||||
<Menu.Divider></Menu.Divider>
|
|
||||||
<Menu.Item key={'5'}>新增数据表</Menu.Item>
|
|
||||||
</Menu>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<span>
|
|
||||||
数据表1 <DownOutlined />
|
|
||||||
</span>
|
|
||||||
</Dropdown>
|
|
||||||
}
|
|
||||||
// width={'800px'}
|
|
||||||
visible={visible}
|
|
||||||
onCancel={() => setVisible(false)}
|
|
||||||
onOk={() => setVisible(false)}
|
|
||||||
// bodyStyle={{ padding: 0 }}
|
|
||||||
// footer={null}
|
|
||||||
>
|
|
||||||
<SchemaRenderer schema={schema} />
|
|
||||||
</Modal>
|
|
||||||
<DatabaseOutlined
|
|
||||||
onClick={() => setVisible(true)}
|
|
||||||
style={{ color: '#fff', lineHeight: '48px', width: 48 }}
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function LayoutWithMenu({ schema }) {
|
|
||||||
const match = useRouteMatch<any>();
|
|
||||||
const location = useLocation();
|
|
||||||
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>
|
|
||||||
<SchemaRenderer
|
|
||||||
schema={schema}
|
|
||||||
scope={{ sideMenuRef, onSelect, selectedKeys: [activeKey].filter(Boolean) }}
|
|
||||||
/>
|
|
||||||
</Layout.Header>
|
|
||||||
<Layout>
|
|
||||||
<Layout.Sider
|
|
||||||
ref={sideMenuRef}
|
|
||||||
theme={'light'}
|
|
||||||
width={200}
|
|
||||||
></Layout.Sider>
|
|
||||||
<Layout.Content>
|
|
||||||
{location.pathname}
|
|
||||||
<Content activeKey={activeKey} />
|
|
||||||
</Layout.Content>
|
|
||||||
</Layout>
|
|
||||||
</Layout>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function Content({ activeKey }) {
|
|
||||||
const { data = {}, loading } = useRequest(
|
|
||||||
`/api/ui-schemas:getTree/${activeKey}?filter[parentId]=${activeKey}`,
|
|
||||||
{
|
|
||||||
refreshDeps: [activeKey],
|
|
||||||
formatResult: (result) => result?.data,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
if (loading) {
|
|
||||||
return <Spin />;
|
|
||||||
}
|
|
||||||
|
|
||||||
return <SchemaRenderer schema={data} />;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function AdminLayout({ route, children }: any) {
|
|
||||||
|
|
||||||
const { data = {}, loading } = useRequest(
|
|
||||||
`/api/ui-schemas:getTree/${route.schemaName}`,
|
|
||||||
{
|
|
||||||
refreshDeps: [route],
|
|
||||||
formatResult: (result) => result?.data,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
if (loading) {
|
|
||||||
return <Spin />;
|
|
||||||
}
|
|
||||||
|
|
||||||
return <LayoutWithMenu schema={data} />;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default AdminLayout;
|
|
@ -1,49 +0,0 @@
|
|||||||
// .fields-collapse {
|
|
||||||
// border: 1px solid #f0f0f0;
|
|
||||||
// border-bottom: 0;
|
|
||||||
// > .ant-collapse-item {
|
|
||||||
// border-bottom: 1px solid #f0f0f0;
|
|
||||||
// }
|
|
||||||
// .ant-collapse-content {
|
|
||||||
// &.ant-collapse-content-active {
|
|
||||||
// border-top: 1px solid #f0f0f0;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// > .ant-collapse-item > .ant-collapse-content {
|
|
||||||
// background: #fff;
|
|
||||||
// }
|
|
||||||
// > .ant-collapse-item > .ant-collapse-content > .ant-collapse-content-box {
|
|
||||||
// padding: 16px;
|
|
||||||
// padding-bottom: 1px;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
.ant-collapse {
|
|
||||||
border: 1px solid #d9d9d9 !important;
|
|
||||||
border-bottom: 0 !important;
|
|
||||||
> .ant-collapse-item {
|
|
||||||
border-bottom: 1px solid #d9d9d9 !important;
|
|
||||||
}
|
|
||||||
.ant-collapse-content {
|
|
||||||
border-top: 1px solid #d9d9d9 !important;
|
|
||||||
}
|
|
||||||
.ant-collapse-content > .ant-collapse-content-box {
|
|
||||||
padding: 24px !important;
|
|
||||||
padding-bottom: 0 !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.database-sider {
|
|
||||||
background: #fafafa;
|
|
||||||
padding-top: 16px;
|
|
||||||
.ant-menu {
|
|
||||||
background: #fafafa;
|
|
||||||
border-right: 0;
|
|
||||||
}
|
|
||||||
.ant-menu:not(.ant-menu-horizontal) .ant-menu-item-selected {
|
|
||||||
background: #fff;
|
|
||||||
&::after {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,14 +0,0 @@
|
|||||||
---
|
|
||||||
title: AuthLayout - 登录布局
|
|
||||||
nav:
|
|
||||||
title: 组件
|
|
||||||
path: /client
|
|
||||||
group:
|
|
||||||
order: 2
|
|
||||||
title: Templates
|
|
||||||
path: /client/templates
|
|
||||||
---
|
|
||||||
|
|
||||||
# AuthLayout - 登录布局
|
|
||||||
|
|
||||||
内置的登录、注册页布局
|
|
@ -1,15 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import { useLocation, useHistory } from 'react-router-dom';
|
|
||||||
|
|
||||||
export function AuthLayout({ children, route }: any) {
|
|
||||||
const location = useLocation();
|
|
||||||
const history = useHistory();
|
|
||||||
return (
|
|
||||||
<div style={{ maxWidth: 320, margin: '0 auto' }}>
|
|
||||||
<h1>NocoBase</h1>
|
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default AuthLayout;
|
|
@ -1,14 +0,0 @@
|
|||||||
---
|
|
||||||
title: PageTemplate - 页面模板
|
|
||||||
nav:
|
|
||||||
title: 组件
|
|
||||||
path: /client
|
|
||||||
group:
|
|
||||||
order: 2
|
|
||||||
title: Templates
|
|
||||||
path: /client/templates
|
|
||||||
---
|
|
||||||
|
|
||||||
# PageTemplate - 页面模板
|
|
||||||
|
|
||||||
常规的页面模板,支持区块配置。
|
|
@ -1,25 +0,0 @@
|
|||||||
import React, { useContext, useEffect, useState } from 'react';
|
|
||||||
import { Spin } from 'antd';
|
|
||||||
import { Helmet } from 'react-helmet';
|
|
||||||
import { useRequest } from 'ahooks';
|
|
||||||
import { SchemaRenderer } from '../../schemas';
|
|
||||||
|
|
||||||
export function DefaultPage({ route }) {
|
|
||||||
const { data = {}, loading } = useRequest(
|
|
||||||
`/api/ui-schemas:getTree/${route.schemaName}`,
|
|
||||||
{
|
|
||||||
refreshDeps: [route],
|
|
||||||
formatResult: (result) => result?.data,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
if (loading) {
|
|
||||||
return <Spin />;
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<SchemaRenderer schema={data} />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default DefaultPage;
|
|
@ -1,3 +0,0 @@
|
|||||||
export * from './auth-layout';
|
|
||||||
export * from './admin-layout';
|
|
||||||
export * from './default-page';
|
|
Loading…
Reference in New Issue
Block a user