Files
xk-hy-transit-go/internal/logweb/web/runs.html
2026-05-22 09:17:39 +08:00

90 lines
3.6 KiB
HTML

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<title>同步流水</title>
<link rel="stylesheet" href="/static/static.css">
</head>
<body>
<div class="wrap">
<header>
<h1>同步流水</h1>
<nav class="nav"><a href="/">首页</a><a href="/logs">文件日志</a><a href="/test">测试</a></nav>
</header>
<div class="toolbar">
<label>锚定日 <input type="date" id="anchor"></label>
<label>类型
<select id="step"></select>
</label>
<button class="primary" id="load">刷新</button>
</div>
<h3 style="color:var(--muted);font-size:0.95rem">同步任务</h3>
<div style="overflow:auto;margin-bottom:1.5rem">
<table><thead><tr>
<th>日期</th><th>类型</th><th>状态</th><th>总数</th><th>成功</th><th>失败</th><th>开始</th><th>结束</th>
</tr></thead><tbody id="jobs"></tbody></table>
</div>
<h3 style="color:var(--muted);font-size:0.95rem">业务记录(拉取 → 上报 → 回调)</h3>
<div style="overflow:auto">
<table><thead><tr>
<th>ID</th><th>日期</th><th>类型</th><th>批次</th><th>biz_key</th><th>拉取校验</th>
<th>上报</th><th>推送明文</th><th>HTTP</th><th>回调</th><th>trace</th><th></th>
</tr></thead><tbody id="items"></tbody></table>
</div>
</div>
<script src="/static/app.js"></script>
<script>
const anchorFromUrl = qs('anchor_date');
if (anchorFromUrl) document.getElementById('anchor').value = anchorFromUrl;
(async () => {
const m = await loadMeta();
if (m && m.stepOptions) fillStepSelect(document.getElementById('step'), m.stepOptions);
})();
async function load() {
const anchor = document.getElementById('anchor').value;
const step = document.getElementById('step').value;
let url = '/api/runs?limit=100';
if (anchor) url += '&anchor_date=' + anchor;
if (step) url += '&step=' + step;
const data = await api(url);
document.getElementById('jobs').innerHTML = (data.jobs || []).map(j => `<tr>
<td>${esc(j.anchorDate)}</td>
<td>${esc(j.stepLabel || j.step)}</td>
<td>${badge(j.status, j.statusLabel)}</td>
<td>${j.totalCount}</td><td>${j.successCount}</td><td>${j.failedCount}</td>
<td>${fmtTimeAny(j.startedAt)}</td>
<td>${fmtTimeAny(j.finishedAt)}</td>
</tr>`).join('') || '<tr><td colspan="8">无任务</td></tr>';
document.getElementById('items').innerHTML = (data.items || []).map(it => {
const r = it.record;
const cb = it.callback;
const ve = it.errors && it.errors.valid ? (it.errors.formatted || it.errors.raw) : (it.errors && it.errors.raw) || '';
const veShort = ve.length > 80 ? ve.slice(0, 80) + '…' : ve;
const ll = r.LastLog;
return `<tr>
<td>${r.ID}</td>
<td>${esc(r.AnchorDate)}</td>
<td>${esc(it.stepLabel || it.step)}</td>
<td>${r.JobID}</td>
<td><code>${esc(r.BizKey)}</code></td>
<td>${veShort ? '<span class="badge warn">有</span> ' + esc(veShort) : badge('success', '通过')}</td>
<td>${badge(r.PushStatus, it.pushStatusLabel)}</td>
<td>${it.hasPushPlain ? '<span class="badge ok">有</span>' : '<span class="badge warn">无</span>'}</td>
<td>${ll ? ll.HTTPCode + ' / ' + (ll.MsgCode && ll.MsgCode.Valid ? ll.MsgCode.Int64 : '-') + ' / ' + ll.DurationMs + 'ms' : '-'}</td>
<td>${badge(cb.callback_status, it.callbackStatusLabel)} ${esc(cb.error_message || '')}</td>
<td>${ll ? esc(ll.TraceID) : '-'}</td>
<td><a href="/runs/record?id=${r.ID}">详情</a></td>
</tr>`;
}).join('') || '<tr><td colspan="12">无记录</td></tr>';
}
document.getElementById('load').onclick = () => load().catch(e => alert(e.message));
load().catch(e => alert(e.message));
</script>
</body>
</html>