common.js 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. // common.js - 通用功能和初始化函数
  2. // 页面加载完成后初始化
  3. document.addEventListener('DOMContentLoaded', function () {
  4. // 添加初始示值误差测试点(因为已移除所有默认测试点)
  5. if (document.querySelectorAll('#error-inputs .error-point-container').length === 0) {
  6. addErrorPoint();
  7. }
  8. // 调用各个模块的占位符更新函数
  9. if (typeof updateRepeatabilityInputPlaceholders === 'function') {
  10. updateRepeatabilityInputPlaceholders();
  11. }
  12. if (typeof updateStabilityInputPlaceholders === 'function') {
  13. updateStabilityInputPlaceholders();
  14. }
  15. // 调用各个模块的删除按钮更新函数
  16. if (typeof updateRepeatabilityDeleteButtons === 'function') {
  17. updateRepeatabilityDeleteButtons();
  18. }
  19. if (typeof updateStabilityDeleteButtons === 'function') {
  20. updateStabilityDeleteButtons();
  21. }
  22. // 调用updateStabilityInputs以保持向后兼容性
  23. if (typeof updateStabilityInputs === 'function') {
  24. updateStabilityInputs();
  25. }
  26. // 初始化示值误差测试点的删除按钮
  27. updateErrorPoints();
  28. loadTimerSettings();
  29. // 初始化页面数据
  30. initializePage();
  31. });
  32. // 标签页切换功能
  33. document.querySelectorAll('.tab').forEach(tab => {
  34. tab.addEventListener('click', function() {
  35. // 保存当前自定义参数
  36. saveCustomParamsData();
  37. // 切换标签页
  38. const tabId = this.getAttribute('data-tab');
  39. document.querySelectorAll('.tab').forEach(t => t.classList.remove('active'));
  40. document.querySelectorAll('.tab-content').forEach(content => content.classList.remove('active'));
  41. this.classList.add('active');
  42. document.getElementById(tabId).classList.add('active');
  43. });
  44. });
  45. // 通用函数
  46. function createInputRow(index, type, onInputFunction, onDeleteFunction) {
  47. const row = document.createElement('div');
  48. row.className = 'input-row';
  49. const timeSpan = document.createElement('span');
  50. timeSpan.id = `${type}-time-text-${index}`;
  51. timeSpan.textContent = `${index}: `;
  52. const input = document.createElement('input');
  53. input.type = 'number';
  54. input.placeholder = '输入值';
  55. input.id = `${type}-value-${index}`;
  56. input.oninput = function() { onInputFunction(index); };
  57. const deleteBtn = document.createElement('span');
  58. deleteBtn.className = 'delete-btn';
  59. deleteBtn.innerHTML = '×';
  60. deleteBtn.onclick = function() { onDeleteFunction(this); };
  61. row.appendChild(timeSpan);
  62. row.appendChild(input);
  63. row.appendChild(deleteBtn);
  64. return row;
  65. }
  66. function updateInputRows(selector, minRows) {
  67. const rows = document.querySelectorAll(selector);
  68. rows.forEach((row, index) => {
  69. const deleteBtn = row.querySelector('.delete-btn');
  70. if (index < minRows - 1) {
  71. deleteBtn.style.visibility = 'hidden';
  72. } else {
  73. deleteBtn.style.visibility = 'visible';
  74. }
  75. });
  76. }
  77. function recordTimeAndCalculate(type, index, timesArray, calculateFunction) {
  78. const now = new Date();
  79. const timeString = now.toLocaleTimeString('zh-CN', { hour: '2-digit', minute: '2-digit', second: '2-digit' });
  80. // 更新时间显示
  81. document.getElementById(`${type}-time-text-${index}`).textContent = `${timeString}: `;
  82. // 记录测试时间
  83. timesArray[index - 1] = timeString;
  84. // 执行计算
  85. calculateFunction();
  86. }
  87. function createOrUpdateChart(chartInstance, ctx, labels, data, label) {
  88. if (chartInstance) {
  89. chartInstance.data.labels = labels;
  90. chartInstance.data.datasets[0].data = data;
  91. chartInstance.update();
  92. return chartInstance;
  93. } else {
  94. return new Chart(ctx, {
  95. type: 'line',
  96. data: {
  97. labels: labels,
  98. datasets: [{
  99. label: label,
  100. data: data,
  101. borderColor: 'rgba(75, 192, 192, 1)',
  102. backgroundColor: 'rgba(75, 192, 192, 0.2)',
  103. borderWidth: 2,
  104. pointRadius: 5,
  105. pointBackgroundColor: 'rgba(75, 192, 192, 1)',
  106. tension: 0.1
  107. }]
  108. },
  109. options: {
  110. responsive: true,
  111. maintainAspectRatio: false,
  112. scales: {
  113. y: {
  114. beginAtZero: false
  115. }
  116. }
  117. }
  118. });
  119. }
  120. }
  121. function getNumericInputs(selector) {
  122. return Array.from(document.querySelectorAll(selector))
  123. .map(input => parseFloat(input.value))
  124. .filter(value => !isNaN(value));
  125. }
  126. function updateResultDisplay(id, value, precision = 6) {
  127. const element = document.getElementById(id);
  128. if (element) {
  129. if (value === null || value === undefined || isNaN(value)) {
  130. element.innerText = '-';
  131. } else {
  132. // 格式化数字,去除尾随的0
  133. const formatted = parseFloat(value.toFixed(precision)).toString();
  134. element.innerText = formatted;
  135. }
  136. }
  137. }
  138. function updateInputPlaceholders() {
  139. updateInputRows('#repeatability-inputs .input-row', 6);
  140. }
  141. function updateStabilityInputs() {
  142. updateInputRows('#stability-inputs .input-row', 6);
  143. }
  144. function updateErrorPoints() {
  145. const pointContainers = document.querySelectorAll('#error-inputs .error-point-container');
  146. pointContainers.forEach((container, index) => {
  147. const deleteBtn = container.querySelector('.delete-btn');
  148. if (pointContainers.length <= 1) {
  149. deleteBtn.style.visibility = 'hidden';
  150. } else {
  151. deleteBtn.style.visibility = 'visible';
  152. }
  153. });
  154. }
  155. function updateProjectTitle() {
  156. const titleInput = document.getElementById('project-title');
  157. const title = titleInput.value.trim() || '无标题';
  158. updateDocumentTitle();
  159. setCookie('projectTitle', title, 365);
  160. }
  161. function updateDocumentTitle() {
  162. const titleInput = document.getElementById('project-title');
  163. const title = titleInput.value.trim() || '无标题';
  164. document.title = `${title} - LabStatistics`;
  165. }
  166. function newProject() {
  167. if (confirm('确定要新建工程吗?这将清除所有当前数据!')) {
  168. // 清除所有数据
  169. clearAllData();
  170. // 重置标题
  171. document.getElementById('project-title').value = '';
  172. updateProjectTitle();
  173. // 重新初始化页面
  174. initializePage();
  175. }
  176. }
  177. function clearAllData() {
  178. // 清除重复性数据
  179. const repeatabilityInputs = document.querySelectorAll('#repeatability-inputs .input-row');
  180. for (let i = 6; i < repeatabilityInputs.length; i++) {
  181. repeatabilityInputs[i].remove();
  182. }
  183. document.querySelectorAll('#repeatability-inputs input[type="number"]').forEach(input => {
  184. input.value = '';
  185. });
  186. repeatabilityTimes = [];
  187. // 重置重复性时间标签
  188. for (let i = 1; i <= 6; i++) {
  189. const timeSpan = document.getElementById(`repeatability-time-text-${i}`);
  190. if (timeSpan) {
  191. timeSpan.textContent = `${i}: `;
  192. }
  193. }
  194. // 清除稳定性数据
  195. const stabilityInputs = document.querySelectorAll('#stability-inputs .input-row');
  196. for (let i = 6; i < stabilityInputs.length; i++) {
  197. stabilityInputs[i].remove();
  198. }
  199. document.querySelectorAll('#stability-inputs input[type="number"]').forEach(input => {
  200. input.value = '';
  201. });
  202. stabilityTimes = [];
  203. // 重置稳定性时间标签
  204. const stabilityTimes = [0, 10, 20, 30, 40, 50];
  205. for (let i = 1; i <= 6; i++) {
  206. const timeSpan = document.getElementById(`stability-time-text-${i}`);
  207. if (timeSpan) {
  208. timeSpan.textContent = `${stabilityTimes[i-1]}: `;
  209. }
  210. }
  211. // 清除示值误差数据
  212. const errorContainer = document.getElementById('error-inputs');
  213. while (errorContainer.firstChild) {
  214. errorContainer.removeChild(errorContainer.firstChild);
  215. }
  216. addErrorPoint();
  217. // 清除自定义参数
  218. const customParamsContainer = document.getElementById('custom-params-container');
  219. while (customParamsContainer.firstChild) {
  220. customParamsContainer.removeChild(customParamsContainer.firstChild);
  221. }
  222. // 重置图表
  223. if (chartInstance) {
  224. chartInstance.destroy();
  225. chartInstance = null;
  226. }
  227. if (stabilityChartInstance) {
  228. stabilityChartInstance.destroy();
  229. stabilityChartInstance = null;
  230. }
  231. if (errorChartInstance) {
  232. errorChartInstance.destroy();
  233. errorChartInstance = null;
  234. }
  235. // 清除结果显示
  236. document.querySelectorAll('.result-item span').forEach(span => {
  237. span.innerText = '-';
  238. });
  239. // 清除cookies
  240. deleteCookie('repeatabilityData');
  241. deleteCookie('stabilityData');
  242. deleteCookie('errorData');
  243. deleteCookie('customParamsData');
  244. }
  245. function initializePage() {
  246. // 加载项目标题
  247. const savedTitle = getCookie('projectTitle');
  248. if (savedTitle) {
  249. document.getElementById('project-title').value = savedTitle;
  250. updateDocumentTitle();
  251. }
  252. // 加载自定义参数
  253. loadCustomParamsFromCookies();
  254. // 加载重复性、稳定性和示值误差数据
  255. loadDataFromCookies();
  256. }
  257. // 更新当前时间显示
  258. function updateCurrentTime() {
  259. const now = new Date();
  260. const timeString = now.toLocaleTimeString('zh-CN', { hour: '2-digit', minute: '2-digit', second: '2-digit' });
  261. document.getElementById('current-time').textContent = timeString;
  262. setTimeout(updateCurrentTime, 1000);
  263. }
  264. // 初始化时启动时间更新
  265. updateCurrentTime();