编辑 | blame | 历史 | 原始文档

用户绑定车辆功能实现说明

概述

实现了完整的用户绑定车辆功能,包括前端绑定页面、后端API接口、数据库表结构和业务逻辑。

1. 数据库表结构

文件: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) 唯一索引确保不重复绑定

2. 后端接口实现

2.1 Controller层

文件VehicleInfoController.java

新增以下接口:

(1) 绑定车辆接口

POST /system/vehicle/bind

请求参数:
json { "userId": 用户ID, "vehicleId": 车辆ID }

(2) 解绑车辆接口

POST /system/vehicle/unbind

请求参数:
json { "userId": 用户ID, "vehicleId": 车辆ID }

(3) 获取用户绑定车辆接口

GET /system/vehicle/user/bound/{userId}

返回数据:
json { "vehicleId": 车辆ID, "vehicleNumber": "车牌号", "vehicleType": "车辆类型", "vehicleBrand": "车辆品牌", "vehicleModel": "车辆型号" }

2.2 Service层

文件IVehicleInfoService.javaVehicleInfoServiceImpl.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);

}
```

2.3 Mapper层

文件VehicleInfoMapper.javaVehicleInfoMapper.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>

3. 前端实现

3.1 API调用

文件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
}
})
}
```

3.2 绑定车辆页面

文件app/pages/bind-vehicle.vue

主要改进:

(1) 从后端加载车辆列表

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)
  })
}

(2) 调用绑定接口

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)
    })
  })
}

(3) 扫码绑定功能

支持扫描二维码快速绑定车辆(需要在实际使用时配置二维码内容格式)

4. 使用流程

4.1 绑定车辆

  1. 用户进入"绑定车辆"页面
  2. 可以选择:
  • 扫描车辆二维码自动绑定
  • 从下拉列表选择车牌号手动绑定
  1. 确认绑定后:
  • 系统自动解绑用户之前绑定的车辆
  • 绑定新选择的车辆
  • 更新用户信息
  • 返回首页

4.2 获取绑定车辆信息

  • 首页自动加载当前用户绑定的车辆信息
  • 创建任务时自动填充绑定的车辆(普通任务)
  • 个人中心显示绑定的车辆信息

4.3 更换车辆

  1. 用户点击"更换车辆"按钮
  2. 进入绑定车辆页面
  3. 选择新车辆并确认
  4. 系统自动解绑旧车辆,绑定新车辆

5. 数据流程

用户操作
  ↓
前端页面 (bind-vehicle.vue)
  ↓
API调用 (vehicle.js)
  ↓
后端Controller (VehicleInfoController)
  ↓
Service层 (VehicleInfoServiceImpl)
  ├── 解绑所有旧绑定 (unbindAllVehiclesFromUser)
  └── 绑定新车辆 (bindVehicleToUser)
  ↓
Mapper层 (VehicleInfoMapper)
  ↓
数据库操作 (sys_user_vehicle表)
  ↓
返回结果
  ↓
更新用户信息 (Vuex)

6. 注意事项

  1. 权限控制:绑定接口使用@Anonymous注解,允许匿名访问(实际部署时可根据需要调整)
  2. 事务处理:绑定操作使用@Transactional确保数据一致性
  3. 唯一性约束:通过数据库唯一索引和业务逻辑确保一个用户只绑定一辆车
  4. 历史记录:通过status字段保留绑定历史,便于追溯
  5. 错误处理:所有接口都有完善的异常捕获和错误提示

7. 测试建议

7.1 单元测试

  • 测试绑定车辆接口
  • 测试解绑车辆接口
  • 测试获取绑定车辆接口
  • 测试重复绑定同一车辆

7.2 集成测试

  • 测试完整的绑定流程
  • 测试更换车辆流程
  • 测试多用户绑定同一车辆
  • 测试并发绑定场景

7.3 UI测试

  • 测试扫码绑定功能
  • 测试下拉选择绑定功能
  • 测试绑定成功后的页面跳转
  • 测试绑定信息的正确显示

8. 后续优化建议

  1. 二维码生成:为每辆车生成唯一的二维码,便于扫码绑定
  2. 绑定审批:添加绑定审批流程,防止随意绑定
  3. 绑定限制:根据用户角色限制可绑定的车辆类型
  4. 通知推送:绑定/解绑成功后发送通知给相关人员
  5. 数据统计:统计车辆绑定情况,分析车辆使用率