(run)
| 189 | } |
| 190 | |
| 191 | function renderRunDetail(run) { |
| 192 | const titleNode = document.getElementById('selfcheck-detail-title'); |
| 193 | const listNode = document.getElementById('selfcheck-check-list'); |
| 194 | if (!titleNode || !listNode) return; |
| 195 | |
| 196 | if (!run) { |
| 197 | selfcheckState.selectedRun = null; |
| 198 | titleNode.textContent = '请在上方点击一条运行记录'; |
| 199 | listNode.innerHTML = '<div class="empty-state">暂无检查数据</div>'; |
| 200 | renderRepairResults([]); |
| 201 | renderRepairPreview(null); |
| 202 | return; |
| 203 | } |
| 204 | selfcheckState.selectedRun = run; |
| 205 | |
| 206 | titleNode.textContent = `运行 #${run.id} | ${run.mode} | ${normalizeStatus(run.status).text} | 评分 ${run.score || 0}`; |
| 207 | const checks = Array.isArray(run?.result_data?.checks) ? run.result_data.checks : []; |
| 208 | if (!checks.length) { |
| 209 | listNode.innerHTML = '<div class="empty-state">当前运行暂无检查结果</div>'; |
| 210 | renderRepairResults(run?.result_data?.repairs || []); |
| 211 | return; |
| 212 | } |
| 213 | |
| 214 | listNode.innerHTML = checks.map((check) => { |
| 215 | const fixes = Array.isArray(check?.fixes) ? check.fixes : []; |
| 216 | const detailsText = check?.details ? JSON.stringify(check.details, null, 2) : ''; |
| 217 | return ` |
| 218 | <div class="check-item"> |
| 219 | <div class="check-item-top"> |
| 220 | <div class="check-item-title">${escapeHtml(check?.name || check?.key || '-')}</div> |
| 221 | <div>${statusBadge(check?.status)} <span class="hint-inline">${Number(check?.duration_ms || 0)}ms</span></div> |
| 222 | </div> |
| 223 | <div class="check-item-desc">${escapeHtml(check?.message || '-')}</div> |
| 224 | ${detailsText ? `<details style="margin-top:8px;"><summary>查看明细</summary><pre style="margin-top:6px;white-space:pre-wrap;word-break:break-word;">${escapeHtml(detailsText)}</pre></details>` : ''} |
| 225 | ${fixes.length ? ` |
| 226 | <div class="check-fixes"> |
| 227 | ${fixes.map((fixKey) => ` |
| 228 | <button class="btn btn-warning btn-sm selfcheck-repair-btn" data-run-id="${run.id}" data-repair-key="${escapeHtml(fixKey)}"> |
| 229 | ${escapeHtml(getRepairName(fixKey))} |
| 230 | </button> |
| 231 | `).join('')} |
| 232 | </div> |
| 233 | ` : ''} |
| 234 | </div> |
| 235 | `; |
| 236 | }).join(''); |
| 237 | |
| 238 | renderRepairResults(run?.result_data?.repairs || []); |
| 239 | } |
| 240 | |
| 241 | async function loadRepairCatalog() { |
| 242 | try { |
no test coverage detected