227 lines
6.4 KiB
Markdown
227 lines
6.4 KiB
Markdown
|
|
# 组织架构显示顺序修复总结
|
|||
|
|
|
|||
|
|
## 问题描述
|
|||
|
|
|
|||
|
|
用户观察到在组织架构显示中,"佛山交通运输局"(无下属单位)显示在"三水区服务部门"(有下属单位)之后,导致视觉上容易被误解为"三水区服务部门"的子节点。
|
|||
|
|
|
|||
|
|
## 解决方案
|
|||
|
|
|
|||
|
|
修改了 `lawrisk/services/licensing_repo.py` 中的 `sort_tree` 函数,实现以下排序规则:
|
|||
|
|
|
|||
|
|
### 新的排序规则
|
|||
|
|
|
|||
|
|
```python
|
|||
|
|
nodes.sort(key=lambda x: (
|
|||
|
|
1 if x.get("children") else 0, # 有子节点的排后面 (1),无子节点的排前面 (0)
|
|||
|
|
x.get("name", "") # 名称排序
|
|||
|
|
))
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**规则说明**:
|
|||
|
|
1. **优先级 1**: 没有子节点的部门(叶子节点)排在前面
|
|||
|
|
2. **优先级 2**: 有子节点的部门(父节点)排在后面
|
|||
|
|
3. **优先级 3**: 同类节点按名称字母顺序排序
|
|||
|
|
|
|||
|
|
## 修改前后对比
|
|||
|
|
|
|||
|
|
### ❌ 修改前(按名称排序)
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
市级服务部门
|
|||
|
|
├── 三水区服务部门 - 有下属单位
|
|||
|
|
│ ├── 三水区交通局
|
|||
|
|
│ └── 三水区水利局
|
|||
|
|
├── 佛山交通运输局 - 无下属单位 (容易被误解为上面的子节点)
|
|||
|
|
└── 佛山人力资源和社会保障局 - 无下属单位
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### ✅ 修改后(叶子节点优先)
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
市级服务部门
|
|||
|
|
├── 佛山交通运输局 - 无下属单位 ✅ 清晰显示为同级
|
|||
|
|
├── 佛山人力资源和社会保障局 - 无下属单位 ✅ 清晰显示为同级
|
|||
|
|
├── 佛山住房城乡规划建设局 - 无下属单位 ✅ 清晰显示为同级
|
|||
|
|
└── 三水区服务部门 - 有下属单位 ⬇️ 清晰显示为父节点
|
|||
|
|
├── 三水区交通局
|
|||
|
|
└── 三水区水利局
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 代码修改详情
|
|||
|
|
|
|||
|
|
**文件**: `lawrisk/services/licensing_repo.py`
|
|||
|
|
**函数**: `build_service_department_tree()`
|
|||
|
|
**行数**: 第 2217-2224 行
|
|||
|
|
|
|||
|
|
### 修改前
|
|||
|
|
```python
|
|||
|
|
def sort_tree(nodes: List[Dict[str, Any]]) -> None:
|
|||
|
|
nodes.sort(key=lambda x: x.get("name", ""))
|
|||
|
|
for node in nodes:
|
|||
|
|
if node.get("children"):
|
|||
|
|
sort_tree(node["children"])
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 修改后
|
|||
|
|
```python
|
|||
|
|
def sort_tree(nodes: List[Dict[str, Any]]) -> None:
|
|||
|
|
nodes.sort(key=lambda x: (
|
|||
|
|
1 if x.get("children") else 0, # 叶子节点优先
|
|||
|
|
x.get("name", "") # 名称排序
|
|||
|
|
))
|
|||
|
|
for node in nodes:
|
|||
|
|
if node.get("children"):
|
|||
|
|
sort_tree(node["children"])
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 预期效果
|
|||
|
|
|
|||
|
|
### 视觉效果改进
|
|||
|
|
|
|||
|
|
1. **减少误解**: 无下属单位的市级部门不会被误认为是区级服务部门的子节点
|
|||
|
|
2. **层次清晰**: 有子节点的父节点显示在后面,视觉层次更清晰
|
|||
|
|
3. **符合直觉**: 同级部门中,先显示简单的(叶子节点),再显示复杂的(父节点)
|
|||
|
|
|
|||
|
|
### 层级关系保持不变
|
|||
|
|
|
|||
|
|
**重要**: 这个修改只改变了**显示顺序**,没有改变**层级关系**。
|
|||
|
|
|
|||
|
|
- 三水区服务部门的层级仍然是 Level 1
|
|||
|
|
- 佛山交通运输局的层级仍然是 Level 1
|
|||
|
|
- 两者仍然是同级,都是市级服务部门的直接子节点
|
|||
|
|
|
|||
|
|
## 测试步骤
|
|||
|
|
|
|||
|
|
### 1. 清除浏览器缓存
|
|||
|
|
```
|
|||
|
|
Ctrl + Shift + Delete → 清除"缓存的图片和文件"
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 2. 强制刷新页面
|
|||
|
|
```
|
|||
|
|
Ctrl + F5
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 3. 访问页面
|
|||
|
|
访问 `/fs-ai-asistant/api/workflow/lawrisk/admin/super`
|
|||
|
|
|
|||
|
|
### 4. 验证显示顺序
|
|||
|
|
|
|||
|
|
在"市级服务部门"下,检查:
|
|||
|
|
|
|||
|
|
✅ **无下属单位的市级部门应该排在前面**:
|
|||
|
|
- 佛山交通运输局
|
|||
|
|
- 佛山人力资源和社会保障局
|
|||
|
|
- 佛山住房城乡规划建设局
|
|||
|
|
- 佛山市场监督管理局
|
|||
|
|
- ...
|
|||
|
|
|
|||
|
|
✅ **有下属单位的区级服务部门应该排在后面**:
|
|||
|
|
- 三水区服务部门
|
|||
|
|
- 南海区服务部门
|
|||
|
|
- 顺德区服务部门
|
|||
|
|
- 高明区服务部门
|
|||
|
|
- 禅城区服务部门
|
|||
|
|
|
|||
|
|
### 5. 验证缩进层级
|
|||
|
|
|
|||
|
|
确保所有市级部门(包括"佛山交通运输局")的缩进一致:
|
|||
|
|
- 都是 Level 1
|
|||
|
|
- 缩进都是 30px
|
|||
|
|
|
|||
|
|
## 验证清单
|
|||
|
|
|
|||
|
|
- [ ] 清除浏览器缓存
|
|||
|
|
- [ ] 强制刷新页面 (Ctrl + F5)
|
|||
|
|
- [ ] 检查"市级服务部门"下的显示顺序
|
|||
|
|
- [ ] 确认无下属单位的部门显示在前
|
|||
|
|
- [ ] 确认有下属单位的部门显示在后
|
|||
|
|
- [ ] 验证"佛山交通运输局"的缩进是 Level 1
|
|||
|
|
- [ ] 验证"三水区服务部门"的缩进是 Level 1
|
|||
|
|
- [ ] 确认两者的缩进一致(都是 30px)
|
|||
|
|
- [ ] 测试展开/折叠功能正常
|
|||
|
|
- [ ] 测试拖拽功能正常
|
|||
|
|
- [ ] 测试搜索功能正常
|
|||
|
|
|
|||
|
|
## 其他改进
|
|||
|
|
|
|||
|
|
### 前端调试日志(已添加)
|
|||
|
|
|
|||
|
|
如果需要进一步调试,前端已添加了详细的日志输出(参考 `FRONTEND_DEBUG_GUIDE.md`):
|
|||
|
|
|
|||
|
|
在浏览器控制台可以看到:
|
|||
|
|
- API 返回的完整树形结构
|
|||
|
|
- 每个节点的 level 值
|
|||
|
|
- 渲染时的 indent 计算
|
|||
|
|
- 所有包含"交通运输"和"三水"的部门列表
|
|||
|
|
|
|||
|
|
### 数据库验证脚本
|
|||
|
|
|
|||
|
|
创建了 `verify_org_hierarchy.py` 脚本,可以验证数据库中的层级关系:
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
python verify_org_hierarchy.py
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 技术细节
|
|||
|
|
|
|||
|
|
### Python 排序元组
|
|||
|
|
|
|||
|
|
Python 的 `sort` 方法支持元组排序,会按照元组的元素顺序依次比较:
|
|||
|
|
|
|||
|
|
```python
|
|||
|
|
nodes.sort(key=lambda x: (
|
|||
|
|
1 if x.get("children") else 0, # 第一优先级
|
|||
|
|
x.get("name", "") # 第二优先级
|
|||
|
|
))
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**排序逻辑**:
|
|||
|
|
1. 先比较第一个元素:
|
|||
|
|
- 有子节点的部门 → 1
|
|||
|
|
- 无子节点的部门 → 0
|
|||
|
|
- 0 < 1,所以无子节点的排在前面
|
|||
|
|
2. 第一个元素相同时,比较第二个元素(名称)
|
|||
|
|
|
|||
|
|
### 递归排序
|
|||
|
|
|
|||
|
|
排序函数是递归的,会对整个树的每一层都应用相同的排序规则:
|
|||
|
|
|
|||
|
|
```python
|
|||
|
|
for node in nodes:
|
|||
|
|
if node.get("children"):
|
|||
|
|
sort_tree(node["children"]) # 递归排序子节点
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
这样确保:
|
|||
|
|
- 根节点按照规则排序
|
|||
|
|
- 每个节点的子节点也按照规则排序
|
|||
|
|
- 整个树结构都遵循"叶子节点优先"的原则
|
|||
|
|
|
|||
|
|
## 相关文件
|
|||
|
|
|
|||
|
|
- `lawrisk/services/licensing_repo.py` - 已修改排序逻辑
|
|||
|
|
- `static/super_admin.html` - 已添加调试日志
|
|||
|
|
- `verify_org_hierarchy.py` - 数据库验证脚本
|
|||
|
|
- `FRONTEND_DEBUG_GUIDE.md` - 前端调试指南
|
|||
|
|
|
|||
|
|
## 总结
|
|||
|
|
|
|||
|
|
✅ **已完成**:
|
|||
|
|
- 修改了后端排序逻辑,实现"叶子节点优先"的显示顺序
|
|||
|
|
- 预期可以解决视觉上的层级误解问题
|
|||
|
|
- 没有改变实际的层级关系,只改变了显示顺序
|
|||
|
|
|
|||
|
|
✅ **待测试**:
|
|||
|
|
- 清除浏览器缓存
|
|||
|
|
- 刷新页面查看新的显示顺序
|
|||
|
|
- 验证"佛山交通运输局"和"三水区服务部门"的缩进一致
|
|||
|
|
|
|||
|
|
✅ **额外功能**:
|
|||
|
|
- 前端调试日志已添加,便于后续调试
|
|||
|
|
- 数据库验证脚本已创建,便于验证数据正确性
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
**下一步**: 清除浏览器缓存,刷新页面,查看新的显示顺序是否符合预期。
|