fix: 设备异常状态清除(清除异常/一键清除,检查与更新原子化防竞态)

This commit is contained in:
2026-08-11 08:22:24 +08:00
parent 5f914c4fe4
commit 8a3cd67a97
4 changed files with 86 additions and 10 deletions
+20 -2
View File
@@ -130,6 +130,19 @@ async function stopSelectedDevices(){
setTimeout(loadMonitor,500);
}
// 清除单台设备的异常状态(error/failed → 未启动)
async function clearDeviceError(serial){
if(!confirm('确认清除设备 '+serial+' 的异常状态?'))return;
const r=await apiPost('/api/device/clear_error',{serial:serial});
handleResult(r,()=>loadMonitor());
}
// 一键清除所有异常/失败设备的错误状态(运行中的任务不受影响)
async function clearAllErrors(){
if(!confirm('确认清除所有设备的异常状态?(运行中/等待重试的设备会跳过)'))return;
const r=await apiPost('/api/device/clear_all_errors');
handleResult(r,()=>loadMonitor());
}
// ================== 设备画面查看 ==================
let _shotTimer=null; // 自动刷新定时器
let _shotSerial=''; // 当前查看的 serial
@@ -456,10 +469,15 @@ function renderDeviceRow(dev){
const endInfo=(dev.worker_status==='running'&&dev.end_time)?'<div style="font-size:11px;color:#94a3b8">预计结束 '+new Date(dev.end_time*1000).toLocaleTimeString()+'</div>':'';
// 选择器健康警告(某步骤连续未找到元素,可能 App 改版选择器失效)
const warnInfo=dev.last_warning?'<div style="font-size:11px;color:#f59e0b" title="'+esc(dev.last_warning)+'">⚠ '+esc(dev.last_warning)+'</div>':'';
const stopBtn=(dev.worker_status==='running'||dev.worker_status==='connecting')?'<button class="btn btn-danger btn-xs" onclick="apiAction(\'/api/stop_device\',{serial:\''+esc(dev.serial)+'\'})">停止</button>':'';
// 设备操作按钮需要"设备控制"权限(无权限只保留截图查看)
const canDev=_can('devices');
const stopBtn=canDev&&(dev.worker_status==='running'||dev.worker_status==='connecting')?'<button class="btn btn-danger btn-xs" onclick="apiAction(\'/api/stop_device\',{serial:\''+esc(dev.serial)+'\'})">停止</button>':'';
// 截图按钮(任何状态都可看,离线时会报错)
const shotBtn='<button class="btn btn-xs" onclick="openScreenshot(\''+esc(dev.serial)+'\')" title="查看设备画面(不影响任务)">截图</button>';
const btns='<div style="display:flex;gap:4px;flex-wrap:wrap">'+shotBtn+stopBtn+'</div>';
// 异常/失败设备提供"清除异常"(把状态恢复为未启动)
const clearBtn=canDev&&(dev.worker_status==='error'||dev.worker_status==='failed')
?'<button class="btn btn-xs" onclick="clearDeviceError(\''+esc(dev.serial)+'\')" title="清除该设备的异常状态,恢复为未启动">清除异常</button>':'';
const btns='<div style="display:flex;gap:4px;flex-wrap:wrap">'+shotBtn+clearBtn+stopBtn+'</div>';
const devName=dev.device_name||dev.model||'';
const devLabel=devName?'<strong>'+esc(dev.serial)+'</strong><br><span style="font-size:11px;color:#94a3b8">'+esc(devName)+'</span>':'<strong>'+esc(dev.serial)+'</strong>';
// 复选框列