| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986 |
- <!DOCTYPE html>
- <html lang="zh">
- <head>
- <meta charset="UTF-8">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>DIPM_resultStatistics</title>
- <style>
- body {
- font-family: Arial, sans-serif;
- margin: 0;
- padding: 0;
- display: flex;
- align-items: center;
- justify-content: center;
- min-height: 100vh;
- background-color: #f4f4f9;
- }
- .container {
- display: flex;
- flex-direction: column;
- width: 90%;
- max-width: 800px;
- background: #fff;
- padding: 1.5rem;
- border-radius: 8px;
- box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
- }
- .tabs {
- display: flex;
- border-bottom: 1px solid #ddd;
- margin-bottom: 1.5rem;
- }
- .tab {
- padding: 0.5rem 1rem;
- cursor: pointer;
- border: 1px solid transparent;
- border-bottom: none;
- border-radius: 4px 4px 0 0;
- margin-right: 0.5rem;
- transition: all 0.3s ease;
- font-size: 0.9rem;
- }
- .tab.active {
- border-color: #ddd;
- border-bottom-color: #fff;
- background-color: #fff;
- color: #007bff;
- font-weight: bold;
- }
- .tab-content {
- display: none;
- }
- .tab-content.active {
- display: block;
- }
- .content-container {
- display: flex;
- flex-direction: row;
- gap: 2rem;
- width: 100%;
- }
- .input-section,
- .results-section {
- flex: 1;
- display: flex;
- flex-direction: column;
- justify-content: space-between;
- }
- h1 {
- font-size: 1.5rem;
- margin-bottom: 1rem;
- }
- .input-group {
- display: flex;
- flex-direction: column;
- gap: 1rem;
- height: 100%;
- justify-content: space-between;
- }
- input[type="number"] {
- padding: 0.5rem;
- font-size: 1rem;
- border: 1px solid #ccc;
- border-radius: 4px;
- transition: border-color 0.3s;
- }
- input[type="number"]:focus {
- outline: none;
- border-color: #007bff;
- }
- .results {
- display: flex;
- flex-direction: column;
- gap: 0.5rem;
- }
- .result-item {
- font-size: 1rem;
- color: #333;
- }
- .result-item:nth-child(4) {
- color: #0f72db;
- }
- .result-item:nth-child(5) {
- color: #11b9b9;
- }
- #stdDev {
- color: #0f72db;
- }
- #rsd {
- color: #11b9b9;
- }
- .stability-container,
- .error-container {
- display: flex;
- flex-direction: column;
- gap: 1rem;
- margin-bottom: 1.5rem;
- }
- .stability-row {
- display: flex;
- align-items: center;
- gap: 0.5rem;
- }
- .stability-row span {
- width: 60px;
- }
- .progress-container {
- display: inline-flex;
- position: relative;
- padding: 0.2rem 0.5rem;
- border-radius: 4px;
- background: linear-gradient(to right, #007bff var(--progress-percent), #e0e0e0 var(--progress-percent));
- background-size: 100% 100%;
- transition: background-position 0.3s ease;
- margin-left: 1em;
- gap: 0.8rem;
- }
- .progress-container.completed {
- background: linear-gradient(to right, #ff0000 100%, #e0e0e0 100%);
- }
- .stability-time-display {
- font-size: 0.9rem;
- color: #666;
- position: relative;
- z-index: 1;
- }
- .stability-time-display.warning {
- color: #ff0000;
- font-weight: bold;
- }
- .error-point-container {
- border: 1px solid #eee;
- border-radius: 4px;
- padding: 1rem;
- margin-bottom: 1rem;
- }
- .error-inputs {
- display: flex;
- flex-wrap: wrap;
- gap: 0.5rem;
- margin: 0.5rem 0;
- }
- .error-input {
- flex: 1;
- min-width: 80px;
- }
- .button-container {
- display: flex;
- justify-content: space-between;
- width: 100%;
- gap: 1rem;
- }
- .export-btn,
- .import-btn {
- flex: 1;
- padding: 1rem;
- border: none;
- border-radius: 4px;
- background-color: #007bff;
- color: white;
- font-size: 1rem;
- cursor: pointer;
- transition: background-color 0.3s;
- }
- .export-btn:hover,
- .import-btn:hover {
- background-color: #0056b3;
- }
- .error-result {
- margin-top: 0.5rem;
- font-weight: bold;
- }
- .error-container {
- display: flex;
- flex-direction: column;
- gap: 1rem;
- }
- .chart-container {
- margin-top: 1.5rem;
- position: relative;
- width: 100%;
- height: 200px;
- border: 1px solid #ddd;
- border-radius: 4px;
- padding-left: 1%;
- }
- canvas {
- width: 100%;
- height: 100%;
- }
- @media (max-width: 600px) {
- .container {
- flex-direction: column;
- }
- .content-container {
- flex-direction: column;
- }
- .input-section,
- .results-section {
- width: 100%;
- }
- h1 {
- font-size: 1.2rem;
- }
- input[type="number"] {
- font-size: 0.9rem;
- padding: 0.4rem;
- }
- .error-inputs {
- flex-direction: row;
- }
- .error-input {
- flex: 1;
- }
- }
- </style>
- </head>
- <body>
- <audio id="alertSound" src="./alert.mp3" preload="auto"></audio>
- <div class="container">
- <div class="tabs">
- <div class="tab active" data-tab="repeatability">重复性</div>
- <div class="tab" data-tab="stability">稳定性</div>
- <div class="tab" data-tab="error">示值误差</div>
- <div class="tab" data-tab="data">数据</div>
- </div>
- <!-- 重复性标签页 -->
- <div id="repeatability" class="tab-content active">
- <div class="content-container">
- <div class="input-section">
- <h1>输入数据</h1>
- <div class="input-group">
- <input type="number" placeholder="1: " oninput="calculateRepeatability()">
- <input type="number" placeholder="2: " oninput="calculateRepeatability()">
- <input type="number" placeholder="3: " oninput="calculateRepeatability()">
- <input type="number" placeholder="4: " oninput="calculateRepeatability()">
- <input type="number" placeholder="5: " oninput="calculateRepeatability()">
- <input type="number" placeholder="6: " oninput="calculateRepeatability()">
- <input type="number" placeholder="7: (可选)"
- oninput="calculateRepeatability()">
- </div>
- </div>
- <div class="results-section">
- <h1>计算结果</h1>
- <div class="results">
- <div class="result-item">极差R: <span id="range">-</span></div>
- <div class="result-item">平均值x̄: <span id="mean">-</span></div>
- <div class="result-item">方差s<sup>2</sup>: <span id="variance">-</span></div>
- <div class="result-item">标准差s: <span id="stdDev">-</span></div>
- <div class="result-item">相对标准偏差RSD: <span id="rsd">-</span></div>
- </div>
- <div class="chart-container">
- <canvas id="lineChart"></canvas>
- </div>
- </div>
- </div>
- </div>
- <!-- 稳定性标签页 -->
- <div id="stability" class="tab-content">
- <div class="content-container">
- <div class="input-section">
- <h1>稳定性测试
- <div class="progress-container">
- <span id="current-time" class="stability-time-display"></span>
- <span class="stability-time-display"> · </span>
- <span id="countdown" class="stability-time-display">10:00</span>
- </div>
- </h1>
- <div class="input-group">
- <div class="stability-row">
- <span id="stability-time-text-1">0: </span>
- <input type="number" placeholder="输入值" id="stability-value-1"
- oninput="recordTimeAndCalculateStability(1)">
- </div>
- <div class="stability-row">
- <span id="stability-time-text-2">10: </span>
- <input type="number" placeholder="输入值" id="stability-value-2"
- oninput="recordTimeAndCalculateStability(2)">
- </div>
- <div class="stability-row">
- <span id="stability-time-text-3">20: </span>
- <input type="number" placeholder="输入值" id="stability-value-3"
- oninput="recordTimeAndCalculateStability(3)">
- </div>
- <div class="stability-row">
- <span id="stability-time-text-4">30: </span>
- <input type="number" placeholder="输入值" id="stability-value-4"
- oninput="recordTimeAndCalculateStability(4)">
- </div>
- <div class="stability-row">
- <span id="stability-time-text-5">40: </span>
- <input type="number" placeholder="输入值" id="stability-value-5"
- oninput="recordTimeAndCalculateStability(5)">
- </div>
- <div class="stability-row">
- <span id="stability-time-text-6">50: </span>
- <input type="number" placeholder="输入值" id="stability-value-6"
- oninput="recordTimeAndCalculateStability(6)">
- </div>
- <div class="stability-row">
- <span id="stability-time-text-7">60: </span>
- <input type="number" placeholder="输入值" id="stability-value-7"
- oninput="recordTimeAndCalculateStability(7)">
- </div>
- </div>
- </div>
- <div class="results-section">
- <h1>稳定性结果</h1>
- <div class="results">
- <div class="result-item">最大值: <span id="stability-max">-</span></div>
- <div class="result-item">最小值: <span id="stability-min">-</span></div>
- <div class="result-item">平均值: <span id="stability-mean">-</span></div>
- <div class="result-item">极值差: <span id="stability-range">-</span></div>
- </div>
- <div class="chart-container">
- <canvas id="stabilityChart"></canvas>
- </div>
- </div>
- </div>
- </div>
- <!-- 示值误差标签页 -->
- <div id="error" class="tab-content">
- <div class="content-container">
- <div class="input-section" style="width: 100%;">
- <h1>示值误差测试</h1>
- <div class="error-container">
- <div class="error-point-container">
- <h3>-400m℃</h3>
- <div class="error-inputs">
- <input type="number" placeholder="测试1" class="error-input"
- data-point="-400" data-index="0" oninput="calculateError()">
- <input type="number" placeholder="测试2" class="error-input"
- data-point="-400" data-index="1" oninput="calculateError()">
- <input type="number" placeholder="测试3" class="error-input"
- data-point="-400" data-index="2" oninput="calculateError()">
- </div>
- <div class="error-result">平均值: <span class="error-avg"
- data-point="-400">-</span></div>
- <div class="error-result">示值误差: <span class="error-value"
- data-point="-400">-</span></div>
- </div>
- <div class="error-point-container">
- <h3>-408m℃</h3>
- <div class="error-inputs">
- <input type="number" placeholder="测试1" class="error-input"
- data-point="-408" data-index="0" oninput="calculateError()">
- <input type="number" placeholder="测试2" class="error-input"
- data-point="-408" data-index="1" oninput="calculateError()">
- <input type="number" placeholder="测试3" class="error-input"
- data-point="-408" data-index="2" oninput="calculateError()">
- </div>
- <div class="error-result">平均值: <span class="error-avg"
- data-point="-408">-</span></div>
- <div class="error-result">示值误差: <span class="error-value"
- data-point="-408">-</span></div>
- </div>
- <div class="error-point-container">
- <h3>-450m℃</h3>
- <div class="error-inputs">
- <input type="number" placeholder="测试1" class="error-input"
- data-point="-450" data-index="0" oninput="calculateError()">
- <input type="number" placeholder="测试2" class="error-input"
- data-point="-450" data-index="1" oninput="calculateError()">
- <input type="number" placeholder="测试3" class="error-input"
- data-point="-450" data-index="2" oninput="calculateError()">
- </div>
- <div class="error-result">平均值: <span class="error-avg"
- data-point="-450">-</span></div>
- <div class="error-result">示值误差: <span class="error-value"
- data-point="-450">-</span></div>
- </div>
- <div class="error-point-container">
- <h3>-500m℃</h3>
- <div class="error-inputs">
- <input type="number" placeholder="测试1" class="error-input"
- data-point="-500" data-index="0" oninput="calculateError()">
- <input type="number" placeholder="测试2" class="error-input"
- data-point="-500" data-index="1" oninput="calculateError()">
- <input type="number" placeholder="测试3" class="error-input"
- data-point="-500" data-index="2" oninput="calculateError()">
- </div>
- <div class="error-result">平均值: <span class="error-avg"
- data-point="-500">-</span></div>
- <div class="error-result">示值误差: <span class="error-value"
- data-point="-500">-</span></div>
- </div>
- <div class="error-point-container">
- <h3>-512m℃</h3>
- <div class="error-inputs">
- <input type="number" placeholder="测试1" class="error-input"
- data-point="-512" data-index="0" oninput="calculateError()">
- <input type="number" placeholder="测试2" class="error-input"
- data-point="-512" data-index="1" oninput="calculateError()">
- <input type="number" placeholder="测试3" class="error-input"
- data-point="-512" data-index="2" oninput="calculateError()">
- </div>
- <div class="error-result">平均值: <span class="error-avg"
- data-point="-512">-</span></div>
- <div class="error-result">示值误差: <span class="error-value"
- data-point="-512">-</span></div>
- </div>
- <div class="error-point-container">
- <h3>-520m℃</h3>
- <div class="error-inputs">
- <input type="number" placeholder="测试1" class="error-input"
- data-point="-520" data-index="0" oninput="calculateError()">
- <input type="number" placeholder="测试2" class="error-input"
- data-point="-520" data-index="1" oninput="calculateError()">
- <input type="number" placeholder="测试3" class="error-input"
- data-point="-520" data-index="2" oninput="calculateError()">
- </div>
- <div class="error-result">平均值: <span class="error-avg"
- data-point="-520">-</span></div>
- <div class="error-result">示值误差: <span class="error-value"
- data-point="-520">-</span></div>
- </div>
- <div class="error-point-container">
- <h3>-557m℃</h3>
- <div class="error-inputs">
- <input type="number" placeholder="测试1" class="error-input"
- data-point="-557" data-index="0" oninput="calculateError()">
- <input type="number" placeholder="测试2" class="error-input"
- data-point="-557" data-index="1" oninput="calculateError()">
- <input type="number" placeholder="测试3" class="error-input"
- data-point="-557" data-index="2" oninput="calculateError()">
- </div>
- <div class="error-result">平均值: <span class="error-avg"
- data-point="-557">-</span></div>
- <div class="error-result">示值误差: <span class="error-value"
- data-point="-557">-</span></div>
- </div>
- <div class="error-point-container">
- <h3>-600m℃</h3>
- <div class="error-inputs">
- <input type="number" placeholder="测试1" class="error-input"
- data-point="-600" data-index="0" oninput="calculateError()">
- <input type="number" placeholder="测试2" class="error-input"
- data-point="-600" data-index="1" oninput="calculateError()">
- <input type="number" placeholder="测试3" class="error-input"
- data-point="-600" data-index="2" oninput="calculateError()">
- </div>
- <div class="error-result">平均值: <span class="error-avg"
- data-point="-600">-</span></div>
- <div class="error-result">示值误差: <span class="error-value"
- data-point="-600">-</span></div>
- </div>
- <div class="chart-container">
- <canvas id="errorChart"></canvas>
- </div>
- </div>
- </div>
- </div>
- </div>
- <!-- 导出/导入标签页 -->
- <div id="data" class="tab-content">
- <div class="content-container">
- <div class="button-container">
- <button class="export-btn" onclick="exportData()">导出数据</button>
- <button class="import-btn"
- onclick="document.getElementById('importFile').click()">导入数据</button>
- <input type="file" id="importFile" accept=".json,.txt" onchange="importData()"
- style="display:none">
- </div>
- </div>
- <div style="text-align: center; margin-top: 1rem; color: #666; font-size: 0.8rem;">Ver
- 1.0.01.250419a1</div>
- </div>
- <script src="./chart.js"></script>
- <script>
- const ctx = document.getElementById('lineChart').getContext('2d');
- const stabilityCtx = document.getElementById('stabilityChart').getContext('2d');
- const errorCtx = document.getElementById('errorChart').getContext('2d');
- let chartInstance = null;
- let stabilityChartInstance = null;
- let errorChartInstance = null;
- // 存储稳定性测试的时间记录
- let stabilityTimes = [];
- let lastStabilityTime = null;
- // 标签页切换功能
- document.querySelectorAll('.tab').forEach(tab => {
- tab.addEventListener('click', () => {
- // 移除所有标签和内容的active类
- document.querySelectorAll('.tab').forEach(t => t.classList.remove('active'));
- document.querySelectorAll('.tab-content').forEach(c => c.classList.remove('active'));
- // 添加当前标签和对应内容的active类
- tab.classList.add('active');
- const tabId = tab.getAttribute('data-tab');
- document.getElementById(tabId).classList.add('active');
- });
- });
- // 重复性计算函数 --------------------------------------------------
- function calculateRepeatability() {
- const inputs = Array.from(document.querySelectorAll('#repeatability input[type="number"]'))
- .map(input => parseFloat(input.value))
- .filter(value => !isNaN(value));
- if (inputs.length === 0) {
- document.getElementById('mean').textContent = '-';
- document.getElementById('variance').textContent = '-';
- document.getElementById('stdDev').textContent = '-';
- document.getElementById('range').textContent = '-';
- updateRepeatabilityChart([]);
- return;
- }
- // 计算最大值与最小值的差
- const range = Math.max(...inputs) - Math.min(...inputs);
- // 计算平均值
- const mean = inputs.reduce((sum, val) => sum + val, 0) / inputs.length;
- // 计算方差
- const variance = inputs.reduce((sum, val) => sum + Math.pow(val - mean, 2), 0) / inputs.length;
- // 计算标准差
- const stdDev = Math.sqrt(variance);
- // 计算RSD
- const rsd = (stdDev / mean) * 100;
- // 更新结果显示
- document.getElementById('range').textContent = range.toFixed(2);
- document.getElementById('mean').textContent = mean.toFixed(2);
- document.getElementById('variance').textContent = variance.toFixed(2);
- document.getElementById('stdDev').textContent = stdDev.toFixed(2);
- document.getElementById('rsd').textContent = rsd.toFixed(2) + '%';
- // 更新折线图
- updateRepeatabilityChart(inputs);
- }
- function updateRepeatabilityChart(data) {
- if (chartInstance) {
- chartInstance.destroy(); // 销毁之前的图表实例
- }
- // 创建标签(1, 2, 3, ...)用于X轴
- const labels = Array.from({ length: data.length }, (_, i) => i + 1);
- chartInstance = new Chart(ctx, {
- type: 'line',
- data: {
- labels: labels,
- datasets: [{
- label: '重复性测试',
- data: data,
- borderColor: 'rgb(75, 192, 192)',
- backgroundColor: 'rgba(75, 192, 192, 0.2)',
- tension: 0.1,
- pointRadius: 5,
- pointHoverRadius: 7
- }]
- },
- options: {
- responsive: true,
- scales: {
- y: {
- beginAtZero: false
- }
- },
- plugins: {
- legend: {
- display: false
- }
- }
- }
- });
- }
- // 稳定性测试函数 --------------------------------------------------
- // 更新当前时间显示
- function updateCurrentTime() {
- const now = new Date();
- const timeString = now.toLocaleTimeString();
- const currentTimeElement = document.getElementById('current-time');
- currentTimeElement.textContent = timeString;
- // 检查是否需要显示警告(与上次稳定性测试时间间隔超过10分钟)
- if (lastStabilityTime) {
- const maxTime = 599; // 10分钟 = 600秒
- let timeDiff = now - lastStabilityTime;
- // 检查所有输入框是否都有值
- const allFilled = Array.from(document.querySelectorAll('#stability input[type="number"]'))
- .every(input => input.value);
- if (allFilled) {
- // 重置为默认状态
- document.getElementById('countdown').textContent = '10:00';
- document.querySelector('.progress-container').style.setProperty('--progress-percent', '0%');
- // 停止警报铃声
- document.getElementById('alertSound').pause();
- document.getElementById('alertSound').currentTime = 0;
- timeDiff = 0;
- }
- const remainingTime = Math.max(0, maxTime - Math.floor(timeDiff / 1000));
- const progressPercent = Math.min(100, Math.max(0, (maxTime - remainingTime) / maxTime * 100));
- document.querySelector('.progress-container').style.setProperty('--progress-percent', progressPercent + '%');
- const minutes = Math.floor(remainingTime / 60);
- const seconds = remainingTime % 60;
- const countdownElement = document.getElementById('countdown');
- countdownElement.textContent = `${minutes}:${seconds.toString().padStart(2, '0')}`;
- if (remainingTime <= 0) {
- currentTimeElement.classList.add('warning');
- countdownElement.classList.add('warning');
- } else {
- currentTimeElement.classList.remove('warning');
- countdownElement.classList.remove('warning');
- }
- if (remainingTime <= 3) {
- document.getElementById('alertSound').play();
- } else {
- document.getElementById('alertSound').pause();
- document.getElementById('alertSound').currentTime = 0;
- }
- }
- // 每秒更新一次时间
- setTimeout(updateCurrentTime, 1000);
- }
- // 初始化时启动时间更新
- updateCurrentTime();
- // 记录时间并计算稳定性
- function recordTimeAndCalculateStability(index) {
- const now = new Date();
- const timeString = now.toLocaleTimeString();
- // 更新时间显示
- document.getElementById(`stability-time-text-${index}`).textContent = `${timeString} `;
- // 记录最后一次测试时间
- lastStabilityTime = now;
- stabilityTimes[index - 1] = timeString;
- // 计算稳定性
- calculateStability();
- }
- function calculateStability() {
- const values = [];
- const times = [];
- // 收集所有稳定性测试的值和时间
- for (let i = 1; i <= 7; i++) {
- const valueInput = document.getElementById(`stability-value-${i}`);
- if (valueInput && valueInput.value) {
- values.push(parseFloat(valueInput.value));
- times.push(stabilityTimes[i - 1] || `测试${i}`);
- }
- }
- if (values.length === 0) {
- document.getElementById('stability-range').textContent = '-';
- document.getElementById('stability-max').textContent = '-';
- document.getElementById('stability-min').textContent = '-';
- document.getElementById('stability-mean').textContent = '-';
- return;
- }
- // 计算极值差
- 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;
- // 更新显示
- document.getElementById('stability-range').textContent = range.toFixed(2);
- document.getElementById('stability-max').textContent = max.toFixed(2);
- document.getElementById('stability-min').textContent = min.toFixed(2);
- document.getElementById('stability-mean').textContent = mean.toFixed(2);
- // 更新稳定性图表
- updateStabilityChart(times, values);
- }
- function updateStabilityChart(times, values) {
- if (!stabilityCtx || values.length === 0) return;
- // 如果已存在图表实例,先销毁
- if (stabilityChartInstance) {
- stabilityChartInstance.destroy();
- }
- // 创建新的图表
- stabilityChartInstance = new Chart(stabilityCtx, {
- type: 'line',
- data: {
- labels: times,
- datasets: [{
- label: '稳定性测试',
- data: values,
- borderColor: 'rgb(75, 192, 192)',
- backgroundColor: 'rgba(75, 192, 192, 0.2)',
- tension: 0.1,
- pointRadius: 5,
- pointHoverRadius: 7
- }]
- },
- options: {
- responsive: true,
- scales: {
- y: {
- beginAtZero: false
- }
- },
- plugins: {
- legend: {
- display: false
- }
- }
- }
- });
- }
- // 示值误差测试函数 ------------------------------------------------
- function calculateError() {
- const errorPoints = ['-400', '-408', '-450', '-500', '-512', '-520', '-557', '-600'];
- const errorData = [];
- errorPoints.forEach(point => {
- const inputs = document.querySelectorAll(`.error-input[data-point="${point}"]`);
- const values = [];
- inputs.forEach(input => {
- if (input.value) {
- values.push(parseFloat(input.value));
- }
- });
- if (values.length > 0) {
- // 计算平均值
- const avg = values.reduce((sum, val) => sum + val, 0) / values.length;
- document.querySelector(`.error-avg[data-point="${point}"]`).textContent = avg.toFixed(2);
- // 计算示值误差 (测量值与标准值的差的绝对值)
- const error = Math.abs(avg - (-1 * parseFloat(point)));
- document.querySelector(`.error-value[data-point="${point}"]`).textContent = error.toFixed(2);
- // 收集数据用于图表
- errorData.push({
- point: (-1 * parseFloat(point)),
- avg: avg,
- error: error
- });
- }
- });
- // 更新误差图表
- updateErrorChart(errorData);
- }
- function updateErrorChart(data) {
- if (errorChartInstance) {
- errorChartInstance.destroy();
- }
- if (data.length === 0) return;
- // 按照点位排序
- data.sort((a, b) => a.point - b.point);
- const labels = data.map(item => item.point);
- const errorValues = data.map(item => item.error);
- errorChartInstance = new Chart(errorCtx, {
- type: 'line',
- data: {
- labels: labels,
- datasets: [{
- label: '示值误差',
- data: errorValues,
- borderColor: 'rgb(75, 192, 192)',
- backgroundColor: 'rgba(75, 192, 192, 0.2)',
- tension: 0.1,
- pointRadius: 5,
- pointHoverRadius: 7
- }]
- },
- options: {
- responsive: true,
- scales: {
- y: {
- beginAtZero: false
- }
- },
- plugins: {
- legend: {
- display: false
- }
- }
- }
- });
- }
- </script>
- </body>
- </html>
- <script>
- function exportData() {
- const data = {
- repeatability: {
- inputs: Array.from(document.querySelectorAll('#repeatability .input-group input')).map(input => input.value),
- results: {
- range: document.getElementById('range').innerText,
- mean: document.getElementById('mean').innerText,
- variance: document.getElementById('variance').innerText,
- stdDev: document.getElementById('stdDev').innerText,
- rsd: document.getElementById('rsd').innerText
- }
- },
- stability: {
- inputs: Array.from(document.querySelectorAll('#stability .input-group input')).map(input => input.value),
- results: {
- max: document.getElementById('stability-max').innerText,
- min: document.getElementById('stability-min').innerText,
- mean: document.getElementById('stability-mean').innerText,
- range: document.getElementById('stability-range').innerText
- }
- },
- error: Array.from(document.querySelectorAll('.error-point-container')).map(container => ({
- point: container.querySelector('h3').innerText,
- inputs: Array.from(container.querySelectorAll('.error-input')).map(input => input.value),
- avg: container.querySelector('.error-avg').innerText,
- error: container.querySelector('.error-value').innerText
- }))
- };
- const now = new Date();
- const dateStr = now.toISOString().replace(/[-:]/g, '').replace('T', '_').substring(0, 15);
- const projectName = document.title.replace(' ', '_');
- const blob = new Blob([JSON.stringify(data, null, 2)], { type: 'application/json' });
- const url = URL.createObjectURL(blob);
- const a = document.createElement('a');
- a.href = url;
- a.download = `${projectName}_data_${dateStr}.json`;
- a.click();
- URL.revokeObjectURL(url);
- }
- function importData() {
- const fileInput = document.getElementById('importFile');
- const file = fileInput.files[0];
- if (!file) return;
- const reader = new FileReader();
- reader.onload = function (e) {
- try {
- const data = JSON.parse(e.target.result);
- console.log(data);
- console.log(data.error);
- // 更新重复性数据
- if (data.repeatability) {
- const inputs = document.querySelectorAll('#repeatability input[type="number"]');
- data.repeatability.inputs.forEach((value, index) => {
- if (inputs[index]) inputs[index].value = value;
- });
- calculateRepeatability();
- }
- // 更新稳定性数据
- if (data.stability) {
- const inputs = document.querySelectorAll('#stability input[type="number"]');
- data.stability.inputs.forEach((value, index) => {
- if (inputs[index]) inputs[index].value = value;
- });
- calculateStability();
- }
- // 更新示值误差数据
- if (data.error) {
- data.error.forEach(item => {
- // 将point转换为字符串形式以确保匹配
- const point = item.point.toString().replace(/m℃$/, '');
- const inputs = document.querySelectorAll(`.error-input[data-point="${point}"]`);
- item.inputs.forEach((value, index) => {
- if (inputs[index]) inputs[index].value = value;
- });
- });
- calculateError();
- }
- } catch (error) {
- alert('导入失败!');
- console.error(error);
- }
- };
- reader.readAsText(file);
- }
- </script>
- </body>
- </html>
|