(batchId)
| 2370 | |
| 2371 | // 连接批量任务 WebSocket |
| 2372 | function connectBatchWebSocket(batchId) { |
| 2373 | activeBatchId = batchId; |
| 2374 | |
| 2375 | if (batchWebSocket && [WebSocket.OPEN, WebSocket.CONNECTING].includes(batchWebSocket.readyState)) { |
| 2376 | return; |
| 2377 | } |
| 2378 | |
| 2379 | if (batchWsReconnectTimer) { |
| 2380 | clearTimeout(batchWsReconnectTimer); |
| 2381 | batchWsReconnectTimer = null; |
| 2382 | } |
| 2383 | batchWsManualClose = false; |
| 2384 | |
| 2385 | const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'; |
| 2386 | const wsUrl = `${protocol}//${window.location.host}/api/ws/batch/${batchId}`; |
| 2387 | |
| 2388 | try { |
| 2389 | const socket = new WebSocket(wsUrl); |
| 2390 | batchWebSocket = socket; |
| 2391 | |
| 2392 | socket.onopen = () => { |
| 2393 | if (batchWebSocket !== socket) return; |
| 2394 | console.log('批量任务 WebSocket 连接成功'); |
| 2395 | clearBatchWebSocketReconnect(); |
| 2396 | // 停止轮询(如果有) |
| 2397 | stopBatchPolling(); |
| 2398 | // 开始心跳 |
| 2399 | startBatchWebSocketHeartbeat(); |
| 2400 | }; |
| 2401 | |
| 2402 | socket.onmessage = (event) => { |
| 2403 | if (batchWebSocket !== socket) return; |
| 2404 | const data = JSON.parse(event.data); |
| 2405 | |
| 2406 | if (data.type === 'log') { |
| 2407 | const logType = getLogType(data.message); |
| 2408 | addLog(logType, data.message); |
| 2409 | } else if (data.type === 'status') { |
| 2410 | // 更新进度 |
| 2411 | if (data.total !== undefined) { |
| 2412 | updateBatchProgress({ |
| 2413 | total: data.total, |
| 2414 | completed: data.completed || 0, |
| 2415 | success: data.success || 0, |
| 2416 | failed: data.failed || 0 |
| 2417 | }); |
| 2418 | } |
| 2419 | |
| 2420 | // 检查是否完成 |
| 2421 | if (['completed', 'failed', 'cancelled', 'cancelling'].includes(data.status)) { |
| 2422 | // 保存最终状态,用于 onclose 判断 |
| 2423 | batchFinalStatus = data.status; |
| 2424 | batchCompleted = true; |
| 2425 | |
| 2426 | // 断开 WebSocket(异步操作) |
| 2427 | disconnectBatchWebSocket(); |
| 2428 | |
| 2429 | // 任务完成后再重置按钮 |
no test coverage detected