Files
vd_test_fixture/edc-web/app/static/js/test_op.js
wangfq 60215eef48 feat: 自动化增加起止时间 + 本轮每次测试明细表
- 显示自动化开始/结束时间
- 测试信息区新增本轮测试明细表(序号、状态、关键字段)
- 方便对照平均值是否计算正确
2026-05-28 15:19:20 +08:00

263 lines
9.2 KiB
JavaScript

// 测试操作页
let autoRunning = false;
let autoTotal = 0;
let autoDone = 0;
let autoFailed = 0;
let autoRemaining = 0;
let autoStartTime = "";
let pollInterval = null;
let timeoutTimers = {}; // record_id → timer
const TIMEOUT_MS = 10000;
// ─── 手动指令 ─────────────────────────────────
async function sendCmd(cmd) {
try {
const resp = await fetch("/api/command", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ dnt_id: DNT_ID, cmd }),
});
const data = await resp.json();
if (data.ok) {
console.log(`指令 ${cmd} 已下发: ${data.send_pkg}`);
}
} catch (e) {
alert("发送失败: " + e.message);
}
}
// ─── 自动化 ────────────────────────────────────
async function toggleAuto() {
if (!autoRunning) {
await startAuto();
} else {
stopAuto();
}
}
async function startAuto() {
const count = parseInt(document.getElementById("test-count").value) || 10;
if (count < 1) return;
// 重置
autoRunning = true;
autoTotal = count;
autoDone = 0;
autoFailed = 0;
autoRemaining = count;
autoStartTime = new Date().toISOString(); // 记录开始时间
// 显示开始时间
document.getElementById("auto-time").style.display = "block";
document.getElementById("time-start").textContent = new Date().toLocaleString();
document.getElementById("time-end").textContent = "-";
// 清空显示
resetAverages();
document.getElementById("latest-result").innerHTML = '<p class="placeholder">等待测试...</p>';
document.getElementById("progress-bar").style.width = "0%";
document.getElementById("progress-text").textContent = "0/" + count + " (0 失败)";
document.getElementById("stat-done").textContent = "0";
document.getElementById("stat-failed").textContent = "0";
document.getElementById("stat-remaining").textContent = count;
// 清空测试明细
document.querySelector("#records-table tbody").innerHTML = "";
document.getElementById("records-empty").style.display = "block";
const btn = document.getElementById("btn-auto");
btn.textContent = "结束";
btn.className = "btn-stop";
// 插入第一条 0xB0
try {
const resp = await fetch("/api/automation/start", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ dnt_id: DNT_ID, count }),
});
const data = await resp.json();
if (data.ok) {
// 启动超时计时器
startTimeout(data.first_record_id);
}
} catch (e) {
console.error("启动失败:", e);
stopAuto();
}
// 启动轮询
pollInterval = setInterval(pollProgress, 1000);
}
function stopAuto() {
autoRunning = false;
clearInterval(pollInterval);
pollInterval = null;
// 记录结束时间
document.getElementById("time-end").textContent = new Date().toLocaleString();
// 清除所有超时计时器
for (const id in timeoutTimers) {
clearTimeout(timeoutTimers[id]);
}
timeoutTimers = {};
const btn = document.getElementById("btn-auto");
btn.textContent = "开始";
btn.className = "btn-start";
}
async function pollProgress() {
if (!autoRunning) return;
try {
const resp = await fetch(`/api/automation/${DNT_ID}/progress?since=${encodeURIComponent(autoStartTime)}`);
const data = await resp.json();
const stats = data.stats;
// 更新计数
autoDone = stats.done || 0;
autoFailed = stats.failed || 0;
autoRemaining = autoTotal - autoDone - autoFailed;
if (autoRemaining < 0) autoRemaining = 0;
updateUI();
// 显示最新结果
if (data.latest) {
renderLatest(data.latest);
}
// 显示平均值
if (data.averages) {
renderAverages(data.averages);
}
// 显示本轮测试明细
if (data.records) {
renderRecords(data.records);
}
// 自动插入下一条 0xB0
if (autoRemaining > 0) {
// 检查是否还有 pending 的记录,没有则插入新的
if (stats.pending === 0 && stats.sent === 0) {
try {
const r = await fetch("/api/command", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ dnt_id: DNT_ID, cmd: "B0" }),
});
const rd = await r.json();
if (rd.ok) {
startTimeout(rd.record_id);
}
} catch (e) {
console.error("插入下一条失败:", e);
}
}
} else {
// 全部完成
stopAuto();
}
} catch (e) {
console.error("轮询失败:", e);
}
}
function startTimeout(recordId) {
timeoutTimers[recordId] = setTimeout(async () => {
// 超时:检查 record 的状态,如果还是 1 → 视为失败
// 后端串行轮询会自动处理超时标记为 state=3
// 前端稍后通过 pollProgress 更新计数
console.log(`记录 ${recordId} 可能已超时`);
}, TIMEOUT_MS);
}
function updateUI() {
document.getElementById("stat-done").textContent = autoDone;
document.getElementById("stat-failed").textContent = autoFailed;
document.getElementById("stat-remaining").textContent = autoRemaining;
const total = autoTotal || 1;
const pct = Math.round((autoDone / total) * 100);
document.getElementById("progress-bar").style.width = pct + "%";
document.getElementById("progress-text").textContent =
`${autoDone}/${autoTotal} (${autoFailed} 失败)`;
}
function toSpeed(v) {
if (v === null || v === undefined || v === '') return '-';
return (parseFloat(v) / 10).toFixed(1);
}
// ─── 显示最新结果 ──────────────────────────────
function renderLatest(data) {
const div = document.getElementById("latest-result");
div.innerHTML = `
<p>设备型号:<strong>${data.str_type || '-'}</strong></p>
<p>峰峰值:${data.ppvalue?.toFixed(2) || '-'} V</p>
<p>开始工作频率:${data.idle_freq || '-'} Hz</p>
<p>进入工作频率:${data.enter_freq || '-'} Hz</p>
<p>离开工作频率:${data.exit_freq || '-'} Hz</p>
<p>进入距离:${data.enter_dist || '-'} mm</p>
<p>离开距离:${data.exit_dist || '-'} mm</p>
<p>进入速度:${toSpeed(data.enter_speed)} m/s</p>
<p>离开速度:${toSpeed(data.exit_speed)} m/s</p>
<p>是否完成:${data.iffinish === '1' ? '是' : '否'}</p>
<p>故障信息:${data.fault_info || '无'}</p>
<p>时间:${data.create_time || '-'}</p>
`;
}
// ─── 显示平均值 ────────────────────────────────
function renderAverages(data) {
document.getElementById("avg-ppvalue").textContent = data.avg_ppvalue || "-";
document.getElementById("avg-idle-freq").textContent = data.avg_idle_freq || "-";
document.getElementById("avg-enter-freq").textContent = data.avg_enter_freq || "-";
document.getElementById("avg-enter-dist").textContent = data.avg_enter_dist || "-";
document.getElementById("avg-exit-dist").textContent = data.avg_exit_dist || "-";
document.getElementById("avg-enter-speed").textContent = data.avg_enter_speed || "-";
document.getElementById("avg-exit-speed").textContent = data.avg_exit_speed || "-";
}
function resetAverages() {
["ppvalue", "idle-freq", "enter-freq", "enter-dist", "exit-dist",
"enter-speed", "exit-speed"].forEach(id => {
document.getElementById("avg-" + id).textContent = "-";
});
}
// ─── 显示本轮测试明细 ──────────────────────────
function renderRecords(records) {
if (!records || !records.length) {
document.getElementById("records-empty").style.display = "block";
document.getElementById("records-table").style.display = "none";
return;
}
document.getElementById("records-empty").style.display = "none";
document.getElementById("records-table").style.display = "";
const tbody = document.querySelector("#records-table tbody");
tbody.innerHTML = records.map((r, i) => `
<tr>
<td>${i + 1}</td>
<td style="color:${r.sn_state === 2 ? '#27ae60' : r.sn_state === 3 ? '#e74c3c' : '#888'}">
${r.sn_state === 2 ? 'OK' : r.sn_state === 3 ? '超时' : '?'}
</td>
<td>${r.ppvalue?.toFixed(2) || '-'}</td>
<td>${r.idle_freq || '-'}</td>
<td>${r.enter_dist || '-'}</td>
<td>${r.exit_dist || '-'}</td>
<td>${toSpeed(r.enter_speed)}</td>
<td>${r.create_time || '-'}</td>
</tr>
`).join("");
}