diff --git a/src/pages/flowEditor/FlowEditorMain.tsx b/src/pages/flowEditor/FlowEditorMain.tsx index 171a77a..38973f6 100644 --- a/src/pages/flowEditor/FlowEditorMain.tsx +++ b/src/pages/flowEditor/FlowEditorMain.tsx @@ -25,6 +25,8 @@ import { useAlignmentGuidelines } from '@/hooks/useAlignmentGuidelines'; import { useHistory } from './components/historyContext'; import { NodeTypes } from '@xyflow/react'; import { useSelector } from 'react-redux'; +import HandlerBar from '@/pages/flowEditor/components/handlerBar'; +import PublishFlowModal from '@/pages/flowEditor/components/publishFlowModal'; const edgeTypes = { custom: CustomEdge @@ -142,6 +144,9 @@ const FlowEditorMain: React.FC = (props) => { // 用于存储隐藏的节点ID const [hiddenNodes, setHiddenNodes] = React.useState>(new Set()); + // 流程发布弹窗状态 + const [publishModalVisible, setPublishModalVisible] = React.useState(false); + // 监听自定义事件以隐藏/显示节点 useEffect(() => { const handleToggleNodeVisibility = (event: CustomEvent) => { @@ -229,6 +234,20 @@ const FlowEditorMain: React.FC = (props) => { }; }, [undo, redo, canUndo, canRedo]); + // 处理流程发布 + const handlePublish = () => { + // 先保存流程数据 + saveFlowDataToServer(); + // 打开发布弹窗 + setPublishModalVisible(true); + }; + + // 发布成功后的回调 + const handlePublishSuccess = () => { + setPublishModalVisible(false); + // 可以在这里添加其他逻辑,比如刷新流程列表等 + }; + // 监听节点和边的变化以拍摄快照 useEffect(() => { // 获取 HistoryProvider 中的 takeSnapshot 方法 @@ -438,6 +457,12 @@ const FlowEditorMain: React.FC = (props) => { isRunning={currentAppIsRunning} > + + + @@ -541,6 +566,16 @@ const FlowEditorMain: React.FC = (props) => { /> )} + + {/*流程发布弹窗*/} + setPublishModalVisible(false)} + onSuccess={handlePublishSuccess} + appId={initialData?.id} + flowId={initialData?.flowId} + currentFlowName={initialData?.name} + /> ); }; diff --git a/src/pages/flowEditor/components/handlerBar.tsx b/src/pages/flowEditor/components/handlerBar.tsx new file mode 100644 index 0000000..962a6d6 --- /dev/null +++ b/src/pages/flowEditor/components/handlerBar.tsx @@ -0,0 +1,28 @@ +import React from 'react'; +import { Button } from '@arco-design/web-react'; +import { IconSend } from '@arco-design/web-react/icon'; + +interface HandlerBarProps { + onPublish?: () => void; + isRunning?: boolean; +} + +const HandlerBar: React.FC = ({ onPublish, isRunning }) => { + return ( +
+
+ +
+
+ ); +}; + +export default HandlerBar; \ No newline at end of file diff --git a/src/pages/flowEditor/components/publishFlowModal.tsx b/src/pages/flowEditor/components/publishFlowModal.tsx new file mode 100644 index 0000000..0699c67 --- /dev/null +++ b/src/pages/flowEditor/components/publishFlowModal.tsx @@ -0,0 +1,259 @@ +import React, { useState, useEffect } from 'react'; +import { Modal, Form, Input, Radio, Message } from '@arco-design/web-react'; +import { appPublish } from '@/api/flow'; +import { getPubFlowList, getMyFlowList } from '@/api/flow'; +import { getMyComponents, getPubComponents, getTeamComponents } from '@/api/components'; +import { useSelector } from 'react-redux'; +import { publishType } from '@/api/interface'; +import dayjs from 'dayjs'; + +interface PublishFlowModalProps { + visible: boolean; + onCancel: () => void; + onSuccess: () => void; + appId?: string; + flowId?: string; + currentFlowName?: string; +} + +const FormItem = Form.Item; +const RadioGroup = Radio.Group; +const TextArea = Input.TextArea; + +const PublishFlowModal: React.FC = ({ + visible, + onCancel, + onSuccess, + appId, + flowId, + currentFlowName + }) => { + const [form] = Form.useForm(); + const [loading, setLoading] = useState(false); + const { appRuntimeData, currentAppData } = useSelector((state: any) => state.ideContainer); + + // 当弹窗打开时,初始化表单数据 + useEffect(() => { + if (visible) { + form.setFieldsValue({ + name: currentFlowName || '', + published: 1, // 默认发布为公共流程 + tag: '', + description: '' + }); + } + }, [visible, currentFlowName, form]); + + // 当弹窗关闭时,重置表单 + useEffect(() => { + if (!visible) { + form.resetFields(); + } + }, [visible, form]); + + // 更新组件和流程库数据 + const updateComponentData = async () => { + try { + const requests = [ + { promise: getMyComponents(), key: 'myLibs' }, + { promise: getPubComponents(), key: 'pubLibs' }, + { promise: getTeamComponents(), key: 'teamLibs' }, + { + promise: getPubFlowList({ + currPage: 1, + pageSize: 999 + }), + key: 'pubFlow' + }, + { + promise: getMyFlowList({ + currPage: 1, + pageSize: 999 + }), + key: 'myFlow' + } + ]; + + const obj: any = { + myLibs: null, + pubLibs: null, + teamLibs: null, + pubFlow: null, + myFlow: null, + updateTime: dayjs().format('YYYY-MM-DD HH:mm:ss') + }; + + const userInfo = JSON.parse(sessionStorage.getItem('userInfo') || '{}'); + + // 分别处理每个请求 + for (const { promise, key } of requests) { + try { + const res: any = await promise; + if (res?.code === 200) { + if (key === 'pubFlow' || key === 'myFlow') { + res?.data.list.forEach(item => { + item['fontCompType'] = 'complex'; + }); + // 更新本地存储数据 + obj[key] = res?.data.list || null; + } + // 给协同组件添加一个后续处理数据时使用的类型 + else if (key === 'teamLibs') { + res.data.forEach(item => { + item.children.forEach(v => { + v['fontCompType'] = 'team'; + }); + }); + obj[key] = res?.data || null; + } + else { + // 更新本地存储数据 + res.data.forEach(item => { + item.children.forEach(v => { + v['fontCompType'] = 'normal'; + }); + }); + obj[key] = res?.data || null; + } + } + sessionStorage.setItem(`compLibs${userInfo.userId}`, JSON.stringify(obj)); + } catch (error) { + console.error(`加载${key}失败:`, error); + } + } + } catch (error) { + console.error('更新组件库失败:', error); + } + }; + + const handleSubmit = async () => { + try { + const values = await form.validate(); + + + console.log('currentAppData:', currentAppData); + setLoading(true); + let publishData: publishType = {}; + + if (currentAppData.hasOwnProperty('parentAppId')) { + publishData = { + appId: currentAppData.parentAppId, + flowId: currentAppData.key, + name: values.name, + published: values.published, + tag: values.tag, + description: values.description, + isMain: 0 // 子流程 + }; + } + else { + publishData = { + appId: currentAppData.id, + flowId: '', + name: values.name, + published: values.published, + tag: values.tag, + description: values.description, + isMain: 1 // 主流程 + }; + } + + const res: any = await appPublish(publishData); + + if (res.code === 200) { + Message.success('流程发布成功'); + form.resetFields(); + + // 发布成功后更新组件和流程库数据 + await updateComponentData(); + + onSuccess(); + } + else { + Message.error(res.msg || '流程发布失败'); + } + } catch (error) { + console.error('流程发布失败:', error); + if (error?.errors) { + // 表单验证错误,不需要显示消息 + return; + } + Message.error('流程发布失败'); + } finally { + setLoading(false); + } + }; + + const handleClose = () => { + form.resetFields(); + onCancel(); + }; + + return ( + +
+ + + + + + + 私有流程(仅自己可见) + 公共流程(所有人可见) + + + + + + + + +