diff --git a/intc-modules/intc-fishery/src/main/java/com/intc/fishery/service/impl/DeviceServiceImpl.java b/intc-modules/intc-fishery/src/main/java/com/intc/fishery/service/impl/DeviceServiceImpl.java
index 55ff2bd..a188e7c 100644
--- a/intc-modules/intc-fishery/src/main/java/com/intc/fishery/service/impl/DeviceServiceImpl.java
+++ b/intc-modules/intc-fishery/src/main/java/com/intc/fishery/service/impl/DeviceServiceImpl.java
@@ -9,6 +9,7 @@ import com.intc.common.core.utils.MapstructUtils;
import com.intc.common.core.utils.StringUtils;
import com.intc.common.mybatis.core.page.PageQuery;
import com.intc.common.mybatis.core.page.TableDataInfo;
+import com.intc.common.redis.utils.RedisUtils;
import com.intc.fishery.domain.AquUser;
import com.intc.fishery.domain.Device;
import com.intc.fishery.domain.DeviceBindRecord;
@@ -20,6 +21,8 @@ import com.intc.fishery.domain.Pond;
import com.intc.fishery.domain.TimingCtrl;
import com.intc.fishery.domain.bo.DeviceBo;
import com.intc.fishery.domain.vo.DeviceVo;
+import com.intc.fishery.constant.DefineDeviceWarnCode;
+import com.intc.fishery.mapper.AquUserMapper;
import com.intc.fishery.mapper.DeviceBindRecordMapper;
import com.intc.fishery.mapper.DeviceCorrectRecordMapper;
import com.intc.fishery.mapper.DeviceErrorCodeMapper;
@@ -28,6 +31,7 @@ import com.intc.fishery.mapper.DeviceSwitchMapper;
import com.intc.fishery.mapper.LinkedCtrlMapper;
import com.intc.fishery.mapper.TimingCtrlMapper;
import com.intc.fishery.service.IDeviceService;
+import com.intc.fishery.utils.MessageOpRecordUtil;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@@ -49,6 +53,7 @@ import lombok.extern.slf4j.Slf4j;
public class DeviceServiceImpl implements IDeviceService {
private final DeviceMapper baseMapper;
+ private final AquUserMapper aquUserMapper;
private final DeviceBindRecordMapper deviceBindRecordMapper;
private final DeviceCorrectRecordMapper deviceCorrectRecordMapper;
private final DeviceErrorCodeMapper deviceErrorCodeMapper;
@@ -56,6 +61,11 @@ public class DeviceServiceImpl implements IDeviceService {
private final LinkedCtrlMapper linkedCtrlMapper;
private final TimingCtrlMapper timingCtrlMapper;
+ /** Redis 离线等待标记前缀(与 DeviceDataHandler 保持一致) */
+ private static final String DEVICE_OFFLINE_WAIT_KEY_PREFIX = "device:offline:wait:";
+ /** Redis 溶解氧探头离线等待标记前缀 */
+ private static final String DETECTOR_OXY_OFFLINE_WAIT_KEY_PREFIX = "device:detector:oxy:offline:wait:";
+
/**
* 查询设备管理
*
@@ -224,8 +234,18 @@ public class DeviceServiceImpl implements IDeviceService {
}
/**
- * 校验并批量删除设备管理信息
- * 删除顺序:故障码 -> 校准记录 -> 定时控制 -> 开关(先解除联动控制引用) -> 联动控制 -> 设备
+ * 校验并批量删除设备管理信息(参考 C# DeleteDevice 逻辑)
+ *
+ * 处理流程:
+ * 1. 查询完整设备信息与用户信息
+ * 2. 新增解绑记录
+ * 3. 删除联动控制
+ * 4. 删除关联数据(故障码、校准记录、定时控制、开关)
+ * 5. 删除设备
+ * 6. 非管理员用户:创建新的无绑定设备(保留IoT信息)
+ * 7. 清除告警数据(warnCode + Redis离线等待标记)
+ * 8. 记录操作日志
+ *
*
* @param ids 待删除的主键集合
* @param isValid 是否进行有效性校验
@@ -234,85 +254,23 @@ public class DeviceServiceImpl implements IDeviceService {
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean deleteWithValidByIds(Collection ids, Boolean isValid) {
- if(isValid){
+ if (isValid) {
//TODO 做一些业务上的校验,判断是否需要校验
}
- // 1. 删除设备关联的故障码记录
- deviceErrorCodeMapper.delete(
- new LambdaQueryWrapper()
- .in(DeviceErrorCode::getDeviceId, ids)
- );
-
- // 2. 删除设备关联的校准记录
- deviceCorrectRecordMapper.delete(
- new LambdaQueryWrapper()
- .in(DeviceCorrectRecord::getDeviceId, ids)
- );
-
- // 3. 查询设备关联的开关
- List switches = deviceSwitchMapper.selectList(
- new LambdaQueryWrapper()
- .in(DeviceSwitch::getDeviceId, ids)
- );
-
- if (!switches.isEmpty()) {
- // 收集开关ID
- List switchIds = switches.stream()
- .map(DeviceSwitch::getId)
- .collect(Collectors.toList());
-
- // 4. 删除开关关联的定时控制
- timingCtrlMapper.delete(
- new LambdaQueryWrapper()
- .in(TimingCtrl::getSwitchId, switchIds)
- );
-
- // 收集开关关联的联动控制ID
- List linkedCtrlIds = switches.stream()
- .map(DeviceSwitch::getLinkedCtrlId)
- .filter(id -> id != null && id > 0)
- .distinct()
- .collect(Collectors.toList());
-
- // 5. 解除开关与联动控制的绑定
- deviceSwitchMapper.update(null,
- new LambdaUpdateWrapper()
- .set(DeviceSwitch::getLinkedCtrlId, null)
- .in(DeviceSwitch::getDeviceId, ids)
- );
-
- // 6. 删除联动控制(如果有)
- if (!linkedCtrlIds.isEmpty()) {
- linkedCtrlMapper.delete(
- new LambdaQueryWrapper()
- .in(LinkedCtrl::getId, linkedCtrlIds)
- );
- }
-
- // 7. 删除开关
- deviceSwitchMapper.delete(
- new LambdaQueryWrapper()
- .in(DeviceSwitch::getDeviceId, ids)
- );
- }
-
- // 8. 删除设备本身关联的联动控制
- linkedCtrlMapper.delete(
- new LambdaQueryWrapper()
- .in(LinkedCtrl::getDeviceId, ids)
- );
-
- // 9. 查询要删除的设备信息,添加解绑记录
+ // 1. 先查询完整设备信息(删除前需要用到各字段)
List devicesToDelete = baseMapper.selectList(
new LambdaQueryWrapper()
.in(Device::getId, ids)
- .select(Device::getId, Device::getUserId, Device::getIotId,
- Device::getDeviceType, Device::getSerialNum)
);
+ if (devicesToDelete.isEmpty()) {
+ return false;
+ }
- // 为每个设备添加解绑记录
for (Device device : devicesToDelete) {
+ Long deviceId = device.getId();
+
+ // 2. 新增解绑记录
try {
DeviceBindRecord unbindRecord = new DeviceBindRecord();
unbindRecord.setUserId(device.getUserId());
@@ -322,15 +280,135 @@ public class DeviceServiceImpl implements IDeviceService {
unbindRecord.setSerialNum(device.getSerialNum());
deviceBindRecordMapper.insert(unbindRecord);
log.info("添加设备解绑记录: deviceId={}, userId={}, serialNum={}",
- device.getId(), device.getUserId(), device.getSerialNum());
+ deviceId, device.getUserId(), device.getSerialNum());
} catch (Exception e) {
- log.error("添加设备解绑记录失败: deviceId={}, error={}", device.getId(), e.getMessage(), e);
- // 不影响删除流程,继续执行
+ log.error("添加设备解绑记录失败: deviceId={}, error={}", deviceId, e.getMessage(), e);
+ }
+
+ // 3. 删除设备关联的联动控制
+ linkedCtrlMapper.delete(
+ new LambdaQueryWrapper()
+ .eq(LinkedCtrl::getDeviceId, deviceId)
+ );
+
+ // 4. 删除设备关联的故障码记录
+ deviceErrorCodeMapper.delete(
+ new LambdaQueryWrapper()
+ .eq(DeviceErrorCode::getDeviceId, deviceId)
+ );
+
+ // 5. 删除设备关联的校准记录
+ deviceCorrectRecordMapper.delete(
+ new LambdaQueryWrapper()
+ .eq(DeviceCorrectRecord::getDeviceId, deviceId)
+ );
+
+ // 6. 查询设备关联的开关,删除定时控制、解除联动绑定后删除开关
+ List switches = deviceSwitchMapper.selectList(
+ new LambdaQueryWrapper()
+ .eq(DeviceSwitch::getDeviceId, deviceId)
+ );
+ if (!switches.isEmpty()) {
+ List switchIds = switches.stream()
+ .map(DeviceSwitch::getId)
+ .collect(Collectors.toList());
+
+ // 删除开关关联的定时控制
+ timingCtrlMapper.delete(
+ new LambdaQueryWrapper()
+ .in(TimingCtrl::getSwitchId, switchIds)
+ );
+
+ // 收集开关关联的联动控制ID
+ List linkedCtrlIds = switches.stream()
+ .map(DeviceSwitch::getLinkedCtrlId)
+ .filter(id -> id != null && id > 0)
+ .distinct()
+ .collect(Collectors.toList());
+
+ // 解除开关与联动控制的绑定
+ deviceSwitchMapper.update(null,
+ new LambdaUpdateWrapper()
+ .set(DeviceSwitch::getLinkedCtrlId, null)
+ .eq(DeviceSwitch::getDeviceId, deviceId)
+ );
+
+ // 删除联动控制(如果有)
+ if (!linkedCtrlIds.isEmpty()) {
+ linkedCtrlMapper.delete(
+ new LambdaQueryWrapper()
+ .in(LinkedCtrl::getId, linkedCtrlIds)
+ );
+ }
+
+ // 删除开关
+ deviceSwitchMapper.delete(
+ new LambdaQueryWrapper()
+ .eq(DeviceSwitch::getDeviceId, deviceId)
+ );
+ }
+
+ // 7. 删除设备记录
+ baseMapper.deleteById(deviceId);
+
+ // 8. 用户:创建新的无绑定设备(保留IoT信息,清除用户和塘口关联)
+ if (device.getUserId() != null) {
+ try {
+ AquUser user = aquUserMapper.selectById(device.getUserId());
+ if (user != null) {
+ Device newDevice = new Device();
+ newDevice.setUserId(null);
+ newDevice.setIsOxygenUsed(device.getIsOxygenUsed());
+ newDevice.setIotId(device.getIotId());
+ newDevice.setSerialNum(device.getSerialNum());
+ newDevice.setDeviceName(device.getDeviceName());
+ newDevice.setDeviceType(device.getDeviceType());
+ newDevice.setIccId(device.getIccId());
+ newDevice.setBindTime(device.getBindTime());
+ newDevice.setDeadTime(device.getDeadTime());
+ newDevice.setPondId(null);
+ newDevice.setSalinityCompensation(0.0);
+ newDevice.setOxyWarnLower(device.getOxyWarnLower());
+ newDevice.setOxyWarnCallOpen(0);
+ newDevice.setOxyWarnCallNoDis(0);
+ newDevice.setTempWarnCallOpen(0);
+ newDevice.setTempWarnCallNoDis(0);
+ newDevice.setWarnCode(DefineDeviceWarnCode.None);
+ newDevice.setCategory(device.getCategory());
+ baseMapper.insert(newDevice);
+ log.info("已为用户重建无绑定设备: oldDeviceId={}, newDeviceId={}, serialNum={}",
+ deviceId, newDevice.getId(), device.getSerialNum());
+ }
+ } catch (Exception e) {
+ log.error("重建无绑定设备失败: deviceId={}, error={}", deviceId, e.getMessage(), e);
+ }
+ }
+
+ // 9. 清除告警数据(Redis离线等待标记)
+ try {
+ String serialNum = device.getSerialNum();
+ if (StringUtils.isNotBlank(serialNum)) {
+ RedisUtils.deleteObject(DEVICE_OFFLINE_WAIT_KEY_PREFIX + serialNum);
+ RedisUtils.deleteObject(DETECTOR_OXY_OFFLINE_WAIT_KEY_PREFIX + serialNum);
+ log.info("已清除设备Redis告警标记: serialNum={}", serialNum);
+ }
+ } catch (Exception e) {
+ log.error("清除Redis告警标记失败: deviceId={}, error={}", deviceId, e.getMessage(), e);
+ }
+
+ // 10. 记录操作日志
+ try {
+ MessageOpRecordUtil.addMessageOpRecordUser(
+ device.getUserId(), device.getUserId(),
+ "设备操作",
+ String.format("%s(%s),解除绑定。", device.getDeviceName(), device.getSerialNum())
+ );
+ } catch (Exception e) {
+ log.error("记录操作日志失败: deviceId={}, error={}", deviceId, e.getMessage(), e);
}
}
- // 10. 最后删除设备
- return baseMapper.deleteByIds(ids) > 0;
+ return true;
}