refractor(web): 优化节点和流程图显示效果
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
import {PlusCircleFilled, RollbackOutlined, SaveFilled} from '@ant-design/icons'
|
import {PlusCircleFilled, RollbackOutlined, SaveFilled} from '@ant-design/icons'
|
||||||
import {Background, BackgroundVariant, Controls, MiniMap, ReactFlow} from '@xyflow/react'
|
import {Background, BackgroundVariant, Controls, MiniMap, Panel, ReactFlow} from '@xyflow/react'
|
||||||
import {Button, Dropdown, message, Popconfirm, Space} from 'antd'
|
import {Button, Dropdown, message, Popconfirm, Space} from 'antd'
|
||||||
import {arrToMap, isEqual, randomId, unique} from 'licia'
|
import {arrToMap, isEqual, randomId, unique} from 'licia'
|
||||||
import {useEffect} from 'react'
|
import {useEffect} from 'react'
|
||||||
@@ -34,13 +34,6 @@ const FlowableDiv = styled.div`
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.toolbar {
|
|
||||||
position: absolute;
|
|
||||||
right: 20px;
|
|
||||||
top: 20px;
|
|
||||||
z-index: 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
.node-card {
|
.node-card {
|
||||||
cursor: default;
|
cursor: default;
|
||||||
|
|
||||||
@@ -85,80 +78,6 @@ function FlowEditor(props: FlowEditorProps) {
|
|||||||
return (
|
return (
|
||||||
<FlowableDiv className="h-full w-full">
|
<FlowableDiv className="h-full w-full">
|
||||||
{contextHolder}
|
{contextHolder}
|
||||||
<Space className="toolbar">
|
|
||||||
<Dropdown
|
|
||||||
menu={{
|
|
||||||
items: unique(NodeRegistry.map(i => i.group))
|
|
||||||
.map(group => ({
|
|
||||||
type: 'group',
|
|
||||||
label: group,
|
|
||||||
children: NodeRegistry.filter(i => isEqual(group, i.group))
|
|
||||||
.map(i => ({key: i.key, label: i.name, icon: i.icon})),
|
|
||||||
})),
|
|
||||||
onClick: ({key}) => {
|
|
||||||
try {
|
|
||||||
if (commonInfo.debug) {
|
|
||||||
console.info('Add', key, JSON.stringify({nodes, edges, data}))
|
|
||||||
}
|
|
||||||
checkAddNode(key, nodes, edges)
|
|
||||||
|
|
||||||
let nodeId = randomId(10, 'qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM')
|
|
||||||
let define = NodeRegistryMap[key]
|
|
||||||
|
|
||||||
setDataById(
|
|
||||||
nodeId,
|
|
||||||
{
|
|
||||||
node: {
|
|
||||||
name: define.name,
|
|
||||||
description: define.description,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
addNode({
|
|
||||||
id: nodeId,
|
|
||||||
type: key,
|
|
||||||
position: {x: 100, y: 100},
|
|
||||||
data: {},
|
|
||||||
})
|
|
||||||
} catch (e) {
|
|
||||||
// @ts-ignore
|
|
||||||
messageApi.error(e.toString())
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Button type="default">
|
|
||||||
<PlusCircleFilled/>
|
|
||||||
新增节点
|
|
||||||
</Button>
|
|
||||||
</Dropdown>
|
|
||||||
<Popconfirm
|
|
||||||
title="返回上一页"
|
|
||||||
description="未保存的流程图将会被丢弃,确认是否返回"
|
|
||||||
onConfirm={() => navigate(-1)}
|
|
||||||
>
|
|
||||||
<Button type="default">
|
|
||||||
<RollbackOutlined/>
|
|
||||||
返回
|
|
||||||
</Button>
|
|
||||||
</Popconfirm>
|
|
||||||
<Button type="primary" onClick={() => {
|
|
||||||
try {
|
|
||||||
if (commonInfo.debug) {
|
|
||||||
console.info('Save', JSON.stringify({nodes, edges, data}))
|
|
||||||
}
|
|
||||||
checkSave(inputSchema, nodes, edges, data)
|
|
||||||
props.onGraphDataChange({nodes, edges, data})
|
|
||||||
} catch (e) {
|
|
||||||
// @ts-ignore
|
|
||||||
messageApi.error(e.toString())
|
|
||||||
}
|
|
||||||
}}>
|
|
||||||
<SaveFilled/>
|
|
||||||
保存
|
|
||||||
</Button>
|
|
||||||
</Space>
|
|
||||||
<ReactFlow
|
<ReactFlow
|
||||||
nodes={nodes}
|
nodes={nodes}
|
||||||
edges={edges}
|
edges={edges}
|
||||||
@@ -179,6 +98,82 @@ function FlowEditor(props: FlowEditorProps) {
|
|||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
nodeTypes={arrToMap(Object.keys(NodeRegistryMap), key => NodeRegistryMap[key]!.component)}
|
nodeTypes={arrToMap(Object.keys(NodeRegistryMap), key => NodeRegistryMap[key]!.component)}
|
||||||
>
|
>
|
||||||
|
<Panel position="top-right">
|
||||||
|
<Space className="toolbar">
|
||||||
|
<Dropdown
|
||||||
|
menu={{
|
||||||
|
items: unique(NodeRegistry.map(i => i.group))
|
||||||
|
.map(group => ({
|
||||||
|
type: 'group',
|
||||||
|
label: group,
|
||||||
|
children: NodeRegistry.filter(i => isEqual(group, i.group))
|
||||||
|
.map(i => ({key: i.key, label: i.name, icon: i.icon})),
|
||||||
|
})),
|
||||||
|
onClick: ({key}) => {
|
||||||
|
try {
|
||||||
|
if (commonInfo.debug) {
|
||||||
|
console.info('Add', key, JSON.stringify({nodes, edges, data}))
|
||||||
|
}
|
||||||
|
checkAddNode(key, nodes, edges)
|
||||||
|
|
||||||
|
let nodeId = randomId(10, 'qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM')
|
||||||
|
let define = NodeRegistryMap[key]
|
||||||
|
|
||||||
|
setDataById(
|
||||||
|
nodeId,
|
||||||
|
{
|
||||||
|
node: {
|
||||||
|
name: define.name,
|
||||||
|
description: define.description,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
addNode({
|
||||||
|
id: nodeId,
|
||||||
|
type: key,
|
||||||
|
position: {x: 100, y: 100},
|
||||||
|
data: {},
|
||||||
|
})
|
||||||
|
} catch (e) {
|
||||||
|
// @ts-ignore
|
||||||
|
messageApi.error(e.toString())
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Button type="default">
|
||||||
|
<PlusCircleFilled/>
|
||||||
|
新增节点
|
||||||
|
</Button>
|
||||||
|
</Dropdown>
|
||||||
|
<Popconfirm
|
||||||
|
title="返回上一页"
|
||||||
|
description="未保存的流程图将会被丢弃,确认是否返回"
|
||||||
|
onConfirm={() => navigate(-1)}
|
||||||
|
>
|
||||||
|
<Button type="default">
|
||||||
|
<RollbackOutlined/>
|
||||||
|
返回
|
||||||
|
</Button>
|
||||||
|
</Popconfirm>
|
||||||
|
<Button type="primary" onClick={() => {
|
||||||
|
try {
|
||||||
|
if (commonInfo.debug) {
|
||||||
|
console.info('Save', JSON.stringify({nodes, edges, data}))
|
||||||
|
}
|
||||||
|
checkSave(inputSchema, nodes, edges, data)
|
||||||
|
props.onGraphDataChange({nodes, edges, data})
|
||||||
|
} catch (e) {
|
||||||
|
// @ts-ignore
|
||||||
|
messageApi.error(e.toString())
|
||||||
|
}
|
||||||
|
}}>
|
||||||
|
<SaveFilled/>
|
||||||
|
保存
|
||||||
|
</Button>
|
||||||
|
</Space>
|
||||||
|
</Panel>
|
||||||
<Controls/>
|
<Controls/>
|
||||||
<MiniMap/>
|
<MiniMap/>
|
||||||
<Background variant={BackgroundVariant.Cross} gap={20} size={3}/>
|
<Background variant={BackgroundVariant.Cross} gap={20} size={3}/>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import {CopyFilled, DeleteFilled, EditFilled} from '@ant-design/icons'
|
import {CopyFilled, DeleteFilled, EditFilled} from '@ant-design/icons'
|
||||||
import {type Edge, Handle, type Node, type NodeProps, Position} from '@xyflow/react'
|
import {type Edge, Handle, type Node, type NodeProps, NodeToolbar, Position} from '@xyflow/react'
|
||||||
import type {Schema} from 'amis'
|
import type {Schema} from 'amis'
|
||||||
import {Button, Card, Drawer} from 'antd'
|
import {Button, Card, Drawer, Space, Tooltip} from 'antd'
|
||||||
import {type JSX, useCallback, useState} from 'react'
|
import {type JSX, useCallback, useState} from 'react'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components'
|
||||||
import {amisRender, commonInfo, horizontalFormOptions} from '../../../util/amis.tsx'
|
import {amisRender, commonInfo, horizontalFormOptions} from '../../../util/amis.tsx'
|
||||||
@@ -247,37 +247,42 @@ const AmisNode: (props: AmisNodeProps) => JSX.Element = ({
|
|||||||
>
|
>
|
||||||
{editDrawerForm}
|
{editDrawerForm}
|
||||||
</Drawer>
|
</Drawer>
|
||||||
|
<NodeToolbar>
|
||||||
|
<Space>
|
||||||
|
<Tooltip title="复制节点">
|
||||||
|
<Button
|
||||||
|
className="text-secondary"
|
||||||
|
disabled
|
||||||
|
type="text"
|
||||||
|
size="small"
|
||||||
|
icon={<CopyFilled/>}
|
||||||
|
/>
|
||||||
|
</Tooltip>
|
||||||
|
<Tooltip title="编辑节点">
|
||||||
|
<Button
|
||||||
|
className="text-secondary"
|
||||||
|
type="text"
|
||||||
|
size="small"
|
||||||
|
icon={<EditFilled/>}
|
||||||
|
onClick={() => onOpenEditDrawerClick()}
|
||||||
|
/>
|
||||||
|
</Tooltip>
|
||||||
|
<Tooltip title="删除节点">
|
||||||
|
<Button
|
||||||
|
className="text-secondary"
|
||||||
|
type="text"
|
||||||
|
size="small"
|
||||||
|
icon={<DeleteFilled/>}
|
||||||
|
onClick={() => onRemoveClick()}
|
||||||
|
/>
|
||||||
|
</Tooltip>
|
||||||
|
</Space>
|
||||||
|
</NodeToolbar>
|
||||||
<Card
|
<Card
|
||||||
className="node-card"
|
className="node-card"
|
||||||
title={nodeName}
|
title={nodeName}
|
||||||
extra={<span className="text-gray-300 text-xs">{id}</span>}
|
extra={<span className="text-gray-300 text-xs">{id}</span>}
|
||||||
size="small"
|
size="small"
|
||||||
actions={[
|
|
||||||
<Button
|
|
||||||
className="text-secondary"
|
|
||||||
disabled
|
|
||||||
type="text"
|
|
||||||
size="small"
|
|
||||||
icon={<CopyFilled/>}
|
|
||||||
block
|
|
||||||
/>,
|
|
||||||
<Button
|
|
||||||
className="text-secondary"
|
|
||||||
type="text"
|
|
||||||
size="small"
|
|
||||||
icon={<EditFilled/>}
|
|
||||||
block
|
|
||||||
onClick={() => onOpenEditDrawerClick()}
|
|
||||||
/>,
|
|
||||||
<Button
|
|
||||||
className="text-secondary"
|
|
||||||
type="text"
|
|
||||||
size="small"
|
|
||||||
icon={<DeleteFilled/>}
|
|
||||||
block
|
|
||||||
onClick={() => onRemoveClick()}
|
|
||||||
/>,
|
|
||||||
]}
|
|
||||||
>
|
>
|
||||||
<div className="card-description p-2 text-secondary text-sm">
|
<div className="card-description p-2 text-secondary text-sm">
|
||||||
{nodeDescription}
|
{nodeDescription}
|
||||||
|
|||||||
Reference in New Issue
Block a user