From 72802cb143ace7701bc8e5d5cf8b258ffda3e08d Mon Sep 17 00:00:00 2001 From: ZLY Date: Thu, 22 Jan 2026 15:34:25 +0800 Subject: [PATCH] =?UTF-8?q?feat(flowEditor):=20=E6=B7=BB=E5=8A=A0=E5=8E=86?= =?UTF-8?q?=E5=8F=B2=E7=89=88=E6=9C=AC=E5=BA=94=E7=94=A8=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/flowEditor/FlowEditorMain.tsx | 2 + .../flowEditor/components/handlerBar.tsx | 13 +++- .../components/historyVersionModal.tsx | 70 +++++++++++++++++-- 3 files changed, 79 insertions(+), 6 deletions(-) diff --git a/src/pages/flowEditor/FlowEditorMain.tsx b/src/pages/flowEditor/FlowEditorMain.tsx index b53317c..1e5512f 100644 --- a/src/pages/flowEditor/FlowEditorMain.tsx +++ b/src/pages/flowEditor/FlowEditorMain.tsx @@ -542,6 +542,8 @@ const FlowEditorMain: React.FC = (props) => { } diff --git a/src/pages/flowEditor/components/handlerBar.tsx b/src/pages/flowEditor/components/handlerBar.tsx index 3502041..7e1fd16 100644 --- a/src/pages/flowEditor/components/handlerBar.tsx +++ b/src/pages/flowEditor/components/handlerBar.tsx @@ -2,19 +2,29 @@ import React, { useState } from 'react'; import { Button } from '@arco-design/web-react'; import { IconSend, IconOrderedList } from '@arco-design/web-react/icon'; import HistoryVersionModal from './historyVersionModal'; +import { Node, Edge } from '@xyflow/react'; interface HandlerBarProps { onPublish?: () => void; isRunning?: boolean; + setNodes?: React.Dispatch>; + setEdges?: React.Dispatch>; } -const HandlerBar: React.FC = ({ onPublish, isRunning }) => { +const HandlerBar: React.FC = ({ onPublish, isRunning, setNodes, setEdges }) => { const [historyModalVisible, setHistoryModalVisible] = useState(false); const handleHistoryClick = () => { setHistoryModalVisible(true); }; + const handleApplyHistory = (nodes: Node[], edges: Edge[]) => { + if (setNodes && setEdges) { + setNodes(nodes); + setEdges(edges); + } + }; + return ( <>
@@ -44,6 +54,7 @@ const HandlerBar: React.FC = ({ onPublish, isRunning }) => { setHistoryModalVisible(false)} + onApply={handleApplyHistory} /> ); diff --git a/src/pages/flowEditor/components/historyVersionModal.tsx b/src/pages/flowEditor/components/historyVersionModal.tsx index 4bbbb07..bbc0e8e 100644 --- a/src/pages/flowEditor/components/historyVersionModal.tsx +++ b/src/pages/flowEditor/components/historyVersionModal.tsx @@ -1,16 +1,18 @@ import React, { useState, useEffect, useMemo } from 'react'; -import { Modal, List, Message, Spin, Pagination } from '@arco-design/web-react'; +import { Modal, List, Message, Spin, Pagination, Button, Space } from '@arco-design/web-react'; import { ReactFlowProvider, ReactFlow, Background, Controls } from '@xyflow/react'; import '@xyflow/react/dist/style.css'; import { historyPage } from '@/api/appRes'; import { convertFlowData } from '@/utils/convertFlowData'; import { nodeTypes } from '@/components/FlowEditor/node'; -import { useSelector } from 'react-redux'; +import { useSelector, useDispatch } from 'react-redux'; +import { updateFlowData, updateCanvasDataMap } from '@/store/ideContainer'; import dayjs from 'dayjs'; interface HistoryVersionModalProps { visible: boolean; onCancel: () => void; + onApply?: (nodes: any[], edges: any[]) => void; } interface HistoryItem { @@ -34,19 +36,19 @@ interface HistoryItem { timestamp: number; } -const HistoryVersionModal: React.FC = ({ visible, onCancel }) => { +const HistoryVersionModal: React.FC = ({ visible, onCancel, onApply }) => { const [loading, setLoading] = useState(false); const [historyList, setHistoryList] = useState([]); const [selectedHistory, setSelectedHistory] = useState(null); const [currPage, setCurrPage] = useState(1); const [totalCount, setTotalCount] = useState(0); const { currentAppData } = useSelector(state => state.ideContainer); + const dispatch = useDispatch(); const pageSize = 10; // 获取历史版本列表 const fetchHistoryList = async (page = 1) => { if (!currentAppData?.id) return; - console.log('currentAppData:', currentAppData); setLoading(true); try { const response: any = await historyPage({ @@ -90,6 +92,53 @@ const HistoryVersionModal: React.FC = ({ visible, onCa return dayjs(Number(timestamp)).format('YYYY-MM-DD HH:mm:ss'); }; + // 应用历史版本到当前画布 + const handleApplyVersion = () => { + if (!selectedHistory) { + Message.warning('请先选择一个历史版本'); + return; + } + + Modal.confirm({ + title: '确认应用历史版本', + content: `确定要将 ${formatTimestamp(selectedHistory.timestamp)} 的版本应用到当前画布吗?当前未保存的修改将会丢失。`, + onOk: () => { + try { + // 转换历史版本数据为 ReactFlow 格式 + const components = selectedHistory.res.main.components; + const convertedData = convertFlowData(components, false); + const { nodes, edges } = convertedData; + + // 如果父组件提供了 onApply 回调,使用回调来更新画布 + if (onApply) { + onApply(nodes, edges); + } + + // 同时更新 Redux store 中的缓存数据 + const canvasKey = currentAppData.key || currentAppData.id; + + // 更新 flowData(全局流程数据) + dispatch(updateFlowData(convertedData)); + + // 更新 canvasDataMap(画布缓存) + dispatch(updateCanvasDataMap({ + [canvasKey]: { + nodes, + edges, + timestamp: Date.now() + } + })); + + Message.success('历史版本已应用到当前画布'); + onCancel(); + } catch (error) { + console.error('应用历史版本失败:', error); + Message.error('应用历史版本失败'); + } + } + }); + }; + // 使用useMemo缓存转换后的画布数据,避免在渲染时调用convertFlowData导致Redux dispatch const canvasData = useMemo(() => { if (!selectedHistory) { @@ -140,7 +189,18 @@ const HistoryVersionModal: React.FC = ({ visible, onCa title="历史版本" visible={visible} onCancel={onCancel} - footer={null} + footer={ + + + + + } style={{ width: '90vw', maxWidth: 1400 }} >