增加三方接口管理
This commit is contained in:
parent
f52f1bed8b
commit
1d222da2dc
@ -1,6 +1,6 @@
|
||||
.container {
|
||||
width: 100%;
|
||||
height: 600px;
|
||||
min-height: 600px;
|
||||
position: relative;
|
||||
background: #fff;
|
||||
border: 1px solid #e8e8e8;
|
||||
@ -10,7 +10,24 @@
|
||||
|
||||
.canvas {
|
||||
flex: 1;
|
||||
height: 100%;
|
||||
min-height: 600px;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
background: #fafafa;
|
||||
}
|
||||
|
||||
.canvas::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-image:
|
||||
linear-gradient(#e8e8e8 1px, transparent 1px),
|
||||
linear-gradient(90deg, #e8e8e8 1px, transparent 1px);
|
||||
background-size: 20px 20px;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.configPanel {
|
||||
@ -18,10 +35,58 @@
|
||||
height: 100%;
|
||||
border-left: 1px solid #e8e8e8;
|
||||
overflow-y: auto;
|
||||
background: #fff;
|
||||
box-shadow: -2px 0 8px rgba(0, 0, 0, 0.06);
|
||||
}
|
||||
|
||||
:global(.lf-control) {
|
||||
position: absolute;
|
||||
right: 330px;
|
||||
top: 10px;
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
background: #fff;
|
||||
padding: 4px;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
:global(.lf-dnd-panel) {
|
||||
position: absolute;
|
||||
left: 10px;
|
||||
top: 10px;
|
||||
width: 160px;
|
||||
background: #fff;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
|
||||
padding: 12px;
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
:global(.lf-dnd-panel .lf-dnd-item) {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
height: 35px;
|
||||
border: 1px solid #e8e8e8;
|
||||
border-radius: 4px;
|
||||
cursor: grab;
|
||||
user-select: none;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
:global(.lf-dnd-panel .lf-dnd-item:hover) {
|
||||
border-color: #1890ff;
|
||||
color: #1890ff;
|
||||
}
|
||||
|
||||
:global(.lf-dnd-panel .lf-dnd-item img) {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
margin-right: 8px;
|
||||
}
|
||||
@ -1,7 +1,7 @@
|
||||
import React, { useEffect, useRef, useState } from 'react';
|
||||
import { Card, Space } from 'antd';
|
||||
import { Card } from 'antd';
|
||||
import LogicFlow from '@logicflow/core';
|
||||
import { DndPanel, SelectionSelect, Control } from '@logicflow/extension';
|
||||
import { DndPanel, SelectionSelect, Control, Menu } from '@logicflow/extension';
|
||||
import '@logicflow/core/es/index.css';
|
||||
import '@logicflow/extension/es/style/index.css';
|
||||
import styles from './index.module.css';
|
||||
@ -21,20 +21,95 @@ const FlowDesigner: React.FC<FlowDesignerProps> = ({
|
||||
const [lf, setLf] = useState<LogicFlow>();
|
||||
const [selectedNode, setSelectedNode] = useState<any>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (containerRef.current) {
|
||||
// 初始化 LogicFlow
|
||||
// 初始化 LogicFlow
|
||||
const initLogicFlow = () => {
|
||||
if (!containerRef.current) {
|
||||
console.error('Container ref is not ready');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// 注册插件
|
||||
LogicFlow.use(DndPanel);
|
||||
LogicFlow.use(SelectionSelect);
|
||||
LogicFlow.use(Control);
|
||||
LogicFlow.use(Menu);
|
||||
|
||||
const logicflow = new LogicFlow({
|
||||
container: containerRef.current,
|
||||
grid: true,
|
||||
plugins: [DndPanel, SelectionSelect, Control]
|
||||
nodeTextEdit: true,
|
||||
edgeTextEdit: true,
|
||||
width: containerRef.current.offsetWidth || 800,
|
||||
height: containerRef.current.offsetHeight || 600,
|
||||
style: {
|
||||
circle: {
|
||||
r: 30,
|
||||
stroke: '#000000',
|
||||
strokeWidth: 1,
|
||||
},
|
||||
rect: {
|
||||
width: 100,
|
||||
height: 50,
|
||||
stroke: '#000000',
|
||||
strokeWidth: 1,
|
||||
},
|
||||
diamond: {
|
||||
rx: 20,
|
||||
ry: 20,
|
||||
stroke: '#000000',
|
||||
strokeWidth: 1,
|
||||
},
|
||||
nodeText: {
|
||||
fontSize: 12,
|
||||
color: '#000000',
|
||||
},
|
||||
edgeText: {
|
||||
fontSize: 12,
|
||||
color: '#000000',
|
||||
background: {
|
||||
fill: '#FFFFFF',
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
console.log('LogicFlow instance created');
|
||||
|
||||
// 注册自定义节点
|
||||
registerNodes(logicflow);
|
||||
|
||||
// 配置拖拽面板
|
||||
logicflow.setPatternItems([
|
||||
{
|
||||
type: 'start',
|
||||
text: '开始节点',
|
||||
label: '开始节点',
|
||||
icon: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAADsSURBVDhP7ZQxDsIwDEV7AcZeggOwMXAFJg7BxMgBuAcrZ2DiGuwcgImNA3AFBgaWDhUlqhKnKWFh4EtWaif2s/OdAn8VY8wE13jEHR6wjUu0eIoL7ODBa0zQzlrswQWvcOcLSpzhFu2sxRN0wTZKLnGOT7jgHXZQcoYuOMKvkFZQcoMuKOdTkH4RpBWUdNEFU0idOsE7bnBYEL0gScvnkE5LgS44wA4+UHY5R3vMMtqZxB4+UQZkl+1M4hTf0K7Szjp4wQztrIMXlEFZQUkXL5jBf4KygpIuXjCDsoLyXwQzKCsoSWGwD3Q5p3qCzuvYAAAAAElFTkSuQmCC'
|
||||
},
|
||||
{
|
||||
type: 'task',
|
||||
text: '任务节点',
|
||||
label: '任务节点',
|
||||
icon: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAB5SURBVDhP7ZTBCYAwDEU7QkfxZi/eHMGbo3Rwhe7hCB3Bo+kHIZgmTUXQgw8k5Cd5tE34VUSkhw3ucYUTrNBiggUecYsNWkzwCyvc4QMtJviFJZ7wCS0mGIQVnvEFLSb4hRVe8A0tJhiEFd7wAy0m+IUVZmHxPyLZAYNFt+rXusajAAAAAElFTkSuQmCC'
|
||||
},
|
||||
{
|
||||
type: 'gateway',
|
||||
text: '网关节点',
|
||||
label: '网关节点',
|
||||
icon: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAACxSURBVDhP7ZQxDoMwDEU5AiM34AqMHXqFTj0EE2MP0L1bz8DENeicgYmNA3AFBgaWVrIiRyZRU1VIPPIT2Mb+NlYS8FeJMQ5wjkvc4QYnWKHFU5zjFtdeY4Z21mIHF7zAjS8ocYprtLMWj9AF2yi5wBk+4II32EHJKbrgAL9CWkHJFbqgnE9B+kWQVlDSRRdMIXXqCG+4wn5B9IIkLZ9DOi0FumAfW3hH2eUU7THLaGcSO/gBUb+nujmI/XsAAAAASUVORK5CYII='
|
||||
},
|
||||
{
|
||||
type: 'end',
|
||||
text: '结束节点',
|
||||
label: '结束节点',
|
||||
icon: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAADsSURBVDhP7ZQxDsIwDEV7AcZeggOwMXAFJg7BxMgBuAcrZ2DiGuwcgImNA3AFBgaWDhUlqhKnKWFh4EtWaif2s/OdAn8VY8wE13jEHR6wjUu0eIoL7ODBa0zQzlrswQWvcOcLSpzhFu2sxRN0wTZKLnGOT7jgHXZQcoYuOMKvkFZQcoMuKOdTkH4RpBWUdNEFU0idOsE7bnBYEL0gScvnkE5LgS44wA4+UHY5R3vMMtqZxB4+UQZkl+1M4hTf0K7Szjp4wQztrIMXlEFZQUkXL5jBf4KygpIuXjCDsoLyXwQzKCsoSWGwD3Q5p3qCzuvYAAAAAElFTkSuQmCC'
|
||||
}
|
||||
]);
|
||||
|
||||
// 注册事件
|
||||
logicflow.on('node:click', ({ data }) => {
|
||||
console.log('Node clicked:', data);
|
||||
setSelectedNode(data);
|
||||
});
|
||||
|
||||
@ -42,22 +117,45 @@ const FlowDesigner: React.FC<FlowDesignerProps> = ({
|
||||
setSelectedNode(null);
|
||||
});
|
||||
|
||||
// 如果有初始值,渲染流程图
|
||||
logicflow.on('history:change', () => {
|
||||
const graphData = logicflow.getGraphData();
|
||||
onChange?.(JSON.stringify(graphData));
|
||||
});
|
||||
|
||||
// 渲染初始数据
|
||||
if (value) {
|
||||
try {
|
||||
const graphData = JSON.parse(value);
|
||||
logicflow.render(graphData);
|
||||
console.log('Initial graph data rendered:', graphData);
|
||||
} catch (error) {
|
||||
console.error('Failed to parse graph data:', error);
|
||||
logicflow.render({ nodes: [], edges: [] });
|
||||
}
|
||||
} else {
|
||||
logicflow.render({ nodes: [], edges: [] });
|
||||
console.log('Empty graph rendered');
|
||||
}
|
||||
|
||||
setLf(logicflow);
|
||||
console.log('LogicFlow initialization completed');
|
||||
|
||||
return () => {
|
||||
logicflow.destroy();
|
||||
};
|
||||
return logicflow;
|
||||
} catch (error) {
|
||||
console.error('Failed to initialize LogicFlow:', error);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const logicflow = initLogicFlow();
|
||||
|
||||
return () => {
|
||||
if (logicflow) {
|
||||
console.log('Destroying LogicFlow instance');
|
||||
logicflow.destroy();
|
||||
}
|
||||
};
|
||||
}, []);
|
||||
|
||||
// 处理节点配置更新
|
||||
@ -74,7 +172,11 @@ const FlowDesigner: React.FC<FlowDesignerProps> = ({
|
||||
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
<div className={styles.canvas} ref={containerRef} />
|
||||
<div
|
||||
className={styles.canvas}
|
||||
ref={containerRef}
|
||||
style={{ minHeight: '600px' }}
|
||||
/>
|
||||
{selectedNode && (
|
||||
<div className={styles.configPanel}>
|
||||
<NodeConfig
|
||||
|
||||
@ -1,10 +1,14 @@
|
||||
import LogicFlow from '@logicflow/core';
|
||||
import { CircleNode, RectNode, DiamondNode } from '@logicflow/core';
|
||||
import { CircleNode, CircleNodeModel, RectNode, RectNodeModel, DiamondNode, DiamondNodeModel } from '@logicflow/core';
|
||||
|
||||
export function registerNodes(lf: LogicFlow) {
|
||||
// 开始节点
|
||||
class StartNode extends CircleNode {
|
||||
static extendKey = 'StartNode';
|
||||
class StartNodeModel extends CircleNodeModel {
|
||||
initNodeData(data: any) {
|
||||
super.initNodeData(data);
|
||||
this.r = 30;
|
||||
}
|
||||
|
||||
getNodeStyle() {
|
||||
const style = super.getNodeStyle();
|
||||
return {
|
||||
@ -13,11 +17,22 @@ export function registerNodes(lf: LogicFlow) {
|
||||
stroke: '#1890FF'
|
||||
};
|
||||
}
|
||||
|
||||
setAttributes() {
|
||||
this.text.editable = false;
|
||||
}
|
||||
}
|
||||
|
||||
class StartNodeView extends CircleNode { }
|
||||
|
||||
// 任务节点
|
||||
class TaskNode extends RectNode {
|
||||
static extendKey = 'TaskNode';
|
||||
class TaskNodeModel extends RectNodeModel {
|
||||
initNodeData(data: any) {
|
||||
super.initNodeData(data);
|
||||
this.width = 120;
|
||||
this.height = 60;
|
||||
}
|
||||
|
||||
getNodeStyle() {
|
||||
const style = super.getNodeStyle();
|
||||
return {
|
||||
@ -28,9 +43,16 @@ export function registerNodes(lf: LogicFlow) {
|
||||
}
|
||||
}
|
||||
|
||||
class TaskNodeView extends RectNode { }
|
||||
|
||||
// 网关节点
|
||||
class GatewayNode extends DiamondNode {
|
||||
static extendKey = 'GatewayNode';
|
||||
class GatewayNodeModel extends DiamondNodeModel {
|
||||
initNodeData(data: any) {
|
||||
super.initNodeData(data);
|
||||
this.rx = 40;
|
||||
this.ry = 40;
|
||||
}
|
||||
|
||||
getNodeStyle() {
|
||||
const style = super.getNodeStyle();
|
||||
return {
|
||||
@ -41,9 +63,15 @@ export function registerNodes(lf: LogicFlow) {
|
||||
}
|
||||
}
|
||||
|
||||
class GatewayNodeView extends DiamondNode { }
|
||||
|
||||
// 结束节点
|
||||
class EndNode extends CircleNode {
|
||||
static extendKey = 'EndNode';
|
||||
class EndNodeModel extends CircleNodeModel {
|
||||
initNodeData(data: any) {
|
||||
super.initNodeData(data);
|
||||
this.r = 30;
|
||||
}
|
||||
|
||||
getNodeStyle() {
|
||||
const style = super.getNodeStyle();
|
||||
return {
|
||||
@ -52,30 +80,39 @@ export function registerNodes(lf: LogicFlow) {
|
||||
stroke: '#FF4D4F'
|
||||
};
|
||||
}
|
||||
|
||||
setAttributes() {
|
||||
this.text.editable = false;
|
||||
}
|
||||
}
|
||||
|
||||
class EndNodeView extends CircleNode { }
|
||||
|
||||
// 注册节点
|
||||
lf.register({
|
||||
type: 'start',
|
||||
view: StartNode,
|
||||
model: StartNode
|
||||
view: StartNodeView,
|
||||
model: StartNodeModel
|
||||
});
|
||||
|
||||
lf.register({
|
||||
type: 'task',
|
||||
view: TaskNode,
|
||||
model: TaskNode
|
||||
view: TaskNodeView,
|
||||
model: TaskNodeModel
|
||||
});
|
||||
|
||||
lf.register({
|
||||
type: 'gateway',
|
||||
view: GatewayNode,
|
||||
model: GatewayNode
|
||||
view: GatewayNodeView,
|
||||
model: GatewayNodeModel
|
||||
});
|
||||
|
||||
lf.register({
|
||||
type: 'end',
|
||||
view: EndNode,
|
||||
model: EndNode
|
||||
view: EndNodeView,
|
||||
model: EndNodeModel
|
||||
});
|
||||
|
||||
// 设置默认连线类型
|
||||
lf.setDefaultEdgeType('polyline');
|
||||
}
|
||||
@ -1,7 +1,6 @@
|
||||
import React, { useState } from 'react';
|
||||
import { Card, Tabs } from 'antd';
|
||||
import type { TabsProps } from 'antd';
|
||||
import FormRender from 'form-render';
|
||||
import { Card } from 'antd';
|
||||
import FormRender, { useForm } from 'form-render';
|
||||
|
||||
interface FormDesignerProps {
|
||||
value?: string;
|
||||
@ -32,6 +31,8 @@ const FormDesigner: React.FC<FormDesignerProps> = ({
|
||||
}
|
||||
});
|
||||
|
||||
const form = useForm();
|
||||
|
||||
const handleSubmit = (formData: any) => {
|
||||
console.log('Form data:', formData);
|
||||
};
|
||||
@ -44,6 +45,7 @@ const FormDesigner: React.FC<FormDesignerProps> = ({
|
||||
<div style={{ padding: 24 }}>
|
||||
<Card title="表单预览">
|
||||
<FormRender
|
||||
form={form}
|
||||
schema={schema}
|
||||
onFinish={handleSubmit}
|
||||
onValidate={handleValidate}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user