feat(client): improve code

This commit is contained in:
chenos 2022-02-20 10:21:22 +08:00
parent ab78655004
commit e56b2b7bf6
13 changed files with 147 additions and 40 deletions

View File

@ -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>

View File

@ -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>
);
};

View File

@ -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>
); );
}; };

View File

@ -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);

View File

@ -13,7 +13,12 @@ export const MarkdownVoidDesigner = () => {
}} }}
/> />
<SchemaSettings.Divider /> <SchemaSettings.Divider />
<SchemaSettings.Remove /> <SchemaSettings.Remove
removeParentsIfNoChildren
breakRemoveOn={{
'x-component': 'Grid',
}}
/>
</GeneralSchemaDesigner> </GeneralSchemaDesigner>
); );
}; };

View File

@ -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>
); );
}; };

View File

@ -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>
); );

View File

@ -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>
); );

View File

@ -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',
}, },
}, },
], ],

View File

@ -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}`,

View File

@ -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>
); );
}); });

View File

@ -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'}>
{props.children} <Space size={2} align={'center'}>
</SchemaSettings> <DragHandler>
<DragHandler /> <DragOutlined />
</DragHandler>
<SchemaSettings title={<MenuOutlined style={{ cursor: 'pointer', fontSize: 12 }} />} {...schemaSettingsProps}>
{props.children}
</SchemaSettings>
</Space>
</div>
</div> </div>
); );
}; };

View File

@ -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,
});
}} }}
> >