增加了每个设备合格的通过时间,将急停灯改为红色

This commit is contained in:
Jay Huang 2024-10-19 16:58:08 +08:00
parent a35baf7d3d
commit 5601bb0f6e
4 changed files with 88 additions and 49 deletions

26
app.py
View File

@ -44,6 +44,7 @@ def analyze_signals():
lights['alarm'] = False lights['alarm'] = False
lights['up'] = False lights['up'] = False
lights['down'] = False lights['down'] = False
all_signals.clear()
return # 如果急停条件满足,立即返回 return # 如果急停条件满足,立即返回
# 然后检查 '08' 信号 # 然后检查 '08' 信号
@ -55,21 +56,24 @@ def analyze_signals():
if '09' in all_signals: if '09' in all_signals:
lights['common'] = True lights['common'] = True
if len(all_signals) >= 3 and all_signals[-3:] == ['09', '08', '09']:
lights['alarm'] = True
if all_signals[-2:] != ['08', '09']:
lights['alarm'] = False
if '0b' in all_signals or (len(all_signals) >= 2 and all_signals[-2:] == ['09', '0b']): if '0b' in all_signals or (len(all_signals) >= 2 and all_signals[-2:] == ['09', '0b']):
lights['up'] = True lights['up'] = True
if all_signals[-1:] != ['0b']: if all_signals[-1:] != ['0b']:
lights['up'] = False lights['up'] = False
if '0d' in all_signals or (len(all_signals) >= 2 and all_signals[-2:] == ['09', '0d']): if '0d' in all_signals or (len(all_signals) >= 2 and all_signals[-2:] == ['09', '0d']):
lights['down'] = True lights['down'] = True
if all_signals[-1:] != ['0d']: if all_signals[-1:] != ['0d']:
lights['down'] = False lights['down'] = False
if len(all_signals) >= 3 and all_signals[-3:] == ['09', '08', '09']:
lights['alarm'] = True
if all_signals[-2:] != ['08', '09']:
lights['alarm'] = False
all_signals.clear()
def read_serial(): def read_serial():
global all_signals, thread_running global all_signals, thread_running
while thread_running: while thread_running:
@ -175,9 +179,15 @@ def test_port():
@app.route('/clear_signal_data', methods=['POST']) @app.route('/clear_signal_data', methods=['POST'])
def clear_signal_data(): def clear_signal_data():
global signal_data global lights_status
signal_data = [] lights_status = {
return '', 204 'common': False,
'alarm': False,
'up': False,
'down': False,
'emergency_stop': False
}
return jsonify({"success": True})
if __name__ == '__main__': if __name__ == '__main__':
app.run(debug=True, host='0.0.0.0', port=5888) app.run(debug=True, host='0.0.0.0', port=5888)

View File

