diff --git a/web/client/api/flow/index.ts b/web/client/api/flow/index.ts index 71add7730..2d5d2d1dd 100644 --- a/web/client/api/flow/index.ts +++ b/web/client/api/flow/index.ts @@ -67,14 +67,14 @@ export const downloadFile = (fileId: string) => { return GET(`/api/v2/serve/file/files/dbgpt/${fileId}`); }; -export const getFlowTemplateList = () => { - return GET>('/api/v2/serve/awel/flow/templates'); -}; - export const getFlowTemplateById = (id: string) => { return GET(`/api/v2/serve/awel/flow/templates/${id}`); }; +export const getFlowTemplates = () => { + return GET(`/api/v2/serve/awel/flow/templates`); +}; + export const getKeys = (data?: IGetKeysRequestParams) => { return GET>('/api/v2/serve/awel/variables/keys', data); }; diff --git a/web/components/flow/canvas-modal/import-flow-modal.tsx b/web/components/flow/canvas-modal/import-flow-modal.tsx index ec3738d72..3711b78ed 100644 --- a/web/components/flow/canvas-modal/import-flow-modal.tsx +++ b/web/components/flow/canvas-modal/import-flow-modal.tsx @@ -5,6 +5,7 @@ import { Button, Form, GetProp, Modal, Radio, Upload, UploadFile, UploadProps, m import { useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { Edge, Node } from 'reactflow'; + type Props = { isImportModalOpen: boolean; setNodes: React.Dispatch[]>>; @@ -39,7 +40,7 @@ export const ImportFlowModal: React.FC = ({ isImportModalOpen, setIsImpor if (res?.success) { messageApi.success(t('Import_Flow_Success')); localStorage.setItem('importFlowData', JSON.stringify(res?.data)); - CanvasWrapper(res?.data); + CanvasWrapper(); } else if (res?.err_msg) { messageApi.error(res?.err_msg); } diff --git a/web/components/flow/canvas-modal/index.ts b/web/components/flow/canvas-modal/index.ts index a7cb14203..6fcb0a5d1 100644 --- a/web/components/flow/canvas-modal/index.ts +++ b/web/components/flow/canvas-modal/index.ts @@ -2,3 +2,4 @@ export * from './add-flow-variable-modal'; export * from './export-flow-modal'; export * from './import-flow-modal'; export * from './save-flow-modal'; +export * from './template-flow-modal'; diff --git a/web/components/flow/canvas-modal/template-flow-modal.tsx b/web/components/flow/canvas-modal/template-flow-modal.tsx new file mode 100644 index 000000000..3fc5500f0 --- /dev/null +++ b/web/components/flow/canvas-modal/template-flow-modal.tsx @@ -0,0 +1,78 @@ +import { getFlowTemplates } from '@/client/api'; +import CanvasWrapper from '@/pages/construct/flow/canvas/index'; +import type { TableProps } from 'antd'; +import { Button, Modal, Space, Table } from 'antd'; +import { useEffect, useState } from 'react'; +import { useTranslation } from 'react-i18next'; + +type Props = { + isFlowTemplateModalOpen: boolean; + setIsFlowTemplateModalOpen: (value: boolean) => void; +}; + +interface DataType { + key: string; + name: string; + age: number; + address: string; + tags: string[]; +} + +export const FlowTemplateModal: React.FC = ({ isFlowTemplateModalOpen, setIsFlowTemplateModalOpen }) => { + const { t } = useTranslation(); + const [dataSource, setDataSource] = useState([]); + + const onTemplateImport = (record: DataType) => { + if (record?.name) { + localStorage.setItem('importFlowData', JSON.stringify(record)); + CanvasWrapper(); + setIsFlowTemplateModalOpen(false); + } + }; + + const columns: TableProps['columns'] = [ + { + title: t('Template_Name'), + dataIndex: 'name', + key: 'name', + }, + { + title: t('Template_Action'), + key: 'action', + render: (_, record) => ( + + + + ), + }, + ]; + + useEffect(() => { + getFlowTemplates().then(res => { + console.log(res); + setDataSource(res?.data?.data?.items); + }); + }, []); + + return ( + <> + setIsFlowTemplateModalOpen(false)} + cancelButtonProps={{ className: 'hidden' }} + okButtonProps={{ className: 'hidden' }} + > + ; + + + ); +}; diff --git a/web/components/flow/node-renderer/upload.tsx b/web/components/flow/node-renderer/upload.tsx index dadd38207..2085dac09 100644 --- a/web/components/flow/node-renderer/upload.tsx +++ b/web/components/flow/node-renderer/upload.tsx @@ -1,12 +1,12 @@ /* eslint-disable react-hooks/rules-of-hooks */ +import { metadataBatch } from '@/client/api'; import { IFlowNodeParameter } from '@/types/flow'; import { convertKeysToCamelCase } from '@/utils/flow'; import { UploadOutlined } from '@ant-design/icons'; -import type { UploadProps,UploadFile } from 'antd'; +import type { UploadFile, UploadProps } from 'antd'; import { Button, Upload, message } from 'antd'; import { useEffect, useRef, useState } from 'react'; import { useTranslation } from 'react-i18next'; -import { metadataBatch } from '@/client/api'; type Props = { formValuesChange: any; @@ -17,31 +17,33 @@ export const renderUpload = (params: Props) => { const { t } = useTranslation(); const urlList = useRef([]); const { data, formValuesChange } = params; - const [fileList, setFileList] = useState([]) + const [fileList, setFileList] = useState([]); // 获取上传文件元数据 - useEffect(() => { + useEffect(() => { if (data.value) { - let uris:string[] = [] - typeof(data.value) === 'string'? uris.push(data.value):uris = data.value - let parameter:any = { - uris - } - metadataBatch(parameter).then((res)=>{ - let urlList:UploadFile[] = [] - for (let index = 0; index < res.data.data.length; index++) { - const element = res.data.data[index]; - urlList.push({ + let uris: string[] = []; + typeof data.value === 'string' ? uris.push(data.value) : (uris = data.value); + const parameter: any = { + uris, + }; + metadataBatch(parameter) + .then(res => { + const urlList: UploadFile[] = []; + for (let index = 0; index < res.data.data.length; index++) { + const element = res.data.data[index]; + urlList.push({ uid: element.file_id, - name:element.file_name, + name: element.file_name, status: 'done', url: element.uri, - }) - } - setFileList(urlList) - }).catch((error)=>{ - console.log(error) - }) + }); + } + setFileList(urlList); + }) + .catch(error => { + console.log(error); + }); } }, []); @@ -102,11 +104,17 @@ export const renderUpload = (params: Props) => { return (
- - - + + +
); }; diff --git a/web/locales/en/flow.ts b/web/locales/en/flow.ts index 11b86a39a..b07925e62 100644 --- a/web/locales/en/flow.ts +++ b/web/locales/en/flow.ts @@ -21,4 +21,7 @@ export const FlowEn = { Add_Parameter: 'Add Parameter', Higher_Order_Nodes: 'Higher Order', All_Nodes: 'All', + Import_From_Template: 'Import from template', + Template_Name: 'Template Name', + Template_Action: 'Action', }; diff --git a/web/locales/zh/flow.ts b/web/locales/zh/flow.ts index 462c429fa..a2c870cd0 100644 --- a/web/locales/zh/flow.ts +++ b/web/locales/zh/flow.ts @@ -21,4 +21,7 @@ export const FlowZn = { Add_Parameter: '添加参数', Higher_Order_Nodes: '高阶', All_Nodes: '所有', + Import_Template: '从模版导入', + Template_Name: '模版名称', + Template_Action: '操作', }; diff --git a/web/pages/construct/flow/canvas/index.tsx b/web/pages/construct/flow/canvas/index.tsx index 29ecf7698..de333bb77 100644 --- a/web/pages/construct/flow/canvas/index.tsx +++ b/web/pages/construct/flow/canvas/index.tsx @@ -2,11 +2,17 @@ import { apiInterceptors, getFlowById } from '@/client/api'; import MuiLoading from '@/components/common/loading'; import AddNodesSider from '@/components/flow/add-nodes-sider'; import ButtonEdge from '@/components/flow/button-edge'; -import { AddFlowVariableModal, ExportFlowModal, ImportFlowModal, SaveFlowModal } from '@/components/flow/canvas-modal'; +import { + AddFlowVariableModal, + ExportFlowModal, + FlowTemplateModal, + ImportFlowModal, + SaveFlowModal, +} from '@/components/flow/canvas-modal'; import CanvasNode from '@/components/flow/canvas-node'; import { IFlowData, IFlowUpdateParam } from '@/types/flow'; import { checkFlowDataRequied, getUniqueNodeId, mapUnderlineToHump } from '@/utils/flow'; -import { ExportOutlined, FrownOutlined, ImportOutlined, SaveOutlined } from '@ant-design/icons'; +import { ExportOutlined, FileAddOutlined, FrownOutlined, ImportOutlined, SaveOutlined } from '@ant-design/icons'; import { Divider, Space, Tooltip, message, notification } from 'antd'; import { useSearchParams } from 'next/navigation'; import React, { DragEvent, useCallback, useEffect, useRef, useState } from 'react'; @@ -43,6 +49,7 @@ const Canvas: React.FC = () => { const [isSaveFlowModalOpen, setIsSaveFlowModalOpen] = useState(false); const [isExportFlowModalOpen, setIsExportFlowModalOpen] = useState(false); const [isImportModalOpen, setIsImportFlowModalOpen] = useState(false); + const [isFlowTemplateModalOpen, setIsFlowTemplateModalOpen] = useState(false); if (localStorage.getItem('importFlowData')) { const importFlowData = JSON.parse(localStorage.getItem('importFlowData') || ''); @@ -191,19 +198,15 @@ const Canvas: React.FC = () => { setIsSaveFlowModalOpen(true); } - function onExport() { - setIsExportFlowModalOpen(true); - } - - function onImport() { - setIsImportFlowModalOpen(true); - } - const getButtonList = () => { const buttonList = [ + { + title: t('template'), + icon: setIsFlowTemplateModalOpen(true)} />, + }, { title: t('Import'), - icon: , + icon: setIsImportFlowModalOpen(true)} />, }, { title: t('save'), @@ -214,7 +217,7 @@ const Canvas: React.FC = () => { if (id !== '') { buttonList.unshift({ title: t('Export'), - icon: , + icon: setIsExportFlowModalOpen(true)} />, }); } @@ -290,6 +293,11 @@ const Canvas: React.FC = () => { setIsImportFlowModalOpen={setIsImportFlowModalOpen} /> + + {contextHolder} );