630 lines
22 KiB
JavaScript
630 lines
22 KiB
JavaScript
console.log('main.js 文件开始执行');
|
||
|
||
let lightHistory = {
|
||
common: false,
|
||
alarm: false,
|
||
up: false,
|
||
down: false,
|
||
emergency_stop: false
|
||
};
|
||
|
||
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 (currentDeviceType === '5' && element5) {
|
||
updateLightStatus(element5, data[light]);
|
||
} else if (currentDeviceType === '4' && element4) {
|
||
updateLightStatus(element4, data[light]);
|
||
}
|
||
|
||
// 更新灯光历史和检查列表
|
||
if (data[light] && !lightHistory[light]) {
|
||
lightHistory[light] = true;
|
||
updateCheckList(light);
|
||
}
|
||
}
|
||
checkAllTestsPassed();
|
||
})
|
||
.catch(error => {
|
||
console.error('获取灯光状态失败:', error);
|
||
});
|
||
}
|
||
|
||
function updateLightStatus(element, isOn) {
|
||
if (isOn) {
|
||
element.classList.add('on');
|
||
element.classList.remove('off');
|
||
} else {
|
||
element.classList.add('off');
|
||
element.classList.remove('on');
|
||
}
|
||
}
|
||
|
||
function updateCheckList(light) {
|
||
const listItem = document.querySelector(`#statusCheckList${currentDeviceType} li[data-light="${light}"]`);
|
||
if (listItem) {
|
||
const checkMark = listItem.querySelector('.badge');
|
||
checkMark.style.display = 'inline-block';
|
||
}
|
||
}
|
||
|
||
function checkAllTestsPassed() {
|
||
// 检查所有测试项是否都通过
|
||
allTestsPassed = Array.from(document.querySelectorAll(`#statusCheckList${currentDeviceType} .badge`))
|
||
.every(badge => badge.style.display === 'inline-block');
|
||
|
||
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() {
|
||
lightHistory = {
|
||
common: false,
|
||
alarm: false,
|
||
up: false,
|
||
down: false,
|
||
emergency_stop: false
|
||
};
|
||
allTestsPassed = false;
|
||
|
||
const deviceType = document.getElementById('deviceType').value;
|
||
const checkList = document.getElementById(`statusCheckList${currentDeviceType}`);
|
||
if (checkList) {
|
||
const badges = checkList.querySelectorAll('.badge');
|
||
badges.forEach(badge => {
|
||
badge.style.display = 'none';
|
||
});
|
||
}
|
||
|
||
// 强制更新最后一行的状态为待测试
|
||
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];
|
||
|
||
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 = lastRow.querySelector('.pass-time');
|
||
|
||
if (allTestsPassed) {
|
||
// 如果所有测试通过,设置为合格状态
|
||
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', {
|
||
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';
|
||
lastRow.classList.add('pending-row');
|
||
lastRow.classList.remove('pass-row', 'fail-row');
|
||
passTimeSpan.textContent = '';
|
||
}
|
||
}
|
||
|
||
function addNewRow(button) {
|
||
const table = document.getElementById('resultTable').getElementsByTagName('tbody')[0];
|
||
const currentRow = button.closest('tr');
|
||
const serialNumberInput = currentRow.querySelector('.serial-number');
|
||
|
||
if (serialNumberInput.value.trim() === '') {
|
||
alert('请输入设备序列号');
|
||
return;
|
||
}
|
||
|
||
// 固定当前行状态
|
||
finalizeRowStatus(currentRow);
|
||
|
||
// 创建新行
|
||
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" style="display: inline;">待测试</span>
|
||
<span class="pass" style="display: none;">合格</span>
|
||
<span class="fail" style="display: none;">不合格</span>
|
||
</label>
|
||
</div>`;
|
||
cell3.innerHTML = '<span class="pass-time"></span>';
|
||
cell4.innerHTML = '<button class="btn btn-primary add-row-btn" onclick="addNewRow(this)">增加下一条</button>';
|
||
|
||
// 直接设置新行的状态(不依赖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();
|
||
}
|
||
|
||
function finalizeRowStatus(row) {
|
||
const serialNumberInput = row.querySelector('.serial-number');
|
||
const addButton = row.querySelector('.add-row-btn');
|
||
const checkbox = row.querySelector('.form-check-input');
|
||
|
||
serialNumberInput.disabled = true;
|
||
addButton.style.display = 'none';
|
||
checkbox.disabled = true;
|
||
}
|
||
|
||
//重置测试结果
|
||
function resetTestResult() {
|
||
allTestsPassed = false;
|
||
updateTestResult();
|
||
}
|
||
|
||
//重置检测状态记录
|
||
function resetDetectionStatus() {
|
||
lightHistory = {
|
||
common: false,
|
||
alarm: false,
|
||
up: false,
|
||
down: false,
|
||
emergency_stop: false
|
||
};
|
||
|
||
const deviceType = document.getElementById('deviceType').value;
|
||
const checkList = document.getElementById(`statusCheckList${deviceType}`);
|
||
if (checkList) {
|
||
const badges = checkList.querySelectorAll('.badge');
|
||
badges.forEach(badge => {
|
||
badge.style.display = 'none';
|
||
});
|
||
}
|
||
}
|
||
|
||
//重置灯光状态
|
||
function resetLightStatus() {
|
||
const lights = document.querySelectorAll('.light');
|
||
lights.forEach(light => {
|
||
light.classList.remove('on');
|
||
light.classList.add('off');
|
||
});
|
||
}
|
||
|
||
function resetForm() {
|
||
// 重置测试结果为待测试状态
|
||
resetTestResult();
|
||
|
||
// 重置灯光状态
|
||
resetLightStatus();
|
||
|
||
// 重置检测状态记录
|
||
resetCheckList();
|
||
|
||
// 重置检测状态记录
|
||
resetDetectionStatus();
|
||
|
||
// 清空信号数据
|
||
clearSignalData();
|
||
|
||
// 重新初始化灯光显示
|
||
updateDeviceTypeDisplay();
|
||
|
||
// 确保 allTestsPassed 被重置
|
||
allTestsPassed = false;
|
||
}
|
||
|
||
function clearSignalData() {
|
||
// 发送请求到后端清空信号数据
|
||
fetch('/clear_signal_data', { method: 'POST' })
|
||
.then(response => response.json())
|
||
.then(data => {
|
||
if (data.success) {
|
||
console.log('信号数据已清空');
|
||
} else {
|
||
console.error('清空信号数据失败');
|
||
}
|
||
})
|
||
.catch(error => {
|
||
console.error('清空信号数据时发生错误:', error);
|
||
});
|
||
}
|
||
|
||
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;
|
||
|
||
const data = [];
|
||
|
||
// 添加测试信息
|
||
data.push(['设备类型', deviceType]);
|
||
data.push(['设备型号', deviceModel]);
|
||
data.push(['检测人员', tester]);
|
||
data.push(['订单编号', orderNumber]);
|
||
data.push(['测试日期', testDate]);
|
||
data.push([]); // 空行
|
||
|
||
const headers = ['设备序列号', '测试结果', '合格时间'];
|
||
data.push(headers);
|
||
|
||
for (let i = 1; i < table.rows.length; i++) {
|
||
const row = table.rows[i];
|
||
const serialNumber = row.cells[0].querySelector('input').value;
|
||
const testResult = row.cells[1].querySelector('input').checked ? '合格' : '不合格';
|
||
const passTime = row.cells[2].querySelector('.pass-time').textContent;
|
||
data.push([serialNumber, testResult, passTime]);
|
||
}
|
||
|
||
const wb = XLSX.utils.book_new();
|
||
const ws = XLSX.utils.aoa_to_sheet(data);
|
||
|
||
const colWidth = [{ wch: 20 }, { wch: 10 }, { wch: 20 }];
|
||
ws['!cols'] = colWidth;
|
||
|
||
XLSX.utils.book_append_sheet(wb, ws, "测试结果");
|
||
|
||
XLSX.writeFile(wb, `测试结果_${orderNumber}_${testDate}.xlsx`);
|
||
}
|
||
|
||
function startTest() {
|
||
disableInfoInputs();
|
||
|
||
const deviceTypeSelect = document.getElementById('deviceType');
|
||
if (deviceTypeSelect) {
|
||
deviceTypeSelect.disabled = false;
|
||
}
|
||
|
||
const firstSerialInput = document.getElementById('firstSerialNumber');
|
||
if (firstSerialInput) {
|
||
firstSerialInput.focus();
|
||
firstSerialInput.scrollIntoView({ behavior: 'smooth', block: 'center' });
|
||
}
|
||
}
|
||
|
||
function disableInfoInputs() {
|
||
const infoInputs = document.querySelectorAll('.info-input:not(#deviceType)');
|
||
infoInputs.forEach(input => {
|
||
input.disabled = true;
|
||
});
|
||
|
||
const startTestBtn = document.getElementById('startTestBtn');
|
||
if (startTestBtn) {
|
||
startTestBtn.disabled = true;
|
||
}
|
||
}
|
||
|
||
function setupDeviceTypeListener() {
|
||
const deviceTypeSelect = document.getElementById('deviceType');
|
||
const deviceModelSelect = document.getElementById('deviceModel');
|
||
|
||
if (deviceTypeSelect) {
|
||
deviceTypeSelect.addEventListener('change', function() {
|
||
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 fiveHoleLights = document.getElementById('fiveHoleLights');
|
||
const fourHoleLights = document.getElementById('fourHoleLights');
|
||
const statusCheckList5 = document.getElementById('statusCheckList5');
|
||
const statusCheckList4 = document.getElementById('statusCheckList4');
|
||
|
||
// 首先隐藏所有元素
|
||
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();
|
||
}
|
||
|
||
function setupPortSelection() {
|
||
const selectPortBtn = document.getElementById('selectPortBtn');
|
||
const confirmPortBtn = document.getElementById('confirmPortBtn');
|
||
const portSelect = document.getElementById('portSelect');
|
||
|
||
selectPortBtn.addEventListener('click', async () => {
|
||
try {
|
||
const response = await fetch('/get_ports');
|
||
const ports = await response.json();
|
||
|
||
portSelect.innerHTML = '';
|
||
if (ports.length === 0) {
|
||
const option = document.createElement('option');
|
||
option.textContent = '没有找到可用的串口';
|
||
portSelect.appendChild(option);
|
||
confirmPortBtn.disabled = true;
|
||
} else {
|
||
ports.forEach(port => {
|
||
const option = document.createElement('option');
|
||
option.value = port.device;
|
||
option.textContent = `${port.device} - ${port.description}`;
|
||
portSelect.appendChild(option);
|
||
});
|
||
confirmPortBtn.disabled = false;
|
||
}
|
||
|
||
const portModal = new bootstrap.Modal(document.getElementById('portModal'));
|
||
portModal.show();
|
||
} catch (error) {
|
||
console.error('获取串口列表失败:', error);
|
||
alert('获取串口列表失败,请重试。');
|
||
}
|
||
});
|
||
|
||
confirmPortBtn.addEventListener('click', async () => {
|
||
const selectedPort = portSelect.value;
|
||
if (selectedPort) {
|
||
try {
|
||
const response = await fetch('/set_port', {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/json',
|
||
},
|
||
body: JSON.stringify({ port: selectedPort }),
|
||
});
|
||
const result = await response.json();
|
||
if (result.success) {
|
||
alert('串口设置成功');
|
||
bootstrap.Modal.getInstance(document.getElementById('portModal')).hide();
|
||
} else {
|
||
alert('串口设置失败: ' + result.message);
|
||
}
|
||
} catch (error) {
|
||
console.error('设置串口失败:', error);
|
||
alert('设置串口失败,请重试。');
|
||
}
|
||
} else {
|
||
alert('请选择一个串口');
|
||
}
|
||
});
|
||
}
|
||
|
||
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();
|
||
|
||
const startTestBtn = document.getElementById('startTestBtn');
|
||
if (startTestBtn) {
|
||
startTestBtn.addEventListener('click', function(event) {
|
||
event.preventDefault();
|
||
startTest();
|
||
});
|
||
}
|
||
|
||
// 初始化设备类型显示
|
||
updateDeviceTypeDisplay();
|
||
|
||
// 每300毫秒更新一次灯光状态
|
||
if (!window.lightUpdateInterval) {
|
||
window.lightUpdateInterval = setInterval(updateLights, 300);
|
||
}
|
||
});
|