20260429_231526-fix: upload field mismatch, WebSocket StrictMode crash, project list refresh after upload

This commit is contained in:
2026-04-29 23:17:09 +08:00
parent 4ec917efe7
commit d7d1e3225f
12 changed files with 260 additions and 10 deletions

View File

@@ -25,9 +25,13 @@ export function Dashboard() {
]);
useEffect(() => {
progressWS.connect();
let mounted = true;
const timer = setTimeout(() => {
if (mounted) progressWS.connect();
}, 500);
const unsubscribe = progressWS.onProgress((data: ProgressMessage) => {
if (!mounted) return;
setIsConnected(progressWS.isConnected());
if (data.type === 'progress' && data.taskId && data.filename) {
@@ -81,10 +85,11 @@ export function Dashboard() {
});
const checkConnection = setInterval(() => {
setIsConnected(progressWS.isConnected());
if (mounted) setIsConnected(progressWS.isConnected());
}, 5000);
return () => {
mounted = false;
unsubscribe();
clearInterval(checkConnection);
progressWS.disconnect();

View File

@@ -93,7 +93,14 @@ export function ProjectLibrary({ onProjectSelect }: ProjectLibraryProps) {
try {
setIsLoading(true);
const result = await uploadMedia(file);
alert(`上传成功: ${file.name}\n已保存至: ${result.url}`);
alert(`上传成功: ${file.name}\n已保存至: ${result.file_url}`);
// 上传成功后创建新项目
const newProject = await createProject({
name: file.name,
description: `导入于 ${new Date().toLocaleString()}`,
});
addProject(newProject);
// 刷新项目列表
const data = await getProjects();
setProjects(data);
} catch (err) {

View File

@@ -87,7 +87,7 @@ export async function deleteTemplate(id: string): Promise<void> {
}
// Media
export async function uploadMedia(file: File, projectId?: string): Promise<{ url: string; id: string }> {
export async function uploadMedia(file: File, projectId?: string): Promise<{ object_name: string; file_url: string; size: number; message: string }> {
const formData = new FormData();
formData.append('file', file);
if (projectId) {

View File

@@ -18,6 +18,7 @@ class ProgressWebSocket {
private reconnectInterval = 3000;
private maxReconnectInterval = 30000;
private shouldReconnect = false;
private shouldCloseAfterOpen = false;
private currentInterval = 3000;
constructor(url = 'ws://192.168.3.11:8000/ws/progress') {
@@ -30,11 +31,18 @@ class ProgressWebSocket {
}
this.shouldReconnect = true;
this.shouldCloseAfterOpen = false;
try {
this.ws = new WebSocket(this.url);
this.ws.onopen = () => {
// 如果连接前被要求关闭React StrictMode 快速卸载),则打开后立即关闭
if (this.shouldCloseAfterOpen) {
this.ws?.close();
this.ws = null;
return;
}
this.currentInterval = this.reconnectInterval;
console.log('[WebSocket] Connected to progress stream');
};
@@ -50,14 +58,18 @@ class ProgressWebSocket {
this.ws.onclose = () => {
console.log('[WebSocket] Connection closed');
this.ws = null;
if (this.shouldReconnect) {
this.scheduleReconnect();
}
};
this.ws.onerror = (err) => {
console.error('[WebSocket] Error:', err);
this.ws?.close();
this.ws.onerror = () => {
// 静默处理错误,避免在 CONNECTING 状态时 close 触发浏览器报错
this.ws = null;
if (this.shouldReconnect) {
this.scheduleReconnect();
}
};
} catch (err) {
console.error('[WebSocket] Failed to connect:', err);
@@ -71,10 +83,19 @@ class ProgressWebSocket {
clearTimeout(this.reconnectTimer);
this.reconnectTimer = null;
}
if (this.ws) {
this.ws.close();
this.ws = null;
if (!this.ws) return;
// 如果还在连接中,设置标志位让 onopen 打开后立即关闭
if (this.ws.readyState === WebSocket.CONNECTING) {
this.shouldCloseAfterOpen = true;
return;
}
// 只有已打开的连接才调用 close()
if (this.ws.readyState === WebSocket.OPEN) {
this.ws.close();
}
this.ws = null;
}
onProgress(callback: ProgressCallback) {