实现了完整的用户绑定车辆功能,包括前端绑定页面、后端API接口、数据库表结构和业务逻辑。
sql/user_vehicle_bind.sql创建了用户车辆绑定表 sys_user_vehicle:
CREATE TABLE IF NOT EXISTS sys_user_vehicle (
id BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
user_id BIGINT(20) NOT NULL COMMENT '用户ID',
vehicle_id BIGINT(20) NOT NULL COMMENT '车辆ID',
bind_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '绑定时间',
bind_by VARCHAR(64) DEFAULT '' COMMENT '绑定操作人',
status CHAR(1) DEFAULT '0' COMMENT '绑定状态(0正常 1解绑)',
remark VARCHAR(500) DEFAULT NULL COMMENT '备注',
create_by VARCHAR(64) DEFAULT '' COMMENT '创建者',
create_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
update_by VARCHAR(64) DEFAULT '' COMMENT '更新者',
update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (id),
UNIQUE KEY idx_user_vehicle (user_id, vehicle_id),
KEY idx_user_id (user_id),
KEY idx_vehicle_id (vehicle_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户车辆绑定表';
业务规则:
- 一个用户同时只能绑定一辆车辆(通过业务逻辑控制)
- 一辆车辆可以被多个用户绑定(如司机轮班)
- status='0'表示当前绑定有效,'1'表示已解绑
- 通过 (user_id, vehicle_id) 唯一索引确保不重复绑定
文件:VehicleInfoController.java
新增以下接口:
POST /system/vehicle/bind
请求参数:json { "userId": 用户ID, "vehicleId": 车辆ID }
POST /system/vehicle/unbind
请求参数:json { "userId": 用户ID, "vehicleId": 车辆ID }
GET /system/vehicle/user/bound/{userId}
返回数据:json { "vehicleId": 车辆ID, "vehicleNumber": "车牌号", "vehicleType": "车辆类型", "vehicleBrand": "车辆品牌", "vehicleModel": "车辆型号" }
文件:IVehicleInfoService.java 和 VehicleInfoServiceImpl.java
新增方法:
- bindVehicleToUser(userId, vehicleId) - 绑定车辆到用户
- unbindVehicleFromUser(userId, vehicleId) - 解绑用户车辆
- getUserBoundVehicle(userId) - 获取用户当前绑定的车辆
业务逻辑:
```java
@Transactional
public int bindVehicleToUser(Long userId, Long vehicleId) {
// 先解绑用户的所有车辆(确保一个用户只绑定一辆车)
vehicleInfoMapper.unbindAllVehiclesFromUser(userId);
// 绑定新车辆
String bindBy = SecurityUtils.getUsername();
return vehicleInfoMapper.bindVehicleToUser(userId, vehicleId, bindBy);
}
```
文件:VehicleInfoMapper.java 和 VehicleInfoMapper.xml
新增Mapper方法:
// 绑定车辆到用户
public int bindVehicleToUser(@Param("userId") Long userId,
@Param("vehicleId") Long vehicleId,
@Param("bindBy") String bindBy);
// 解绑用户车辆
public int unbindVehicleFromUser(@Param("userId") Long userId,
@Param("vehicleId") Long vehicleId);
// 解绑用户的所有车辆
public int unbindAllVehiclesFromUser(@Param("userId") Long userId);
// 获取用户当前绑定的车辆
public VehicleInfo getUserBoundVehicle(@Param("userId") Long userId);
新增SQL映射:
<!-- 绑定车辆到用户 -->
<insert id="bindVehicleToUser">
INSERT INTO sys_user_vehicle (user_id, vehicle_id, bind_time, bind_by, status, create_by, create_time)
VALUES (#{userId}, #{vehicleId}, NOW(), #{bindBy}, '0', #{bindBy}, NOW())
</insert>
<!-- 解绑用户车辆 -->
<update id="unbindVehicleFromUser">
UPDATE sys_user_vehicle
SET status = '1', update_time = NOW()
WHERE user_id = #{userId} AND vehicle_id = #{vehicleId} AND status = '0'
</update>
<!-- 解绑用户的所有车辆 -->
<update id="unbindAllVehiclesFromUser">
UPDATE sys_user_vehicle
SET status = '1', update_time = NOW()
WHERE user_id = #{userId} AND status = '0'
</update>
<!-- 获取用户当前绑定的车辆 -->
<select id="getUserBoundVehicle" resultMap="VehicleInfoResult">
SELECT v.*
FROM tb_vehicle_info v
INNER JOIN sys_user_vehicle uv ON v.vehicle_id = uv.vehicle_id
WHERE uv.user_id = #{userId} AND uv.status = '0'
ORDER BY uv.bind_time DESC
LIMIT 1
</select>
文件:app/api/vehicle.js
已有接口定义:
```javascript
// 绑定车辆到用户
export function bindVehicleToUser(userId, vehicleId) {
return request({
url: '/vehicle/bind',
method: 'post',
data: {
userId: userId,
vehicleId: vehicleId
}
})
}
// 解绑用户车辆
export function unbindVehicleFromUser(userId, vehicleId) {
return request({
url: '/vehicle/unbind',
method: 'post',
data: {
userId: userId,
vehicleId: vehicleId
}
})
}
```
文件:app/pages/bind-vehicle.vue
主要改进:
loadVehicleList() {
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,
type: vehicle.vehicleType,
brand: vehicle.vehicleBrand,
model: vehicle.vehicleModel
}))
this.vehiclePlates = this.vehicleOptions.map(v => v.name)
})
}
bindVehicle() {
if (!this.selectedVehiclePlate || !this.selectedVehicleId) {
this.$modal.showToast('请选择车牌号')
return
}
this.$modal.confirm('确认绑定车辆 ' + this.selectedVehiclePlate + ' 吗?').then(() => {
const userId = this.currentUser.userId
bindVehicleToUser(userId, this.selectedVehicleId).then(response => {
this.$modal.showToast('车辆绑定成功')
// 更新Vuex中的用户信息
this.$store.dispatch('GetInfo')
// 返回上一页
setTimeout(() => {
this.$tab.navigateBack()
}, 1500)
})
})
}
支持扫描二维码快速绑定车辆(需要在实际使用时配置二维码内容格式)
用户操作
↓
前端页面 (bind-vehicle.vue)
↓
API调用 (vehicle.js)
↓
后端Controller (VehicleInfoController)
↓
Service层 (VehicleInfoServiceImpl)
├── 解绑所有旧绑定 (unbindAllVehiclesFromUser)
└── 绑定新车辆 (bindVehicleToUser)
↓
Mapper层 (VehicleInfoMapper)
↓
数据库操作 (sys_user_vehicle表)
↓
返回结果
↓
更新用户信息 (Vuex)