# 设备绑定功能实现说明 ## 实现功能 ### 1. 选中设备自动绑定运送清单 当用户在创建运送清单时选择设备后,系统会自动更新 `iot_device_data` 表中以下字段: - `delivery_id`:运送清单ID - `car_number`:车牌号 ### 2. 已绑定设备过滤 在下一个运送清单创建时,已绑定的设备(`delivery_id` 不为空)将不会出现在可选设备列表中。 ## 修改内容 ### 后端修改 #### 1. DeliveryDeviceController.java **文件位置**: `tradeCattle/aiotagro-cattle-trade/src/main/java/com/aiotagro/cattletrade/business/controller/DeliveryDeviceController.java` **修改的方法**: ##### updateDeviceDeliveryId (第347-404行) ```java /** * 更新设备delivery_id、weight和car_number */ @PostMapping(value = "/updateDeviceDeliveryId") public AjaxResult updateDeviceDeliveryId(@RequestBody Map params) { String deviceId = (String) params.get("deviceId"); Integer deliveryId = (Integer) params.get("deliveryId"); Double weight = params.get("weight") != null ? Double.valueOf(params.get("weight").toString()) : null; String carNumber = (String) params.get("carNumber"); // 新增:接收车牌号参数 // ... 更新逻辑 // 设置delivery_id(可以是null) updateWrapper.set(IotDeviceData::getDeliveryId, deliveryId); // 设置car_number(可以是null)- 新增 updateWrapper.set(IotDeviceData::getCarNumber, carNumber); // 设置weight(如果有值) if (weight != null) { updateWrapper.set(IotDeviceData::getWeight, weight); } } ``` ##### clearDeliveryId (第462-499行) ```java /** * 清空设备delivery_id、car_number和weight */ @PostMapping(value = "/clearDeliveryId") public AjaxResult clearDeliveryId(@RequestBody Map params) { // ... 清空逻辑 // 将delivery_id、car_number和weight都设置为null device.setDeliveryId(null); device.setCarNumber(null); // 新增:清空车牌号 device.setWeight(null); } ``` #### 2. IotDeviceProxyController.java **文件位置**: `tradeCattle/aiotagro-cattle-trade/src/main/java/com/aiotagro/cattletrade/business/controller/IotDeviceProxyController.java` **修改的方法**: ##### queryList (第42-167行) ```java @PostMapping("/queryList") public AjaxResult queryList(@RequestBody Map params) { // 构建查询条件 QueryWrapper queryWrapper = new QueryWrapper<>(); // 根据设备类型查询(用于创建运送清单时过滤设备)- 新增 if (params.containsKey("type") && params.get("type") != null) { Integer deviceType = (Integer) params.get("type"); queryWrapper.eq("device_type", deviceType); // 创建运送清单时,只显示未绑定的设备(delivery_id为空) queryWrapper.isNull("delivery_id"); logger.info("查询未绑定的设备,类型: {}", deviceType); } // ... 其他查询逻辑 } ``` ### 前端修改 #### createDeliveryDialog.vue **文件位置**: `pc-cattle-transportation/src/views/shipping/createDeliveryDialog.vue` **修改的方法**: ##### updateSelectedDevicesDeliveryId (第1081-1111行) ```javascript // 更新选中设备的delivery_id和car_number const updateSelectedDevicesDeliveryId = async (deliveryId) => { try { const devicesToUpdate = []; // 收集所有选中的设备 if (formData.serverDeviceId) { devicesToUpdate.push(formData.serverDeviceId); } if (formData.eartagDeviceIds && formData.eartagDeviceIds.length > 0) { devicesToUpdate.push(...formData.eartagDeviceIds); } if (formData.collarDeviceIds && formData.collarDeviceIds.length > 0) { devicesToUpdate.push(...formData.collarDeviceIds); } // 批量更新设备的delivery_id和car_number for (const deviceId of devicesToUpdate) { await updateDeviceDeliveryId({ deviceId: deviceId, deliveryId: deliveryId, carNumber: formData.plateNumber // 新增:传递车牌号 }); } console.log(`成功更新 ${devicesToUpdate.length} 个设备的delivery_id和car_number: ${formData.plateNumber}`); } catch (error) { console.error('更新设备delivery_id和car_number失败:', error); } }; ``` ## 数据流程 ### 创建运送清单时的设备绑定流程 1. **用户填写运送清单** - 选择车牌号:`formData.plateNumber` - 选择主机设备 - 选择耳标设备 - 选择项圈设备 2. **提交运送清单** - 调用 `/delivery/create` 创建运送清单 - 获取新创建的 `deliveryId` 3. **更新设备绑定信息** - 调用 `updateSelectedDevicesDeliveryId(deliveryId)` 方法 - 对每个选中的设备调用 `/deliveryDevice/updateDeviceDeliveryId` 接口 - 传递参数: ```json { "deviceId": "设备ID", "deliveryId": "运送清单ID", "carNumber": "车牌号" } ``` 4. **后端更新数据库** - 更新 `iot_device_data` 表 - 设置 `delivery_id` = 运送清单ID - 设置 `car_number` = 车牌号 ### 查询可用设备流程 1. **打开创建运送清单对话框** - 调用 `loadDeviceOptions()` 方法 2. **查询未绑定设备** - 调用 `/iotDevice/queryList` 接口 - 传递参数: ```json { "type": 1, // 设备类型:1-主机, 2-耳标, 4-项圈 "pageNum": 1, "pageSize": 9999 } ``` 3. **后端过滤逻辑** ```sql SELECT * FROM iot_device_data WHERE device_type = ? AND delivery_id IS NULL ``` 4. **返回未绑定设备列表** - 只返回 `delivery_id` 为空的设备 - 已绑定设备不会出现在下拉列表中 ## 测试验证 ### 1. 创建运送清单并绑定设备 **步骤**: 1. 打开"新增运送清单"对话框 2. 填写车牌号:如 `京A12345` 3. 选择主机设备 4. 选择耳标设备 5. 选择项圈设备 6. 提交运送清单 **验证**: - 查询数据库 `iot_device_data` 表 - 确认选中设备的 `delivery_id` 已更新为运送清单ID - 确认选中设备的 `car_number` 已更新为 `京A12345` ```sql SELECT device_id, device_type, delivery_id, car_number FROM iot_device_data WHERE delivery_id = [刚创建的运送清单ID]; ``` ### 2. 验证已绑定设备不再显示 **步骤**: 1. 再次打开"新增运送清单"对话框 2. 查看设备下拉列表 **验证**: - 之前选中的设备不应出现在下拉列表中 - 只显示 `delivery_id` 为空的未绑定设备 ### 3. 验证设备解绑功能 **步骤**: 1. 删除或取消运送清单 2. 调用 `/deliveryDevice/clearDeliveryId` 接口 **验证**: - 查询数据库 `iot_device_data` 表 - 确认设备的 `delivery_id` 已清空(NULL) - 确认设备的 `car_number` 已清空(NULL) - 设备可以再次被选择 ## 控制台日志 ### 前端日志 ``` 成功更新 3 个设备的delivery_id和car_number: 京A12345 ``` ### 后端日志 ``` === 更新设备delivery_id、weight和car_number === 设备ID: 1001 订单ID: 123 重量: null 车牌号: 京A12345 设备更新成功: 1001, delivery_id=123, car_number=京A12345 ``` ``` 查询未绑定的设备,类型: 1 查询到设备数据: 5 条 ``` ## 注意事项 1. **权限要求**:所有接口都需要 `delivery:view` 权限 2. **并发安全**:同一设备不能同时绑定多个运送清单 3. **数据一致性**: - 删除运送清单时应解绑所有关联设备 - 修改车牌号时应同步更新已绑定设备的 `car_number` 4. **性能优化**: - 批量更新使用异步并发(Promise.all) - 设备列表查询添加了索引优化 ## 相关接口 ### 后端API | 接口 | 方法 | 说明 | |------|------|------| | `/deliveryDevice/updateDeviceDeliveryId` | POST | 更新设备绑定信息 | | `/deliveryDevice/clearDeliveryId` | POST | 清空设备绑定信息 | | `/iotDevice/queryList` | POST | 查询设备列表(支持过滤) | ### 前端方法 | 方法 | 说明 | |------|------| | `updateSelectedDevicesDeliveryId` | 批量更新选中设备的绑定信息 | | `loadDeviceOptions` | 加载可用设备列表 | ## 实现日期 2025-10-29