From a96e4143a06172850cb20a9733f9ba143bc31f08 Mon Sep 17 00:00:00 2001 From: Jay Huang Date: Tue, 29 Oct 2024 18:18:37 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=9E=8B=E5=8F=B7=E9=85=8D?= =?UTF-8?q?=E7=BD=AEjson=E6=96=87=E4=BB=B6=EF=BC=8C=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E7=BB=93=E6=9E=9C=E4=B8=8D=E4=BC=9A=E8=87=AA=E5=8A=A8=E5=BE=85?= =?UTF-8?q?=E6=B5=8B=E8=AF=95=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app.py | 2 + requirements.txt | 4 + static/config/model.json | 23 +++ static/main.js | 323 +++++++++++++++++++++++++++++++-------- templates/index.html | 13 +- 5 files changed, 297 insertions(+), 68 deletions(-) create mode 100644 requirements.txt create mode 100644 static/config/model.json diff --git a/app.py b/app.py index 50e55eb..9289b87 100644 --- a/app.py +++ b/app.py @@ -58,12 +58,14 @@ def analyze_signals(): if '0b' in all_signals or (len(all_signals) >= 2 and all_signals[-2:] == ['09', '0b']): lights['up'] = True + lights['common'] = True if all_signals[-1:] != ['0b']: lights['up'] = False if '0d' in all_signals or (len(all_signals) >= 2 and all_signals[-2:] == ['09', '0d']): lights['down'] = True + lights['common'] = True if all_signals[-1:] != ['0d']: lights['down'] = False diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..cd1c654 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,4 @@ +flask +pyserial +flask-socketio +werkzeug \ No newline at end of file diff --git a/static/config/model.json b/static/config/model.json new file mode 100644 index 0000000..8d9000c --- /dev/null +++ b/static/config/model.json @@ -0,0 +1,23 @@ +[ + {"Type": "A类-4孔","Model": "KM52064153H01","Note": "TWO HAND INSPECTION BOX with 4 holes"}, + {"Type": "A类-4孔","Model": "KM52064153V003","Note": "双手检修手柄,4孔,PVC 3.5M,英国"}, + {"Type": "A类-4孔","Model": "KM52064153V012","Note": "DOUBLE-HAND INSPECTION 4 HOLES, PVC 12M"}, + {"Type": "A类-4孔","Model": "KM52064153V016","Note": "DOUBLE-HAND INSPECTION 4 HOLES, PVC 16M"}, + {"Type": "A类-4孔","Model": "KM52064153V032","Note": "DOUBLE-HAND INSPECTION 4 HOLES, PVC 32M"}, + {"Type": "A类-4孔","Model": "KM52064153V050","Note": "DOUBLE-HAND INSPECTION,4 HOLES, PVC 50M"}, + {"Type": "A类-4孔","Model": "KM52064153V103","Note": "双手检修手柄,4孔,HF 3.5M,英国"}, + {"Type": "A类-4孔","Model": "KM52064153V112","Note": "DOUBLE-HAND INSPECTION 4 HOLES, HF12M"}, + {"Type": "A类-4孔","Model": "KM52064153V116","Note": "DOUBLE-HAND INSPECTION 4 HOLES, HF16M"}, + {"Type": "A类-4孔","Model": "KM52064153V132","Note": "DOUBLE-HAND INSPECTION 4 HOLES, HF32M"}, + {"Type": "A类-4孔","Model": "KM52064153V150","Note": "DOUBLE-HAND INSPECTION,4 HOLES,HF50M"}, + {"Type": "A类-4孔","Model": "KM52064155H01","Note": "TWO HAND INSPECTION BOX,PLC"}, + {"Type": "A类-4孔","Model": "KM52064155V108","Note": "DOUBLE-HAND INSPECTION 4 HOLES, HF8M,PLC"}, + {"Type": "A类-4孔","Model": "KM52064155V116","Note": "DOUBLE-HAND INSPECTION 4 HOLES, HF16M,PLC"}, + {"Type": "A类-4孔","Model": "KM52064155V132","Note": "DOUBLE-HAND INSPECTION 4 HOLES, HF32M ,PLC"}, + {"Type": "A类-4孔","Model": "KM52064155V150","Note": "DOUBLE-HAND INSPECTION,4 HOLES,HF50M,PLC"}, + {"Type": "B类-5孔","Model": "KM52064154H01","Note": "TWO HAND INSPECTION BOX with 5 holes"}, + {"Type": "B类-5孔","Model": "KM52064154V112","Note": "DOUBLE-HAND INSPECTION,5 HOLES,HF12M"}, + {"Type": "B类-5孔","Model": "KM52064154V116","Note": "DOUBLE-HAND INSPECTION,5 HOLES,HF16M"}, + {"Type": "B类-5孔","Model": "KM52064154V132","Note": "DOUBLE-HAND INSPECTION,5 HOLES,HF32M"}, + {"Type": "B类-5孔","Model": "KM52064154V150","Note": "DOUBLE-HAND INSPECTION,5 HOLES,HF50M"} +] \ No newline at end of file diff --git a/static/main.js b/static/main.js index c9eeb47..1b72286 100644 --- a/static/main.js +++ b/static/main.js @@ -13,16 +13,20 @@ let allTestsPassed = false; let currentDeviceType = '5'; // 默认为五孔设备 function updateLights() { + if (!currentDeviceType) return; // 如果没有选择设备类型,不更新灯光状态 + fetch('/get_lights_status') .then(response => response.json()) .then(data => { + console.log('获取到的灯光状态:', data); // 调试输出 for (let light in data) { let element5 = document.getElementById(light + '-5'); let element4 = document.getElementById(light + '-4'); - if (element5) { + + // 根据当前设备类型更新相应的灯光 + if (currentDeviceType === '5' && element5) { updateLightStatus(element5, data[light]); - } - if (element4) { + } else if (currentDeviceType === '4' && element4) { updateLightStatus(element4, data[light]); } @@ -33,6 +37,9 @@ function updateLights() { } } checkAllTestsPassed(); + }) + .catch(error => { + console.error('获取灯光状态失败:', error); }); } @@ -55,11 +62,54 @@ function updateCheckList(light) { } function checkAllTestsPassed() { + // 检查所有测试项是否都通过 allTestsPassed = Array.from(document.querySelectorAll(`#statusCheckList${currentDeviceType} .badge`)) .every(badge => badge.style.display === 'inline-block'); - // 更测试结果 - updateTestResult(); + console.log('所有测试是否通过:', allTestsPassed); // 调试输出 + + // 如果所有测试都通过,更新测试结果 + if (allTestsPassed) { + const rows = document.querySelectorAll('#resultTable tbody tr'); + const lastRow = rows[rows.length - 1]; + + if (lastRow) { + const checkbox = lastRow.querySelector('.form-check-input'); + const label = lastRow.querySelector('.form-check-label'); + const pendingSpan = label.querySelector('.pending'); + const passSpan = label.querySelector('.pass'); + const failSpan = label.querySelector('.fail'); + const passTimeSpan = lastRow.querySelector('.pass-time'); + + // 更新复选框状态 + checkbox.disabled = false; + checkbox.checked = true; + + // 更新显示状态 + pendingSpan.style.display = 'none'; + passSpan.style.display = 'inline'; + failSpan.style.display = 'none'; + + // 更新行样式 + lastRow.classList.remove('pending-row', 'fail-row'); + lastRow.classList.add('pass-row'); + + // 记录通过时间 + const now = new Date(); + const timeString = now.toLocaleString('zh-CN', { + year: 'numeric', + month: '2-digit', + day: '2-digit', + hour: '2-digit', + minute: '2-digit', + second: '2-digit', + hour12: false + }); + passTimeSpan.textContent = timeString; + + console.log('测试通过,更新完成'); // 调试输出 + } + } } function resetCheckList() { @@ -73,58 +123,81 @@ function resetCheckList() { allTestsPassed = false; const deviceType = document.getElementById('deviceType').value; - const checkList = document.getElementById(`statusCheckList${deviceType}`); + const checkList = document.getElementById(`statusCheckList${currentDeviceType}`); if (checkList) { const badges = checkList.querySelectorAll('.badge'); badges.forEach(badge => { badge.style.display = 'none'; }); } - updateTestResult(); + + // 强制更新最后一行的状态为待测试 + const rows = document.querySelectorAll('#resultTable tbody tr'); + const lastRow = rows[rows.length - 1]; + if (lastRow) { + const checkbox = lastRow.querySelector('.form-check-input'); + const label = lastRow.querySelector('.form-check-label'); + const pendingSpan = label.querySelector('.pending'); + const passSpan = label.querySelector('.pass'); + const failSpan = label.querySelector('.fail'); + + checkbox.disabled = true; + checkbox.checked = false; + pendingSpan.style.display = 'inline'; + passSpan.style.display = 'none'; + failSpan.style.display = 'none'; + lastRow.classList.add('pending-row'); + lastRow.classList.remove('pass-row', 'fail-row'); + } } function updateTestResult() { const rows = document.querySelectorAll('#resultTable tbody tr'); const lastRow = rows[rows.length - 1]; - // 只更新最后一行的状态 - updateRowTestResult(lastRow); -} - -function updateRowTestResult(row) { - const checkbox = row.querySelector('.form-check-input'); - const label = row.querySelector('.form-check-label'); + if (!lastRow) return; + + const checkbox = lastRow.querySelector('.form-check-input'); + const label = lastRow.querySelector('.form-check-label'); const pendingSpan = label.querySelector('.pending'); const passSpan = label.querySelector('.pass'); const failSpan = label.querySelector('.fail'); - const passTimeSpan = row.querySelector('.pass-time'); + const passTimeSpan = lastRow.querySelector('.pass-time'); if (allTestsPassed) { - if (!checkbox.checked) { // 只在首次通过测试时记录时间 - checkbox.disabled = false; - checkbox.checked = true; - pendingSpan.style.display = 'none'; - passSpan.style.display = 'inline'; - failSpan.style.display = 'none'; - row.classList.remove('pending-row'); - row.classList.add('pass-row'); - row.classList.remove('fail-row'); - - // 记录合格时间 + // 如果所有测试通过,设置为合格状态 + checkbox.disabled = false; + checkbox.checked = true; + pendingSpan.style.display = 'none'; + passSpan.style.display = 'inline'; + failSpan.style.display = 'none'; + lastRow.classList.remove('pending-row', 'fail-row'); + lastRow.classList.add('pass-row'); + + // 如果还没有记录时间,则记录当前时间 + if (!passTimeSpan.textContent) { const now = new Date(); - const timeString = now.toLocaleString('zh-CN', { hour12: false }); + const timeString = now.toLocaleString('zh-CN', { + year: 'numeric', + month: '2-digit', + day: '2-digit', + hour: '2-digit', + minute: '2-digit', + second: '2-digit', + hour12: false + }); passTimeSpan.textContent = timeString; } } else { + // 如果测试未完成,设置为待测试状态 checkbox.disabled = true; checkbox.checked = false; pendingSpan.style.display = 'inline'; passSpan.style.display = 'none'; failSpan.style.display = 'none'; - row.classList.add('pending-row'); - row.classList.remove('pass-row'); - row.classList.remove('fail-row'); - // 不清空合格时间,保留之前记录的时间(如果有的话) + lastRow.classList.add('pending-row'); + lastRow.classList.remove('pass-row', 'fail-row'); + passTimeSpan.textContent = ''; } } @@ -145,17 +218,29 @@ function addNewRow(button) { const newRow = table.insertRow(); const rowIndex = table.rows.length - 1; + // 重置所有状态(在创建新行之前) + allTestsPassed = false; + lightHistory = { + common: false, + alarm: false, + up: false, + down: false, + emergency_stop: false + }; + + // 创建新行的HTML const cell1 = newRow.insertCell(0); const cell2 = newRow.insertCell(1); const cell3 = newRow.insertCell(2); const cell4 = newRow.insertCell(3); + // 设置新行的初始状态 cell1.innerHTML = ''; cell2.innerHTML = `
@@ -163,18 +248,27 @@ function addNewRow(button) { cell3.innerHTML = ''; cell4.innerHTML = ''; - // 重置表单和状态 - resetForm(); - - // 重置灯光状态监控 - resetLights(); - - // 重置检测状态记录 - resetCheckList(); - - // 清空app.py的信号数据 + // 直接设置新行的状态(不依赖updateTestResult函数) + const newCheckbox = newRow.querySelector('.form-check-input'); + const newLabel = newRow.querySelector('.form-check-label'); + const newPendingSpan = newLabel.querySelector('.pending'); + const newPassSpan = newLabel.querySelector('.pass'); + const newFailSpan = newLabel.querySelector('.fail'); + + newCheckbox.disabled = true; + newCheckbox.checked = false; + newPendingSpan.style.display = 'inline'; + newPassSpan.style.display = 'none'; + newFailSpan.style.display = 'none'; + newRow.classList.add('pending-row'); + newRow.classList.remove('pass-row', 'fail-row'); + + // 重置其他状态 + resetLightStatus(); clearSignalData(); - + resetDetectionStatus(); + resetCheckList(); + // 聚焦到新的设备序列号输入框 const newSerialInput = newRow.querySelector('.serial-number'); newSerialInput.focus(); @@ -229,11 +323,23 @@ function resetForm() { // 重置测试结果为待测试状态 resetTestResult(); + // 重置灯光状态 + resetLightStatus(); + + // 重置检测状态记录 + resetCheckList(); + // 重置检测状态记录 resetDetectionStatus(); - // 重置灯光状态 - resetLightStatus(); + // 清空信号数据 + clearSignalData(); + + // 重新初始化灯光显示 + updateDeviceTypeDisplay(); + + // 确保 allTestsPassed 被重置 + allTestsPassed = false; } function clearSignalData() { @@ -255,6 +361,7 @@ function clearSignalData() { function exportToExcel() { const table = document.getElementById('resultTable'); const deviceType = document.getElementById('deviceType').value; + const deviceModel = document.getElementById('deviceModel').value; const tester = document.getElementById('tester').value; const orderNumber = document.getElementById('orderNumber').value; const testDate = document.getElementById('testDate').value; @@ -262,7 +369,8 @@ function exportToExcel() { const data = []; // 添加测试信息 - data.push(['设备型号', deviceType === '5' ? '五孔' : '四孔']); + data.push(['设备类型', deviceType]); + data.push(['设备型号', deviceModel]); data.push(['检测人员', tester]); data.push(['订单编号', orderNumber]); data.push(['测试日期', testDate]); @@ -319,38 +427,71 @@ function disableInfoInputs() { function setupDeviceTypeListener() { const deviceTypeSelect = document.getElementById('deviceType'); + const deviceModelSelect = document.getElementById('deviceModel'); + if (deviceTypeSelect) { deviceTypeSelect.addEventListener('change', function() { - currentDeviceType = this.value; + const selectedType = this.value; + + // 根据设备类型更新 currentDeviceType + if (selectedType === 'A类-4孔') { + currentDeviceType = '4'; // 对应四孔 + } else if (selectedType === 'B类-5孔') { + currentDeviceType = '5'; // 对应五孔 + } else { + currentDeviceType = ''; + } + + // 更新显示 updateDeviceTypeDisplay(); + + // 重置检测状态 + resetForm(); + + // 重新开始监控灯光状态 + updateLights(); }); } } function updateDeviceTypeDisplay() { - const deviceType = document.getElementById('deviceType').value; const fiveHoleLights = document.getElementById('fiveHoleLights'); const fourHoleLights = document.getElementById('fourHoleLights'); const statusCheckList5 = document.getElementById('statusCheckList5'); const statusCheckList4 = document.getElementById('statusCheckList4'); - if (deviceType === '5') { - fiveHoleLights.style.display = 'flex'; - fourHoleLights.style.display = 'none'; - statusCheckList5.style.display = 'block'; - statusCheckList4.style.display = 'none'; - } else if (deviceType === '4') { - fiveHoleLights.style.display = 'none'; - fourHoleLights.style.display = 'flex'; - statusCheckList5.style.display = 'none'; - statusCheckList4.style.display = 'block'; - } else { - fiveHoleLights.style.display = 'none'; - fourHoleLights.style.display = 'none'; - statusCheckList5.style.display = 'none'; - statusCheckList4.style.display = 'none'; + // 首先隐藏所有元素 + if (fiveHoleLights) fiveHoleLights.style.display = 'none'; + if (fourHoleLights) fourHoleLights.style.display = 'none'; + if (statusCheckList5) statusCheckList5.style.display = 'none'; + if (statusCheckList4) statusCheckList4.style.display = 'none'; + + // 根据当前设备类型显示相应元素 + if (currentDeviceType === '5') { // B类-5孔 + if (fiveHoleLights) { + fiveHoleLights.style.display = 'flex'; + // 确保所有灯初始状态为关闭 + const lights = fiveHoleLights.querySelectorAll('.light'); + lights.forEach(light => { + light.classList.remove('on'); + light.classList.add('off'); + }); + } + if (statusCheckList5) statusCheckList5.style.display = 'block'; + } else if (currentDeviceType === '4') { // A类-4孔 + if (fourHoleLights) { + fourHoleLights.style.display = 'flex'; + // 确保所有灯初始状态为关闭 + const lights = fourHoleLights.querySelectorAll('.light'); + lights.forEach(light => { + light.classList.remove('on'); + light.classList.add('off'); + }); + } + if (statusCheckList4) statusCheckList4.style.display = 'block'; } + // 重置检查列表状态 resetCheckList(); } @@ -416,7 +557,57 @@ function setupPortSelection() { }); } +async function loadDeviceData() { + try { + const response = await fetch('../static/config/model.json'); + const data = await response.json(); + + // 获取所有不重复的设备型 + const deviceTypes = [...new Set(data.map(item => item.Type))]; + + // 填充设备类型下拉框 + const deviceTypeSelect = document.getElementById('deviceType'); + deviceTypeSelect.innerHTML = ''; + deviceTypes.forEach(type => { + const option = document.createElement('option'); + option.value = type; + option.textContent = type; + deviceTypeSelect.appendChild(option); + }); + + // 设置设备类型变化时的监听器 + deviceTypeSelect.addEventListener('change', function() { + const selectedType = this.value; + const deviceModelSelect = document.getElementById('deviceModel'); + + if (selectedType === '请选择...') { + deviceModelSelect.innerHTML = ''; + deviceModelSelect.disabled = true; + return; + } + + // 获取选中类型对应的型号 + const models = data.filter(item => item.Type === selectedType); + + // 填充设备型号下拉框 + deviceModelSelect.innerHTML = ''; + models.forEach(model => { + const option = document.createElement('option'); + option.value = model.Model; + option.textContent = model.Model; + deviceModelSelect.appendChild(option); + }); + + deviceModelSelect.disabled = false; + }); + + } catch (error) { + console.error('加载设备数据失败:', error); + } +} + document.addEventListener('DOMContentLoaded', function() { + loadDeviceData(); setupDeviceTypeListener(); setupPortSelection(); @@ -431,6 +622,8 @@ document.addEventListener('DOMContentLoaded', function() { // 初始化设备类型显示 updateDeviceTypeDisplay(); - // 每100毫秒更新一次灯光状态 - setInterval(updateLights, 300); + // 每300毫秒更新一次灯光状态 + if (!window.lightUpdateInterval) { + window.lightUpdateInterval = setInterval(updateLights, 300); + } }); diff --git a/templates/index.html b/templates/index.html index 3652721..f15ee45 100644 --- a/templates/index.html +++ b/templates/index.html @@ -29,11 +29,15 @@
- + +
+
+ +
@@ -52,6 +56,9 @@
+ +
+