6.0 KiB
6.0 KiB
id, title, phase, deps, status, created
| id | title | phase | deps | status | created |
|---|---|---|---|---|---|
| T-582 | 修复①导入 Excel 失败通知弹窗偶发只显示一半(延迟一拍弹窗) | 7 | DONE | 2026-07-10 |
问题 / 背景
用户反馈:①采集导入 Excel 后的通知弹窗偶发只显示一半、显示不全。界面本身不卡死——导入通常很快、无可感知冻结,纯粹是弹窗画不全。「偶尔」也排除纯 HiDPI 缩放(那会稳定半截),更像绘制时序竞态。
已核代码事实:
- 当前
CollectTab.import_excel()成功导入后没有完成弹窗,只是在refresh_tasks()后调用_set_status("导入完成...")更新左下角状态栏。因此本任务不得新增“导入成功”弹窗,否则会变成新需求。 - 当前导入失败路径在
except中写 run log / 诊断日志后直接调用_show_error(safe_error);_show_error()立即执行QMessageBox.warning(self, "导入采集", str(message))。 - 失败弹窗可能在同一调用栈内、界面刷新/状态更新还未完成时立即进入模态
exec(),首帧几何/内容没算稳 → 偶发只画一半。修法不是“把导入改慢/改 worker”,而是“让通知弹窗晚一拍,等当前事件循环先把待处理绘制冲刷完”。
范围收敛:本任务只修①导入 Excel 失败通知弹窗,不建统一弹窗 helper、不重构其它 QMessageBox 调用点、不改导入线程模型(导入 worker 化不在本任务)。
方案(改哪个文件、改成什么)
1. 让导入失败通知弹窗晚一拍弹(app/gui/tabs/collect.py)
- 把
_show_error(message)改为:先同步更新状态栏_set_status(str(message), level="danger" 或现有口径);再用QTimer.singleShot(0, lambda: QMessageBox.warning(...))延迟显示导入失败通知。 - 这样导入失败路径原有 run log、diagnostic log、状态栏错误信息仍在当前调用栈完成;真正的模态弹窗等当前事件循环下一拍再打开,降低首帧绘制不完整概率。
- 只改
_show_error()这一处导入失败通知;不改import_excel()成功路径,不新增导入成功弹窗。 - 不改
_show_account_guide():它属于采集前账号就绪引导,不是导入 Excel 完成链路;本任务不外扩到采集链路。 - 不改
QMessageBox.question/ 删除批次确认等需要立即返回用户选择的确认类弹窗。
2. 本任务不做 HiDPI 全局设置
- 先不在
app/gui/__init__.py增加QGuiApplication.setHighDpiScaleFactorRoundingPolicy(...)。该设置影响全局窗口缩放,且当前问题是“偶发”,优先按事件循环时序修复。 - 如果后续能稳定复现 HiDPI 缩放导致的弹窗裁切,再另立任务处理全局缩放策略。
验收要点
excel.import_tasks()抛异常时,导入失败通知经QTimer.singleShot(0, ...)延迟显示;单测 mockQTimer.singleShot断言被调用,不真正弹窗。excel.import_tasks()抛异常时,不再在同一调用栈直接调用QMessageBox.warning;可通过 mockQMessageBox.warning断言在执行singleShot回调前未被直接调用。- 导入失败既有行为不回归:run log 标记 failed、诊断日志写入、状态栏显示脱敏错误文案、
_show_error的窗口标题/正文仍为中文导入失败提示。 - 导入成功路径不新增
QMessageBox;仍然刷新列表、更新 summary、写状态栏“导入完成...”。 - 未改动导入链路以外的弹窗调用点(
git diff范围仅app/gui/tabs/collect.py+ 对应tests/test_gui.py)。 - 验证命令(unittest,不引入 pytest;GUI 测试用 offscreen):
py -3.10 -m unittest tests.test_guipython -m ruff check app tests main.pypy -3.10 -m compileall app main.pypy -3.10 -m unittest discover -s testsgit diff --check
边界(不改什么)
- 不建统一弹窗 helper、不收敛/替换其它模块的
QMessageBox调用。 - 不把①导入改成 worker 线程(如后续要治界面卡死另立任务/backlog)。
- 不新增导入成功弹窗;成功导入仍只用状态栏提示。
- 不改
_show_account_guide()账号未就绪弹窗;它属于采集链路,不属于导入 Excel 链路。 - 不做 HiDPI 全局缩放策略调整。
- 不改弹窗文案/业务语义、不改
excel.import_tasks解析入库逻辑。 - 不改 CDP/DB/AI/cmhub、主窗口尺寸逻辑。
执行记录
- 2026-07-10:已实现
_show_error()延迟弹出导入失败通知:状态栏仍同步显示错误,QMessageBox.warning(self, "导入采集", text)改为经QTimer.singleShot(0, ...)下一拍执行,降低刷新/绘制同栈内立即弹模态框导致首帧显示不完整的概率。 - 2026-07-10:未改导入成功路径;成功导入仍只刷新列表、更新 summary、状态栏显示“导入完成...”,不新增成功弹窗。未改
_show_account_guide()、删除批次确认框、HiDPI 全局设置、导入解析入库逻辑。 - 2026-07-10:补
tests/test_gui.py:成功导入断言不会调用QTimer.singleShot和弹窗;导入异常时断言QTimer.singleShot(0, callback)被调用、回调执行前不直接弹窗、run log/脱敏错误/弹窗标题正文不回归。 - 当前工作区验证通过:
py -3.10 -m unittest tests.test_gui.GuiTests.test_collect_tab_import_button_imports_excel_and_refreshes_tasks tests.test_gui.GuiTests.test_collect_tab_import_error_dialog_is_delayed_one_event_loop tests.test_gui.GuiTests.test_collect_tab_import_excel_writes_diagnostic_run_logpython -m ruff check app tests main.pypy -3.10 -m compileall app main.pygit diff --check(仅输出当前工作区既有 CRLF 提示,无空白错误)
- 当前工作区直接运行
py -3.10 -m unittest tests.test_gui失败 2 项,原因是本任务开始前已有未提交改动把默认封面提示词从papa1改成「默认」,导致两个旧断言仍期望papa1;该提示词改名不属于 T-582,本次未处理、未提交。提交后需用干净 worktree 验证本次提交本身。