添加了IFLOW描述文件;

优化 调整了历史记录悬浮窗的显示位置;
This commit is contained in:
yuantao
2025-09-19 16:31:09 +08:00
parent c5ee5dd2a3
commit 9a5e4d8041
4 changed files with 297 additions and 387 deletions

View File

@@ -1,4 +1,4 @@
import React, { useEffect } from 'react';
import React, { useEffect, useState } from 'react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { cn } from './utils/cn';
import { Header } from './components/Header';
@@ -23,6 +23,7 @@ function AppContent() {
useKeyboardShortcuts();
const { showPromptPanel, setShowPromptPanel, setShowHistory } = useAppStore();
const [hoveredImage, setHoveredImage] = useState<{url: string, title: string, width?: number, height?: number} | null>(null);
// 在挂载时初始化IndexedDB并清理base64数据
useEffect(() => {
@@ -78,7 +79,7 @@ function AppContent() {
<Header />
</div>
<div className="flex-1 flex overflow-hidden p-4 gap-4">
<div className="flex-1 flex overflow-hidden p-4 gap-4 relative">
<div className={cn("flex-shrink-0 transition-all duration-300 ease-in-out", !showPromptPanel && "w-8")}>
<div className="h-full card card-lg">
<PromptComposer />
@@ -91,10 +92,39 @@ function AppContent() {
</div>
<div className="flex-shrink-0">
<div className="h-full card card-lg">
<HistoryPanel />
<HistoryPanel setHoveredImage={setHoveredImage} />
</div>
</div>
</div>
{/* 悬浮预览 */}
{hoveredImage && (
<div
className="fixed inset-0 z-[99999] flex items-center justify-center pointer-events-none"
>
<div className="bg-white rounded-xl shadow-2xl border border-gray-300 overflow-hidden max-w-2xl max-h-[80vh] flex flex-col">
<div className="bg-gray-900 text-white text-sm p-3 truncate font-medium">
{hoveredImage.title}
</div>
<div className="flex-1 flex items-center justify-center p-4">
<img
src={hoveredImage.url}
alt="预览"
className="max-w-full max-h-[60vh] object-contain"
/>
</div>
{/* 图像信息 */}
<div className="p-3 bg-gray-50 border-t border-gray-200 text-sm">
{hoveredImage.width && hoveredImage.height && (
<div className="flex justify-between text-gray-600">
<span>:</span>
<span className="text-gray-800 font-medium">{hoveredImage.width} × {hoveredImage.height}</span>
</div>
)}
</div>
</div>
</div>
)}
</div>
);
}

View File

@@ -9,7 +9,7 @@ import { useIndexedDBListener } from '../hooks/useIndexedDBListener';
import { DayPicker } from 'react-day-picker';
import zhCN from 'react-day-picker/dist/locale/zh-CN';
export const HistoryPanel: React.FC = () => {
export const HistoryPanel: React.FC<{ setHoveredImage: (image: {url: string, title: string, width?: number, height?: number} | null) => void }> = ({ setHoveredImage }) => {
const {
currentProject,
canvasImage,
@@ -63,9 +63,7 @@ export const HistoryPanel: React.FC = () => {
const [currentPage, setCurrentPage] = useState(1);
const itemsPerPage = 20; // 减少每页显示的项目数
// 悬浮预览状态
const [hoveredImage, setHoveredImage] = useState<{url: string, title: string, width?: number, height?: number} | null>(null);
const [previewPosition, setPreviewPosition] = useState<{x: number, y: number}>({x: 0, y: 0});
const generations = currentProject?.generations || [];
const edits = currentProject?.edits || [];
@@ -536,49 +534,6 @@ export const HistoryPanel: React.FC = () => {
width: img.width,
height: img.height
});
// 计算预览位置,确保不超出屏幕边界
const previewWidth = 300; // 减小预览窗口大小
const previewHeight = 300;
const offsetX = 10;
const offsetY = 10;
// 获取HistoryPanel的位置
const historyPanel = document.querySelector('.w-72.bg-white.p-4');
const panelRect = historyPanel ? historyPanel.getBoundingClientRect() : { left: 0, top: 0 };
// 计算相对于HistoryPanel的位置
let x = e.clientX - panelRect.left + offsetX;
let y = e.clientY - panelRect.top + offsetY;
// 确保预览窗口不会超出右边界
if (x + previewWidth > window.innerWidth) {
x = window.innerWidth - previewWidth - 10;
}
// 确保预览窗口不会超出下边界
if (y + previewHeight > window.innerHeight) {
y = window.innerHeight - previewHeight - 10;
}
// 确保预览窗口不会超出左边界
if (x < 0) {
x = 10;
}
// 确保预览窗口不会超出上边界
if (y < 0) {
y = 10;
}
// 添加额外的安全边界检查
x = Math.max(10, Math.min(x, window.innerWidth - previewWidth - 10));
y = Math.max(10, Math.min(y, window.innerHeight - previewHeight - 10));
setPreviewPosition({x, y});
};
img.onerror = (error) => {
console.error('图像加载失败:', error);
@@ -589,89 +544,12 @@ export const HistoryPanel: React.FC = () => {
width: 0,
height: 0
});
// 计算预览位置
const previewWidth = 300;
const previewHeight = 300;
const offsetX = 10;
const offsetY = 10;
let x = e.clientX + offsetX;
let y = e.clientY + offsetY;
// 确保预览窗口不会超出右边界
if (x + previewWidth > window.innerWidth) {
x = window.innerWidth - previewWidth - 10;
}
// 确保预览窗口不会超出下边界
if (y + previewHeight > window.innerHeight) {
y = window.innerHeight - previewHeight - 10;
}
// 确保预览窗口不会超出左边界
if (x < 0) {
x = 10;
}
// 确保预览窗口不会超出上边界
if (y < 0) {
y = 10;
}
// 添加额外的安全边界检查
x = Math.max(10, Math.min(x, window.innerWidth - previewWidth - 10));
y = Math.max(10, Math.min(y, window.innerHeight - previewHeight - 10));
setPreviewPosition({x, y});
};
img.src = imageUrl;
}
}}
onMouseMove={(e) => {
// 调整预览位置以避免被遮挡
const previewWidth = 300;
const previewHeight = 300;
const offsetX = 10;
const offsetY = 10;
// 获取HistoryPanel的位置
const historyPanel = document.querySelector('.w-72.bg-white.p-4');
const panelRect = historyPanel ? historyPanel.getBoundingClientRect() : { left: 0, top: 0 };
// 计算相对于HistoryPanel的位置
let x = e.clientX - panelRect.left + offsetX;
let y = e.clientY - panelRect.top + offsetY;
// 确保预览窗口不会超出右边界
if (x + previewWidth > (historyPanel ? historyPanel.clientWidth : window.innerWidth)) {
x = (historyPanel ? historyPanel.clientWidth : window.innerWidth) - previewWidth - 10;
}
// 确保预览窗口不会超出下边界
if (y + previewHeight > (historyPanel ? historyPanel.clientHeight : window.innerHeight)) {
y = (historyPanel ? historyPanel.clientHeight : window.innerHeight) - previewHeight - 10;
}
// 确保预览窗口不会超出左边界
if (x < 0) {
x = 10;
}
// 确保预览窗口不会超出上边界
if (y < 0) {
y = 10;
}
// 添加额外的安全边界检查
const maxWidth = historyPanel ? historyPanel.clientWidth : window.innerWidth;
const maxHeight = historyPanel ? historyPanel.clientHeight : window.innerHeight;
x = Math.max(10, Math.min(x, maxWidth - previewWidth - 10));
y = Math.max(10, Math.min(y, maxHeight - previewHeight - 10));
setPreviewPosition({x, y});
onMouseMove={() => {
// 不需要处理鼠标移动事件,因为预览现在在页面中心显示
}}
onMouseLeave={() => {
setHoveredImage(null);
@@ -753,42 +631,6 @@ export const HistoryPanel: React.FC = () => {
width: img.width,
height: img.height
});
// 计算预览位置,确保不超出屏幕边界
const previewWidth = 300;
const previewHeight = 300;
const offsetX = 10;
const offsetY = 10;
let x = e.clientX + offsetX;
let y = e.clientY + offsetY;
// 确保预览窗口不会超出右边界
if (x + previewWidth > window.innerWidth) {
x = window.innerWidth - previewWidth - 10;
}
// 确保预览窗口不会超出下边界
if (y + previewHeight > window.innerHeight) {
y = window.innerHeight - previewHeight - 10;
}
// 确保预览窗口不会超出左边界
if (x < 0) {
x = 10;
}
// 确保预览窗口不会超出上边界
if (y < 0) {
y = 10;
}
// 添加额外的安全边界检查
x = Math.max(10, Math.min(x, window.innerWidth - previewWidth - 10));
y = Math.max(10, Math.min(y, window.innerHeight - previewHeight - 10));
setPreviewPosition({x, y});
};
img.onerror = (error) => {
console.error('图像加载失败:', error);
@@ -799,85 +641,12 @@ export const HistoryPanel: React.FC = () => {
width: 0,
height: 0
});
// 计算预览位置
const previewWidth = 300;
const previewHeight = 300;
const offsetX = 10;
const offsetY = 10;
// 获取HistoryPanel的位置信息
const historyPanel = e.currentTarget.closest('.w-72');
const panelRect = historyPanel ? historyPanel.getBoundingClientRect() : { left: 0, top: 0 };
// 计算相对于整个视窗的位置
let x = e.clientX + offsetX;
let y = e.clientY + offsetY;
// 确保预览窗口不会超出右边界
if (x + previewWidth > window.innerWidth) {
x = window.innerWidth - previewWidth - 10;
}
// 确保预览窗口不会超出下边界
if (y + previewHeight > window.innerHeight) {
y = window.innerHeight - previewHeight - 10;
}
// 确保预览窗口不会超出左边界
if (x < 0) {
x = 10;
}
// 确保预览窗口不会超出上边界
if (y < 0) {
y = 10;
}
// 添加额外的安全边界检查
x = Math.max(10, Math.min(x, window.innerWidth - previewWidth - 10));
y = Math.max(10, Math.min(y, window.innerHeight - previewHeight - 10));
setPreviewPosition({x, y});
};
img.src = imageUrl;
}
}}
onMouseMove={(e) => {
// 调整预览位置以避免被遮挡
const previewWidth = 300;
const previewHeight = 300;
const offsetX = 10;
const offsetY = 10;
let x = e.clientX + offsetX;
let y = e.clientY + offsetY;
// 确保预览窗口不会超出右边界
if (x + previewWidth > window.innerWidth) {
x = window.innerWidth - previewWidth - 10;
}
// 确保预览窗口不会超出下边界
if (y + previewHeight > window.innerHeight) {
y = window.innerHeight - previewHeight - 10;
}
// 确保预览窗口不会超出左边界
if (x < 0) {
x = 10;
}
// 确保预览窗口不会超出上边界
if (y < 0) {
y = 10;
}
// 添加额外的安全边界检查
x = Math.max(10, Math.min(x, window.innerWidth - previewWidth - 10));
y = Math.max(10, Math.min(y, window.innerHeight - previewHeight - 10));
setPreviewPosition({x, y});
onMouseMove={() => {
// 不需要处理鼠标移动事件,因为预览现在在页面中心显示
}}
onMouseLeave={() => {
setHoveredImage(null);
@@ -1188,37 +957,6 @@ export const HistoryPanel: React.FC = () => {
title={previewModal.title}
description={previewModal.description}
/>
{/* 悬浮预览 */}
{hoveredImage && (
<div
className="absolute z-[9999] shadow-2xl border border-gray-300 rounded-lg overflow-hidden bg-white backdrop-blur-sm pointer-events-none"
style={{
left: `${previewPosition.x}px`,
top: `${previewPosition.y}px`,
maxWidth: '200px', // 减小最大宽度
maxHeight: '200px'
}}
>
<div className="bg-gray-900 text-white text-xs p-2 truncate font-medium">
{hoveredImage.title}
</div>
<img
src={hoveredImage.url}
alt="预览"
className="w-full h-auto max-h-[150px] object-contain"
/>
{/* 图像信息 */}
<div className="p-2 bg-gray-50 border-t border-gray-200 text-xs">
{hoveredImage.width && hoveredImage.height && (
<div className="flex justify-between text-gray-600">
<span>:</span>
<span className="text-gray-800">{hoveredImage.width} × {hoveredImage.height}</span>
</div>
)}
</div>
</div>
)}
</div>
);
};

View File

@@ -2,31 +2,31 @@
import { UploadResult } from '../types'
// 上传接口URL
const UPLOAD_URL = 'https://api.pandorastudio.cn/auth/OSSupload'
const UPLOAD_URL = import.meta.env.VITE_UPLOAD_API
// 创建一个Map来缓存已上传的图像
const uploadCache = new Map<string, UploadResult>()
// 缓存配置
const MAX_CACHE_SIZE = 50; // 减少最大缓存条目数
const CACHE_EXPIRY_TIME = 15 * 60 * 1000; // 缓存过期时间15分钟
const MAX_CACHE_SIZE = 50 // 减少最大缓存条目数
const CACHE_EXPIRY_TIME = 15 * 60 * 1000 // 缓存过期时间15分钟
/**
* 清理过期的缓存条目
*/
function cleanupExpiredCache(): void {
const now = Date.now();
let deletedCount = 0;
const now = Date.now()
let deletedCount = 0
uploadCache.forEach((value, key) => {
if (now - value.timestamp > CACHE_EXPIRY_TIME) {
uploadCache.delete(key);
deletedCount++;
uploadCache.delete(key)
deletedCount++
}
});
})
if (deletedCount > 0) {
console.log(`清除了 ${deletedCount} 个过期的缓存条目`);
console.log(`清除了 ${deletedCount} 个过期的缓存条目`)
}
}
@@ -37,16 +37,16 @@ function maintainCacheSize(): void {
// 如果缓存大小超过限制,删除最旧的条目
if (uploadCache.size >= MAX_CACHE_SIZE) {
// 获取所有条目并按时间排序
const entries = Array.from(uploadCache.entries());
entries.sort((a, b) => a[1].timestamp - b[1].timestamp);
const entries = Array.from(uploadCache.entries())
entries.sort((a, b) => a[1].timestamp - b[1].timestamp)
// 删除最旧的条目,直到缓存大小在限制内
const deleteCount = Math.max(1, Math.floor(MAX_CACHE_SIZE * 0.2)); // 删除20%的条目
const deleteCount = Math.max(1, Math.floor(MAX_CACHE_SIZE * 0.2)) // 删除20%的条目
for (let i = 0; i < deleteCount && uploadCache.size >= MAX_CACHE_SIZE; i++) {
uploadCache.delete(entries[i][0]);
uploadCache.delete(entries[i][0])
}
console.log(`缓存已满,删除了 ${deleteCount} 个最旧的条目`);
console.log(`缓存已满,删除了 ${deleteCount} 个最旧的条目`)
}
}
@@ -60,17 +60,17 @@ function getImageHash(imageData: string): string {
if (imageData.startsWith('blob:')) {
// 对于Blob URL我们使用URL本身作为标识符的一部分
// 这不是完美的解决方案,但对于大多数情况足够了
return btoa(imageData).slice(0, 32);
return btoa(imageData).slice(0, 32)
}
// 对于base64数据使用简单的哈希函数生成图像标识符
let hash = 0;
let hash = 0
for (let i = 0; i < imageData.length; i++) {
const char = imageData.charCodeAt(i);
hash = ((hash << 5) - hash) + char;
hash = hash & hash; // 转换为32位整数
const char = imageData.charCodeAt(i)
hash = (hash << 5) - hash + char
hash = hash & hash // 转换为32位整数
}
return hash.toString();
return hash.toString()
}
/**
@@ -81,37 +81,37 @@ function getImageHash(imageData: string): string {
async function getBlobFromUrl(blobUrl: string): Promise<Blob> {
try {
// 从AppStore获取Blob
const { useAppStore } = await import('../store/useAppStore');
const blob = useAppStore.getState().getBlob(blobUrl);
const { useAppStore } = await import('../store/useAppStore')
const blob = useAppStore.getState().getBlob(blobUrl)
if (!blob) {
// 如果AppStore中没有找到Blob尝试从URL获取
console.warn('无法从AppStore获取Blob尝试从URL获取:', blobUrl);
console.warn('无法从AppStore获取Blob尝试从URL获取:', blobUrl)
try {
const response = await fetch(blobUrl);
const response = await fetch(blobUrl)
if (!response.ok) {
throw new Error(`获取Blob失败: ${response.status} ${response.statusText}`);
throw new Error(`获取Blob失败: ${response.status} ${response.statusText}`)
}
return await response.blob();
return await response.blob()
} catch (error) {
console.error('从URL获取Blob失败:', error);
throw new Error('无法从Blob URL获取图像数据');
console.error('从URL获取Blob失败:', error)
throw new Error('无法从Blob URL获取图像数据')
}
}
return blob;
return blob
} catch (error) {
console.error('从AppStore获取Blob时出错:', error);
console.error('从AppStore获取Blob时出错:', error)
// 如果导入AppStore失败直接尝试从URL获取
try {
const response = await fetch(blobUrl);
const response = await fetch(blobUrl)
if (!response.ok) {
throw new Error(`获取Blob失败: ${response.status} ${response.statusText}`);
throw new Error(`获取Blob失败: ${response.status} ${response.statusText}`)
}
return await response.blob();
return await response.blob()
} catch (fetchError) {
console.error('从URL获取Blob失败:', fetchError);
throw new Error('无法从Blob URL获取图像数据');
console.error('从URL获取Blob失败:', fetchError)
throw new Error('无法从Blob URL获取图像数据')
}
}
}
@@ -125,118 +125,118 @@ async function getBlobFromUrl(blobUrl: string): Promise<Blob> {
*/
export const uploadImage = async (imageData: string | Blob, accessToken: string, skipCache: boolean = false): Promise<{ success: boolean; url?: string; error?: string }> => {
// 检查缓存中是否已有该图像的上传结果
const imageHash = typeof imageData === 'string' ? getImageHash(imageData) : 'blob-' + Date.now();
const imageHash = typeof imageData === 'string' ? getImageHash(imageData) : 'blob-' + Date.now()
if (!skipCache && typeof imageData === 'string' && uploadCache.has(imageHash)) {
const cachedResult = uploadCache.get(imageHash)!;
const cachedResult = uploadCache.get(imageHash)!
// 检查缓存是否过期
if (Date.now() - cachedResult.timestamp < CACHE_EXPIRY_TIME) {
console.log('从缓存中获取上传结果');
return cachedResult;
console.log('从缓存中获取上传结果')
return cachedResult
} else {
// 缓存过期,删除它
uploadCache.delete(imageHash);
uploadCache.delete(imageHash)
}
}
try {
let blob: Blob;
let blob: Blob
if (typeof imageData === 'string') {
if (imageData.startsWith('blob:')) {
// 从Blob URL获取Blob数据
blob = await getBlobFromUrl(imageData);
blob = await getBlobFromUrl(imageData)
} else if (imageData.includes('base64,')) {
// 从base64数据创建Blob
const base64Data = imageData.split('base64,')[1];
const byteString = atob(base64Data);
const mimeString = 'image/png'; // 默认MIME类型
const ab = new ArrayBuffer(byteString.length);
const ia = new Uint8Array(ab);
const base64Data = imageData.split('base64,')[1]
const byteString = atob(base64Data)
const mimeString = 'image/png' // 默认MIME类型
const ab = new ArrayBuffer(byteString.length)
const ia = new Uint8Array(ab)
for (let i = 0; i < byteString.length; i++) {
ia[i] = byteString.charCodeAt(i);
ia[i] = byteString.charCodeAt(i)
}
blob = new Blob([ab], { type: mimeString });
blob = new Blob([ab], { type: mimeString })
} else {
// 从URL获取Blob
const response = await fetch(imageData);
blob = await response.blob();
const response = await fetch(imageData)
blob = await response.blob()
}
} else {
// 如果已经是Blob对象直接使用
blob = imageData;
blob = imageData
}
// 创建FormData对象
const formData = new FormData();
formData.append('file', blob, 'generated-image.png');
const formData = new FormData()
formData.append('file', blob, 'generated-image.png')
// 发送POST请求
const response = await fetch(UPLOAD_URL, {
method: 'POST',
headers: {
'accessToken': accessToken,
headers: {
accessToken: accessToken,
// 添加其他可能需要的头部
},
body: formData,
});
})
// 记录响应状态以帮助调试
console.log('上传响应状态:', response.status, response.statusText);
console.log('上传响应状态:', response.status, response.statusText)
if (!response.ok) {
const errorText = await response.text();
console.error('上传失败响应内容:', errorText);
throw new Error(`上传失败: ${response.status} ${response.statusText} - ${errorText}`);
const errorText = await response.text()
console.error('上传失败响应内容:', errorText)
throw new Error(`上传失败: ${response.status} ${response.statusText} - ${errorText}`)
}
const result = await response.json();
console.log('上传响应结果:', result);
const result = await response.json()
console.log('上传响应结果:', result)
// 根据返回格式处理结果: {"code": 200,"msg": "上传成功","data": "9ecbaa0a0.jpg"}
if (result.code === 200) {
// 使用环境变量中的VITE_UPLOAD_ASSET_URL作为前缀
const uploadAssetUrl = import.meta.env.VITE_UPLOAD_ASSET_URL || '';
const fullUrl = uploadAssetUrl ? `${uploadAssetUrl}/${result.data}` : result.data;
const uploadAssetUrl = import.meta.env.VITE_UPLOAD_ASSET_URL || ''
const fullUrl = uploadAssetUrl ? `${uploadAssetUrl}/${result.data}` : result.data
// 清理过期缓存
cleanupExpiredCache();
cleanupExpiredCache()
// 维护缓存大小
maintainCacheSize();
maintainCacheSize()
// 将上传结果存储到缓存中
const uploadResult = { success: true, url: fullUrl, error: undefined };
const uploadResult = { success: true, url: fullUrl, error: undefined }
if (typeof imageData === 'string') {
uploadCache.set(imageHash, {
...uploadResult,
timestamp: Date.now()
});
timestamp: Date.now(),
})
}
return uploadResult;
return uploadResult
} else {
throw new Error(`上传失败: ${result.msg}`);
throw new Error(`上传失败: ${result.msg}`)
}
} catch (error) {
console.error('上传图像时出错:', error);
const errorResult = { success: false, error: error instanceof Error ? error.message : String(error) };
console.error('上传图像时出错:', error)
const errorResult = { success: false, error: error instanceof Error ? error.message : String(error) }
// 清理过期缓存
cleanupExpiredCache();
cleanupExpiredCache()
// 维护缓存大小(即使是失败的结果也缓存,但时间较短)
maintainCacheSize();
maintainCacheSize()
// 将失败的上传结果也存储到缓存中(可选)
if (typeof imageData === 'string') {
uploadCache.set(imageHash, {
...errorResult,
timestamp: Date.now()
});
timestamp: Date.now(),
})
}
return errorResult;
return errorResult
}
}
@@ -249,43 +249,43 @@ export const uploadImage = async (imageData: string | Blob, accessToken: string,
*/
export const uploadImages = async (imageDatas: (string | Blob)[], accessToken: string, skipCache: boolean = false): Promise<UploadResult[]> => {
try {
const results: UploadResult[] = [];
const results: UploadResult[] = []
for (let i = 0; i < imageDatas.length; i++) {
const imageData = imageDatas[i];
const imageData = imageDatas[i]
try {
const uploadResult = await uploadImage(imageData, accessToken, skipCache);
const uploadResult = await uploadImage(imageData, accessToken, skipCache)
const result: UploadResult = {
success: uploadResult.success,
url: uploadResult.url,
error: uploadResult.error,
timestamp: Date.now(),
};
results.push(result);
console.log(`${i + 1}张图像上传${uploadResult.success ? '成功' : '失败'}:`, uploadResult);
}
results.push(result)
console.log(`${i + 1}张图像上传${uploadResult.success ? '成功' : '失败'}:`, uploadResult)
} catch (error) {
const result: UploadResult = {
success: false,
error: error instanceof Error ? error.message : String(error),
timestamp: Date.now(),
};
results.push(result);
console.error(`${i + 1}张图像上传失败:`, error);
}
results.push(result)
console.error(`${i + 1}张图像上传失败:`, error)
}
}
// 检查是否有任何上传失败
const failedUploads = results.filter(r => !r.success);
const failedUploads = results.filter(r => !r.success)
if (failedUploads.length > 0) {
console.warn(`${failedUploads.length}张图像上传失败`);
console.warn(`${failedUploads.length}张图像上传失败`)
} else {
console.log(`所有${results.length}张图像上传成功`);
console.log(`所有${results.length}张图像上传成功`)
}
return results;
return results
} catch (error) {
console.error('批量上传图像时出错:', error);
throw error;
console.error('批量上传图像时出错:', error)
throw error
}
}
@@ -293,6 +293,6 @@ export const uploadImages = async (imageDatas: (string | Blob)[], accessToken: s
* 清除上传缓存
*/
export const clearUploadCache = (): void => {
uploadCache.clear();
console.log('上传缓存已清除');
}
uploadCache.clear()
console.log('上传缓存已清除')
}