// repeatability.js - 重复性测试相关功能 // 重复性测试时间数组 let repeatabilityTimes = []; // 图表相关变量 let ctx = null; let chartInstance = null; // 初始化重复性图表 function initRepeatabilityChart() { ctx = document.getElementById('lineChart').getContext('2d'); } // 在页面加载完成后初始化图表 document.addEventListener('DOMContentLoaded', function() { initRepeatabilityChart(); }); // 更新重复性输入框的占位符 function updateRepeatabilityInputPlaceholders() { document.querySelectorAll('#repeatability-inputs input[type="number"]').forEach((input, index) => { input.placeholder = `测量值 ${index + 1}`; }); } // 更新重复性输入框的删除按钮 function updateRepeatabilityDeleteButtons() { const repeatabilityInputs = document.querySelectorAll('#repeatability-inputs .input-row'); repeatabilityInputs.forEach((row, index) => { const deleteBtn = row.querySelector('.delete-btn'); if (deleteBtn) { deleteBtn.style.display = index < 6 ? 'none' : 'inline'; } }); } // 重复性测试函数 function addRepeatabilityInput() { const container = document.getElementById('repeatability-inputs'); const newIndex = container.children.length + 1; const row = createInputRow(newIndex, 'repeatability', recordTimeAndCalculateRepeatability, deleteRepeatabilityInput); container.appendChild(row); updateRepeatabilityInputPlaceholders(); } function deleteRepeatabilityInput(btn) { const row = btn.parentNode; const container = row.parentNode; const index = Array.from(container.children).indexOf(row); // 移除对应的时间记录 repeatabilityTimes.splice(index, 1); // 移除输入行 container.removeChild(row); // 更新剩余输入行的索引 const rows = container.querySelectorAll('.input-row'); rows.forEach((row, i) => { const timeSpan = row.querySelector(`span[id^="repeatability-time-text-"]`); const input = row.querySelector(`input[id^="repeatability-value-"]`); // 更新ID和文本 const newIndex = i + 1; timeSpan.id = `repeatability-time-text-${newIndex}`; input.id = `repeatability-value-${newIndex}`; // 如果有保存的时间,则显示时间,否则显示索引 if (repeatabilityTimes[i]) { timeSpan.textContent = `${repeatabilityTimes[i]}: `; } else { timeSpan.textContent = `${newIndex}: `; } // 更新输入事件 input.oninput = function() { recordTimeAndCalculateRepeatability(newIndex); }; }); updateRepeatabilityInputPlaceholders(); calculateRepeatability(); saveRepeatabilityData(); } function recordTimeAndCalculateRepeatability(index) { recordTimeAndCalculate('repeatability', index, repeatabilityTimes, calculateRepeatability); } function calculateRepeatability() { const values = getNumericInputs('#repeatability-inputs input[type="number"]'); if (values.length >= 2) { // 计算统计量 const max = Math.max(...values); const min = Math.min(...values); const range = max - min; const mean = values.reduce((sum, val) => sum + val, 0) / values.length; // 计算方差和标准差 const variance = values.reduce((sum, val) => sum + Math.pow(val - mean, 2), 0) / values.length; const stdDev = Math.sqrt(variance); const rsd = (stdDev / mean) * 100; // 相对标准偏差,以百分比表示 // 更新结果显示 updateResultDisplay('range', range); updateResultDisplay('mean', mean); updateResultDisplay('variance', variance); updateResultDisplay('stdDev', stdDev); updateResultDisplay('rsd', rsd); // 更新图表 updateRepeatabilityChart(values); } else { // 清空结果显示 document.querySelectorAll('#repeatability .result-item span').forEach(span => { span.innerText = '-'; }); // 清空图表 if (chartInstance) { chartInstance.data.labels = []; chartInstance.data.datasets[0].data = []; chartInstance.update(); } } } function updateRepeatabilityChart(values) { // 创建标签(1, 2, 3, ...) const labels = Array.from({length: values.length}, (_, i) => i + 1); // 使用通用图表创建函数 chartInstance = createOrUpdateChart(chartInstance, ctx, labels, values, '重复性'); } function saveRepeatabilityData() { collectAndSaveData('#repeatability-inputs input[type="number"]', 'repeatability-time-text', { range: 'range', mean: 'mean', variance: 'variance', stdDev: 'stdDev', rsd: 'rsd' }, 'repeatabilityData'); }