Add sorting capability for "选择" and "材料名称" columns in the CheckboxTreeview: - Click column header to cycle through: asc (↑) → desc (↓) → unsort - Sort "选择" column by checkbox state (checked/unchecked) - Sort "材料名称" column alphabetically - Preserve checkbox states during sorting using move() instead of delete+insert - Separate event handlers for cell clicks and heading clicks Implementation details: - Added 6 new helper methods to CheckboxTreeview class - Store original headings to properly display sort arrows - Use identify_region() to distinguish between cell and heading clicks - Column index conversion (#1/#2) to column identifiers The sorting is a pure frontend feature with no database changes. Available to all users without permission restrictions. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
178 lines
5.7 KiB
Markdown
178 lines
5.7 KiB
Markdown
# CheckboxTreeview 排序功能实施总结
|
||
|
||
## 实施日期
|
||
2026-02-24
|
||
|
||
## 功能概述
|
||
为物料校验界面的校验结果表格添加了排序功能,支持对"选择"和"材料名称"列进行升序、降序排序,并可取消排序。
|
||
|
||
## 修改文件
|
||
- `D:\python\playwrite\gui\material_validation_tab.py`
|
||
|
||
## 修改内容
|
||
|
||
### 1. CheckboxTreeview.__init__ 方法(第35-60行)
|
||
|
||
**新增变量**:
|
||
```python
|
||
# 排序状态
|
||
self.sort_column = None # 当前排序列的列标识符
|
||
self.sort_direction = None # 'asc', 'desc', 或 None
|
||
self.sortable_columns = ["选择", "材料名称"] # 可排序的列白名单
|
||
self.original_headings = {} # 存储原始列标题文本(不含箭头)
|
||
|
||
# 存储原始列标题(延迟执行以确保标题已设置)
|
||
self.after(100, self._store_original_headings)
|
||
|
||
# 绑定表头点击事件
|
||
self.bind("<ButtonRelease-1>", self._on_heading_click)
|
||
```
|
||
|
||
### 2. CheckboxTreeview._on_click 方法(第62-83行)
|
||
|
||
**修改内容**:
|
||
- 添加注释说明仅处理单元格点击,不处理表头点击
|
||
- 确保与表头点击事件分离,避免冲突
|
||
|
||
### 3. 新增方法
|
||
|
||
#### _store_original_headings(第142-145行)
|
||
存储原始列标题文本,避免排序箭头影响后续操作。
|
||
|
||
#### _get_column_id_from_column_index(第147-160行)
|
||
将列索引('#1', '#2')转换为列标识符('选择', '材料名称')。
|
||
|
||
#### _on_heading_click(第162-172行)
|
||
处理表头点击事件,触发排序操作。仅对可排序列("选择"、"材料名称")生效。
|
||
|
||
#### _toggle_sort(第174-204行)
|
||
切换排序状态的核心方法:
|
||
- 同一列:asc → desc → None(循环)
|
||
- 不同列:重置为升序
|
||
- 调用排序方法并更新表头显示
|
||
|
||
#### _sort_by_column(第206-237行)
|
||
执行实际排序操作:
|
||
- 收集所有项目的数据和复选框状态
|
||
- 根据列类型使用不同的排序逻辑
|
||
- 使用 `move()` 方法保留项目ID和复选框状态
|
||
|
||
**排序逻辑**:
|
||
- **"选择"列**: 按复选框状态排序(False 未选中在前 → True 选中在前)
|
||
- **"材料名称"列**: 按字符串字母顺序排序
|
||
|
||
#### _update_heading_display(第239-248行)
|
||
更新列标题显示:
|
||
- 排序列:显示原始标题 + 箭头(↑ 升序,↓ 降序)
|
||
- 非排序列:显示原始标题
|
||
|
||
## 排序行为
|
||
|
||
### "选择"列
|
||
- **升序 (↑)**: 未选中 (☐) → 选中 (☑)
|
||
- **降序 (↓)**: 选中 (☑) → 未选中 (☐)
|
||
|
||
### "材料名称"列
|
||
- **升序 (↑)**: A → Z 字母顺序
|
||
- **降序 (↓)**: Z → A 字母顺序
|
||
|
||
### 点击循环
|
||
1. 第一次点击: 升序(显示 ↑)
|
||
2. 第二次点击: 降序(显示 ↓)
|
||
3. 第三次点击: 取消排序(移除箭头)
|
||
|
||
## 技术要点
|
||
|
||
### 1. 使用 move() 而非 delete() + insert()
|
||
- `delete()` 会删除项目及其关联的复选框状态
|
||
- `move()` 仅改变项目位置,保留项目ID
|
||
- 项目ID与 `self.checkboxes` 字典中的复选框状态关联
|
||
- 使用 `move()` 可自动保持复选框状态
|
||
|
||
### 2. 事件绑定策略
|
||
- `<Button-1>`: 现有复选框点击事件(在 `_on_click` 中处理)
|
||
- `<ButtonRelease-1>`: 新增的表头点击事件(在 `_on_heading_click` 中处理)
|
||
- 使用 `identify_region` 区分点击区域("cell" vs "heading")
|
||
|
||
### 3. 延迟存储原始标题
|
||
```python
|
||
self.after(100, self._store_original_headings)
|
||
```
|
||
确保在 Treeview 标题设置完成后再存储,避免获取空值。
|
||
|
||
### 4. 复选框状态保持
|
||
排序过程中:
|
||
1. 收集所有项目的 `item_id` 和 `checkbox_state`
|
||
2. 对数据列表进行排序
|
||
3. 使用 `move()` 重新排列项目
|
||
4. `self.checkboxes` 字典自动保持正确状态(key 是 item_id)
|
||
|
||
## 兼容性
|
||
|
||
### 向后兼容
|
||
- ✅ 所有现有功能保持不变
|
||
- ✅ 复选框点击功能正常
|
||
- ✅ 全选/取消全选功能正常
|
||
- ✅ 复选框状态同步功能正常
|
||
- ✅ 双击编辑负责人功能正常
|
||
|
||
### 无权限限制
|
||
- ✅ 适用于所有用户(管理员和普通用户)
|
||
- ✅ 无需修改权限控制代码
|
||
|
||
## 测试建议
|
||
|
||
### 功能测试
|
||
1. **"选择"列排序**:
|
||
- 点击列头 → 未选中项目排到最前面
|
||
- 再次点击 → 选中项目排到最前面
|
||
- 第三次点击 → 箭头消失
|
||
|
||
2. **"材料名称"列排序**:
|
||
- 点击列头 → 按字母 A-Z 升序排列
|
||
- 再次点击 → 按字母 Z-A 降序排列
|
||
- 第三次点击 → 箭头消失
|
||
|
||
3. **复选框状态保持**:
|
||
- 选中几个项目
|
||
- 进行排序
|
||
- 验证复选框状态保持不变
|
||
|
||
4. **跨列切换**:
|
||
- 在"选择"列排序后,点击"材料名称"列
|
||
- 验证"选择"列箭头消失,"材料名称"列显示箭头
|
||
- 验证按新的列排序
|
||
|
||
5. **复选框点击兼容性**:
|
||
- 排序后点击复选框
|
||
- 验证复选框状态切换功能正常
|
||
|
||
### 边界情况测试
|
||
1. **空表格**: 排序不应报错
|
||
2. **单行数据**: 排序不应报错
|
||
3. **所有项目相同值**: 排序不应改变顺序
|
||
4. **中文字符排序**: 验证中文排序正确
|
||
5. **动态添加数据**: 排序后添加新数据,验证排序状态保持
|
||
|
||
## 风险评估
|
||
- **低风险**: 仅影响 CheckboxTreeview 的显示和交互
|
||
- **向后兼容**: 所有现有功能保持不变
|
||
- **无数据库改动**: 纯前端排序功能
|
||
- **可测试性**: 容易手动测试验证
|
||
|
||
## 预期效果
|
||
用户可以通过点击"选择"或"材料名称"列头,快速对数据进行排序,提高数据查看和分析效率。排序状态通过箭头直观显示,符合常见 UI 交互习惯。
|
||
|
||
## 测试文件
|
||
已创建测试脚本:`tests/test_sorting.py`
|
||
|
||
运行测试:
|
||
```bash
|
||
python tests/test_sorting.py
|
||
```
|
||
|
||
## 后续优化建议
|
||
1. 可扩展到其他列的排序(如"负责人"、"材料代码"等)
|
||
2. 可添加多列排序功能(按住 Shift 点击第二列)
|
||
3. 可添加排序持久化(记住用户的排序偏好)
|