This commit is contained in:
asp_ly 2024-12-14 13:21:57 +08:00
parent b843b4603f
commit b0dadc9a24
2 changed files with 276 additions and 152 deletions

View File

@ -0,0 +1,110 @@
.workflow-design {
height: 100%;
display: flex;
flex-direction: column;
background: #fff;
.header {
padding: 16px;
border-bottom: 1px solid #f0f0f0;
display: flex;
justify-content: space-between;
align-items: center;
flex-shrink: 0;
.back-button {
margin-right: 16px;
}
.actions {
.ant-space-compact {
margin-right: 8px;
}
}
}
.content {
flex: 1;
min-height: 0;
display: flex;
padding: 16px;
gap: 16px;
.sidebar {
width: 280px;
flex-shrink: 0;
border-right: 1px solid #f0f0f0;
overflow-y: auto;
background: #fff;
border-radius: 4px;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
:global {
.ant-collapse {
border: none;
background: transparent;
.ant-collapse-item {
border-radius: 0;
.ant-collapse-header {
padding: 8px 16px;
}
.ant-collapse-content-box {
padding: 0;
}
}
}
}
.node-item {
padding: 8px 16px;
margin: 4px 8px;
border: 1px solid #d9d9d9;
border-radius: 4px;
cursor: move;
transition: all 0.3s;
&:hover {
background: #f5f5f5;
border-color: #1890ff;
}
}
}
.main-area {
flex: 1;
display: flex;
flex-direction: column;
min-width: 0;
.workflow-container {
flex: 1;
position: relative;
border: 1px solid #d9d9d9;
border-radius: 4px;
background: #f5f5f5;
overflow: hidden;
.workflow-canvas {
width: 100%;
height: 100%;
}
.minimap-container {
position: absolute;
right: 20px;
bottom: 20px;
width: 200px;
height: 150px;
border: 1px solid #f0f0f0;
border-radius: 4px;
background: #fff;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
z-index: 1;
}
}
}
}
}

View File

@ -1,6 +1,6 @@
import React, {useEffect, useState, useRef} from 'react';
import {useParams, useNavigate} from 'react-router-dom';
import {Button, Space, Card, Row, Col, message, Modal} from 'antd';
import {Button, Space, Card, Row, Col, message, Modal, Collapse} from 'antd';
import {
ArrowLeftOutlined,
SaveOutlined,
@ -18,6 +18,7 @@ import '@antv/x6-plugin-snapline';
import '@antv/x6-plugin-clipboard';
import '@antv/x6-plugin-history';
import { Selection } from '@antv/x6-plugin-selection';
import { MiniMap } from '@antv/x6-plugin-minimap';
import {getDefinitionDetail, saveDefinition} from '../service';
import {getNodeDefinitionList} from './service';
import NodePanel from './components/NodePanel';
@ -32,12 +33,14 @@ import {
HIGHLIGHTING_CONFIG,
DEFAULT_STYLES,
} from './constants';
import './index.less';
const WorkflowDesign: React.FC = () => {
const {id} = useParams<{ id: string }>();
const navigate = useNavigate();
const [title, setTitle] = useState<string>('工作流设计');
const graphContainerRef = useRef<HTMLDivElement>(null);
const minimapContainerRef = useRef<HTMLDivElement>(null);
const [graph, setGraph] = useState<Graph | null>(null);
const [selectedNode, setSelectedNode] = useState<Cell | null>(null);
const [selectedNodeDefinition, setSelectedNodeDefinition] = useState<NodeDefinition | null>(null);
@ -79,6 +82,8 @@ const WorkflowDesign: React.FC = () => {
background: {
color: '#f5f5f5',
},
width: graphContainerRef.current.clientWidth,
height: graphContainerRef.current.clientHeight,
});
// 注册选择插件
@ -94,6 +99,18 @@ const WorkflowDesign: React.FC = () => {
})
);
// 注册小地图插件
if (minimapContainerRef.current) {
graph.use(
new MiniMap({
container: minimapContainerRef.current,
width: 200,
height: 150,
padding: 10,
})
);
}
// 添加右键菜单
graph.on('node:contextmenu', ({cell, view, e}) => {
e.preventDefault();
@ -233,6 +250,11 @@ const WorkflowDesign: React.FC = () => {
};
}, [graphContainerRef, id, nodeDefinitions, isNodeDefinitionsLoaded]);
useEffect(() => {
if (!graph || !minimapContainerRef.current) return;
}, [graph]);
const loadDefinitionDetail = async (graphInstance: Graph, definitionId: string) => {
try {
const response = await getDefinitionDetail(Number(definitionId));
@ -399,26 +421,19 @@ const WorkflowDesign: React.FC = () => {
};
return (
<div>
<Row gutter={16}>
<Col span={4}>
<NodePanel
nodeDefinitions={nodeDefinitions}
onNodeDragStart={handleNodeDragStart}
/>
</Col>
<Col span={20}>
<Card
styles={{
body: {
padding: 0,
height: 'calc(100vh - 250px)',
background: '#f5f5f5',
border: '1px solid #d9d9d9',
borderRadius: '4px',
}
}}
extra={
<div className="workflow-design">
<div className="header">
<Space>
<Button
icon={<ArrowLeftOutlined />}
onClick={() => navigate('/workflow/definition')}
className="back-button"
>
</Button>
<span></span>
</Space>
<div className="actions">
<Space>
<Space.Compact>
<Button
@ -522,41 +537,40 @@ const WorkflowDesign: React.FC = () => {
title="重做"
/>
</Space.Compact>
<Button
icon={<SaveOutlined/>}
type="primary"
onClick={handleSaveWorkflow}
>
<Button onClick={handleSaveWorkflow} type="primary" icon={<SaveOutlined />}>
</Button>
<Button
icon={<ArrowLeftOutlined/>}
onClick={() => navigate('/workflow/definition')}
>
</Button>
</Space>
}
>
</div>
</div>
<div className="content">
<div className="sidebar">
<NodePanel
nodeDefinitions={nodeDefinitions}
onNodeDragStart={handleNodeDragStart}
/>
</div>
<div className="main-area">
<div className="workflow-container">
<div
ref={graphContainerRef}
style={{
width: '100%',
height: '100%',
}}
className="workflow-canvas"
onDrop={handleDrop}
onDragOver={handleDragOver}
/>
</Card>
</Col>
</Row>
<div ref={minimapContainerRef} className="minimap-container" />
</div>
</div>
</div>
{configModalVisible && selectedNode && selectedNodeDefinition && (
<NodeConfigDrawer
visible={configModalVisible}
node={selectedNode}
nodeDefinition={selectedNodeDefinition}
onOk={handleNodeConfigUpdate}
onCancel={() => setConfigModalVisible(false)}
onOk={handleNodeConfigUpdate}
/>
)}
</div>
);
};