赞
踩
- // 创建项目
- npm create vite@latest my-react-flow-app -- --template react
- // 安装插件
- npm install reactflow
- npm install antd
- // 运行项目
- npm run dev
- import { useCallback, useState } from 'react';
- import ReactFlow,
- {
- addEdge,
- ReactFlowProvider,
- MiniMap,
- Controls,
- useNodesState,
- useEdgesState,
- useReactFlow,
- MarkerType,
- Panel,
- ConnectionMode
- } from 'reactflow';
- import 'reactflow/dist/style.css';
- import './index.css';
-
- import UpdateNode from './components/nodeContent';
- import UpdateEdge from './components/edgeContent';
- import ResizableNodeSelected from './components/ResizableNodeSelected';
- import {nodes as initialNodes1,edges as initialEdges1} from './components/data';
-
- const nodeTypes = {
- ResizableNodeSelected,
- };
-
- const rfStyle = {
- backgroundColor: '#B8CEFF',
- };
-
- const initialNodes = [
- {
- id: '1',
- type: 'ResizableNodeSelected',
- position: { x: 100, y: 100 },
- data: { label: '1' },
- style: {
- background: "#F3A011",
- color: "white",
- border: '1px solid orange',
- borderRadius: '100%',
- width: 80,
- height: 80,
- },
- },
- {
- id: '2',
- type: 'ResizableNodeSelected',
- position: { x: 200, y: 300 },
- data: { label: '2' },
- style: {
- background: "#F3A011",
- color: "white",
- border: '1px solid orange',
- borderRadius: '100%',
- width: 80,
- height: 80,
- },
- },
- {
- id: '3',
- type: 'ResizableNodeSelected',
- position: { x: 100, y: 500 },
- data: { label: '3' },
- style: {
- background: "#F3A011",
- color: "white",
- border: '1px solid orange',
- borderRadius: '100%',
- width: 80,
- height: 80,
- },
- },
- ];
- const initialEdges = [
- {
- id: 'e1-2',
- source: '1',
- target: '2',
- style: { stroke: "#116F97" },
- label: "连接1-2",
- sourceHandle: 'c',
- targetHandle: 'a',
- },
- {
- id: "e2-3",
- source: "2",
- target: "3",
- // labelStyle: { fill: "#116F97", fontWeight: 100 }, // 连接线名称样式
- style: { stroke: "#116F97" }, // 连接线颜色
- label: "连接2-3",
- sourceHandle: 'c',
- targetHandle: 'a',
- },
- ];
-
- const flowKey = 'flow_test';
- const localNodes = JSON.parse(localStorage.getItem(flowKey)).nodes;
- const localEdges = JSON.parse(localStorage.getItem(flowKey)).edges;
- let nodeId = 1;
-
- function App1() {
- const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes1);
- const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges1);
- const [nodeInfo, setNodeInfo] = useState({});
- const [edgeInfo, setEdgeInfo] = useState({});
- const [nodeShow, setNodeShow] = useState(true);
- const onConnect = useCallback(
- (connection) => setEdges((eds) => addEdge(connection, eds)),
- [setEdges]
- );
-
- // 保存
- const [rfInstance, setRfInstance] = useState({});
- const onSave = useCallback(() => {
- if (rfInstance) {
- const flow = rfInstance.toObject();
- localStorage.setItem(flowKey, JSON.stringify(flow));
- console.log(JSON.stringify(flow));
- }
- }, [rfInstance]
- );
-
- // 恢复
- const { setViewport } = useReactFlow();
- const onRestore = useCallback(() => {
- const restoreFlow = async () => {
- const flow = JSON.parse(localStorage.getItem(flowKey));
- if (flow) {
- const { x = 0, y = 0, zoom = 0 } = flow.viewport;
- setNodes(flow.nodes || []);
- setEdges(flow.edges || []);
- setViewport({ x, y, zoom });
- }
- };
- restoreFlow();
- }, [setNodes, setViewport]
- );
-
- // 清空
- const onDelete = useCallback(() => {
- const restoreFlow = async () => {
- setNodes([] || []);
- setEdges([] || []);
- };
- restoreFlow();
- }, [setNodes]
- );
-
- // 点击节点
- const onNodeClick = (e, node) => {
- setNodeInfo({
- ...node.data,
- id: node.id,
- nodeBg: node.style && node.style.background ? node.style.background : '#ffffff',
- });
- setNodeShow(true);
- };
-
- // 点击节点连接线
- const onEdgeClick = (e, edge) => {
- setEdgeInfo(edges.find((item) => edge.id === item.id));
- setNodeShow(false);
- };
-
-
- // 新增节点
- const reactFlowInstance = useReactFlow();
- const onAdd = useCallback(() => {
- const id = `${++nodeId}`;
- const newNode = {
- id,
- type: 'ResizableNodeSelected',
- position: {
- x: 100,
- y: 300,
- // x: Math.random() * 200,
- // y: Math.random() * 200,
- },
- data: {
- label: `Node ${id}`,
- },
- style: {
- background: "#F3A011",
- color: "white",
- border: '1px solid orange',
- borderRadius: '100%',
- width: 80,
- height: 80,
-
- },
- };
- reactFlowInstance.addNodes(newNode);
- }, []);
-
- // 改变节点内容
- const changeNode = (val) => {
- setNodes((nds) =>
- nds.map((item) => {
- if (item.id === val.id) {
- item.data = val;
- item.hidden = val.isHidden;
- item.style = { background: val.nodeBg, width: 80, height: 80, borderRadius: '100%', color: "white", fontSize: 2 };
- }
- return item;
- }),
- );
- };
-
- // 改变连接线内容
- const changeEdge = (val) => {
- setEdges((nds) =>
- nds.map((item) => {
- if (item.id === val.id) {
- item.label = val.label;
- item.type = val.type;
- item.hidden = val.isHidden;
- item.style = { stroke: val.color };
- }
- return item;
- }),
- );
- };
-
- // 默认edge样式
- const defaultEdgeOptions = {
- style: {
- strokeWidth: 1,
- stroke: '#116F97'
- },
- type: 'default',
- markerEnd: {
- type: MarkerType.ArrowClosed,
- color: '#116F97'
- } // 连接线尾部的箭头
- }
-
- return (
- <div style={{ width: '100vw', height: '100vh' }}>
-
- <ReactFlow
- nodes={nodes} // 节点
- edges={edges} // 连接线
- onNodesChange={onNodesChange} // 节点拖拽等改变
- onEdgesChange={onEdgesChange} // 连接线拖拽等改变
- onNodeClick={onNodeClick} // 点击节点
- onEdgeClick={onEdgeClick} // 点击连接线
- onConnect={onConnect} // 节点直接连接
- nodeTypes={nodeTypes} // 节点类型
- // edgeTypes={edgeTypes}
- fitView // 渲染节点数据
- style={rfStyle} // 背景色
- defaultEdgeOptions={defaultEdgeOptions} // 默认连接线样式
- onInit={setRfInstance} // 初始化保存的数据
- connectionMode={ConnectionMode.Loose}
- />
- {nodeShow ? (
- <UpdateNode info={nodeInfo} onChange={changeNode} />
- ) : (
- <UpdateEdge info={edgeInfo} onChange={changeEdge} />
- )}
- <Panel position='top-left'>
- <button onClick={onAdd}>add node</button>
- <button onClick={onSave}>save</button>
- <button onClick={onRestore}>restore</button>
- <button onClick={onDelete}>delete</button>
- </Panel>
- <MiniMap />
- <Controls />
- </div>
- );
- }
-
- export default function () {
- return (
- <ReactFlowProvider>
- <App1 />
-
- </ReactFlowProvider>
- );
- }
- :root {
- font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
- /* line-height: 2; */
- font-weight: 400;
-
- /* color-scheme: light dark; */
- color: rgba(255, 255, 255, 0.87);
- background-color: #242424;
-
- font-synthesis: none;
- text-rendering: optimizeLegibility;
- -webkit-font-smoothing: antialiased;
- -moz-osx-font-smoothing: grayscale;
- /* -webkit-text-size-adjust: 100%; */
- }
-
- a {
- font-weight: 500;
- color: #646cff;
- text-decoration: inherit;
- }
- a:hover {
- color: #535bf2;
- }
-
- body {
- margin: 0;
- display: flex;
- place-items: center;
- min-width: 320px;
- min-height: 100vh;
- }
-
- h1 {
- font-size: 3.2em;
- line-height: 1.1;
- }
-
- button {
- border-radius: 8px;
- border: 1px solid transparent;
- padding: 0.6em 1.2em;
- font-size: 1em;
- font-weight: 500;
- font-family: inherit;
- background-color: #1a1a1a;
- cursor: pointer;
- transition: border-color 0.25s;
- }
- button:hover {
- border-color: #646cff;
- }
- button:focus,
- button:focus-visible {
- outline: 4px auto -webkit-focus-ring-color;
- }
-
- @media (prefers-color-scheme: light) {
- :root {
- color: #213547;
- background-color: #ffffff;
- }
- a:hover {
- color: #116F97;
- }
- button {
- background-color: #f9f9f9;
- }
- }
-
- /* edge颜色 */
- .react-flow__handle{
- color: #116F97;
- background-color: #116F97;
- border:0;
- border-radius: 100%;
- min-width: 1px;
- min-height: 1px;
- }
- .react-flow__edge-textbg{
- fill:#3a94BB;
- }
- .react-flow__handle.connectionindicator{
- width: 1;
- height: 1;
- }
- .react-flow__node{
- width: 50;
- height: 50;
- }
-
-
- /* 4个连接点样式 */
- .simple-floatingedges {
- flex-direction: column;
- display: flex;
- flex-grow: 1;
- height: 100%;
- }
- .simple-floatingedges .react-flow__handle {
- width: 8px;
- height: 8px;
- background-color: #bbb;
- }
- .simple-floatingedges .react-flow__handle-top {
- top: -5px;
- }
- .simple-floatingedges .react-flow__handle-bottom {
- bottom: -5px;
- }
- .simple-floatingedges .react-flow__handle-left {
- left: -5px;
- }
- .simple-floatingedges .react-flow__handle-right {
- right: -5px;
- }
- .simple-floatingedges .react-flow__node-custom {
- background: #fff;
- border: 1px solid #1a192b;
- border-radius: 3px;
- color: #222;
- font-size: 12px;
- padding: 10px;
- text-align: center;
- width: 150px;
- }
-
- /* node与wdge编辑样式 */
- .dndflow {
- display: flex;
- flex-direction: column;
- flex-grow: 1;
- height: 70vh;
- }
- .react-flow__attribution {
- display: none;
- }
- .dndflow aside {
- padding: 15px 10px;
- font-size: 12px;
- background: #fcfcfc;
- border-right: 1px solid #eee;
- }
- .dndflow aside .description {
- margin-bottom: 10px;
- }
- .dndflow .dndnode {
- display: flex;
- align-items: center;
- justify-content: center;
- height: 20px;
- margin-bottom: 10px;
- padding: 4px;
- border: 1px solid #1a192b;
- border-radius: 2px;
- cursor: grab;
- }
- .dndflow .dndnode.input {
- border-color: #0041d0;
- }
- .dndflow .dndnode.output {
- border-color: #ff0072;
- }
- .dndflow .reactflow-wrapper {
- flex-grow: 1;
- height: 100%;
- }
- .dndflow .selectall {
- margin-top: 10px;
- }
- @media screen and (min-width: 768px) {
- .dndflow {
- flex-direction: row;
- }
-
- .dndflow aside {
- width: 20%;
- max-width: 250px;
- }
- }
- .my_handle {
- z-index: 99;
- }
- .nodeContent {
- position: relative;
- color: #222;
- font-size: 12px;
- line-height: 10px;
- text-align: center;
- background-color: #fff;
- border: 1px solid #1a192b;
- border-radius: 3px;
- }
- .nodeStyle {
- width: 110px;
- height: 30px;
- line-height: 10px;
- }
- .updatenode__controls {
- position: absolute;
- top: 10px;
- right: 10px;
- z-index: 4;
- padding: 16px;
- font-size: 12px;
- background-color: #fff;
- }
- .updatenode__controls label {
- display: block;
- }
- .updatenode__bglabel {
- margin-top: 10px;
- }
- .updatenode__checkboxwrapper {
- display: flex;
- align-items: center;
- margin-top: 10px;
- }
-
-
- import React, { useState, useEffect } from 'react';
- import { Input, Switch } from 'antd';
-
- export type nodeProps = {
- info: any;
- onChange: (val: any) => void;
- };
-
- export default ({ info, onChange }: nodeProps) => {
- const [nodeInfo, setNodeInfo] = useState<any>({});
-
- useEffect(() => {
- if (info.id) {
- if (!info.isHidden) {
- info.isHidden = false;
- }
- setNodeInfo(info);
- }
- }, [info.id]);
-
- // 改变名称
- const setNodeName = (value: string) => {
- setNodeInfo({
- ...nodeInfo,
- label: value,
- });
- onChange({
- ...nodeInfo,
- label: value,
- });
- };
-
- // 改变背景色
- const setNodeBg = (value: string) => {
- setNodeInfo({
- ...nodeInfo,
- nodeBg: value,
- });
- onChange({
- ...nodeInfo,
- nodeBg: value,
- });
- };
-
- // 是否隐藏
- const setNodeHidden = (value: boolean) => {
- setNodeInfo({
- ...nodeInfo,
- isHidden: value,
- });
- onChange({
- ...nodeInfo,
- isHidden: value,
- });
- };
-
- return nodeInfo.id ? (
- <div className="updatenode__controls">
- <label>名称:</label>
- <Input
- placeholder=""
- value={nodeInfo.label}
- onChange={(evt) => setNodeName(evt.target.value)}
- />
- <label className="updatenode__bglabel">背景色:</label>
- <Input type="color" value={nodeInfo.nodeBg} onChange={(evt) => setNodeBg(evt.target.value)} />
- <div className="updatenode__checkboxwrapper">
- <label>是否隐藏:</label>
- {/* <Switch checked={nodeInfo.isHidden} onChange={setNodeHidden} /> */}
- <input type='checkbox' checked={nodeInfo.isHidden} onChange={(evt) => setNodeHidden(evt.target.checked)} />
- </div>
- </div>
- ) : (
- <></>
- );
- };
- import React, { useState, useEffect } from 'react';
- import { Input, Select, Switch } from 'antd';
-
- const { Option } = Select;
-
- export type edgeProps = {
- info: any;
- onChange: (val: any) => void;
- };
-
- export default ({ info, onChange }: edgeProps) => {
- const [edgeInfo, setEdgeInfo] = useState<any>({});
- const edgeTypes = [
- { label: '曲线', value: 'default' },
- { label: '直线', value: 'straight' },
- { label: '直角线', value: 'step' },
- { label: '圆滑直角线', value: 'smoothstep' },
- ];
-
- useEffect(() => {
- if (info.id) {
- if (info.style) {
- info.color = info.style.stroke;
- }
- if (!info.isHidden) {
- info.isHidden = false;
- }
- setEdgeInfo(info);
- }
- }, [info.id]);
-
- // 改变名称
- const setNodeName = (value: string) => {
- setEdgeInfo({
- ...edgeInfo,
- label: value,
- });
- onChange({
- ...edgeInfo,
- label: value,
- });
- };
-
- // 改变颜色
- const setNodeBg = (value: string) => {
- setEdgeInfo({
- ...edgeInfo,
- color: value,
- });
- onChange({
- ...edgeInfo,
- color: value,
- });
- };
-
- // 改变类型
- const changeEdgeType = (value: string) => {
- setEdgeInfo({
- ...edgeInfo,
- type: value,
- });
- onChange({
- ...edgeInfo,
- type: value,
- });
- };
-
- // 是否隐藏
- const setEdgeHidden = (value: boolean) => {
- setEdgeInfo({
- ...edgeInfo,
- isHidden: value,
- });
- onChange({
- ...edgeInfo,
- isHidden: value,
- });
- };
-
- return edgeInfo.id ? (
- <div className="updatenode__controls">
- <label>连接线名称:</label>
- <Input
- placeholder=""
- value={edgeInfo.label}
- onChange={(evt) => setNodeName(evt.target.value)}
- />
- <label className="updatenode__bglabel">连接线颜色:</label>
- <Input type="color" value={edgeInfo.color} onChange={(evt) => setNodeBg(evt.target.value)} />
- <div className="updatenode__checkboxwrapper">
- <label>连接线类型:</label>
- <Select defaultValue="曲线 " value={edgeInfo.type} onChange={changeEdgeType}>
- {edgeTypes.map((item) => (
- <Option value={item.value} key={item.value}>
- {item.label}
- </Option>
- ))}
- </Select>
- </div>
- <div className="updatenode__checkboxwrapper">
- <label>是否隐藏:</label>
- <Switch checked={edgeInfo.isHidden} onChange={setEdgeHidden} />
- </div>
- </div>
- ) : (
- <></>
- );
- };
- import { memo } from 'react';
- import { Handle, Position, NodeResizer } from 'reactflow';
-
- const ResizableNodeSelected = ({ data, selected }) => {
- return (
- <>
- <NodeResizer color="#F3A011" isVisible={selected} minWidth={80} minHeight={80} />
- <div
- style={{
- // width: 60,
- // height: 60,
- padding: 10,
- // display: "flex",
- // justifyContent: "center",
- // alignItems: "center",
- // fontSize: 2
- }}
- >
- {data.label}
- </div>
- <Handle style={{ opacity: 0 }} type="source" position={Position.Top} id='a' />
- <Handle style={{ opacity: 0 }} type="source" position={Position.Right} id='b' />
- <Handle style={{ opacity: 0 }} type="source" position={Position.Bottom} id='c' />
- <Handle style={{ opacity: 0 }} type="source" position={Position.Left} id='d' />
- </>
- );
- };
-
- export default memo(ResizableNodeSelected);
- export const nodes = [
- { "width": 80, "height": 80, "id": "13", "type": "ResizableNodeSelected", "position": { "x": 181.99158953145331, "y": 472.7199877834713 }, "data": { "label": "服务实例JVM堆大小", "id": "13", "nodeBg": "#F3A011", "isHidden": false }, "style": { "background": "#F3A011", "width": 80, "height": 80, "borderRadius": "100%", "color": "white", "fontSize": 2 }, "selected": false, "positionAbsolute": { "x": 181.99158953145331, "y": 472.7199877834713 }, "dragging": false, "hidden": false },
- { "width": 80, "height": 80, "id": "12", "type": "ResizableNodeSelected", "position": { "x": 458.51664737488375, "y": 497.7400344424826 }, "data": { "label": "服务实例JVM线程数", "id": "12", "nodeBg": "#F3A011", "isHidden": false }, "style": { "background": "#F3A011", "width": 80, "height": 80, "borderRadius": "100%", "color": "white", "fontSize": 2 }, "selected": false, "positionAbsolute": { "x": 458.51664737488375, "y": 497.7400344424826 }, "dragging": false, "hidden": false },
- { "width": 80, "height": 80, "id": "11", "type": "ResizableNodeSelected", "position": { "x": 456.86503312460417, "y": 278.4940093032253 }, "data": { "label": "应用服务平均响应时长", "id": "11", "nodeBg": "#F3A011", "isHidden": false }, "style": { "background": "#F3A011", "width": 80, "height": 80, "borderRadius": "100%", "color": "white", "fontSize": 2 }, "selected": false, "positionAbsolute": { "x": 456.86503312460417, "y": 278.4940093032253 }, "dragging": false, "hidden": false },
- { "width": 80, "height": 80, "id": "10", "type": "ResizableNodeSelected", "position": { "x": 188.70901987307826, "y": 316.5335073980088 }, "data": { "label": "存储I/O负载", "id": "10", "nodeBg": "#F3A011", "isHidden": false }, "style": { "background": "#F3A011", "width": 80, "height": 80, "borderRadius": "100%", "color": "white", "fontSize": 2 }, "selected": false, "positionAbsolute": { "x": 188.70901987307826, "y": 316.5335073980088 }, "dragging": false, "hidden": false },
- { "width": 80, "height": 80, "id": "9", "type": "ResizableNodeSelected", "position": { "x": 86.9908194969212, "y": 56.769326529302944 }, "data": { "label": "服务端点平均响应时长", "id": "9", "nodeBg": "#F3A011", "isHidden": false }, "style": { "background": "#F3A011", "width": 80, "height": 80, "borderRadius": "100%", "color": "white", "fontSize": 2 }, "selected": false, "positionAbsolute": { "x": 86.9908194969212, "y": 56.769326529302944 }, "dragging": false, "hidden": false },
- { "width": 80, "height": 80, "id": "8", "type": "ResizableNodeSelected", "position": { "x": 461.40008223448365, "y": 92.49854876752454 }, "data": { "label": "服务实例", "id": "8", "nodeBg": "#F3A011", "isHidden": false }, "style": { "background": "#F3A011", "width": 80, "height": 80, "borderRadius": "100%", "color": "white", "fontSize": 2 }, "selected": false, "positionAbsolute": { "x": 461.40008223448365, "y": 92.49854876752454 }, "dragging": false, "hidden": false },
- { "width": 80, "height": 80, "id": "7", "type": "ResizableNodeSelected", "position": { "x": -87.30759005365732, "y": 133.76253323256137 }, "data": { "label": "端点链路(动态模型)平均响应时长", "id": "7", "nodeBg": "#F3A011", "isHidden": false }, "style": { "background": "#F3A011", "width": 80, "height": 80, "borderRadius": "100%", "color": "white", "fontSize": 4 }, "selected": false, "dragging": false, "hidden": false, "positionAbsolute": { "x": -87.30759005365732, "y": 133.76253323256137 } },
- { "width": 80, "height": 80, "id": "6", "type": "ResizableNodeSelected", "position": { "x": -11.910201399135396, "y": 485.8445794117532 }, "data": { "label": "主机I/O负载", "id": "6", "nodeBg": "#F3A011", "isHidden": false }, "style": { "background": "#F3A011", "width": 80, "height": 80, "borderRadius": "100%", "color": "white", "fontSize": 4 }, "selected": false, "dragging": false, "hidden": false, "positionAbsolute": { "x": -11.910201399135396, "y": 485.8445794117532 }, "resizing": false },
- { "width": 80, "height": 80, "id": "5", "type": "ResizableNodeSelected", "position": { "x": -10, "y": 280.5 }, "data": { "label": "Mysql实例慢查询", "id": "5", "nodeBg": "#F3A011", "isHidden": false }, "style": { "background": "#F3A011", "width": 80, "height": 80, "borderRadius": "100%", "color": "white", "fontSize": 4 }, "selected": false, "dragging": false, "hidden": false, "positionAbsolute": { "x": -10, "y": 280.5 } },
- { "width": 80, "height": 80, "id": "4", "type": "ResizableNodeSelected", "position": { "x": -282.5, "y": 453 }, "data": { "label": "主机内存使用率", "id": "4", "nodeBg": "#F3A011", "isHidden": false }, "style": { "background": "#F3A011", "width": 80, "height": 80, "borderRadius": "100%", "color": "white", "fontSize": 4 }, "selected": false, "dragging": false, "hidden": false, "positionAbsolute": { "x": -282.5, "y": 453 } },
- { "width": 80, "height": 80, "id": "3", "type": "ResizableNodeSelected", "position": { "x": -275, "y": 283 }, "data": { "label": "主机CPU使用率", "id": "3", "nodeBg": "#F3A011", "isHidden": false }, "style": { "background": "#F3A011", "width": 80, "height": 80, "borderRadius": "100%", "color": "white", "fontSize": 4 }, "selected": false, "positionAbsolute": { "x": -275, "y": 283 }, "dragging": false, "hidden": false },
- { "width": 80, "height": 80, "id": "2", "type": "ResizableNodeSelected", "position": { "x": -271, "y": 133.5 }, "data": { "label": "消息中间件堆积数", "id": "2", "nodeBg": "#F3A011", "isHidden": false }, "style": { "background": "#F3A011", "width": 80, "height": 80, "borderRadius": "100%", "color": "white", "fontSize": 4 }, "selected": false, "dragging": false, "hidden": false, "positionAbsolute": { "x": -271, "y": 133.5 } }
- ];
-
- export const edges = [
- { "style": { "stroke": "#116F97" }, "type": "smoothstep", "markerEnd": { "type": "arrowclosed", "color": "#116F97" }, "source": "4", "sourceHandle": "a", "target": "5", "targetHandle": "d", "id": "reactflow__edge-4a-5d", "selected": false, "hidden": true },
- { "style": { "stroke": "#116F97" }, "type": "straight", "markerEnd": { "type": "arrowclosed", "color": "#116F97" }, "source": "4", "sourceHandle": "b", "target": "5", "targetHandle": "c", "id": "reactflow__edge-4b-5c", "selected": false, "hidden": true },
- { "style": { "stroke": "#116F97" }, "type": "default", "markerEnd": { "type": "arrowclosed", "color": "#116F97" }, "source": "5", "sourceHandle": "d", "target": "4", "targetHandle": "a", "id": "reactflow__edge-5d-4a", "selected": false, "hidden": true },
- { "style": { "stroke": "#116F97" }, "type": "default", "markerEnd": { "type": "arrowclosed", "color": "#116F97" }, "source": "2", "sourceHandle": "b", "target": "7", "targetHandle": "d", "id": "reactflow__edge-2b-7d", "selected": false, "label": "模型间接关系", "hidden": false },
- { "style": { "stroke": "#116F97" }, "type": "default", "markerEnd": { "type": "arrowclosed", "color": "#116F97" }, "source": "5", "sourceHandle": "d", "target": "3", "targetHandle": "b", "id": "reactflow__edge-5d-3b", "selected": false, "label": "模型直接关系", "hidden": false },
- { "style": { "stroke": "#116F97" }, "type": "default", "markerEnd": { "type": "arrowclosed", "color": "#116F97" }, "source": "6", "sourceHandle": "a", "target": "5", "targetHandle": "c", "id": "reactflow__edge-6a-5c", "selected": false, "label": "模型直接关系", "hidden": false },
- { "style": { "stroke": "#116F97" }, "type": "smoothstep", "markerEnd": { "type": "arrowclosed", "color": "#116F97" }, "source": "5", "sourceHandle": "a", "target": "7", "targetHandle": "c", "id": "reactflow__edge-5a-7c", "selected": false, "label": "模型直接关系", "hidden": false },
- { "style": { "stroke": "#116F97" }, "type": "smoothstep", "markerEnd": { "type": "arrowclosed", "color": "#116F97" }, "source": "4", "sourceHandle": "a", "target": "5", "targetHandle": "c", "id": "reactflow__edge-4a-5c", "selected": false, "label": "模型直接关系", "hidden": false },
- { "style": { "stroke": "#116F97" }, "type": "step", "markerEnd": { "type": "arrowclosed", "color": "#116F97" }, "source": "5", "sourceHandle": "b", "target": "7", "targetHandle": "b", "id": "reactflow__edge-5b-7b", "selected": false, "label": "模型直接关系", "hidden": false },
- { "style": { "stroke": "#116F97" }, "type": "smoothstep", "markerEnd": { "type": "arrowclosed", "color": "#116F97" }, "source": "7", "sourceHandle": "b", "target": "9", "targetHandle": "d", "id": "reactflow__edge-7b-9d", "selected": false, "hidden": false },
- { "style": { "stroke": "#116F97" }, "type": "smoothstep", "markerEnd": { "type": "arrowclosed", "color": "#116F97" }, "source": "10", "sourceHandle": "d", "target": "5", "targetHandle": "b", "id": "reactflow__edge-10d-5b", "selected": false, "label": "模型直接关系", "hidden": false },
- { "style": { "stroke": "#116F97" }, "type": "smoothstep", "markerEnd": { "type": "arrowclosed", "color": "#116F97" }, "source": "8", "sourceHandle": "c", "target": "11", "targetHandle": "a", "id": "reactflow__edge-8c-11a", "selected": false, "label": "模型直接关系", "hidden": false },
- { "style": { "stroke": "#116F97" }, "type": "straight", "markerEnd": { "type": "arrowclosed", "color": "#116F97" }, "source": "12", "sourceHandle": "a", "target": "11", "targetHandle": "c", "id": "reactflow__edge-12a-11c", "selected": false, "label": "模型直接关系", "hidden": false },
- { "style": { "stroke": "#116F97" }, "type": "smoothstep", "markerEnd": { "type": "arrowclosed", "color": "#116F97" }, "source": "13", "sourceHandle": "b", "target": "11", "targetHandle": "d", "id": "reactflow__edge-13b-11d", "selected": false, "label": "模型直接关系", "hidden": false },
- { "style": { "stroke": "#116F97" }, "type": "smoothstep", "markerEnd": { "type": "arrowclosed", "color": "#116F97" }, "source": "9", "sourceHandle": "b", "target": "11", "targetHandle": "d", "id": "reactflow__edge-9b-11d", "selected": false, "label": "模型直接关系", "hidden": false }
- ]
-
- // "viewport": { "x": 654.5507940552135, "y": -54.945769269730704, "zoom": 1.6908994642667994 } }
- {
- "name": "my-react-flow-app",
- "private": true,
- "version": "0.0.0",
- "type": "module",
- "scripts": {
- "dev": "vite",
- "build": "vite build",
- "lint": "eslint src --ext js,jsx --report-unused-disable-directives --max-warnings 0",
- "preview": "vite preview"
- },
- "dependencies": {
- "antd": "^5.7.1",
- "react": "^18.2.0",
- "react-dom": "^18.2.0",
- "reactflow": "^11.7.4"
- },
- "devDependencies": {
- "@types/react": "^18.2.14",
- "@types/react-dom": "^18.2.6",
- "@vitejs/plugin-react": "^4.0.1",
- "eslint": "^8.44.0",
- "eslint-plugin-react": "^7.32.2",
- "eslint-plugin-react-hooks": "^4.6.0",
- "eslint-plugin-react-refresh": "^0.4.1",
- "vite": "^4.4.0"
- }
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。