safesight-control/internal/web/ui/templates/task.html
2026-01-10 21:30:28 +08:00

107 lines
3.7 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{{define "task"}}
<div class="card">
<div><a href="/ui/tasks">← 返回任务列表</a></div>
</div>
<div class="card">
<h2>任务详情</h2>
<div class="row" style="margin-top:10px">
<div>
<div class="muted small">任务ID</div>
<div class="mono"><b>{{.Task.ID}}</b></div>
</div>
<div>
<div class="muted small">类型</div>
<div class="mono">{{.Task.Type}}</div>
</div>
<div>
<div class="muted small">状态</div>
<div>
{{if eq .Task.Status "success"}}<span class="pill ok">成功</span>
{{else if eq .Task.Status "failed"}}<span class="pill bad">失败</span>
{{else if eq .Task.Status "running"}}<span class="pill warn">执行中</span>
{{else}}<span class="pill">待执行</span>{{end}}
<span class="muted small mono" style="margin-left:8px">({{.Task.Status}})</span>
</div>
</div>
</div>
</div>
<div class="card">
<h2>设备执行情况</h2>
<div class="table-wrap" style="margin-top:10px">
<table>
<thead>
<tr><th>设备ID</th><th>状态</th><th>进度</th><th>错误</th></tr>
</thead>
<tbody id="devices-body">
{{range $id, $st := .Task.Devices}}
<tr data-device-id="{{$id}}">
<td class="mono">{{$id}}</td>
<td class="st">
{{if eq $st.Status "success"}}<span class="pill ok">成功</span>
{{else if eq $st.Status "failed"}}<span class="pill bad">失败</span>
{{else if eq $st.Status "running"}}<span class="pill warn">执行中</span>
{{else}}<span class="pill">待执行</span>{{end}}
</td>
<td class="pg mono">{{$st.Progress}}</td>
<td class="er">{{$st.Error}}</td>
</tr>
{{end}}
</tbody>
</table>
</div>
</div>
<div class="card">
<h2>实时推送SSE</h2>
<div class="muted small">订阅:<code class="mono">/api/tasks/{{.TaskID}}/events</code></div>
<div class="actions" style="margin-top:8px">
<button type="button" onclick="startSSE()">连接</button>
<button type="button" onclick="stopSSE()">断开</button>
<span class="muted small" id="sse-status">未连接</span>
</div>
<pre id="sse-log" style="margin-top:10px;max-height:320px"></pre>
</div>
<script>
let es;
function pill(status){
if(status === 'success') return '<span class="pill ok">成功</span>';
if(status === 'failed') return '<span class="pill bad">失败</span>';
if(status === 'running') return '<span class="pill warn">执行中</span>';
return '<span class="pill">待执行</span>';
}
function startSSE(){
stopSSE();
const url = `/api/tasks/{{.TaskID}}/events`;
es = new EventSource(url);
document.getElementById('sse-status').textContent = '连接中...';
es.onopen = () => { document.getElementById('sse-status').textContent = '已连接'; };
es.onerror = () => { document.getElementById('sse-status').textContent = '连接异常(自动重试)'; };
es.addEventListener('device_update', (ev) => {
const line = ev.data;
const log = document.getElementById('sse-log');
log.textContent += line + "\n";
log.scrollTop = log.scrollHeight;
try {
const u = JSON.parse(line);
const tr = document.querySelector(`tr[data-device-id="${cssEscape(u.device_id)}"]`);
if(tr){
tr.querySelector('.st').innerHTML = pill(u.status);
tr.querySelector('.pg').textContent = u.progress;
tr.querySelector('.er').textContent = u.error || '';
}
} catch(e){}
});
}
function stopSSE(){
if(es){ es.close(); es = null; }
document.getElementById('sse-status').textContent = '未连接';
}
function cssEscape(s){
return String(s).replace(/[^a-zA-Z0-9_-]/g, (c) => "\\"+c);
}
</script>
{{end}}