在车辆查询时,无论用户传入的是分公司ID还是子部门ID(如技术部、业务部),系统都会自动查找其所属的分公司,并返回该分公司的车辆。
100 (总公司)
├── 101 (深圳分公司) ← 车辆归属于分公司
│ ├── 201 (技术部) ← 用户可能属于子部门
│ ├── 202 (业务部)
│ └── 203 (财务部)
├── 102 (广州分公司)
│ ├── 204 (技术部)
│ ├── 205 (业务部)
│ └── 206 (财务部)
└── 103 (北京分公司)
├── 207 (技术部)
└── 208 (业务部)
原有逻辑:
- 用户A(技术部,deptId=201)查询车辆
- 系统查询:WHERE dept_id = 201
- 结果:❌ 查不到车辆(因为车辆的dept_id=101,不是201)
期望逻辑:
- 用户A(技术部,deptId=201)查询车辆
- 系统自动找到分公司:201 → 101(深圳分公司)
- 系统查询:WHERE dept_id = 101
- 结果:✅ 查到深圳分公司的所有车辆
<!-- 部门过滤:自动查找传入部门所属的分公司(parent_id=100) -->
<if test="deptId != null">
and v.dept_id = (
<!-- 如果传入的就是分公司(parent_id=100),直接返回 -->
select case
when exists(select 1 from sys_dept where dept_id = #{deptId} and parent_id = 100)
then #{deptId}
else (
<!-- 否则从 ancestors 中查找分公司ID -->
select d.dept_id
from sys_dept d
where d.parent_id = 100
and FIND_IN_SET(d.dept_id, (
select ancestors from sys_dept where dept_id = #{deptId}
))
limit 1
)
end
)
</if>
when exists(select 1 from sys_dept where dept_id = #{deptId} and parent_id = 100)
deptId 的 parent_id = 100,说明传入的就是分公司deptId 查询select d.dept_id
from sys_dept d
where d.parent_id = 100
and FIND_IN_SET(d.dept_id, (
select ancestors from sys_dept where dept_id = #{deptId}
))
原理:
- 每个部门的 ancestors 字段存储了所有上级部门ID(用逗号分隔)
- 例如:技术部(201)的 ancestors 可能是 "100,101,201"
- 使用 FIND_IN_SET 在 ancestors 中查找 parent_id=100 的部门
- 找到的就是分公司ID
输入:javascript deptId: 101 // 深圳分公司
SQL执行:sql -- 检查:101 的 parent_id = 100 ✅ -- 直接使用:dept_id = 101 WHERE v.dept_id = 101
结果:✅ 返回深圳分公司的所有车辆
输入:javascript deptId: 201 // 深圳分公司-技术部
数据:sql -- sys_dept 表数据 dept_id | parent_id | ancestors 101 | 100 | 100,101 201 | 101 | 100,101,201
SQL执行:sql -- 1. 检查:201 的 parent_id = 100 ❌ -- 2. 查询 ancestors:select ancestors from sys_dept where dept_id = 201 -- 结果:"100,101,201" -- 3. 在 ancestors 中查找 parent_id=100 的部门 -- FIND_IN_SET(d.dept_id, "100,101,201") and d.parent_id = 100 -- 找到:101 -- 4. 使用:dept_id = 101 WHERE v.dept_id = 101
结果:✅ 返回深圳分公司的所有车辆
输入:javascript deptId: 301 // 深圳分公司-技术部-开发组
数据:sql -- sys_dept 表数据 dept_id | parent_id | ancestors 101 | 100 | 100,101 201 | 101 | 100,101,201 301 | 201 | 100,101,201,301
SQL执行:sql -- 1. 检查:301 的 parent_id = 100 ❌ -- 2. 查询 ancestors:"100,101,201,301" -- 3. 在 ancestors 中查找 parent_id=100 的部门 -- 找到:101 -- 4. 使用:dept_id = 101 WHERE v.dept_id = 101
结果:✅ 返回深圳分公司的所有车辆
用户:技术部员工(deptId=201)
// 前端调用
listAvailableVehicles(201, 'GENERAL')
// 后端查询
SELECT * FROM tb_vehicle_info v
WHERE v.dept_id = (
-- 自动找到分公司:201 → 101
...
)
结果:显示深圳分公司的所有车辆
用户:业务部员工(deptId=202)
// 前端调用
listAvailableVehicles(202, 'EMERGENCY')
// 后端查询
SELECT * FROM tb_vehicle_info v
WHERE v.dept_id = (
-- 自动找到分公司:202 → 101
...
)
结果:显示深圳分公司的所有车辆
sequenceDiagram
participant User as 用户(技术部)
participant Page as 前端页面
participant API as 后端API
participant DB as 数据库
User->>Page: 打开绑定车辆页面
Page->>Page: 获取用户部门ID: 201
Page->>API: listAvailableVehicles(201, 'GENERAL')
API->>DB: SELECT dept_id FROM sys_dept WHERE dept_id=201
DB-->>API: parent_id=101 (不是100)
API->>DB: SELECT ancestors FROM sys_dept WHERE dept_id=201
DB-->>API: "100,101,201"
API->>DB: FIND_IN_SET in ancestors WHERE parent_id=100
DB-->>API: 找到分公司ID: 101
API->>DB: SELECT * FROM tb_vehicle_info WHERE dept_id=101
DB-->>API: 深圳分公司的车辆列表
API-->>Page: 返回车辆数据
Page-->>User: 显示深圳分公司的车辆
| 输入deptId | 部门类型 | 查询结果 |
|---|---|---|
| 101 | 分公司 | 101的车辆 ✅ |
| 201 | 子部门 | 101的车辆 ✅ |
| 301 | 孙部门 | 101的车辆 ✅ |
| 401 | 曾孙部门 | 101的车辆 ✅ |
| 输入deptId | 说明 | 查询结果 |
|---|---|---|
| 100 | 总公司 | ❌ 查不到(车辆必须归属于分公司) |
| null | 空值 | ❌ 不执行部门过滤 |
为了提高查询性能,建议在 sys_dept 表添加索引:
-- 部门表索引
CREATE INDEX idx_parent_id ON sys_dept(parent_id);
CREATE INDEX idx_ancestors ON sys_dept(ancestors(100));
-- 车辆表索引(已存在)
CREATE INDEX idx_dept_id ON tb_vehicle_info(dept_id);
CASE WHEN 减少子查询次数LIMIT 1 限制结果集FIND_IN_SET 利用索引查询-- 模拟输入:deptId = 101
SELECT * FROM tb_vehicle_info v
WHERE v.dept_id = (
select case
when exists(select 1 from sys_dept where dept_id = 101 and parent_id = 100)
then 101
else (...)
end
)
-- 结果:dept_id = 101
-- 模拟输入:deptId = 201
SELECT * FROM tb_vehicle_info v
WHERE v.dept_id = (
select case
when exists(select 1 from sys_dept where dept_id = 201 and parent_id = 100)
then 201
else (
select d.dept_id
from sys_dept d
where d.parent_id = 100
and FIND_IN_SET(d.dept_id, (
select ancestors from sys_dept where dept_id = 201
))
limit 1
)
end
)
-- 结果:dept_id = 101
VehicleInfoMapper.xml - 车辆查询MapperselectVehicleInfoList 的地方sys_dept 表的 ancestors 字段正确维护更新时间: 2025-10-25
版本: v1.0
状态: ✅ 已实现