From 02cf52aed4f65315c51ff7018510fe3634521a99 Mon Sep 17 00:00:00 2001 From: tianyongbao Date: Tue, 12 May 2026 05:49:27 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E8=AE=BE=E5=A4=87=E8=A7=A3=E7=BB=91?= =?UTF-8?q?=E5=90=8E=EF=BC=8C=E6=96=B0=E7=94=9F=E6=88=90=E4=B8=80=E4=B8=AA?= =?UTF-8?q?=E6=97=A0=E7=94=A8=E6=88=B7=E6=97=A0=E5=A1=98=E5=8F=A3=E7=9A=84?= =?UTF-8?q?=E8=AE=BE=E5=A4=87=E4=BF=A1=E6=81=AF=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/impl/DeviceServiceImpl.java | 232 ++++++++++++------ 1 file changed, 155 insertions(+), 77 deletions(-) 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; }