JavaScript如何避免多次上传文件时分配的设备序列号重复
问题原因
当前代码出现序列号重复分配的核心问题有两个:
- 原
randomNoRepeats函数逻辑中,当备用序列号池被取空后会直接重置整个池,已分配过的序列号会重新进入待分配队列 - 没有全局存储已分配的序列号记录,多次上传文件时都会从初始序列号列表中取值,自然会出现重复
修复方案
我们新增全局已使用序列号存储,移除序列号池自动重置逻辑,同时增加序列号不足的提示,完整修改后的代码如下:
<!DOCTYPE HTML> <html> <head> <script type="text/javascript" src="https://unpkg.com/xlsx@0.15.1/dist/xlsx.full.min.js"></script> <!-- 可选引入bootstrap用于样式,你原有代码用到了相关类名 --> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet"> </head> <body> <div class="container"> <h2 class="text-center mt-4 mb-4">使用JavaScript将Excel转换为HTML表格</h2> <div class="card"> <div class="card-header"> <b>选择Excel文件</b> </div> <div class="card-body"> <input type="file" id="excel_file" /> <!-- 可选增加重置按钮,用于清空已使用序列号记录 --> <button id="reset_btn" class="btn btn-warning ms-3">重置已分配序列号</button> </div> </div> <div id="excel_data" class="mt-5"></div> </div> </body> </html> <script> const excel_file = document.getElementById('excel_file'); const reset_btn = document.getElementById('reset_btn'); // 原始序列号池 const filterserial = ['K4Z7-9RFL-XCXS', 'TEIK-YMJF-4QQG', '4SB9-NR2D-742E', 'TY83-FPSX-C3WS', 'YVLM-W2T1-YNSI']; // 全局存储已经被使用的序列号 const usedSerials = new Set(); // 重置已使用序列号记录 reset_btn.addEventListener('click', () => { usedSerials.clear(); alert('已清空已分配序列号记录'); }); // 获取当前可用的序列号列表 function getAvailableSerials() { return filterserial.filter(serial => !usedSerials.has(serial)); } // 从可用列表中随机取一个序列号 function getRandomSerial() { const available = getAvailableSerials(); if (available.length === 0) return null; const index = Math.floor(Math.random() * available.length); const selected = available[index]; usedSerials.add(selected); return selected; } excel_file.addEventListener('change', (event) => { if (!['application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'application/vnd.ms-excel'].includes(event.target.files[0].type)) { document.getElementById('excel_data').innerHTML = '<div class="alert alert-danger">仅允许.xlsx或.xls格式的文件</div>'; excel_file.value = ''; return false; } var reader = new FileReader(); reader.readAsArrayBuffer(event.target.files[0]); reader.onload = function(event) { var data = new Uint8Array(reader.result); var work_book = XLSX.read(data, {type: 'array'}); var sheet_name = work_book.SheetNames; var sheet_data = XLSX.utils.sheet_to_json(work_book.Sheets[sheet_name[0]], {header: 1}); if (sheet_data.length > 0) { // 本次需要的序列号数量(减去表头行) const needSerialCount = sheet_data.length - 1; const availableCount = getAvailableSerials().length; // 剩余序列号不足提前提示 if (needSerialCount > availableCount) { document.getElementById('excel_data').innerHTML = `<div class="alert alert-danger">剩余可用序列号不足,当前剩余${availableCount}个,本次需要${needSerialCount}个</div>`; excel_file.value = ''; return; } var table_output = '<table class="table table-striped table-bordered">'; for (var row = 0; row < sheet_data.length; row++) { table_output += '<tr>'; if (row == 0) { table_output += '<th>Device</th>' } else { const serial = getRandomSerial(); table_output += `<td>${serial}</td>` } for (var cell = 0; cell < sheet_data[row].length; cell++) { if (row == 0) { table_output += '<th>' + sheet_data[row][cell] + '</th>'; } else { table_output += '<td>' + sheet_data[row][cell] + '</td>'; } } table_output += '</tr>'; } table_output += '</table>'; document.getElementById('excel_data').innerHTML = table_output; } excel_file.value = ''; } }); </script>
核心修改点
- 新增
usedSerials全局Set集合,永久存储所有已经被分配过的序列号,不会因为多次上传被重置 - 移除了原逻辑中序列号耗尽自动重置的代码,新增剩余序列号不足的提前提示
- 可选增加了重置按钮,可手动清空已分配序列号记录,适合需要重新开始分配的场景
内容的提问来源于stack exchange,提问作者terry5546
相关产品推荐
相关产品推荐

