mirror of
https://gitee.com/nocobase/nocobase.git
synced 2024-11-30 19:28:34 +08:00
feat(client): improve code
This commit is contained in:
parent
ab78655004
commit
e56b2b7bf6
@ -1,3 +1,5 @@
|
|||||||
|
import { css } from '@emotion/css';
|
||||||
|
import cls from 'classnames';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { SortableItem } from '../../common';
|
import { SortableItem } from '../../common';
|
||||||
import { useDesigner } from '../../hooks';
|
import { useDesigner } from '../../hooks';
|
||||||
@ -5,7 +7,55 @@ import { useDesigner } from '../../hooks';
|
|||||||
export const BlockItem: React.FC<any> = (props) => {
|
export const BlockItem: React.FC<any> = (props) => {
|
||||||
const Designer = useDesigner();
|
const Designer = useDesigner();
|
||||||
return (
|
return (
|
||||||
<SortableItem className={'nb-block-item'} style={{ position: 'relative' }}>
|
<SortableItem
|
||||||
|
className={cls(
|
||||||
|
'nb-block-item',
|
||||||
|
props.className,
|
||||||
|
css`
|
||||||
|
position: relative;
|
||||||
|
&:hover {
|
||||||
|
> .general-schema-designer {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&.nb-form-item:hover {
|
||||||
|
.general-schema-designer {
|
||||||
|
background: rgba(241, 139, 98, 0.06) !important;
|
||||||
|
border: 0 !important;
|
||||||
|
top: -5px !important;
|
||||||
|
bottom: -5px !important;
|
||||||
|
left: -5px !important;
|
||||||
|
right: -5px !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.general-schema-designer {
|
||||||
|
position: absolute;
|
||||||
|
z-index: 999;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
display: none;
|
||||||
|
border: 2px solid rgba(241, 139, 98, 0.3);
|
||||||
|
pointer-events: none;
|
||||||
|
.general-schema-designer-icons {
|
||||||
|
position: absolute;
|
||||||
|
right: 2px;
|
||||||
|
top: 2px;
|
||||||
|
line-height: 16px;
|
||||||
|
pointer-events: all;
|
||||||
|
.ant-space-item {
|
||||||
|
background-color: #f18b62;
|
||||||
|
color: #fff;
|
||||||
|
line-height: 16px;
|
||||||
|
width: 16px;
|
||||||
|
padding-left: 1px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
)}
|
||||||
|
>
|
||||||
<Designer />
|
<Designer />
|
||||||
{props.children}
|
{props.children}
|
||||||
</SortableItem>
|
</SortableItem>
|
||||||
|
@ -1,11 +1,25 @@
|
|||||||
import { FormItem as Item } from '@formily/antd';
|
import { FormItem as Item } from '@formily/antd';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { GeneralSchemaDesigner, SchemaSettings } from '../../../schema-settings';
|
||||||
import { BlockItem } from '../block-item';
|
import { BlockItem } from '../block-item';
|
||||||
|
|
||||||
export const FormItem: React.FC = (props) => {
|
export const FormItem: any = (props) => {
|
||||||
return (
|
return (
|
||||||
<BlockItem className={'nb-form-item'}>
|
<BlockItem className={'nb-form-item'}>
|
||||||
<Item {...props} />
|
<Item {...props} />
|
||||||
</BlockItem>
|
</BlockItem>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
FormItem.Designer = () => {
|
||||||
|
return (
|
||||||
|
<GeneralSchemaDesigner>
|
||||||
|
<SchemaSettings.Remove
|
||||||
|
removeParentsIfNoChildren
|
||||||
|
breakRemoveOn={{
|
||||||
|
'x-component': 'Grid',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</GeneralSchemaDesigner>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
@ -4,7 +4,12 @@ import { GeneralSchemaDesigner, SchemaSettings } from '../../../schema-settings'
|
|||||||
export const FormDesigner = () => {
|
export const FormDesigner = () => {
|
||||||
return (
|
return (
|
||||||
<GeneralSchemaDesigner>
|
<GeneralSchemaDesigner>
|
||||||
<SchemaSettings.Remove />
|
<SchemaSettings.Remove
|
||||||
|
removeParentsIfNoChildren
|
||||||
|
breakRemoveOn={{
|
||||||
|
'x-component': 'Grid',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
</GeneralSchemaDesigner>
|
</GeneralSchemaDesigner>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -17,7 +17,7 @@ const ColDivider = (props) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const droppableStyle = {
|
const droppableStyle = {
|
||||||
backgroundColor: isOver ? 'green' : undefined,
|
backgroundColor: isOver ? 'rgba(241, 139, 98, .1)' : undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
return <div ref={setNodeRef} style={{ width: 24, ...droppableStyle }}></div>;
|
return <div ref={setNodeRef} style={{ width: 24, ...droppableStyle }}></div>;
|
||||||
@ -32,7 +32,7 @@ const RowDivider = (props) => {
|
|||||||
const droppableStyle = {};
|
const droppableStyle = {};
|
||||||
|
|
||||||
if (isOver) {
|
if (isOver) {
|
||||||
droppableStyle['backgroundColor'] = 'green';
|
droppableStyle['backgroundColor'] = 'rgba(241, 139, 98, .1)';
|
||||||
}
|
}
|
||||||
|
|
||||||
const [active, setActive] = useState(false);
|
const [active, setActive] = useState(false);
|
||||||
|
@ -13,7 +13,12 @@ export const MarkdownVoidDesigner = () => {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<SchemaSettings.Divider />
|
<SchemaSettings.Divider />
|
||||||
<SchemaSettings.Remove />
|
<SchemaSettings.Remove
|
||||||
|
removeParentsIfNoChildren
|
||||||
|
breakRemoveOn={{
|
||||||
|
'x-component': 'Grid',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
</GeneralSchemaDesigner>
|
</GeneralSchemaDesigner>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -4,7 +4,12 @@ import { GeneralSchemaDesigner, SchemaSettings } from '../../../schema-settings'
|
|||||||
export const VoidTableDesigner = () => {
|
export const VoidTableDesigner = () => {
|
||||||
return (
|
return (
|
||||||
<GeneralSchemaDesigner>
|
<GeneralSchemaDesigner>
|
||||||
<SchemaSettings.Remove />
|
<SchemaSettings.Remove
|
||||||
|
removeParentsIfNoChildren
|
||||||
|
breakRemoveOn={{
|
||||||
|
'x-component': 'Grid',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
</GeneralSchemaDesigner>
|
</GeneralSchemaDesigner>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { DndContext as DndKitContext, DragEndEvent, rectIntersection } from '@dnd-kit/core';
|
import { DndContext as DndKitContext, DragEndEvent, DragOverlay, rectIntersection } from '@dnd-kit/core';
|
||||||
import { observer } from '@formily/react';
|
import { observer } from '@formily/react';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { useAPIClient } from '../../../';
|
import { useAPIClient } from '../../../';
|
||||||
@ -49,6 +49,9 @@ const useDragEnd = () => {
|
|||||||
export const DndContext = observer((props) => {
|
export const DndContext = observer((props) => {
|
||||||
return (
|
return (
|
||||||
<DndKitContext collisionDetection={rectIntersection} onDragEnd={useDragEnd()}>
|
<DndKitContext collisionDetection={rectIntersection} onDragEnd={useDragEnd()}>
|
||||||
|
<DragOverlay>
|
||||||
|
<span style={{ whiteSpace: 'nowrap' }}>拖拽中</span>
|
||||||
|
</DragOverlay>
|
||||||
{props.children}
|
{props.children}
|
||||||
</DndKitContext>
|
</DndKitContext>
|
||||||
);
|
);
|
||||||
|
@ -19,7 +19,7 @@ export const Sortable = (props: any) => {
|
|||||||
const droppableStyle = { ...style };
|
const droppableStyle = { ...style };
|
||||||
|
|
||||||
if (isOver) {
|
if (isOver) {
|
||||||
droppableStyle['color'] = 'green';
|
droppableStyle['color'] = 'rgba(241, 139, 98, .1)';
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -35,17 +35,13 @@ export const SortableItem: React.FC<any> = observer((props) => {
|
|||||||
const field = useField();
|
const field = useField();
|
||||||
const fieldSchema = useFieldSchema();
|
const fieldSchema = useFieldSchema();
|
||||||
return (
|
return (
|
||||||
<Sortable
|
<Sortable {...props} id={field.address.toString()} data={{ insertAdjacent: 'afterEnd', schema: fieldSchema }}>
|
||||||
{...props}
|
|
||||||
id={field.address.toString()}
|
|
||||||
data={{ insertAdjacent: 'afterEnd', schema: fieldSchema }}
|
|
||||||
>
|
|
||||||
{props.children}
|
{props.children}
|
||||||
</Sortable>
|
</Sortable>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
export const DragHandler = () => {
|
export const DragHandler = (props) => {
|
||||||
const { isDragging, attributes, listeners, setNodeRef, transform } = useContext(DraggableContext);
|
const { isDragging, attributes, listeners, setNodeRef, transform } = useContext(DraggableContext);
|
||||||
const style = transform
|
const style = transform
|
||||||
? {
|
? {
|
||||||
@ -57,18 +53,19 @@ export const DragHandler = () => {
|
|||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
display: 'inline-block',
|
display: 'inline-block',
|
||||||
|
width: 12,
|
||||||
|
height: 12,
|
||||||
|
lineHeight: '12px',
|
||||||
|
textAlign: 'left',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div style={{ display: isDragging ? 'inline-block' : 'none', fontSize: 10, position: 'absolute', zIndex: 0 }}>
|
|
||||||
Drag
|
|
||||||
</div>
|
|
||||||
<div
|
<div
|
||||||
ref={setNodeRef}
|
ref={setNodeRef}
|
||||||
style={{
|
style={{
|
||||||
...style,
|
// ...style,
|
||||||
position: 'relative',
|
position: 'relative',
|
||||||
zIndex: 1,
|
zIndex: 1,
|
||||||
backgroundColor: '#333',
|
// backgroundColor: '#333',
|
||||||
lineHeight: 0,
|
lineHeight: 0,
|
||||||
height: 2,
|
height: 2,
|
||||||
width: 2,
|
width: 2,
|
||||||
@ -78,7 +75,7 @@ export const DragHandler = () => {
|
|||||||
{...listeners}
|
{...listeners}
|
||||||
{...attributes}
|
{...attributes}
|
||||||
>
|
>
|
||||||
<div style={{ fontSize: 10 }}>Drag</div>
|
<span style={{ cursor: 'move', fontSize: 12 }}>{props.children}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -58,21 +58,20 @@ export const DetailsActionInitializer = observer((props: any) => {
|
|||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
type: 'item',
|
type: 'item',
|
||||||
title: 'Create',
|
title: 'Edit',
|
||||||
component: InitializeAction,
|
component: InitializeAction,
|
||||||
schema: {
|
schema: {
|
||||||
title: 'Create',
|
title: 'Edit',
|
||||||
'x-action': 'posts:create',
|
'x-action': 'update',
|
||||||
'x-align': 'left',
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'item',
|
type: 'item',
|
||||||
title: 'Update',
|
title: 'Delete',
|
||||||
component: InitializeAction,
|
component: InitializeAction,
|
||||||
schema: {
|
schema: {
|
||||||
title: 'Update',
|
title: 'Delete',
|
||||||
'x-action': 'posts:update',
|
'x-action': 'delete',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -16,7 +16,7 @@ const useFormItems = () => {
|
|||||||
component: InitializeFormItem,
|
component: InitializeFormItem,
|
||||||
schema: {
|
schema: {
|
||||||
name: field.name,
|
name: field.name,
|
||||||
'x-designer': 'TestDesigner',
|
'x-designer': 'FormItem.Designer',
|
||||||
'x-component': 'CollectionField',
|
'x-component': 'CollectionField',
|
||||||
'x-decorator': 'FormItem',
|
'x-decorator': 'FormItem',
|
||||||
'x-collection-field': `${name}.${field.name}`,
|
'x-collection-field': `${name}.${field.name}`,
|
||||||
|
@ -92,7 +92,14 @@ SchemaInitializer.Button = observer((props: SchemaInitializerButtonProps) => {
|
|||||||
{...dropdown}
|
{...dropdown}
|
||||||
overlay={menu}
|
overlay={menu}
|
||||||
>
|
>
|
||||||
<Button {...others} />
|
<Button
|
||||||
|
{...others}
|
||||||
|
type={'dashed'}
|
||||||
|
style={{
|
||||||
|
borderColor: '#f18b62',
|
||||||
|
color: '#f18b62',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
</Dropdown>
|
</Dropdown>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
|
import { DragOutlined, MenuOutlined } from '@ant-design/icons';
|
||||||
import { useField, useFieldSchema } from '@formily/react';
|
import { useField, useFieldSchema } from '@formily/react';
|
||||||
|
import { Space } from 'antd';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { DragHandler, useDesignable } from '../schema-component';
|
import { DragHandler, useDesignable } from '../schema-component';
|
||||||
import { SchemaSettings } from './SchemaSettings';
|
import { SchemaSettings } from './SchemaSettings';
|
||||||
@ -13,11 +15,17 @@ export const GeneralSchemaDesigner = (props: any) => {
|
|||||||
fieldSchema,
|
fieldSchema,
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<div>
|
<div className={'general-schema-designer'}>
|
||||||
<SchemaSettings title={'配置'} {...schemaSettingsProps}>
|
<div className={'general-schema-designer-icons'}>
|
||||||
|
<Space size={2} align={'center'}>
|
||||||
|
<DragHandler>
|
||||||
|
<DragOutlined />
|
||||||
|
</DragHandler>
|
||||||
|
<SchemaSettings title={<MenuOutlined style={{ cursor: 'pointer', fontSize: 12 }} />} {...schemaSettingsProps}>
|
||||||
{props.children}
|
{props.children}
|
||||||
</SchemaSettings>
|
</SchemaSettings>
|
||||||
<DragHandler />
|
</Space>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { GeneralField } from '@formily/core';
|
import { GeneralField } from '@formily/core';
|
||||||
import { Schema } from '@formily/react';
|
import { ISchema, Schema } from '@formily/react';
|
||||||
import { Dropdown, Menu, MenuItemProps } from 'antd';
|
import { Dropdown, Menu, MenuItemProps } from 'antd';
|
||||||
import React, { createContext, useContext } from 'react';
|
import React, { createContext, useContext } from 'react';
|
||||||
import { Designable } from '..';
|
import { Designable } from '..';
|
||||||
@ -23,8 +23,13 @@ export const useSchemaSettings = () => {
|
|||||||
return useContext(SchemaSettingsContext);
|
return useContext(SchemaSettingsContext);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
interface RemoveProps {
|
||||||
|
removeParentsIfNoChildren?: boolean;
|
||||||
|
breakRemoveOn?: ISchema | ((s: ISchema) => boolean);
|
||||||
|
}
|
||||||
|
|
||||||
type SchemaSettingsNested = {
|
type SchemaSettingsNested = {
|
||||||
Remove?: React.FC;
|
Remove?: React.FC<RemoveProps>;
|
||||||
Item?: React.FC<MenuItemProps>;
|
Item?: React.FC<MenuItemProps>;
|
||||||
Divider?: React.FC;
|
Divider?: React.FC;
|
||||||
[key: string]: any;
|
[key: string]: any;
|
||||||
@ -59,7 +64,11 @@ export const SchemaSettings: React.FC<SchemaSettingsProps> & SchemaSettingsNeste
|
|||||||
};
|
};
|
||||||
|
|
||||||
SchemaSettings.Item = (props) => {
|
SchemaSettings.Item = (props) => {
|
||||||
return <Menu.Item {...props}>{props.children || props.title}</Menu.Item>;
|
return (
|
||||||
|
<Menu.Item {...props} style={{ minWidth: 120 }}>
|
||||||
|
{props.children || props.title}
|
||||||
|
</Menu.Item>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
SchemaSettings.ItemGroup = (props) => {
|
SchemaSettings.ItemGroup = (props) => {
|
||||||
@ -74,12 +83,17 @@ SchemaSettings.Divider = (props) => {
|
|||||||
return <Menu.Divider {...props} />;
|
return <Menu.Divider {...props} />;
|
||||||
};
|
};
|
||||||
|
|
||||||
SchemaSettings.Remove = () => {
|
SchemaSettings.Remove = (props: any) => {
|
||||||
|
const { removeParentsIfNoChildren, breakRemoveOn } = props;
|
||||||
const { dn } = useSchemaSettings();
|
const { dn } = useSchemaSettings();
|
||||||
return (
|
return (
|
||||||
<Menu.Item
|
<Menu.Item
|
||||||
|
style={{ minWidth: 120 }}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
dn.remove();
|
dn.remove(null, {
|
||||||
|
removeParentsIfNoChildren,
|
||||||
|
breakRemoveOn,
|
||||||
|
});
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
移除
|
移除
|
||||||
|
Loading…
Reference in New Issue
Block a user