@ -58,7 +58,7 @@ function checkAllTestsPassed() {
allTestsPassed = Array.from(document.querySelectorAll(`#statusCheckList${currentDeviceType} .badge`)) allTestsPassed = Array.from(document.querySelectorAll(`#statusCheckList${currentDeviceType} .badge`))
.every(badge => badge.style.display === 'inline-block'); .every(badge => badge.style.display === 'inline-block');
// 更测试结果 // 更测试结果
updateTestResult(); updateTestResult();
} }
@ -97,16 +97,24 @@ function updateRowTestResult(row) {
const pendingSpan = label.querySelector('.pending'); const pendingSpan = label.querySelector('.pending');
const passSpan = label.querySelector('.pass'); const passSpan = label.querySelector('.pass');
const failSpan = label.querySelector('.fail'); const failSpan = label.querySelector('.fail');
const passTimeSpan = row.querySelector('.pass-time');
if (allTestsPassed) { if (allTestsPassed) {
checkbox.disabled = false; if (!checkbox.checked) { // 只在首次通过测试时记录时间
checkbox.checked = true; checkbox.disabled = false;
pendingSpan.style.display = 'none'; checkbox.checked = true;
passSpan.style.display = 'inline'; pendingSpan.style.display = 'none';
failSpan.style.display = 'none'; passSpan.style.display = 'inline';
row.classList.remove('pending-row'); failSpan.style.display = 'none';
row.classList.add('pass-row'); row.classList.remove('pending-row');
row.classList.remove('fail-row'); row.classList.add('pass-row');
row.classList.remove('fail-row');
// 记录合格时间
const now = new Date();
const timeString = now.toLocaleString('zh-CN', { hour12: false });
passTimeSpan.textContent = timeString;
}
} else { } else {
checkbox.disabled = true; checkbox.disabled = true;
checkbox.checked = false; checkbox.checked = false;
@ -116,6 +124,7 @@ function updateRowTestResult(row) {
row.classList.add('pending-row'); row.classList.add('pending-row');
row.classList.remove('pass-row'); row.classList.remove('pass-row');
row.classList.remove('fail-row'); row.classList.remove('fail-row');
// 不清空合格时间,保留之前记录的时间(如果有的话)
} }
} }
@ -139,6 +148,7 @@ function addNewRow(button) {
const cell1 = newRow.insertCell(0); const cell1 = newRow.insertCell(0);
const cell2 = newRow.insertCell(1); const cell2 = newRow.insertCell(1);
const cell3 = newRow.insertCell(2); const cell3 = newRow.insertCell(2);
const cell4 = newRow.insertCell(3);
cell1.innerHTML = '<input type="text" class="form-control serial-number" placeholder="输入设备序列号">'; cell1.innerHTML = '<input type="text" class="form-control serial-number" placeholder="输入设备序列号">';
cell2.innerHTML = ` cell2.innerHTML = `
@ -150,17 +160,24 @@ function addNewRow(button) {
<span class="fail" style="display: none;">不合格</span> <span class="fail" style="display: none;">不合格</span>
</label> </label>
</div>`; </div>`;
cell3.innerHTML = '<button class="btn btn-primary add-row-btn" onclick="addNewRow(this)">增加下一条</button>'; cell3.innerHTML = '<span class="pass-time"></span>';
cell4.innerHTML = '<button class="btn btn-primary add-row-btn" onclick="addNewRow(this)">增加下一条</button>';
// 重置表单和状态 // 重置表单和状态
resetForm(); resetForm();
// 聚焦到新的设备序列号输入框 // 重置灯光状态监控
const newSerialInput = newRow.querySelector('.serial-number'); resetLights();
newSerialInput.focus();
// 重置检测状态记录
resetCheckList();
// 清空app.py的信号数据 // 清空app.py的信号数据
clearSignalData(); clearSignalData();
// 聚焦到新的设备序列号输入框
const newSerialInput = newRow.querySelector('.serial-number');
newSerialInput.focus();
} }
function finalizeRowStatus(row) { function finalizeRowStatus(row) {
@ -173,22 +190,13 @@ function finalizeRowStatus(row) {
checkbox.disabled = true; checkbox.disabled = true;
} }
function resetForm() { //重置测试结果
// 重置测试结果为待测试状态
resetTestResult();
// 重置检测状态记录
resetDetectionStatus();
// 重置灯光状态
resetLightStatus();
}
function resetTestResult() { function resetTestResult() {
allTestsPassed = false; allTestsPassed = false;
updateTestResult(); updateTestResult();
} }
//重置检测状态记录
function resetDetectionStatus() { function resetDetectionStatus() {
lightHistory = { lightHistory = {
common: false, common: false,
@ -208,6 +216,7 @@ function resetDetectionStatus() {
} }
} }
//重置灯光状态
function resetLightStatus() { function resetLightStatus() {
const lights = document.querySelectorAll('.light'); const lights = document.querySelectorAll('.light');
lights.forEach(light => { lights.forEach(light => {
@ -216,14 +225,31 @@ function resetLightStatus() {
}); });
} }
function resetForm() {
// 重置测试结果为待测试状态
resetTestResult();
// 重置检测状态记录
resetDetectionStatus();
// 重置灯光状态
resetLightStatus();
}
function clearSignalData() { function clearSignalData() {
fetch('/clear_signal_data', { // 发送请求到后端清空信号数据
method: 'POST', fetch('/clear_signal_data', { method: 'POST' })
}).then(response => { .then(response => response.json())
if (!response.ok) { .then(data => {
console.error('清空信号数据失败'); if (data.success) {
} console.log('信号数据已清空');
}); } else {
console.error('清空信号数据失败');
}
})
.catch(error => {
console.error('清空信号数据时发生错误:', error);
});
} }
function exportToExcel() { function exportToExcel() {
@ -242,20 +268,21 @@ function exportToExcel() {
data.push(['测试日期', testDate]); data.push(['测试日期', testDate]);
data.push([]); // 空行 data.push([]); // 空行
const headers = ['设备序列号', '测试结果']; const headers = ['设备序列号', '测试结果', '合格时间'];
data.push(headers); data.push(headers);
for (let i = 1; i < table.rows.length; i++) { for (let i = 1; i < table.rows.length; i++) {
const row = table.rows[i]; const row = table.rows[i];
const serialNumber = row.cells[0].querySelector('input').value; const serialNumber = row.cells[0].querySelector('input').value;
const testResult = row.cells[1].querySelector('input').checked ? '合格' : '不合格'; const testResult = row.cells[1].querySelector('input').checked ? '合格' : '不合格';
data.push([serialNumber, testResult]); const passTime = row.cells[2].querySelector('.pass-time').textContent;
data.push([serialNumber, testResult, passTime]);
} }
const wb = XLSX.utils.book_new(); const wb = XLSX.utils.book_new();
const ws = XLSX.utils.aoa_to_sheet(data); const ws = XLSX.utils.aoa_to_sheet(data);
const colWidth = [{ wch: 20 }, { wch: 20 }]; const colWidth = [{ wch: 20 }, { wch: 10 }, { wch: 20 }];
ws['!cols'] = colWidth; ws['!cols'] = colWidth;
XLSX.utils.book_append_sheet(wb, ws, "测试结果"); XLSX.utils.book_append_sheet(wb, ws, "测试结果");
@ -405,5 +432,5 @@ document.addEventListener('DOMContentLoaded', function() {
updateDeviceTypeDisplay(); updateDeviceTypeDisplay();
// 每100毫秒更新一次灯光状态 // 每100毫秒更新一次灯光状态
setInterval(updateLights, 100); setInterval(updateLights, 300);
}); });

View File

@ -64,8 +64,8 @@ body {
} }
.light.emergency_stop.on { .light.emergency_stop.on {
background-color: #007bff; /* 蓝色 */ background-color: #9d002c; /* 深红色 */
box-shadow: 0 0 20px 5px rgba(0, 123, 255, 0.5); box-shadow: 0 0 20px 5px rgba(157, 0, 44, 0.5);
} }
.light.up.on { .light.up.on {

View File

@ -119,10 +119,6 @@
<div class="light common off" id="common-4"></div> <div class="light common off" id="common-4"></div>
<p>公共灯</p> <p>公共灯</p>
</div> </div>
<div class="light-item">
<div class="light emergency_stop off" id="emergency_stop-4"></div>
<p>急停灯</p>
</div>
<div class="light-item"> <div class="light-item">
<div class="light up off" id="up-4"></div> <div class="light up off" id="up-4"></div>
<p>上行灯</p> <p>上行灯</p>
@ -131,6 +127,10 @@
<div class="light down off" id="down-4"></div> <div class="light down off" id="down-4"></div>
<p>下行灯</p> <p>下行灯</p>
</div> </div>
<div class="light-item">
<div class="light emergency_stop off" id="emergency_stop-4"></div>
<p>急停灯</p>
</div>
</div> </div>
</div> </div>
</div> </div>
@ -195,6 +195,7 @@
<tr> <tr>
<th>设备序列号</th> <th>设备序列号</th>
<th>测试结果</th> <th>测试结果</th>
<th>合格时间</th>
<th>操作</th> <th>操作</th>
</tr> </tr>
</thead> </thead>
@ -211,6 +212,7 @@
</label> </label>
</div> </div>
</td> </td>
<td><span class="pass-time"></span></td>
<td><button class="btn btn-primary add-row-btn" onclick="addNewRow(this)">增加下一条</button></td> <td><button class="btn btn-primary add-row-btn" onclick="addNewRow(this)">增加下一条</button></td>
</tr> </tr>
</tbody> </tbody>