Skip to content

主面板与设置面板单选点击无效/多选的原因与修复总结

现象复盘

  • 在导入模式导入行为导出路径等单选组中,点击切换后高亮不更新或出现两个选项同时高亮(看起来像多选)。
  • 控制台可见日志高级导入模式已更改为: direct/custom_folder,但界面仍显示上一次选择;同时导出模式日志保持为 custom_folder,与导入模式切换无关。

根因分析(并列因素叠加)

  1. 事件顺序导致选择被回滚
  • 导入模式的 change 处理在早期实现中先调用 updateSettingsUI(),该方法根据旧的 settings.mode 重绘 UI。
  • 因为未先保存新选择到设置,重绘会把刚刚点击的单选按钮恢复为旧值,导致点击无效。
  1. 样式刷新触发不足
  • 多数单选组点击后并未统一调用样式刷新,label 上的 .checked.checked-export 类没有即时切换;
  • 新旧标签的类未被清理,视觉上出现两个选项同时高亮(多选)。
  1. 样式计算来源不一致(设置值强制覆盖 DOM)
  • updateModeButtonStyles() 曾尝试用当前设置值去强制 radio.checked,其与用户点击后的 DOM 状态产生竞争;
  • 在设置未及时更新的情况下,样式函数会覆盖用户刚选中的项,引发显示异常。
  1. 快速设置与高级设置的同步耦合不健壮
  • 仅在 quickSettingsInitialized 为真时才把导入模式写入设置;在扩展面板复杂初始化阶段,该标志可能为假,导致主/设置面板状态不同步。
  1. CSS 机制及 CEP 兼容性
  • 由于 CEP 环境不可靠支持 :has,本项目用 .checked/.checked-export 类模拟选中态;
  • 一旦事件未触发样式更新或类没有被正确增删,就会出现看起来多选或高亮不更新。

触发链路(典型一次点击)

  • 用户点击导入模式”。
  • 旧逻辑:未立即 updateField('mode', ...);直接 updateSettingsUI() 依据旧设置重绘 新选择被回滚。
  • 同时样式函数未被统一调用,导致旧 label 的选中类仍存在,新 label 也显示选中,形成视觉多选。

修复措施(当前已生效)

  • 事件顺序调整:在导入模式 change 中,先 this.settingsManager.updateField('mode', radio.value, false),再调用 updateSettingsUI()updateModeButtonStyles(),避免重绘回滚。
  • 简化样式刷新策略:updateModeButtonStyles() 仅基于 DOM 的 input[type="radio"].checked 来增删 .checked / .checked-export,不再用设置值强制覆盖 radio.checked
  • 增加通用监听器:对 import-modequick-import-modeadvanced-import-behaviorimport-behaviortimeline-placementexport-modechange 统一触发样式刷新,保证即时高亮与互斥视觉。
  • 保持导出模式独立:导出模式日志与导入模式无关,维持其原本的独立保存与高亮逻辑,避免误关联导致混乱。

验证方法

  • 在设置面板逐一点击上述单选组,确认:
    • 只存在一个选项高亮(蓝/橙/紫),视觉互斥;
    • 切换后立即生效,关闭再打开面板仍保持最后选择;
    • 控制台日志与视觉一致。

相关代码位置

  • index.html:单选结构与类(导入/导入行为/导出) 约 42884365 行;选中态 CSS 约 28102880 行。
  • js/main.js
    • 导入模式 change 处理约 63656505 行(已改为先保存再刷新)。
    • 通用 change 监听器约 65956755 行(统一触发样式刷新)。
    • updateModeButtonStyles() 约 84588635 行(仅依据 DOM 选中状态增删类)。

避坑与建议

  • UI 刷新前务必先更新底层设置,避免按旧设置重绘。
  • 视觉选中态应源于真实 DOM 状态,避免逻辑层强制覆盖。
  • 在 CEP/旧浏览器场景下,避免依赖 :has,用类驱动样式并确保每次交互都增删到位。
  • 快速设置与高级设置的双向同步尽量解耦事件与保存顺序,保证一致性。

变更摘要

  • 调整导入模式 change 的保存顺序。
  • 重写 updateModeButtonStyles() 为 DOM 驱动。
  • 增加通用单选变化监听,统一触发样式刷新。

Released under the MIT License.