返回开发日志
飞书多维表同步工具2026-07-10v4.1.4

保存路径被覆盖+save_path空值+GUI自动化测试

bug修复v4.1.4

需求描述

v4.1.3修复后API下载仍报错"[WinError 3] 系统找不到指定的路径: ''",且任务编辑面板中看不到保存路径选择入口。深入排查发现两个关键bug:

  1. 保存路径控件和文件命名设置LabelFrame都grid在row=6,后者覆盖了前者的显示位置
  2. save_path为空字符串时task.get("save_path", DEFAULT_SAVE_PATH)返回空字符串(key存在value为空),导致os.makedirs("")报WinError 3

根因分析

  1. grid row冲突:erp_report_tab.py第1064-1078行,保存路径Label/Entry/Button和naming_frame都grid在row=6。Tkinter grid中同一位置后创建的控件会覆盖先创建的,导致保存路径不可见
  2. save_path空值处理:lingxing_api_downloader.py第303行task.get("save_path", DEFAULT_SAVE_PATH),当task中save_path=""(空字符串)时,dict.get返回空字符串而非默认值(因为key存在),os.makedirs("")报错

改动文件清单

文件类型改动内容
tabs/erp_report_tab.py修改naming_frame从row=6移到row=7,不再覆盖保存路径控件的显示位置
erp/lingxing_api_downloader.py修改save_path读取改为task.get("save_path") or DEFAULT_SAVE_PATH,空字符串/None/缺失都回退到默认值
tests/test_erp_dialog_gui.py新建GUI自动化测试(13个测试):凭据切换模拟、保存路径grid布局验证、导出方式切换完整流程模拟、save_path空值处理、report_type保存正确性
gui_sync.py修改版本号 4.1.3→4.1.4

技术要点

  1. Tkinter grid同一位置覆盖机制:grid(row=6)中后创建的控件会覆盖先创建的控件。解决方法:确保不同控件使用不同的row编号
  2. dict.get的默认值陷阱dict.get(key, default)只在key不存在时返回default,key存在但value为空字符串时返回空字符串。需要用dict.get(key) or default处理空值
  3. GUI自动化测试方法:用tk.Tk() + root.withdraw()创建隐藏窗口,tk.Toplevel()创建模拟对话框,用grid_info()检查控件布局位置,不依赖winfo_ismapped()(withdraw后总是返回0)

验证结果

  • 语法检查:3个修改文件全部通过py_compile
  • 自动化测试:38个测试全部通过(python -m unittest tests.test_erp_credential_flow tests.test_erp_dialog_gui -v
    • 凭据加载逻辑:5项通过
    • 执行器凭据读取:4项通过
    • GUI凭据切换:5项通过
    • 端到端凭据流:2项通过
    • 旧任务兼容性:3项通过
    • report_type正确性:6项通过
    • GUI对话框凭据切换模拟:3项通过
    • GUI保存路径布局验证:2项通过(grid不冲突、Entry被正确放置)
    • 导出方式切换完整流程:1项通过(API→Web→API完整切换)
    • save_path空值处理:4项通过(空字符串/None/缺失/有值)
    • report_type保存正确性:3项通过(id不含中文、name含中文、保存逻辑用id)

踩坑与解决

  • winfo_ismapped在withdraw后返回0:测试中用dialog.withdraw()隐藏窗口后,所有控件的winfo_ismapped()都返回0,导致测试失败。解决方法:改用grid_info()检查控件是否被grid放置(检查row字段是否存在),不依赖窗口可见性
  • grid覆盖问题:保存路径Label/Entry/Button和naming_frame都grid在row=6,naming_frame是columnspan=3的LabelFrame会完全覆盖整行。解决方法:naming_frame移到row=7

下一阶段规划

  • 考虑在on_save中增加save_path空值校验提示("请选择保存路径")
  • 考虑API方式下output_mode=feishu_only时save_path可选(不需要本地保存)