feat: 兼容minio下载链接

feature
鱼星 3 weeks ago
parent 097fc169c7
commit fefa0054ad

@ -123,6 +123,20 @@
max-height: 120px; max-height: 120px;
object-fit: contain; object-fit: contain;
} }
.node-image-loading,
.node-image-download {
display: block;
color: #86909c;
font-size: 12px;
line-height: 22px;
text-align: center;
word-break: break-all;
}
.node-image-download {
color: #165dff;
}
} }
.node-content-box { .node-content-box {

@ -1,4 +1,4 @@
import React from 'react'; import React, { useEffect, useState } from 'react';
import styles from '@/components/FlowEditor/node/style/baseOther.module.less'; import styles from '@/components/FlowEditor/node/style/baseOther.module.less';
import { Handle, Position } from '@xyflow/react'; import { Handle, Position } from '@xyflow/react';
import { Image } from '@arco-design/web-react'; import { Image } from '@arco-design/web-react';
@ -103,7 +103,26 @@ const renderRegularNodeHandles = (dataIns: any[], dataOuts: any[], apiIns: any[]
}; };
const getImageBlobType = (url: string, blobType: string) => {
if (blobType && blobType !== 'application/octet-stream') {
return blobType;
}
const cleanUrl = url.split('?')[0].toLowerCase();
if (cleanUrl.endsWith('.png')) return 'image/png';
if (cleanUrl.endsWith('.jpg') || cleanUrl.endsWith('.jpeg')) return 'image/jpeg';
if (cleanUrl.endsWith('.gif')) return 'image/gif';
if (cleanUrl.endsWith('.webp')) return 'image/webp';
if (cleanUrl.endsWith('.bmp')) return 'image/bmp';
if (cleanUrl.endsWith('.svg')) return 'image/svg+xml';
if (cleanUrl.endsWith('.tif') || cleanUrl.endsWith('.tiff')) return 'image/tiff';
return blobType || 'application/octet-stream';
};
const NodeContent = ({ data, imageUrl = '' }: { data: NodeContentData; imageUrl?: string }) => { const NodeContent = ({ data, imageUrl = '' }: { data: NodeContentData; imageUrl?: string }) => {
const [previewUrl, setPreviewUrl] = useState('');
const [imageLoadError, setImageLoadError] = useState(false);
const apiIns = data.parameters?.apiIns || []; const apiIns = data.parameters?.apiIns || [];
const apiOuts = data.parameters?.apiOuts || []; const apiOuts = data.parameters?.apiOuts || [];
const dataIns = data.parameters?.dataIns || []; const dataIns = data.parameters?.dataIns || [];
@ -114,6 +133,52 @@ const NodeContent = ({ data, imageUrl = '' }: { data: NodeContentData; imageUrl?
const isEndNode = data.type === 'end'; const isEndNode = data.type === 'end';
const isSpecialNode = isStartNode || isEndNode; const isSpecialNode = isStartNode || isEndNode;
useEffect(() => {
let canceled = false;
let objectUrl = '';
setPreviewUrl('');
setImageLoadError(false);
if (!imageUrl) {
return undefined;
}
const loadImageBlob = async () => {
try {
const response = await fetch(imageUrl);
if (!response.ok) {
throw new Error(`load image failed: ${response.status}`);
}
const blob = await response.blob();
const typedBlob = new Blob([blob], {
type: getImageBlobType(imageUrl, blob.type),
});
objectUrl = URL.createObjectURL(typedBlob);
if (!canceled) {
setPreviewUrl(objectUrl);
}
} catch (error) {
console.error('图片下载预览失败:', error);
if (!canceled) {
setPreviewUrl(imageUrl);
setImageLoadError(true);
}
}
};
loadImageBlob();
return () => {
canceled = true;
if (objectUrl) {
URL.revokeObjectURL(objectUrl);
}
};
}, [imageUrl]);
return ( return (
<> <>
{/*content栏-api部分*/} {/*content栏-api部分*/}
@ -180,12 +245,27 @@ const NodeContent = ({ data, imageUrl = '' }: { data: NodeContentData; imageUrl?
{imageUrl && ( {imageUrl && (
<div className={styles['node-image-box']}> <div className={styles['node-image-box']}>
{previewUrl ? (
<Image <Image
width={150} width={150}
src={imageUrl} src={previewUrl}
alt="图片展示" alt="图片展示"
style={{ display: 'block' }} style={{ display: 'block' }}
onError={() => setImageLoadError(true)}
/> />
) : (
<div className={styles['node-image-loading']}></div>
)}
{imageLoadError && (
<a
className={styles['node-image-download']}
href={imageUrl}
target="_blank"
rel="noreferrer"
>
</a>
)}
</div> </div>
)} )}

Loading…
Cancel
Save