增加型号配置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']):
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

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'; // 默认为五孔设备
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 = '<input type="text" class="form-control serial-number" placeholder="输入设备序列号">';
cell2.innerHTML = `
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" id="result-${rowIndex}" disabled>
<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="fail" style="display: none;">不合格</span>
</label>
@ -163,18 +248,27 @@ function addNewRow(button) {
cell3.innerHTML = '<span class="pass-time"></span>';
cell4.innerHTML = '<button class="btn btn-primary add-row-btn" onclick="addNewRow(this)">增加下一条</button>';
// 重置表单和状态
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 = '<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() {
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);
}
});

View File

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