在绑定车辆功能中,需要限制用户只能绑定与自己同一分公司的车辆,避免跨分公司绑定,确保车辆管理的规范性。
根据项目规范,部门结构如下:
100 (总公司)
├── 101 (深圳分公司) ← 用户A所在分公司
│ ├── 201 (技术部)
│ └── 202 (业务部)
├── 102 (广州分公司) ← 用户B所在分公司
│ ├── 203 (技术部)
│ └── 204 (业务部)
└── 103 (北京分公司)
文件: app/pages/bind-vehicle.vue
问题点:
loadVehicleList() {
this.loading = true
// ❌ 使用默认值 100(总公司),加载所有车辆
const deptId = this.currentUser.deptId || 100
listAvailableVehicles(deptId, 'GENERAL').then(response => {
// ...
})
}
存在的问题:
1. ❌ 当用户的 deptId 为空时,默认使用 100(总公司),会加载所有分公司的车辆
2. ❌ 没有验证 deptId 是否存在
3. ❌ 用户可能看到其他分公司的车辆
4. ❌ 缺少友好的提示信息
修改前:javascript loadVehicleList() { this.loading = true const deptId = this.currentUser.deptId || 100 // ❌ 使用默认值 listAvailableVehicles(deptId, 'GENERAL').then(response => { const vehicleList = response.data || response.rows || [] this.vehicleOptions = vehicleList.map(vehicle => ({ id: vehicle.vehicleId, name: vehicle.vehicleNo, // ... })) this.vehiclePlates = this.vehicleOptions.map(v => v.name) }).catch(error => { this.loading = false console.error('加载车辆列表失败:', error) this.$modal.showToast('加载车辆列表失败') }) }
修改后:
```javascript
loadVehicleList() {
this.loading = true
// ✅ 获取当前用户的部门ID
const deptId = this.currentUser.deptId
// ✅ 验证部门ID是否存在
if (!deptId) {
this.loading = false
console.error('无法获取用户部门信息')
this.$modal.showToast('无法获取用户部门信息')
return
}
// ✅ 使用用户所在的部门ID加载车辆列表
listAvailableVehicles(deptId, 'GENERAL').then(response => {
this.loading = false
const vehicleList = response.data || response.rows || []
// ✅ 提示无可用车辆
if (vehicleList.length === 0) {
console.log('当前分公司暂无可用车辆')
this.$modal.showToast('当前分公司暂无可用车辆')
}
this.vehicleOptions = vehicleList.map(vehicle => ({
id: vehicle.vehicleId,
name: vehicle.vehicleNo,
type: vehicle.vehicleType,
brand: vehicle.vehicleBrand,
model: vehicle.vehicleModel
}))
this.vehiclePlates = this.vehicleOptions.map(v => v.name)
// ✅ 记录日志
console.log(`加载了 ${vehicleList.length} 辆车辆(部门ID: ${deptId})`)
}).catch(error => {
this.loading = false
console.error('加载车辆列表失败:', error)
this.$modal.showToast('加载车辆列表失败')
})
}
```
deptId 是否存在,不使用默认值用户信息:javascript { userId: 1, userName: "张三", deptId: 101, // 深圳分公司 deptName: "深圳分公司" }
操作流程:
1. 用户张三打开绑定车辆页面
2. 系统使用 deptId: 101 查询车辆
3. 只返回深圳分公司的车辆列表
显示结果:
```
车牌号下拉列表:
- 粤A12345 (深圳分公司)
- 粤A67890 (深圳分公司)
- 粤A11111 (深圳分公司)
❌ 不显示:
- 粤B12345 (广州分公司)
- 京A12345 (北京分公司)
```
用户信息:javascript { userId: 2, userName: "李四", deptId: 102, // 广州分公司 deptName: "广州分公司" }
显示结果:
```
车牌号下拉列表:
- 粤B12345 (广州分公司)
- 粤B67890 (广州分公司)
❌ 不显示:
- 粤A12345 (深圳分公司)
- 京A12345 (北京分公司)
```
用户信息:javascript { userId: 3, userName: "王五", deptId: null // 无部门信息 }
操作流程:
1. 用户王五打开绑定车辆页面
2. 系统检测到 deptId 为空
3. 显示提示:"无法获取用户部门信息"
4. 不加载任何车辆
显示结果:
```
车牌号下拉列表:
- 请选择车牌号 (空列表,无法选择)
提示信息:无法获取用户部门信息
```
用户信息:javascript { userId: 4, userName: "赵六", deptId: 103, // 北京分公司 deptName: "北京分公司" }
假设:北京分公司目前没有车辆
显示结果:
```
车牌号下拉列表:
- 请选择车牌号 (空列表)
提示信息:当前分公司暂无可用车辆
```
sequenceDiagram
participant User as 用户
participant Page as 绑定车辆页面
participant Vuex as Vuex Store
participant API as 后端API
User->>Page: 打开绑定车辆页面
Page->>Vuex: 获取 currentUser.deptId
alt deptId 存在
Vuex-->>Page: 返回 deptId: 101
Page->>API: listAvailableVehicles(101, 'GENERAL')
alt 有车辆数据
API-->>Page: 返回深圳分公司的车辆列表
Page-->>User: 显示车辆列表
else 无车辆数据
API-->>Page: 返回空列表
Page-->>User: 提示:当前分公司暂无可用车辆
end
else deptId 不存在
Vuex-->>Page: 返回 null
Page-->>User: 提示:无法获取用户部门信息
end
export function listAvailableVehicles(deptId, taskType) {
return request({
url: '/task/vehicle/available',
method: 'get',
params: {
deptId: deptId, // 部门ID,用于过滤车辆
taskType: taskType // 任务类型
}
})
}
后端接口: /task/vehicle/available
请求示例: GET /task/vehicle/available?deptId=101&taskType=GENERAL
响应示例:json { "code": 200, "msg": "查询成功", "data": [ { "vehicleId": 1, "vehicleNo": "粤A12345", "vehicleType": "救护车", "vehicleBrand": "福特", "vehicleModel": "全顺", "deptId": 101, "deptName": "深圳分公司" }, { "vehicleId": 2, "vehicleNo": "粤A67890", "vehicleType": "救护车", "vehicleBrand": "丰田", "vehicleModel": "海狮", "deptId": 101, "deptName": "深圳分公司" } ] }
无车辆时:json { "code": 200, "msg": "查询成功", "data": [] }
deptId,不使用默认值建议在后端接口中增加以下验证:
// 验证请求的 deptId 是否与用户的 deptId 一致
@GetMapping("/available")
public AjaxResult listAvailableVehicles(@RequestParam Long deptId, @RequestParam String taskType) {
LoginUser loginUser = SecurityUtils.getLoginUser();
Long userDeptId = loginUser.getUser().getDeptId();
// ✅ 验证部门权限
if (!deptId.equals(userDeptId)) {
return error("无权查询其他部门的车辆");
}
// 查询车辆列表...
}
// 测试用例1:深圳分公司用户
{
userId: 1,
deptId: 101,
expectedVehicles: ['粤A12345', '粤A67890'], // 只有深圳的车
notExpectedVehicles: ['粤B12345', '京A12345'] // 不应包含其他分公司
}
// 测试用例2:广州分公司用户
{
userId: 2,
deptId: 102,
expectedVehicles: ['粤B12345', '粤B67890'], // 只有广州的车
notExpectedVehicles: ['粤A12345', '京A12345'] // 不应包含其他分公司
}
控制台输出:
加载了 3 辆车辆(部门ID: 101)
控制台输出:
无法获取用户部门信息
用户看到:
Toast提示:无法获取用户部门信息
控制台输出:
当前分公司暂无可用车辆
用户看到:
Toast提示:当前分公司暂无可用车辆
app/pages/bind-vehicle.vue - 绑定车辆页面app/api/vehicle.js - 车辆 APIapp/store/modules/user.js - Vuex 用户状态在车辆列表中显示车辆所属分公司:
<picker mode="selector" :range="vehiclePlates" @change="onVehiclePlateChange">
<view class="form-input picker-input">
<text v-if="selectedVehiclePlate">
{{ selectedVehiclePlate }} ({{ currentUser.deptName }})
</text>
<text v-else>请选择车牌号</text>
<uni-icons type="arrowright" size="16" color="#999"></uni-icons>
</view>
</picker>
选择车辆后显示车辆详细信息:
<view v-if="selectedVehicleId" class="vehicle-detail">
<text>车辆类型:{{ selectedVehicleType }}</text>
<text>车辆品牌:{{ selectedVehicleBrand }}</text>
<text>车辆型号:{{ selectedVehicleModel }}</text>
</view>
缓存车辆列表,避免重复请求:
// 使用本地缓存
const cacheKey = `vehicle_list_${deptId}`
const cachedData = storage.get(cacheKey)
if (cachedData && Date.now() - cachedData.timestamp < 5 * 60 * 1000) {
// 5分钟内使用缓存
this.vehicleOptions = cachedData.data
} else {
// 请求新数据并缓存
listAvailableVehicles(deptId, 'GENERAL').then(response => {
const data = response.data || []
storage.set(cacheKey, {
data: data,
timestamp: Date.now()
})
})
}
通过本次优化,实现了以下目标:
核心价值:
- 提高了数据安全性
- 规范了车辆管理流程
- 提升了用户体验
- 便于后续维护和扩展
| 版本 | 日期 | 修改内容 | 修改人 |
|---|
| 1.0 | 2025-10-15 | 实现绑定车辆部门过滤功能 | - |