| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311 |
- // repeatability.js - 重复性测试相关功能
- // 重复性测试时间数组
- let repeatabilityTimes = [];
- // 图表相关变量
- let repeatabilityCtx = null;
- let repeatabilityChartInstance = null;
- function initializeRepeatabilityPage() {
- // 生成重复性标签页内容
- generateRepeatabilityTabContent();
- // 加载重复性数据
- loadRepeatabilityData();
- }
- // 生成重复性标签页内容
- function generateRepeatabilityTabContent() {
- console.log('generateRepeatabilityTabContent');
- const repeatabilityTab = document.createElement('div');
- repeatabilityTab.id = 'repeatability';
- repeatabilityTab.className = 'tab-content active';
- // 创建内容容器
- const contentContainer = document.createElement('div');
- contentContainer.className = 'content-container';
- // 创建输入部分
- const inputSection = document.createElement('div');
- inputSection.className = 'input-section';
- // 创建输入组
- const inputGroup = document.createElement('div');
- inputGroup.className = 'input-group';
- inputGroup.id = 'repeatability-inputs';
- // 添加默认的6个输入行
- for (let i = 1; i <= 6; i++) {
- const row = createInputRow(i, 'repeatability', recordTimeAndCalculateRepeatability, deleteRepeatabilityInput);
- inputGroup.appendChild(row);
- }
- // 添加按钮
- const addInputBtn = document.createElement('div');
- addInputBtn.className = 'add-input-btn';
- addInputBtn.onclick = addRepeatabilityInput;
- const addInputSpan = document.createElement('span');
- addInputSpan.textContent = '+ 添加输入';
- addInputBtn.appendChild(addInputSpan);
- // 组装输入部分
- inputSection.appendChild(inputGroup);
- inputSection.appendChild(addInputBtn);
- // 创建结果部分
- const resultsSection = document.createElement('div');
- resultsSection.className = 'results-section';
- // 创建结果显示
- const results = document.createElement('div');
- results.className = 'results';
- // 添加结果项
- const resultItems = [
- { label: '极差R:', id: 'range' },
- { label: '平均值x̄:', id: 'mean' },
- { label: '方差s<sup>2</sup>:', id: 'variance' },
- { label: '标准差s:', id: 'stdDev' },
- { label: '相对标准偏差RSD(%):', id: 'rsd' }
- ];
- resultItems.forEach(item => {
- const resultItem = document.createElement('div');
- resultItem.className = 'result-item';
- resultItem.innerHTML = `${item.label} <span id="${item.id}">-</span>`;
- results.appendChild(resultItem);
- });
- // 创建图表容器
- const chartContainer = document.createElement('div');
- chartContainer.className = 'chart-container';
- const canvas = document.createElement('canvas');
- canvas.id = 'lineChart';
- chartContainer.appendChild(canvas);
- repeatabilityCtx = canvas.getContext('2d');
- // 组装结果部分
- resultsSection.appendChild(results);
- resultsSection.appendChild(chartContainer);
- // 组装整个内容
- contentContainer.appendChild(inputSection);
- contentContainer.appendChild(resultsSection);
- repeatabilityTab.appendChild(contentContainer);
- if (document.getElementById('container')) {
- console.log('appendChild repeatabilityTab');
- document.getElementById('container').appendChild(repeatabilityTab);
- }
- // document.querySelectorAll('#repeatability-inputs .input-row').forEach((row, index) => {
- // const deleteBtn = row.querySelector('.delete-btn');
- // if (deleteBtn) {
- // deleteBtn.style.display = index < 0 ? 'none' : '';
- // }
- // });
- }
- // 添加重复性输入行
- function addRepeatabilityInput() {
- const container = document.getElementById('repeatability-inputs');
- const newIndex = container.children.length + 1;
- const row = createInputRow(newIndex, 'repeatability', recordTimeAndCalculateRepeatability, deleteRepeatabilityInput);
- container.appendChild(row);
- }
- // 删除重复性输入行
- 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 = `${parseUnixTime(repeatabilityTimes[i])}: `;
- } else {
- timeSpan.textContent = `${newIndex}: `;
- }
- // 更新输入事件
- input.oninput = function () { recordTimeAndCalculateRepeatability(newIndex); };
- });
- document.querySelectorAll('#repeatability-inputs input[type="number"]').forEach((input) => {
- input.placeholder = `输入值`;
- });
- calculateRepeatability();
- saveRepeatabilityData();
- }
- // 清除重复性数据
- function clearRepeatabilityData() {
- // 清除重复性数据
- const repeatabilityInputs = document.querySelectorAll('#repeatability-inputs .input-row');
- for (let i = 6; i < repeatabilityInputs.length; i++) {
- repeatabilityInputs[i].remove();
- }
- document.querySelectorAll('#repeatability-inputs input[type="number"]').forEach(input => {
- input.value = '';
- });
- repeatabilityTimes = [];
- // 重置重复性时间标签
- for (let i = 1; i <= 6; i++) {
- const timeSpan = document.getElementById(`repeatability-time-text-${i}`);
- if (timeSpan) {
- timeSpan.textContent = `${i}: `;
- }
- }
- // 重置图表
- if (repeatabilityChartInstance) {
- repeatabilityChartInstance.destroy();
- repeatabilityChartInstance = null;
- }
- }
- // 记录重复性时间并计算
- 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);
- // 保存数据
- saveRepeatabilityData();
- // 更新图表
- updateRepeatabilityChart(values);
- } else {
- // 清空结果显示
- document.querySelectorAll('#repeatability .result-item span').forEach(span => {
- span.innerText = '-';
- });
- // 清空图表
- if (repeatabilityChartInstance) {
- repeatabilityChartInstance.data.labels = [];
- repeatabilityChartInstance.data.datasets[0].data = [];
- repeatabilityChartInstance.update();
- }
- }
- }
- // 重复性图表更新
- function updateRepeatabilityChart(values) {
- // 获取时间标签
- const timeLabels = [];
- repeatabilityTimes.forEach((time) => {
- // 使用已保存的时间戳生成标签
- if (time > 9999) {
- timeLabels.push(parseUnixTime(time));
- }
- });
- // 使用通用图表创建函数
- repeatabilityChartInstance = createOrUpdateChart(repeatabilityChartInstance, repeatabilityCtx, timeLabels, values, '重复性');
- }
- // 重复性数据保存
- function saveRepeatabilityData() {
- collectAndSaveData('#repeatability-inputs input[type="number"]', repeatabilityTimes, {
- range: 'range',
- mean: 'mean',
- variance: 'variance',
- stdDev: 'stdDev',
- rsd: 'rsd'
- }, 'repeatabilityData');
- }
- // 重复性数据加载
- function loadRepeatabilityData() {
- const savedRepeatabilityData = getLocalStorage('repeatabilityData');
- if (savedRepeatabilityData) {
- try {
- const data = JSON.parse(savedRepeatabilityData);
- // 清除现有的额外输入框(保留前6个)
- const repeatabilityInputs = document.querySelectorAll('#repeatability-inputs .input-row');
- for (let i = 6; i < repeatabilityInputs.length; i++) {
- repeatabilityInputs[i].remove();
- }
- // 清除现有输入值
- document.querySelectorAll('#repeatability-inputs input[type="number"]').forEach(input => {
- input.value = '';
- });
- // 填充保存的数据
- if (data.inputs && data.inputs.length > 0) {
- data.inputs.forEach((item, index) => {
- const time = typeof item === 'object' ? item.time : '';
- const value = typeof item === 'object' ? item.value : '';
- // 如果索引超出现有输入框数量,添加新的输入框
- if (index >= 6) {
- addRepeatabilityInput();
- }
- // 设置时间
- if (time) {
- const timeSpan = document.getElementById(`repeatability-time-text-${index + 1}`);
- if (timeSpan) {
- timeSpan.textContent = parseUnixTime(time) + ': ';
- repeatabilityTimes[index] = time;
- }
- }
- // 设置值
- const input = document.querySelector(`#repeatability-inputs .input-row:nth-child(${index + 1}) input`);
- if (input) {
- input.value = value;
- }
- });
- // 计算结果
- calculateRepeatability();
- }
- } catch (e) {
- console.error('加载重复性数据失败:', e);
- }
- }
- }
|