mirror of
https://gitee.com/nocobase/nocobase.git
synced 2024-12-05 05:38:23 +08:00
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}>
|
||||
<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={() => {
|
||||
insertBefore({
|
||||
type: 'void',
|
||||
title: uid(),
|
||||
"x-component": 'Menu.Item',
|
||||
})
|
||||
}} style={{ minWidth: 150 }}>
|
||||
<AntdMenu.Item
|
||||
onClick={() => {
|
||||
insertBefore({
|
||||
type: 'void',
|
||||
title: uid(),
|
||||
'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;
|
||||
@ -60,4 +62,16 @@
|
||||
right: -20px;
|
||||
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>
|
||||
</Layout.Header>
|
||||
<Layout>
|
||||
<Layout.Sider ref={ref} theme={'light'} width={200}>
|
||||
</Layout.Sider>
|
||||
<Layout.Content>
|
||||
{location.pathname}
|
||||
<Content activeKey={activeKey}/>
|
||||
</Layout.Content>
|
||||
</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 }) {
|
||||
@ -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