飞书多维表同步工具2026-07-09v4.0.11
列宽显示异常深入修复:schema版本重置+最小宽度保护+stretch=False
bug修复v4.0.11
需求描述
- 数据同步任务板块的状态列默认宽度无法正常显示"就绪"文字
- ERP报表导出各个默认列宽相当离谱,默认只能显示两列的样子
- 虽然可以人工拖动修改列宽并保存,但新用户第一眼看到列宽显示不正常会觉得产品很次
- 要求深入分析根因,调用UI设计技能彻底解决
根因分析
经检查 config/ui_layout.json,发现保存了用户拖动产生的不合理窄值:
sync_tasks.status = 85(无法显示"就绪"二字,至少需90px)sync_tasks.mode = 96、erp_tasks.name = 130、erp_tasks.export_method = 197、erp_tasks.cycle = 169等均不合理
三层根因叠加:
- v4.0.9的
apply_treeview_widths()无条件下发保存值覆盖默认值,且无最小宽度保护——用户拖动产生的任意窄值都会被无脑应用 - 列的
stretch=True(ttk默认)——窗口缩小时列被自动压缩,进一步加剧显示异常 - 无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.py | setup_treeview 调用增加 min_widths 参数:status最小90确保"就绪"完整显示,name最小100,credential最小90,folder最小120 |
tabs/credentials_tab.py | setup_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.py | setup_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 |
技术要点
- schema_version版本重置机制:升级列宽规则时只需将
LAYOUT_SCHEMA_VERSION+1,加载时自动检测版本不匹配并清除旧的treeview_widths,用户无需手动删除配置文件。其他字段(如window_geometry)保留不受影响 - 最小宽度保护三层模型:
- 默认宽度(default_widths):首次打开时显示的理想宽度
- 最小宽度(min_widths):基于内容计算的下限,确保关键文字完整显示(如"就绪"二字≈28px+padding=90px)
- 实际应用值:
max(保存值, 最小宽度),既尊重用户拖动习惯,又防止不合理窄值
- stretch=False:所有列设
stretch=False,防止窗口缩小时列被ttk自动压缩导致文字截断。列宽完全由 width 值决定,不受窗口尺寸影响 - 最小宽度未指定时的兜底:
min_widths未指定的列自动取default_widths的80%作为最小值,避免遗漏
验证结果
自动化测试验证(4项全部通过):
| 测试项 | 预期结果 | 实际结果 | 状态 |
|---|---|---|---|
| schema_version重置机制 | 旧数据清除、新版本号写入、其他字段保留 | schema_version=2写入成功,treeview_widths清除,window_geometry保留 | 通过 |
| 最小宽度保护+stretch=False | status 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.11 | APP_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 值
- 考虑为列宽增加"重置为默认值"右键菜单项,方便用户一键恢复