feat: upload metadata 、ui size settings 276 320 530 、import flow (#1965)

# Description

Please include a summary of the change and which issue is fixed. Please
also include relevant motivation and context. List any dependencies that
are required for this change.

# How Has This Been Tested?

Please describe the tests that you ran to verify your changes. Provide
instructions so we can reproduce. Please also list any relevant details
for your test configuration

# Snapshots:

Include snapshots for easier review.

# Checklist:

- [ ] My code follows the style guidelines of this project
- [ ] I have already rebased the commits and make the commit message
conform to the project standard.
- [ ] I have performed a self-review of my own code
- [ ] I have commented my code, particularly in hard-to-understand areas
- [ ] I have made corresponding changes to the documentation
- [ ] Any dependent changes have been merged and published in downstream
modules
This commit is contained in:
Dreammy23 2024-09-04 18:33:44 +08:00 committed by GitHub
commit b87b42f8ae
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 58 additions and 21 deletions

View File

@ -71,3 +71,6 @@ export const getFlowTemplateList = () => {
export const getFlowTemplateById = (id: string) => { export const getFlowTemplateById = (id: string) => {
return GET<null, any>(`/api/v2/serve/awel/flow/templates/${id}`); return GET<null, any>(`/api/v2/serve/awel/flow/templates/${id}`);
}; };
export const metadataBatch = (data: IUploadFileRequestParams) => {
return POST<IUploadFileRequestParams, Array<IUploadFileResponse>>('/api/v2/serve/file/files/metadata/batch', data);
};

View File

@ -4,7 +4,7 @@ import { Button, Form, GetProp, Modal, Radio, Space, Upload, UploadFile, UploadP
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { Edge, Node } from 'reactflow'; import { Edge, Node } from 'reactflow';
import CanvasWrapper from '@/pages/construct/flow/canvas/index';
type Props = { type Props = {
isImportModalOpen: boolean; isImportModalOpen: boolean;
setNodes: React.Dispatch<React.SetStateAction<Node<any, string | undefined>[]>>; setNodes: React.Dispatch<React.SetStateAction<Node<any, string | undefined>[]>>;
@ -37,9 +37,12 @@ export const ImportFlowModal: React.FC<Props> = ({ isImportModalOpen, setIsImpor
const [, , res] = await apiInterceptors(importFlow(formData)); const [, , res] = await apiInterceptors(importFlow(formData));
if (res?.success) { if (res?.success) {
messageApi.success(t('Export_Flow_Success')); messageApi.success(t('Import_Flow_Success'));
localStorage.setItem('importFlowData', JSON.stringify(res?.data));
CanvasWrapper(res?.data)
} else if (res?.err_msg) { } else if (res?.err_msg) {
messageApi.error(res?.err_msg); messageApi.error(res?.err_msg);
} }
setIsImportFlowModalOpen(false); setIsImportFlowModalOpen(false);
}; };

View File

@ -19,7 +19,6 @@ type CanvasNodeProps = {
function TypeLabel({ label }: { label: string }) { function TypeLabel({ label }: { label: string }) {
return <div className='w-full h-8 align-middle font-semibold'>{label}</div>; return <div className='w-full h-8 align-middle font-semibold'>{label}</div>;
} }
const forceTypeList = ['file', 'multiple_files', 'time'];
const CanvasNode: React.FC<CanvasNodeProps> = ({ data }) => { const CanvasNode: React.FC<CanvasNodeProps> = ({ data }) => {
const node = data; const node = data;
@ -128,9 +127,6 @@ const CanvasNode: React.FC<CanvasNodeProps> = ({ data }) => {
function onParameterValuesChange(changedValues: any, allValues: any) { function onParameterValuesChange(changedValues: any, allValues: any) {
const [changedKey, changedVal] = Object.entries(changedValues)[0]; const [changedKey, changedVal] = Object.entries(changedValues)[0];
if (!allValues?.force && forceTypeList.includes(changedKey)) {
return;
}
updateCurrentNodeValue(changedKey, changedVal); updateCurrentNodeValue(changedKey, changedVal);
if (changedVal) { if (changedVal) {
updateDependsNodeValue(changedKey, changedVal); updateDependsNodeValue(changedKey, changedVal);
@ -197,8 +193,11 @@ const CanvasNode: React.FC<CanvasNodeProps> = ({ data }) => {
> >
<div <div
className={classNames( className={classNames(
'w-80 h-auto rounded-xl shadow-md px-2 py-4 border bg-white dark:bg-zinc-800 cursor-grab flex flex-col space-y-2 text-sm', 'h-auto rounded-xl shadow-md px-2 py-4 border bg-white dark:bg-zinc-800 cursor-grab flex flex-col space-y-2 text-sm',
{ {
'w-80':node?.tags?.ui_size === 'middle' || !node?.tags?.ui_size,
'w-[256px]':node?.tags?.ui_size === 'small',
'w-[530px]':node?.tags?.ui_size === 'large',
'border-blue-500': node.selected || isHovered, 'border-blue-500': node.selected || isHovered,
'border-stone-400 dark:border-white': !node.selected && !isHovered, 'border-stone-400 dark:border-white': !node.selected && !isHovered,
'border-dashed': flowType !== 'operator', 'border-dashed': flowType !== 'operator',

View File

@ -131,6 +131,7 @@ const NodeParamHandler: React.FC<NodeParamHandlerProps> = ({ formValuesChange, n
if (ui_type === 'slider' && data.is_list) { if (ui_type === 'slider' && data.is_list) {
defaultValue = [0, 1]; defaultValue = [0, 1];
} }
return ( return (
<Form.Item <Form.Item
className='mb-2' className='mb-2'

View File

@ -2,10 +2,11 @@
import { IFlowNodeParameter } from '@/types/flow'; import { IFlowNodeParameter } from '@/types/flow';
import { convertKeysToCamelCase } from '@/utils/flow'; import { convertKeysToCamelCase } from '@/utils/flow';
import { UploadOutlined } from '@ant-design/icons'; import { UploadOutlined } from '@ant-design/icons';
import type { UploadProps } from 'antd'; import type { UploadProps,UploadFile } from 'antd';
import { Button, Upload, message } from 'antd'; import { Button, Upload, message } from 'antd';
import { useRef, useState } from 'react'; import { useEffect, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { metadataBatch } from '@/client/api';
type Props = { type Props = {
formValuesChange: any; formValuesChange: any;
@ -16,6 +17,33 @@ export const renderUpload = (params: Props) => {
const { t } = useTranslation(); const { t } = useTranslation();
const urlList = useRef<string[]>([]); const urlList = useRef<string[]>([]);
const { data, formValuesChange } = params; const { data, formValuesChange } = params;
const [fileList, setFileList] = useState<UploadFile[]>([])
// 获取上传文件元数据
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({
uid: element.file_id,
name:element.file_name,
status: 'done',
url: element.uri,
})
}
setFileList(urlList)
}).catch((error)=>{
console.log(error)
})
}
}, []);
const attr = convertKeysToCamelCase(data.ui?.attr || {}); const attr = convertKeysToCamelCase(data.ui?.attr || {});
const [uploading, setUploading] = useState(false); const [uploading, setUploading] = useState(false);
@ -51,6 +79,7 @@ export const renderUpload = (params: Props) => {
headers: { headers: {
authorization: 'authorization-text', authorization: 'authorization-text',
}, },
defaultFileList: fileList,
onChange(info) { onChange(info) {
setUploading(true); setUploading(true);
if (info.file.status !== 'uploading') { if (info.file.status !== 'uploading') {
@ -73,19 +102,11 @@ export const renderUpload = (params: Props) => {
return ( return (
<div className='p-2 text-sm text-center'> <div className='p-2 text-sm text-center'>
{data.is_list ? ( <Upload onRemove={handleFileRemove} {...props} {...attr} multiple={data.is_list?true:false} accept={uploadType}>
<Upload onRemove={handleFileRemove} {...props} {...attr} multiple={true} accept={uploadType}>
<Button loading={uploading} icon={<UploadOutlined />}> <Button loading={uploading} icon={<UploadOutlined />}>
{t('Upload_Data')} {t('Upload_Data')}
</Button> </Button>
</Upload> </Upload>
) : (
<Upload onRemove={handleFileRemove} {...props} {...attr} multiple={false} accept={uploadType}>
<Button loading={uploading} icon={<UploadOutlined />}>
{t('Upload_Data')}
</Button>
</Upload>
)}
</div> </div>
); );
}; };

View File

@ -26,8 +26,8 @@ import 'reactflow/dist/style.css';
const nodeTypes = { customNode: CanvasNode }; const nodeTypes = { customNode: CanvasNode };
const edgeTypes = { buttonedge: ButtonEdge }; const edgeTypes = { buttonedge: ButtonEdge };
const Canvas: React.FC = () => { const Canvas: React.FC = () => {
const { t } = useTranslation(); const { t } = useTranslation();
const [messageApi, contextHolder] = message.useMessage(); const [messageApi, contextHolder] = message.useMessage();
@ -43,7 +43,17 @@ const Canvas: React.FC = () => {
const [isSaveFlowModalOpen, setIsSaveFlowModalOpen] = useState(false); const [isSaveFlowModalOpen, setIsSaveFlowModalOpen] = useState(false);
const [isExportFlowModalOpen, setIsExportFlowModalOpen] = useState(false); const [isExportFlowModalOpen, setIsExportFlowModalOpen] = useState(false);
const [isImportModalOpen, setIsImportFlowModalOpen] = useState(false); const [isImportModalOpen, setIsImportFlowModalOpen] = useState(false);
if (localStorage.getItem('importFlowData') ) {
const importFlowData = JSON.parse(localStorage.getItem('importFlowData') );
localStorage.removeItem('importFlowData')
setLoading(true);
const flowData = mapUnderlineToHump(importFlowData.flow_data);
setFlowInfo(importFlowData);
setNodes(flowData.nodes);
setEdges(flowData.edges);
setLoading(false);
}
async function getFlowData() { async function getFlowData() {
setLoading(true); setLoading(true);
const [_, data] = await apiInterceptors(getFlowById(id)); const [_, data] = await apiInterceptors(getFlowById(id));

View File

@ -122,4 +122,4 @@ table {
.rc-md-editor .editor-container>.section { .rc-md-editor .editor-container>.section {
border-right: none !important; border-right: none !important;
} }