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

列宽显示异常深入修复:schema版本重置+最小宽度保护+stretch=False

bug修复v4.0.11

需求描述

  1. 数据同步任务板块的状态列默认宽度无法正常显示"就绪"文字
  2. ERP报表导出各个默认列宽相当离谱,默认只能显示两列的样子
  3. 虽然可以人工拖动修改列宽并保存,但新用户第一眼看到列宽显示不正常会觉得产品很次
  4. 要求深入分析根因,调用UI设计技能彻底解决

根因分析

经检查 config/ui_layout.json,发现保存了用户拖动产生的不合理窄值:

  • sync_tasks.status = 85(无法显示"就绪"二字,至少需90px)
  • sync_tasks.mode = 96erp_tasks.name = 130erp_tasks.export_method = 197erp_tasks.cycle = 169 等均不合理

三层根因叠加

  1. v4.0.9的apply_treeview_widths()无条件下发保存值覆盖默认值,且无最小宽度保护——用户拖动产生的任意窄值都会被无脑应用
  2. 列的stretch=True(ttk默认)——窗口缩小时列被自动压缩,进一步加剧显示异常
  3. 无schema版本机制——升级列宽规则后,旧的不合理保存值无法被自动清除

改动文件清单

文件改动内容
utils/ui_layout.py新增 LAYOUT_SCHEMA_VERSION=2 常量;_load_layout_data() 增加schema版本检查,不匹配时清除旧 treeview_widths 并写入新版本号;_save_layout_data() 确保schema_version字段存在;apply_treeview_widths() 增加 min_widths 参数,所有列设 stretch=False,应用值取 max(保存值, 最小宽度)setup_treeview() 增加 min_widths 参数透传
tabs/sync_tasks_tab.pysetup_treeview 调用增加 min_widths 参数:status最小90确保"就绪"完整显示,name最小100,credential最小90,folder最小120
tabs/credentials_tab.pysetup_treeview 调用增加 min_widths 参数:name最小80,platform最小70,type最小70,account最小90,table_token最小100,status最小60
tabs/erp_report_tab.py重新校准默认列宽:name 180→200、report_type 140→160;增加 min_widths 参数:name最小120,report_type最小100,export_method最小65,cycle最小55,status最小60
tabs/log_center_tab.pysetup_treeview 调用增加 min_widths 参数:time最小135确保"2026-07-09 10:30:45"完整显示,level最小50,source最小70,message最小200
gui_sync.py版本号 4.0.10 → 4.0.11

技术要点

  1. schema_version版本重置机制:升级列宽规则时只需将 LAYOUT_SCHEMA_VERSION +1,加载时自动检测版本不匹配并清除旧的 treeview_widths,用户无需手动删除配置文件。其他字段(如 window_geometry)保留不受影响
  2. 最小宽度保护三层模型
    • 默认宽度(default_widths):首次打开时显示的理想宽度
    • 最小宽度(min_widths):基于内容计算的下限,确保关键文字完整显示(如"就绪"二字≈28px+padding=90px)
    • 实际应用值:max(保存值, 最小宽度),既尊重用户拖动习惯,又防止不合理窄值
  3. stretch=False:所有列设 stretch=False,防止窗口缩小时列被ttk自动压缩导致文字截断。列宽完全由 width 值决定,不受窗口尺寸影响
  4. 最小宽度未指定时的兜底min_widths 未指定的列自动取 default_widths 的80%作为最小值,避免遗漏

验证结果

自动化测试验证(4项全部通过):

测试项预期结果实际结果状态
schema_version重置机制旧数据清除、新版本号写入、其他字段保留schema_version=2写入成功,treeview_widths清除,window_geometry保留通过
最小宽度保护+stretch=Falsestatus 85→90、name 80→100、folder 100→120、select 40保持、所有列stretch=False全部符合预期,Treeview实际列宽与应用值一致通过
各Tab min_widths配置4个Tab均已配置min_widths且tree_id正确sync_tasks/credentials/erp_tasks/log_center全部配置完成通过
版本号4.0.11APP_VERSION="4.0.11"、APP_VERSION_NUM=40011已升级通过

语法检查:6个文件(utils/ui_layout.py、4个tab、gui_sync.py)全部通过 py_compile

踩坑与解决

  • v4.0.9只做了"持久化"没做"保护":当时 apply_treeview_widths() 无条件下发保存值覆盖默认值,等于把用户拖动的任意窄值都当成了"用户意图"来尊重,结果用户拖窄后下次打开就显示异常。v4.0.11增加最小宽度保护,既尊重用户拖动(保存值大于最小宽度时用保存值),又兜底防止不合理窄值(保存值小于最小宽度时用最小宽度)
  • ttk Treeview的stretch默认True是隐藏陷阱:窗口缩小时ttk会自动压缩所有 stretch=True 的列来塞进可见区域,导致即使设置了合理的 width 也会被压缩。本次统一设 stretch=False,列宽完全由 width 决定

下一阶段规划

  • 观察v4.0.11上线后用户实际列宽使用情况,必要时调整 min_widths 值
  • 考虑为列宽增加"重置为默认值"右键菜单项,方便用户一键恢复