Files
cattleTransportation/DEVICE_BINDING_IMPLEMENTATION.md
2025-10-29 17:33:32 +08:00

291 lines
8.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 设备绑定功能实现说明
## 实现功能
### 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<String, Object> 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<String, Object> 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<String, Object> params) {
// 构建查询条件
QueryWrapper<IotDeviceData> 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