增加型号配置json文件,修复结果不会自动待测试问题

This commit is contained in:
Jay Huang 2024-10-29 18:18:37 +08:00
parent 5601bb0f6e
commit a96e4143a0
5 changed files with 297 additions and 68 deletions

2
app.py
View File

@ -58,12 +58,14 @@ def analyze_signals():
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
lights['common'] = 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
lights['common'] = True
if all_signals[-1:] != ['0d']: if all_signals[-1:] != ['0d']:
lights['down'] = False lights['down'] = False

4
requirements.txt Normal file
View File

@ -0,0 +1,4 @@
flask
pyserial
flask-socketio
werkzeug

23
static/config/model.json Normal file
View File

@ -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"}
]

View File

@ -13,16 +13,20 @@ let allTestsPassed = false;
let currentDeviceType = '5'; // 默认为五孔设备 let currentDeviceType = '5'; // 默认为五孔设备
function updateLights() { function updateLights() {
if (!currentDeviceType) return; // 如果没有选择设备类型,不更新灯光状态
fetch('/get_lights_status') fetch('/get_lights_status')
.then(response => response.json()) .then(response => response.json())
.then(data => { .then(data => {
console.log('获取到的灯光状态:', data); // 调试输出
for (let light in data) { for (let light in data) {
let element5 = document.getElementById(light + '-5'); let element5 = document.getElementById(light + '-5');
let element4 = document.getElementById(light + '-4'); let element4 = document.getElementById(light + '-4');
if (element5) {
// 根据当前设备类型更新相应的灯光
if (currentDeviceType === '5' && element5) {
updateLightStatus(element5, data[light]); updateLightStatus(element5, data[light]);
} } else if (currentDeviceType === '4' && element4) {
if (element4) {
updateLightStatus(element4, data[light]); updateLightStatus(element4, data[light]);
} }
@ -33,6 +37,9 @@ function updateLights() {
} }
} }
checkAllTestsPassed(); checkAllTestsPassed();
})
.catch(error => {
console.error('获取灯光状态失败:', error);
}); });
} }
@ -55,11 +62,54 @@ function updateCheckList(light) {
} }
function checkAllTestsPassed() { 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');
// 更测试结果 console.log('所有测试是否通过:', allTestsPassed); // 调试输出
updateTestResult();
// 如果所有测试都通过,更新测试结果
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() { function resetCheckList() {
@ -73,58 +123,81 @@ function resetCheckList() {
allTestsPassed = false; allTestsPassed = false;
const deviceType = document.getElementById('deviceType').value; const deviceType = document.getElementById('deviceType').value;
const checkList = document.getElementById(`statusCheckList${deviceType}`); const checkList = document.getElementById(`statusCheckList${currentDeviceType}`);
if (checkList) { if (checkList) {
const badges = checkList.querySelectorAll('.badge'); const badges = checkList.querySelectorAll('.badge');
badges.forEach(badge => { badges.forEach(badge => {
badge.style.display = 'none'; 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() { function updateTestResult() {
const rows = document.querySelectorAll('#resultTable tbody tr'); const rows = document.querySelectorAll('#resultTable tbody tr');
const lastRow = rows[rows.length - 1]; const lastRow = rows[rows.length - 1];
// 只更新最后一行的状态 if (!lastRow) return;
updateRowTestResult(lastRow);
}
function updateRowTestResult(row) { const checkbox = lastRow.querySelector('.form-check-input');
const checkbox = row.querySelector('.form-check-input'); const label = lastRow.querySelector('.form-check-label');
const label = row.querySelector('.form-check-label');
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'); const passTimeSpan = lastRow.querySelector('.pass-time');
if (allTestsPassed) { if (allTestsPassed) {
if (!checkbox.checked) { // 只在首次通过测试时记录时间 // 如果所有测试通过,设置为合格状态
checkbox.disabled = false; checkbox.disabled = false;
checkbox.checked = true; checkbox.checked = true;
pendingSpan.style.display = 'none'; pendingSpan.style.display = 'none';
passSpan.style.display = 'inline'; passSpan.style.display = 'inline';
failSpan.style.display = 'none'; failSpan.style.display = 'none';
row.classList.remove('pending-row'); lastRow.classList.remove('pending-row', 'fail-row');
row.classList.add('pass-row'); lastRow.classList.add('pass-row');
row.classList.remove('fail-row');
// 记录合格时间 // 如果还没有记录时间,则记录当前时间
if (!passTimeSpan.textContent) {
const now = new Date(); 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; passTimeSpan.textContent = timeString;
} }
} else { } else {
// 如果测试未完成,设置为待测试状态
checkbox.disabled = true; checkbox.disabled = true;
checkbox.checked = false; checkbox.checked = false;
pendingSpan.style.display = 'inline'; pendingSpan.style.display = 'inline';
passSpan.style.display = 'none'; passSpan.style.display = 'none';
failSpan.style.display = 'none'; failSpan.style.display = 'none';
row.classList.add('pending-row'); lastRow.classList.add('pending-row');
row.classList.remove('pass-row'); lastRow.classList.remove('pass-row', 'fail-row');
row.classList.remove('fail-row'); passTimeSpan.textContent = '';
// 不清空合格时间,保留之前记录的时间(如果有的话)
} }
} }
@ -145,17 +218,29 @@ function addNewRow(button) {
const newRow = table.insertRow(); const newRow = table.insertRow();
const rowIndex = table.rows.length - 1; 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 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); 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 = `
<div class="form-check form-switch"> <div class="form-check form-switch">
<input class="form-check-input" type="checkbox" id="result-${rowIndex}" disabled> <input class="form-check-input" type="checkbox" id="result-${rowIndex}" disabled>
<label class="form-check-label" for="result-${rowIndex}"> <label class="form-check-label" for="result-${rowIndex}">
<span class="pending">待测试</span> <span class="pending" style="display: inline;">待测试</span>
<span class="pass" style="display: none;">合格</span> <span class="pass" style="display: none;">合格</span>
<span class="fail" style="display: none;">不合格</span> <span class="fail" style="display: none;">不合格</span>
</label> </label>
@ -163,17 +248,26 @@ function addNewRow(button) {
cell3.innerHTML = '<span class="pass-time"></span>'; cell3.innerHTML = '<span class="pass-time"></span>';
cell4.innerHTML = '<button class="btn btn-primary add-row-btn" onclick="addNewRow(this)">增加下一条</button>'; cell4.innerHTML = '<button class="btn btn-primary add-row-btn" onclick="addNewRow(this)">增加下一条</button>';
// 重置表单和状态 // 直接设置新行的状态不依赖updateTestResult函数
resetForm(); 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;
resetLights(); 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');
// 重置检测状态记录 // 重置其他状态
resetCheckList(); resetLightStatus();
// 清空app.py的信号数据
clearSignalData(); clearSignalData();
resetDetectionStatus();
resetCheckList();
// 聚焦到新的设备序列号输入框 // 聚焦到新的设备序列号输入框
const newSerialInput = newRow.querySelector('.serial-number'); const newSerialInput = newRow.querySelector('.serial-number');
@ -229,11 +323,23 @@ function resetForm() {
// 重置测试结果为待测试状态 // 重置测试结果为待测试状态
resetTestResult(); resetTestResult();
// 重置灯光状态
resetLightStatus();
// 重置检测状态记录
resetCheckList();
// 重置检测状态记录 // 重置检测状态记录
resetDetectionStatus(); resetDetectionStatus();
// 重置灯光状态 // 清空信号数据
resetLightStatus(); clearSignalData();
// 重新初始化灯光显示
updateDeviceTypeDisplay();
// 确保 allTestsPassed 被重置
allTestsPassed = false;
} }
function clearSignalData() { function clearSignalData() {
@ -255,6 +361,7 @@ function clearSignalData() {
function exportToExcel() { function exportToExcel() {
const table = document.getElementById('resultTable'); const table = document.getElementById('resultTable');
const deviceType = document.getElementById('deviceType').value; const deviceType = document.getElementById('deviceType').value;
const deviceModel = document.getElementById('deviceModel').value;
const tester = document.getElementById('tester').value; const tester = document.getElementById('tester').value;
const orderNumber = document.getElementById('orderNumber').value; const orderNumber = document.getElementById('orderNumber').value;
const testDate = document.getElementById('testDate').value; const testDate = document.getElementById('testDate').value;
@ -262,7 +369,8 @@ function exportToExcel() {
const data = []; const data = [];
// 添加测试信息 // 添加测试信息
data.push(['设备型号', deviceType === '5' ? '五孔' : '四孔']); data.push(['设备类型', deviceType]);
data.push(['设备型号', deviceModel]);
data.push(['检测人员', tester]); data.push(['检测人员', tester]);
data.push(['订单编号', orderNumber]); data.push(['订单编号', orderNumber]);
data.push(['测试日期', testDate]); data.push(['测试日期', testDate]);
@ -319,38 +427,71 @@ function disableInfoInputs() {
function setupDeviceTypeListener() { function setupDeviceTypeListener() {
const deviceTypeSelect = document.getElementById('deviceType'); const deviceTypeSelect = document.getElementById('deviceType');
const deviceModelSelect = document.getElementById('deviceModel');
if (deviceTypeSelect) { if (deviceTypeSelect) {
deviceTypeSelect.addEventListener('change', function() { 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(); updateDeviceTypeDisplay();
// 重置检测状态
resetForm();
// 重新开始监控灯光状态
updateLights();
}); });
} }
} }
function updateDeviceTypeDisplay() { function updateDeviceTypeDisplay() {
const deviceType = document.getElementById('deviceType').value;
const fiveHoleLights = document.getElementById('fiveHoleLights'); const fiveHoleLights = document.getElementById('fiveHoleLights');
const fourHoleLights = document.getElementById('fourHoleLights'); const fourHoleLights = document.getElementById('fourHoleLights');
const statusCheckList5 = document.getElementById('statusCheckList5'); const statusCheckList5 = document.getElementById('statusCheckList5');
const statusCheckList4 = document.getElementById('statusCheckList4'); const statusCheckList4 = document.getElementById('statusCheckList4');
if (deviceType === '5') { // 首先隐藏所有元素
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'; fiveHoleLights.style.display = 'flex';
fourHoleLights.style.display = 'none'; // 确保所有灯初始状态为关闭
statusCheckList5.style.display = 'block'; const lights = fiveHoleLights.querySelectorAll('.light');
statusCheckList4.style.display = 'none'; lights.forEach(light => {
} else if (deviceType === '4') { light.classList.remove('on');
fiveHoleLights.style.display = 'none'; light.classList.add('off');
});
}
if (statusCheckList5) statusCheckList5.style.display = 'block';
} else if (currentDeviceType === '4') { // A类-4孔
if (fourHoleLights) {
fourHoleLights.style.display = 'flex'; fourHoleLights.style.display = 'flex';
statusCheckList5.style.display = 'none'; // 确保所有灯初始状态为关闭
statusCheckList4.style.display = 'block'; const lights = fourHoleLights.querySelectorAll('.light');
} else { lights.forEach(light => {
fiveHoleLights.style.display = 'none'; light.classList.remove('on');
fourHoleLights.style.display = 'none'; light.classList.add('off');
statusCheckList5.style.display = 'none'; });
statusCheckList4.style.display = 'none'; }
if (statusCheckList4) statusCheckList4.style.display = 'block';
} }
// 重置检查列表状态
resetCheckList(); 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 = '<option selected>请选择...</option>';
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 = '<option selected>请先选择设备类型...</option>';
deviceModelSelect.disabled = true;
return;
}
// 获取选中类型对应的型号
const models = data.filter(item => item.Type === selectedType);
// 填充设备型号下拉框
deviceModelSelect.innerHTML = '<option selected>请选择型号...</option>';
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() { document.addEventListener('DOMContentLoaded', function() {
loadDeviceData();
setupDeviceTypeListener(); setupDeviceTypeListener();
setupPortSelection(); setupPortSelection();
@ -431,6 +622,8 @@ document.addEventListener('DOMContentLoaded', function() {
// 初始化设备类型显示 // 初始化设备类型显示
updateDeviceTypeDisplay(); updateDeviceTypeDisplay();
// 每100毫秒更新一次灯光状态 // 每300毫秒更新一次灯光状态
setInterval(updateLights, 300); if (!window.lightUpdateInterval) {
window.lightUpdateInterval = setInterval(updateLights, 300);
}
}); });

View File

@ -29,11 +29,15 @@
<div class="row"> <div class="row">
<!-- 现有的输入字段 --> <!-- 现有的输入字段 -->
<div class="col-md-3"> <div class="col-md-3">
<label for="deviceType" class="form-label">设备型</label> <label for="deviceType" class="form-label">设备</label>
<select class="form-select info-input" id="deviceType"> <select class="form-select info-input" id="deviceType">
<option selected>请选择...</option> <option selected>请选择...</option>
<option value="4">四孔</option> </select>
<option value="5">五孔</option> </div>
<div class="col-md-3">
<label for="deviceModel" class="form-label">设备型号</label>
<select class="form-select info-input" id="deviceModel" disabled>
<option selected>请先选择设备类型...</option>
</select> </select>
</div> </div>
<div class="col-md-3"> <div class="col-md-3">
@ -52,6 +56,9 @@
<label for="testDate" class="form-label">测试日期</label> <label for="testDate" class="form-label">测试日期</label>
<input type="text" class="form-control flatpickr info-input" id="testDate"> <input type="text" class="form-control flatpickr info-input" id="testDate">
</div> </div>
</div>
<div class="row">
<!-- 添加开始测试按钮 --> <!-- 添加开始测试按钮 -->
<div class="col-md-3 mb-3 mt-3"> <div class="col-md-3 mb-3 mt-3">
<button id="startTestBtn" class="btn btn-primary ">开始测试</button> <button id="startTestBtn" class="btn btn-primary ">开始测试</button>