# Fix-BUG-20260415-0008 > 适用场景:记录某个 BUG 的修复方案、影响评估、验证结果与落地信息。 ## 关联信息 - Fix ID: Fix-BUG-20260415-0008 - 关联 BUG ID: BUG-20260415-0008 - 修复目标: 修正 TabControl 页签层级和重复激活已激活页签的回调链 - 状态:已完成 - 负责人: Codex - 分支 / 版本: 当前工作区 ## 根因分析 - 根因: - `TabControl::draw()` 与局部重绘顺序为“先页签按钮,后页面”,导致页签 Tooltip 被页面盖掉。 - `Button::setButtonClick()` 对 `TOGGLE` 没有做“同状态短路”,外部重复激活同一页签会重复触发 `onToggleOnCallback`。 - `TabControl::setActiveIndex()` 也没有对“目标已是当前激活页”做保护,导致当前可见页的 `onWindowResize()` / `setIsVisible(true)` 链被重复执行。 - 触发条件: - 任意页打开时触发页签 Tooltip - 外部对已激活页签再次 `setActiveIndex()` - 为什么之前没发现: KEY1 外部按钮重复激活场景和 KEY5 页签 Tooltip 场景是后续专项回归才补出来的。 - 关键证据: - 所有页关闭时页签 Tooltip 正常,说明问题在页面层级覆盖 - 只点一次外部激活正常,重复激活后残影出现,说明问题在重复回调链 ## 修复方案 - 修复思路: - 把 TabControl 绘制/局部重绘顺序改为“先页面、后页签按钮” - 给 `TOGGLE` 状态设置和 `setActiveIndex()` 增加同状态短路 - 关键改动: - `TabControl::draw()` 改成先画页面、后画页签按钮 - `TabControl::requestRepaint(this)` 的局部提交顺序同步调整 - `Button::setButtonClick()` 在 `TOGGLE` 同状态时直接返回 - `TabControl::setActiveIndex()` 若目标已是当前激活页则直接返回 - 涉及文件 / 类 / 函数: - `TabControl.cpp` - `Button.cpp` - 影响的 API / 行为: - 重复设置相同 `TOGGLE` 状态不再重复触发回调 - 关键约束 / 不变量: - 页签按钮视觉层级应始终高于页面 - 外部重复激活同一页签不应重新走页面显示链 - 回滚点 / 开关:无 ## 影响评估 - 影响范围: TabControl 页签 Tooltip、外部页签激活、页内超出页面边界的复合控件 - 兼容性影响:有(收紧了 TOGGLE 同状态重复 set 的回调语义) - 行为变化:有(页签 Tooltip 层级恢复正确;重复激活同一页签不再重复触发回调) - 性能影响:无 - 回归风险: - 如有外部代码依赖“同状态重复 set 也要重复触发回调”,该行为将被收掉 - 需重点回归 KEY1 和 KEY5 的 TabControl 场景 ## 验证结果 - 验证步骤: 1. 编译 `Button.cpp / TabControl.cpp` 2. 编译 `z-testDome.cpp` 的 `KEY=1` 3. 回归 `KEY5` 页签 Tooltip 与 `KEY1` 外部按钮重复激活页签场景 - 验证结果: 编译通过;逻辑推演闭合;GUI 需用户本机手测 - 回归检查:KEY1 页签 1 表格超出区、KEY5 页签 Tooltip - 验证证据:编译级验证通过 ## 落地信息 - Commit: 未单独提交 - PR:[可选] - 发布版本:[可选] - 备注:此修复不包含 TabControl 其它内部布局专题