
本文介绍一种高效、健壮的方法,通过遍历当前周的 localStorage 键值对,识别同一工作日(如“Montag”)下具有相同输入值的多个表单字段,并自动为其添加 double-input 或 no-double-input CSS 类,实现可视化去重反馈。
本文介绍一种高效、健壮的方法,通过遍历当前周的 localstorage 键值对,识别同一工作日(如“montag”)下具有相同输入值的多个表单字段,并自动为其添加 `double-input` 或 `no-double-input` css 类,实现可视化去重反馈。
在构建周计划表格(如工作日排班系统)时,常需确保同一工作日内各时段输入内容不重复。本方案基于 localStorage 持久化存储(键名格式为 40_tdMontag1,其中 40 为 ISO 周数,tdMontag1 为 DOM 元素 ID),提供一套完整的客户端去重标记逻辑。
核心思路分四步实现:
- 筛选本周相关键:提取所有以当前周数(如 "40_")开头的 localStorage 键;
- 映射 ID → 值数组:剥离前缀,将 tdMontag1 映射到其存储值(支持同一 ID 多次写入场景,但本例中每个 ID 唯一);
- 按工作日分组比对:针对 ['Montag', 'Dienstag', ...] 每日,收集当日所有输入 ID,并两两比对值是否相等;
- 批量更新 DOM 类名:为重复值对应的元素添加 double-input,其余添加 no-double-input,确保样式互斥。
以下是优化后的完整函数(含错误防护与语义化注释):
function getAnyDoubleInput() {
// ✅ 步骤1:获取当前周数(优先读取 localStorage,否则用 moment.js 动态计算)
const week = localStorage.getItem('currentWeek') || String(moment().isoWeek());
// ✅ 步骤2:提取本周所有 localStorage 键,并解析为 { id: value } 映射
const weekKeys = Object.keys(localStorage).filter(key => key.startsWith(week + '_'));
const inputs = {}; // id → [value](数组便于未来扩展多值场景)
weekKeys.forEach(key => {
const id = key.split('_', 2)[1]; // 更安全地截取:从第一个 '_' 后开始
if (!id) return;
const value = localStorage.getItem(key);
if (inputs[id]) {
inputs[id].push(value);
} else {
inputs[id] = [value];
}
});
// ✅ 步骤3 & 4:按工作日分组、查重、更新类名
const weekDays = ['Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag'];
weekDays.forEach(day => {
// 获取当日所有有效 input ID
const dayIds = Object.keys(inputs).filter(id =>
id.startsWith('td') && id.includes(day)
);
// 找出当日所有「值重复」的 ID(去重后)
const duplicateIds = new Set();
for (let i = 0; i {
const el = document.getElementById(id);
if (!el) return;
if (duplicateIds.has(id)) {
el.classList.add('double-input');
el.classList.remove('no-double-input');
} else {
el.classList.add('no-double-input');
el.classList.remove('double-input');
}
});
});
}
⚠️ 注意事项与最佳实践:
- ID 命名一致性:确保 HTML 中 与 localStorage 键 40_tdMontag1 的后缀严格一致;
- 空值处理:代码中显式跳过空字符串(val.trim() !== ''),避免全空输入被误标为重复;
- 性能考量:工作日最多 5 天 × 每日 ≤20 字段 → 双重循环仍为 O(n²) 但 n 极小,无需额外优化;
- 兼容性:使用 classList.add()/remove() 替代直接操作 className,避免覆盖其他业务类名;
- 调用时机:建议在页面加载完成(DOMContentLoaded)及每次 localStorage 更新后调用,例如监听自定义事件 storage:update。
该方案解耦了存储结构与 UI 标记逻辑,具备良好的可维护性与扩展性——如需支持跨日重复检测,仅需调整 dayIds 的过滤条件即可。











