// 去重记录(「任务 → 去重记录」页) // 账本在 done_mark 表(跨设备幂等),后端见 core/dedup.py + web/tasks_api.py 的三个接口。 // 这一页的价值:**"谁做过了、还差谁"看得见**——用户原来不知道任务什么时候跑完, // 只能一直重跑,而重跑本身又在制造重复。 var _dedupMarks = []; function loadDedup(){ var sel=document.getElementById('dedup-job'); if(!sel)return; var jobId=sel.value||''; apiGet('/api/done_marks?limit=300'+(jobId?('&job='+encodeURIComponent(jobId)):'')).then(function(r){ if(!r||!r.ok){ var tb=document.getElementById('tb-dedup'); if(tb)tb.innerHTML='读取失败:'+esc((r&&r.error)||'')+''; return; } _dedupMarks=r.marks||[]; renderDedupJobs(r.job_id||''); renderDedup(r.stats||{}); }); } // 任务下拉:用已加载的任务列表填(含"全部任务");保持当前选中项 // `_jobsData` 是全局任务列表(monitor.js 声明、tasks.js 的 loadTasks 填充) function renderDedupJobs(current){ var sel=document.getElementById('dedup-job'); if(!sel)return; var jobs=_jobsData||[]; if(!jobs.length)return; // 任务列表还没加载就先留着旧选项 var cur=current!==undefined?current:(sel.value||''); var html=''; jobs.forEach(function(j){ html+=''; }); sel.innerHTML=html; sel.value=cur; } function renderDedup(stats){ var tb=document.getElementById('tb-dedup'); if(!tb)return; var st=document.getElementById('dedup-stats'); if(st){ st.textContent='共 '+stats.total+' 条 · 涉及 '+stats.devices+' 台设备 / ' +stats.identities+' 个身份值|今天已做 '+stats.today_devices+' 台 · ' +stats.today_identities+' 个身份值'; } if(!_dedupMarks.length){ tb.innerHTML='暂无记录(任务里用了「去重」条件 + 「记为已做」并成功做完之后才会有)'; return; } var KIND={day:'每天一次',all:'只做一次',hours:'按小时'}; tb.innerHTML=_dedupMarks.map(function(m){ var who=m.device_name?(''+esc(m.device_name)+'
' +''+esc(m.serial)+'') :(''+esc(m.serial||'-')+''); return ''+esc(m.created_at)+''+ ''+who+''+ ''+esc(m.identity||'-')+''+ ''+esc(KIND[m.kind]||m.kind)+''+ ''+esc(m.job_name||m.job_id||'-')+''+ ''; }).join(''); } function deleteDedupMark(id){ if(!confirm('删掉这条去重记录?\n\n删掉之后,这台设备/这个身份下次跑该任务时会重新执行一遍。'))return; apiPost('/api/done_marks/delete',{id:id}).then(function(r){ if(r&&r.ok){showToast(r.msg||'已删除','success');loadDedup();} else showToast('删除失败: '+((r&&r.error)||''),'error'); }); } function clearJobDedup(){ var sel=document.getElementById('dedup-job'); var jobId=sel?sel.value:''; if(!jobId){showToast('先在左边选一个任务("清空本任务记录"要指定任务)','error');return;} if(!confirm('清空这个任务的全部去重记录?\n\n清空之后,所有设备/身份下次跑该任务都会重新执行一遍。'))return; apiPost('/api/done_marks/clear',{job:jobId}).then(function(r){ if(r&&r.ok){showToast(r.msg||'已清空','success');loadDedup();} else showToast('清空失败: '+((r&&r.error)||''),'error'); }); }