fix: 设备解绑后,新生成一个无用户无塘口的设备信息。

This commit is contained in:
tianyongbao
2026-05-12 05:49:27 +08:00
parent b643662856
commit 02cf52aed4

View File

@@ -9,6 +9,7 @@ import com.intc.common.core.utils.MapstructUtils;
import com.intc.common.core.utils.StringUtils; import com.intc.common.core.utils.StringUtils;
import com.intc.common.mybatis.core.page.PageQuery; import com.intc.common.mybatis.core.page.PageQuery;
import com.intc.common.mybatis.core.page.TableDataInfo; 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.AquUser;
import com.intc.fishery.domain.Device; import com.intc.fishery.domain.Device;
import com.intc.fishery.domain.DeviceBindRecord; 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.TimingCtrl;
import com.intc.fishery.domain.bo.DeviceBo; import com.intc.fishery.domain.bo.DeviceBo;
import com.intc.fishery.domain.vo.DeviceVo; 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.DeviceBindRecordMapper;
import com.intc.fishery.mapper.DeviceCorrectRecordMapper; import com.intc.fishery.mapper.DeviceCorrectRecordMapper;
import com.intc.fishery.mapper.DeviceErrorCodeMapper; 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.LinkedCtrlMapper;
import com.intc.fishery.mapper.TimingCtrlMapper; import com.intc.fishery.mapper.TimingCtrlMapper;
import com.intc.fishery.service.IDeviceService; import com.intc.fishery.service.IDeviceService;
import com.intc.fishery.utils.MessageOpRecordUtil;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
@@ -49,6 +53,7 @@ import lombok.extern.slf4j.Slf4j;
public class DeviceServiceImpl implements IDeviceService { public class DeviceServiceImpl implements IDeviceService {
private final DeviceMapper baseMapper; private final DeviceMapper baseMapper;
private final AquUserMapper aquUserMapper;
private final DeviceBindRecordMapper deviceBindRecordMapper; private final DeviceBindRecordMapper deviceBindRecordMapper;
private final DeviceCorrectRecordMapper deviceCorrectRecordMapper; private final DeviceCorrectRecordMapper deviceCorrectRecordMapper;
private final DeviceErrorCodeMapper deviceErrorCodeMapper; private final DeviceErrorCodeMapper deviceErrorCodeMapper;
@@ -56,6 +61,11 @@ public class DeviceServiceImpl implements IDeviceService {
private final LinkedCtrlMapper linkedCtrlMapper; private final LinkedCtrlMapper linkedCtrlMapper;
private final TimingCtrlMapper timingCtrlMapper; 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 逻辑)
* 删除顺序:故障码 -> 校准记录 -> 定时控制 -> 开关(先解除联动控制引用) -> 联动控制 -> 设备 * <p>
* 处理流程:
* 1. 查询完整设备信息与用户信息
* 2. 新增解绑记录
* 3. 删除联动控制
* 4. 删除关联数据(故障码、校准记录、定时控制、开关)
* 5. 删除设备
* 6. 非管理员用户创建新的无绑定设备保留IoT信息
* 7. 清除告警数据warnCode + Redis离线等待标记
* 8. 记录操作日志
* </p>
* *
* @param ids 待删除的主键集合 * @param ids 待删除的主键集合
* @param isValid 是否进行有效性校验 * @param isValid 是否进行有效性校验
@@ -238,31 +258,62 @@ public class DeviceServiceImpl implements IDeviceService {
//TODO 做一些业务上的校验,判断是否需要校验 //TODO 做一些业务上的校验,判断是否需要校验
} }
// 1. 删除设备关联的故障码记录 // 1. 先查询完整设备信息(删除前需要用到各字段)
List<Device> devicesToDelete = baseMapper.selectList(
new LambdaQueryWrapper<Device>()
.in(Device::getId, ids)
);
if (devicesToDelete.isEmpty()) {
return false;
}
for (Device device : devicesToDelete) {
Long deviceId = device.getId();
// 2. 新增解绑记录
try {
DeviceBindRecord unbindRecord = new DeviceBindRecord();
unbindRecord.setUserId(device.getUserId());
unbindRecord.setIsBind(0); // 0表示解绑
unbindRecord.setIotId(device.getIotId());
unbindRecord.setDeviceType(device.getDeviceType() != null ? Long.valueOf(device.getDeviceType()) : null);
unbindRecord.setSerialNum(device.getSerialNum());
deviceBindRecordMapper.insert(unbindRecord);
log.info("添加设备解绑记录: deviceId={}, userId={}, serialNum={}",
deviceId, device.getUserId(), device.getSerialNum());
} catch (Exception e) {
log.error("添加设备解绑记录失败: deviceId={}, error={}", deviceId, e.getMessage(), e);
}
// 3. 删除设备关联的联动控制
linkedCtrlMapper.delete(
new LambdaQueryWrapper<LinkedCtrl>()
.eq(LinkedCtrl::getDeviceId, deviceId)
);
// 4. 删除设备关联的故障码记录
deviceErrorCodeMapper.delete( deviceErrorCodeMapper.delete(
new LambdaQueryWrapper<DeviceErrorCode>() new LambdaQueryWrapper<DeviceErrorCode>()
.in(DeviceErrorCode::getDeviceId, ids) .eq(DeviceErrorCode::getDeviceId, deviceId)
); );
// 2. 删除设备关联的校准记录 // 5. 删除设备关联的校准记录
deviceCorrectRecordMapper.delete( deviceCorrectRecordMapper.delete(
new LambdaQueryWrapper<DeviceCorrectRecord>() new LambdaQueryWrapper<DeviceCorrectRecord>()
.in(DeviceCorrectRecord::getDeviceId, ids) .eq(DeviceCorrectRecord::getDeviceId, deviceId)
); );
// 3. 查询设备关联的开关 // 6. 查询设备关联的开关,删除定时控制、解除联动绑定后删除开关
List<DeviceSwitch> switches = deviceSwitchMapper.selectList( List<DeviceSwitch> switches = deviceSwitchMapper.selectList(
new LambdaQueryWrapper<DeviceSwitch>() new LambdaQueryWrapper<DeviceSwitch>()
.in(DeviceSwitch::getDeviceId, ids) .eq(DeviceSwitch::getDeviceId, deviceId)
); );
if (!switches.isEmpty()) { if (!switches.isEmpty()) {
// 收集开关ID
List<Long> switchIds = switches.stream() List<Long> switchIds = switches.stream()
.map(DeviceSwitch::getId) .map(DeviceSwitch::getId)
.collect(Collectors.toList()); .collect(Collectors.toList());
// 4. 删除开关关联的定时控制 // 删除开关关联的定时控制
timingCtrlMapper.delete( timingCtrlMapper.delete(
new LambdaQueryWrapper<TimingCtrl>() new LambdaQueryWrapper<TimingCtrl>()
.in(TimingCtrl::getSwitchId, switchIds) .in(TimingCtrl::getSwitchId, switchIds)
@@ -275,14 +326,14 @@ public class DeviceServiceImpl implements IDeviceService {
.distinct() .distinct()
.collect(Collectors.toList()); .collect(Collectors.toList());
// 5. 解除开关与联动控制的绑定 // 解除开关与联动控制的绑定
deviceSwitchMapper.update(null, deviceSwitchMapper.update(null,
new LambdaUpdateWrapper<DeviceSwitch>() new LambdaUpdateWrapper<DeviceSwitch>()
.set(DeviceSwitch::getLinkedCtrlId, null) .set(DeviceSwitch::getLinkedCtrlId, null)
.in(DeviceSwitch::getDeviceId, ids) .eq(DeviceSwitch::getDeviceId, deviceId)
); );
// 6. 删除联动控制(如果有) // 删除联动控制(如果有)
if (!linkedCtrlIds.isEmpty()) { if (!linkedCtrlIds.isEmpty()) {
linkedCtrlMapper.delete( linkedCtrlMapper.delete(
new LambdaQueryWrapper<LinkedCtrl>() new LambdaQueryWrapper<LinkedCtrl>()
@@ -290,47 +341,74 @@ public class DeviceServiceImpl implements IDeviceService {
); );
} }
// 7. 删除开关 // 删除开关
deviceSwitchMapper.delete( deviceSwitchMapper.delete(
new LambdaQueryWrapper<DeviceSwitch>() new LambdaQueryWrapper<DeviceSwitch>()
.in(DeviceSwitch::getDeviceId, ids) .eq(DeviceSwitch::getDeviceId, deviceId)
); );
} }
// 8. 删除设备本身关联的联动控制 // 7. 删除设备记录
linkedCtrlMapper.delete( baseMapper.deleteById(deviceId);
new LambdaQueryWrapper<LinkedCtrl>()
.in(LinkedCtrl::getDeviceId, ids)
);
// 9. 查询要删除的设备信息,添加解绑记录 // 8. 用户创建新的无绑定设备保留IoT信息清除用户和塘口关联
List<Device> devicesToDelete = baseMapper.selectList( if (device.getUserId() != null) {
new LambdaQueryWrapper<Device>()
.in(Device::getId, ids)
.select(Device::getId, Device::getUserId, Device::getIotId,
Device::getDeviceType, Device::getSerialNum)
);
// 为每个设备添加解绑记录
for (Device device : devicesToDelete) {
try { try {
DeviceBindRecord unbindRecord = new DeviceBindRecord(); AquUser user = aquUserMapper.selectById(device.getUserId());
unbindRecord.setUserId(device.getUserId()); if (user != null) {
unbindRecord.setIsBind(0); // 0表示解绑 Device newDevice = new Device();
unbindRecord.setIotId(device.getIotId()); newDevice.setUserId(null);
unbindRecord.setDeviceType(device.getDeviceType() != null ? Long.valueOf(device.getDeviceType()) : null); newDevice.setIsOxygenUsed(device.getIsOxygenUsed());
unbindRecord.setSerialNum(device.getSerialNum()); newDevice.setIotId(device.getIotId());
deviceBindRecordMapper.insert(unbindRecord); newDevice.setSerialNum(device.getSerialNum());
log.info("添加设备解绑记录: deviceId={}, userId={}, serialNum={}", newDevice.setDeviceName(device.getDeviceName());
device.getId(), device.getUserId(), device.getSerialNum()); 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) { } catch (Exception e) {
log.error("添加设备解绑记录失败: deviceId={}, error={}", device.getId(), e.getMessage(), e); log.error("重建无绑定设备失败: deviceId={}, error={}", deviceId, e.getMessage(), e);
// 不影响删除流程,继续执行
} }
} }
// 10. 最后删除设备 // 9. 清除告警数据Redis离线等待标记
return baseMapper.deleteByIds(ids) > 0; 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);
}
}
return true;
} }