Browse Source

手持表增加同组人报警提示

master
wangwei_123 4 days ago
parent
commit
48a98fb39c
  1. 3
      cc-admin-master/yudao-module-hand-mqtt/src/main/java/cn/iocoder/yudao/module/mqtt/mqtt/Client.java
  2. 15
      cc-admin-master/yudao-module-hand-mqtt/src/main/java/cn/iocoder/yudao/module/mqtt/mqtt/ThreadPoolConfig.java
  3. 81
      cc-admin-master/yudao-module-hand-mqtt/src/main/java/cn/iocoder/yudao/module/mqtt/processor/DeviceMessageProcessor.java
  4. 8
      cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/controller/admin/HandDetectorController.java
  5. 2
      cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/controller/admin/PersonnelController.java
  6. 8
      cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/dal/AlarmRuleDO.java
  7. 5
      cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/dal/AlarmTypeDO.java
  8. 5
      cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/dal/FactoryDO.java
  9. 5
      cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/dal/FenceAlarmDO.java
  10. 5
      cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/dal/FenceDO.java
  11. 7
      cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/dal/GasTypeDO.java
  12. 4
      cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/dal/HandAlarmDO.java
  13. 10
      cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/dal/HandDetectorDO.java
  14. 5
      cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/dal/PersonnelDO.java
  15. 35
      cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/datapermission/config/HandDataPermissionConfiguration.java
  16. 4
      cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/datapermission/package-info.java
  17. 20
      cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/job/OfflineAlarmJob.java
  18. 22
      cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/mapper/HandDetectorMapper.java
  19. 1
      cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/mapper/PersonnelMapper.java
  20. 4
      cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/service/HandDetectorService.java
  21. 2
      cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/service/PersonnelService.java
  22. 22
      cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/service/impl/AlarmRuleServiceImpl.java
  23. 4
      cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/service/impl/FenceAlarmServiceImpl.java
  24. 110
      cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/service/impl/HandDetectorServiceImpl.java
  25. 30
      cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/service/impl/PersonnelServiceImpl.java
  26. 16
      cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/service/impl/TdengineServiceImpl.java
  27. 8
      cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/util/RedisUtil.java
  28. 3
      cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/vo/AlarmRulePageReqVO.java
  29. 3
      cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/vo/AlarmRuleRespVO.java
  30. 2
      cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/vo/AlarmRuleSaveReqVO.java
  31. 2
      cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/vo/AlarmTypePageReqVO.java
  32. 2
      cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/vo/AlarmTypeRespVO.java
  33. 4
      cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/vo/AlarmTypeSaveReqVO.java
  34. 3
      cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/vo/FactoryPageReqVO.java
  35. 4
      cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/vo/FactoryRespVO.java
  36. 3
      cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/vo/FactorySaveReqVO.java
  37. 3
      cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/vo/FenceAlarmPageReqVO.java
  38. 6
      cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/vo/FenceAlarmRespVO.java
  39. 3
      cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/vo/FenceAlarmSaveReqVO.java
  40. 3
      cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/vo/FencePageReqVO.java
  41. 3
      cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/vo/FenceRespVO.java
  42. 3
      cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/vo/FenceSaveReqVO.java
  43. 3
      cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/vo/GasTypePageReqVO.java
  44. 3
      cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/vo/GasTypeRespVO.java
  45. 3
      cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/vo/GasTypeSaveReqVO.java
  46. 3
      cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/vo/HandAlarmPageReqVO.java
  47. 3
      cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/vo/HandAlarmRespVO.java
  48. 3
      cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/vo/HandAlarmSaveReqVO.java
  49. 6
      cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/vo/HandDataVo.java
  50. 3
      cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/vo/HandDetectorPageReqVO.java
  51. 3
      cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/vo/HandDetectorRespVO.java
  52. 8
      cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/vo/HandDetectorSaveReqVO.java
  53. 2
      cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/vo/PersonnelPageReqVO.java
  54. 2
      cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/vo/PersonnelRespVO.java
  55. 2
      cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/vo/PersonnelSaveReqVO.java
  56. 12
      cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/vo/personnelAlarmVo.java
  57. 7
      cc-admin-master/yudao-module-hand/src/main/resources/mapper/TdengineMapper.xml
  58. 2
      cc-admin-master/yudao-server/pom.xml
  59. 34
      cc-admin-master/yudao-server/src/main/resources/application-dev.yaml
  60. 4
      cc-admin-master/yudao-server/src/main/resources/application-local.yaml
  61. 7
      cc-admin-master/yudao-server/src/main/resources/application-prod.yaml
  62. 3
      cc-admin-master/yudao-server/src/main/resources/application.yaml

3
cc-admin-master/yudao-module-hand-mqtt/src/main/java/cn/iocoder/yudao/module/mqtt/mqtt/Client.java

@ -6,6 +6,7 @@ import lombok.extern.slf4j.Slf4j;
import org.eclipse.paho.client.mqttv3.*; import org.eclipse.paho.client.mqttv3.*;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence; import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.event.EventListener; import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async; import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -51,7 +52,7 @@ public class Client {
this.onMessageCallback = onMessageCallback; this.onMessageCallback = onMessageCallback;
} }
@PostConstruct
@EventListener(ApplicationReadyEvent.class)
public void init() { public void init() {
if (!enable) { if (!enable) {
log.info("MQTT 功能已禁用。"); log.info("MQTT 功能已禁用。");

15
cc-admin-master/yudao-module-hand-mqtt/src/main/java/cn/iocoder/yudao/module/mqtt/mqtt/ThreadPoolConfig.java

@ -9,7 +9,6 @@ import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.ThreadPoolExecutor;
@Configuration @Configuration
public class ThreadPoolConfig { public class ThreadPoolConfig {
@Bean("mqttExecutor") @Bean("mqttExecutor")
public TaskExecutor taskExecutor() { public TaskExecutor taskExecutor() {
@ -19,7 +18,7 @@ public class ThreadPoolConfig {
// 最大线程数:CPU核心数 * 2 // 最大线程数:CPU核心数 * 2
executor.setMaxPoolSize(Runtime.getRuntime().availableProcessors() * 2); executor.setMaxPoolSize(Runtime.getRuntime().availableProcessors() * 2);
// 队列大小 // 队列大小
executor.setQueueCapacity(1000);
executor.setQueueCapacity(2000);
// 线程名称前缀 // 线程名称前缀
executor.setThreadNamePrefix("mqtt-executor-"); executor.setThreadNamePrefix("mqtt-executor-");
// 拒绝策略:由调用者线程处理 // 拒绝策略:由调用者线程处理
@ -28,4 +27,16 @@ public class ThreadPoolConfig {
executor.initialize(); executor.initialize();
return executor; return executor;
} }
@Bean("mqttAlarmExecutor")
public TaskExecutor mqttAlarmExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(5);
executor.setMaxPoolSize(10);
executor.setQueueCapacity(2000); // 队列大一点,应对瞬间并发
executor.setThreadNamePrefix("alarm-push-");
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.initialize();
return executor;
}
} }

81
cc-admin-master/yudao-module-hand-mqtt/src/main/java/cn/iocoder/yudao/module/mqtt/processor/DeviceMessageProcessor.java

@ -9,13 +9,20 @@ import cn.iocoder.yudao.module.hand.service.*;
import cn.iocoder.yudao.module.hand.util.*; import cn.iocoder.yudao.module.hand.util.*;
import cn.iocoder.yudao.module.hand.vo.*; import cn.iocoder.yudao.module.hand.vo.*;
import cn.iocoder.yudao.module.mqtt.config.TdengineBatchConfig; import cn.iocoder.yudao.module.mqtt.config.TdengineBatchConfig;
import cn.iocoder.yudao.module.mqtt.mqtt.Client;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.eclipse.paho.client.mqttv3.IMqttClient;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.redisson.api.RLock; import org.redisson.api.RLock;
import org.redisson.api.RedissonClient; import org.redisson.api.RedissonClient;
import org.springframework.core.task.TaskExecutor;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import java.nio.charset.StandardCharsets;
import java.sql.Timestamp; import java.sql.Timestamp;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.*; import java.util.*;
@ -25,6 +32,7 @@ import java.util.concurrent.TimeUnit;
@Component @Component
public class DeviceMessageProcessor { public class DeviceMessageProcessor {
private static final ObjectMapper objectMapper = new ObjectMapper();
@Resource @Resource
private RedisUtil redisUtil; private RedisUtil redisUtil;
@Resource @Resource
@ -33,21 +41,22 @@ public class DeviceMessageProcessor {
private TdengineBatchConfig<TdengineDataVo> tdengineBatchConfig; private TdengineBatchConfig<TdengineDataVo> tdengineBatchConfig;
@Resource @Resource
private HandDetectorService handDetectorService; private HandDetectorService handDetectorService;
@Resource @Resource
private HandAlarmService handAlarmService; private HandAlarmService handAlarmService;
@Resource @Resource
private AlarmRuleService alarmRuleService; private AlarmRuleService alarmRuleService;
@Resource @Resource
private RedissonClient redissonClient; private RedissonClient redissonClient;
@Resource @Resource
private FenceService fenceService; private FenceService fenceService;
@Resource @Resource
private FenceAlarmService fenceAlarmService; private FenceAlarmService fenceAlarmService;
@Resource
private Client client;
@Resource(name = "mqttAlarmExecutor")
private TaskExecutor alarmExecutor;
public void process(String topic, String payload) { public void process(String topic, String payload) {
log.debug("[设备上报] 开始处理 -> 主题: {}, 内容: {}", topic, payload); log.debug("[设备上报] 开始处理 -> 主题: {}, 内容: {}", topic, payload);
@ -92,6 +101,7 @@ public class DeviceMessageProcessor {
log.info("未启用的手持探测器 sn: {}", topic); log.info("未启用的手持探测器 sn: {}", topic);
return; return;
} }
// 数据解析与转换 // 数据解析与转换
HandDataVo handVo = dataConvert(topic, payload, detector); HandDataVo handVo = dataConvert(topic, payload, detector);
@ -272,7 +282,7 @@ public class DeviceMessageProcessor {
private void fanceAlarm(HandDataVo handVo) { private void fanceAlarm(HandDataVo handVo) {
if (StringUtils.isBlank(handVo.getFenceIds())) { if (StringUtils.isBlank(handVo.getFenceIds())) {
handVo.setFenceStatus(HandAlarmType.NORMAL.getType()); handVo.setFenceStatus(HandAlarmType.NORMAL.getType());
log.info("当前设备未绑定围栏,sn{}", handVo.getSn());
log.error("当前设备未绑定围栏,sn{}", handVo.getSn());
return; return;
} }
List<Long> list = Arrays.stream(handVo.getFenceIds().split(",")) List<Long> list = Arrays.stream(handVo.getFenceIds().split(","))
@ -404,6 +414,9 @@ public class DeviceMessageProcessor {
private AlarmRuleDO getAlarmRule(HandDataVo handVo, Map<Long, List<AlarmRuleDO>> ruleMap) { private AlarmRuleDO getAlarmRule(HandDataVo handVo, Map<Long, List<AlarmRuleDO>> ruleMap) {
if (null == handVo.getValue()) {
return null;
}
double gasValue = handVo.getValue(); double gasValue = handVo.getValue();
Long gasTypeId = handVo.getGasTypeId(); Long gasTypeId = handVo.getGasTypeId();
@ -445,6 +458,9 @@ public class DeviceMessageProcessor {
return redisData; return redisData;
} }
String sn = redisData.getSn();
String gasName = alarmRule.getGasTypeName();
LocalDateTime now = LocalDateTime.now(); LocalDateTime now = LocalDateTime.now();
//离线报警结束 //离线报警结束
if (OnlineStatusType.ONLINE.getType().equals(redisData.getOnlineStatus()) if (OnlineStatusType.ONLINE.getType().equals(redisData.getOnlineStatus())
@ -452,6 +468,7 @@ public class DeviceMessageProcessor {
HandAlarmDO handAlarmDO = new HandAlarmDO(); HandAlarmDO handAlarmDO = new HandAlarmDO();
handAlarmDO.setId(redisData.getAlarmId()); handAlarmDO.setId(redisData.getAlarmId());
handAlarmDO.setTAlarmEnd(now); handAlarmDO.setTAlarmEnd(now);
handAlarmDO.setStatus(EnableStatus.HANDLE.value());
handAlarmService.updateById(handAlarmDO); handAlarmService.updateById(handAlarmDO);
//删除离线报警 //删除离线报警
redisData.setAlarmId(null); redisData.setAlarmId(null);
@ -465,6 +482,12 @@ public class DeviceMessageProcessor {
redisData.setAlarmLevel(0); redisData.setAlarmLevel(0);
redisData.setTAlarmEnd(now); redisData.setTAlarmEnd(now);
redisData.setGasStatus(HandAlarmType.NORMAL.getType()); redisData.setGasStatus(HandAlarmType.NORMAL.getType());
// 【新增逻辑】推送报警结束
sendGroupMessage(redisData, gasName, redisData.getValue(), false);
// 清除上一次推送的数值记录,防止下次报警数值一样时不推送(如果需要)
redisData.setLastPushValue(null);
return redisData; return redisData;
} }
@ -498,11 +521,60 @@ public class DeviceMessageProcessor {
// 更新最大值 // 更新最大值
redisData.setMaxValue(redisData.getValue()); redisData.setMaxValue(redisData.getValue());
} }
if (redisData.getLastPushValue() == null || !redisData.getLastPushValue().equals(redisData.getValue())) {
sendGroupMessage(redisData, gasName, redisData.getValue(), true);
// 更新最后推送的值
redisData.setLastPushValue(redisData.getValue());
}
} }
redisData.setGasStatus(HandAlarmType.ALARM.getType()); redisData.setGasStatus(HandAlarmType.ALARM.getType());
return redisData; return redisData;
} }
/**
* 辅助方法发送同组人消息
*
* @param gasName 气体名称
* @param value 当前浓度值
* @param isAlarming true=报警中, false=报警结束
*/
private void sendGroupMessage(HandDataVo redisData, String gasName, Double value, boolean isAlarming) {
if (null == redisData.getDeptId()) return;
// 1. 准备数据(在主线程做,只做一次)
String valueStr = (value != null && value % 1 == 0) ? String.valueOf(value.intValue()) : String.valueOf(value);
String statusText = isAlarming ? "报警" : "报警结束";
String msgContent = String.format("%s%s,%s气体浓度为%s", redisData.getName(), statusText, gasName, valueStr);
Map<String, String> map = new HashMap<>();
map.put("message", msgContent);
final String payload; // 声明为 final 供内部类使用
try {
payload = objectMapper.writeValueAsString(map);
} catch (JsonProcessingException e) {
log.error("JSON转换失败", e);
return;
}
// 2. 查人(查同组所有设备的SN)
List<HandDetectorDO> listAll = handDetectorService.getListAll(redisData.getDeptId(), redisData.getTenantId());
if (listAll == null || listAll.isEmpty()) return;
alarmExecutor.execute(() -> {
for (HandDetectorDO device : listAll) {
String deviceSn = device.getSn();
if (deviceSn == null || deviceSn.isEmpty()) continue;
String topic = deviceSn + "/zds_down";
try {
client.publish(topic, payload);
} catch (Exception e) {
log.error("异步报警推送失败, SN: {}", deviceSn, e);
}
}
});
}
/** /**
* 数据转换 * 数据转换
@ -543,7 +615,6 @@ public class DeviceMessageProcessor {
detector.setGpsType(Integer.parseInt(type)); detector.setGpsType(Integer.parseInt(type));
return detector; return detector;
} }

8
cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/controller/admin/HandDetectorController.java

@ -150,4 +150,12 @@ public class HandDetectorController {
Map<Object, Object> monitor = handDetectorService.getMonitor(); Map<Object, Object> monitor = handDetectorService.getMonitor();
return CommonResult.success(monitor); return CommonResult.success(monitor);
} }
@PostMapping("/dataMigrate")
@Operation(summary = "数据迁移")
public CommonResult<Boolean> dataMigrate(@RequestBody HandDetectorSaveReqVO updateReqVO) {
handDetectorService.dataMigrate(updateReqVO);
return CommonResult.success(true);
}
} }

2
cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/controller/admin/PersonnelController.java

@ -94,7 +94,7 @@ public class PersonnelController {
@Operation(summary = "获得全部人员信息") @Operation(summary = "获得全部人员信息")
@PreAuthorize("@ss.hasPermission('gas:personnel:query')") @PreAuthorize("@ss.hasPermission('gas:personnel:query')")
public CommonResult<List<PersonnelDO>> getListAll() { public CommonResult<List<PersonnelDO>> getListAll() {
List<PersonnelDO> listAll = personnelService.getListAll();
List<PersonnelDO> listAll = personnelService.getListAll(null);
return success(listAll); return success(listAll);
} }
@GetMapping("/export-excel") @GetMapping("/export-excel")

8
cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/dal/AlarmRuleDO.java

@ -76,4 +76,12 @@ public class AlarmRuleDO extends BaseDO {
* 租户id * 租户id
*/ */
private Long tenantId; private Long tenantId;
/**
* 部门id
*/
private Long deptId;
@TableField(exist = false)
private String gasTypeName;
} }

5
cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/dal/AlarmTypeDO.java

@ -56,5 +56,8 @@ public class AlarmTypeDO extends BaseDO {
*/ */
private Integer tenantId; private Integer tenantId;
/**
* 部门id
*/
private Long deptId;
} }

5
cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/dal/FactoryDO.java

@ -92,6 +92,9 @@ public class FactoryDO extends BaseDO {
*/ */
private String remark; private String remark;
/**
* 部门id
*/
private Long deptId;
} }

5
cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/dal/FenceAlarmDO.java

@ -85,4 +85,9 @@ public class FenceAlarmDO extends BaseDO {
* 租户id * 租户id
*/ */
private Integer tenantId; private Integer tenantId;
/**
* 部门id
*/
private Long deptId;
} }

5
cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/dal/FenceDO.java

@ -52,4 +52,9 @@ public class FenceDO extends BaseDO {
* 租户id * 租户id
*/ */
private Integer tenantId; private Integer tenantId;
/**
* 部门id
*/
private Long deptId;
} }

7
cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/dal/GasTypeDO.java

@ -48,9 +48,14 @@ public class GasTypeDO extends BaseDO {
*/ */
private String remark; private String remark;
/** /**
* 租户id * 租户id
*/ */
private Integer tenantId; private Integer tenantId;
/**
* 部门id
*/
private Long deptId;
} }

4
cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/dal/HandAlarmDO.java

@ -103,4 +103,8 @@ public class HandAlarmDO extends BaseDO {
*/ */
private Long tenantId; private Long tenantId;
/**
* 部门id
*/
private Long deptId;
} }

10
cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/dal/HandDetectorDO.java

@ -28,6 +28,7 @@ public class HandDetectorDO extends BaseDO {
@TableId @TableId
private Long id; private Long id;
@TableField(updateStrategy = FieldStrategy.ALWAYS)
private Long personId; private Long personId;
/** /**
@ -37,15 +38,18 @@ public class HandDetectorDO extends BaseDO {
/** /**
* 持有人姓名 * 持有人姓名
*/ */
@TableField(updateStrategy = FieldStrategy.ALWAYS)
private String name; private String name;
/** /**
* 围栏id * 围栏id
*/ */
@TableField(updateStrategy = FieldStrategy.ALWAYS)
private String fenceIds; private String fenceIds;
/** /**
* 围栏类型 * 围栏类型
*/ */
@TableField(updateStrategy = FieldStrategy.ALWAYS)
private Integer fenceType; private Integer fenceType;
/** /**
* 气体类型ID * 气体类型ID
@ -110,6 +114,12 @@ public class HandDetectorDO extends BaseDO {
*/ */
private Integer tenantId; private Integer tenantId;
/**
* 部门id
*/
@TableField(updateStrategy = FieldStrategy.ALWAYS)
private Long deptId;
// 在 Setter 方法中加入 trim() 逻辑 // 在 Setter 方法中加入 trim() 逻辑
public void setSn(String sn) { public void setSn(String sn) {
// 先判断是否为 null,避免 NullPointerException // 先判断是否为 null,避免 NullPointerException

5
cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/dal/PersonnelDO.java

@ -52,5 +52,8 @@ public class PersonnelDO extends BaseDO {
*/ */
private Integer status; private Integer status;
/**
* 部门id
*/
private Long deptId;
} }

35
cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/datapermission/config/HandDataPermissionConfiguration.java

@ -0,0 +1,35 @@
package cn.iocoder.yudao.module.hand.datapermission.config;
import cn.iocoder.yudao.framework.datapermission.core.rule.dept.DeptDataPermissionRuleCustomizer;
import cn.iocoder.yudao.module.hand.dal.*;
import cn.iocoder.yudao.module.hand.enums.AlarmType;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* lock 模块的数据权限 Configuration
*
* @author 芋道源码
*/
@Configuration(proxyBeanMethods = false)
public class HandDataPermissionConfiguration {
@Bean
public DeptDataPermissionRuleCustomizer handDeptDataPermissionRuleCustomizer() {
return rule -> {
// dept
rule.addDeptColumn(AlarmRuleDO.class);
rule.addDeptColumn(AlarmTypeDO.class);
rule.addDeptColumn(FactoryDO.class);
rule.addDeptColumn(FenceAlarmDO.class);
rule.addDeptColumn(FenceDO.class);
rule.addDeptColumn(HandAlarmDO.class);
rule.addDeptColumn(HandDetectorDO.class);
rule.addDeptColumn(PersonnelDO.class);
// user
//rule.addUserColumn(AdminUserDO.class, "id");
};
}
}

4
cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/datapermission/package-info.java

@ -0,0 +1,4 @@
/**
* system 模块的数据权限配置
*/
package cn.iocoder.yudao.module.hand.datapermission;

20
cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/job/OfflineAlarmJob.java

@ -11,16 +11,14 @@ import cn.iocoder.yudao.module.hand.util.RedisKeyUtil;
import cn.iocoder.yudao.module.hand.util.RedisUtil; import cn.iocoder.yudao.module.hand.util.RedisUtil;
import cn.iocoder.yudao.module.hand.vo.HandAlarmSaveReqVO; import cn.iocoder.yudao.module.hand.vo.HandAlarmSaveReqVO;
import cn.iocoder.yudao.module.hand.vo.HandDataVo; import cn.iocoder.yudao.module.hand.vo.HandDataVo;
import com.alibaba.fastjson.JSON;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.time.ZoneId; import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@Component @Component
@ -58,6 +56,7 @@ public class OfflineAlarmJob implements JobHandler {
long currentTimeMillis = System.currentTimeMillis(); long currentTimeMillis = System.currentTimeMillis();
// 用于存储需要批量插入数据库的新报警记录 // 用于存储需要批量插入数据库的新报警记录
List<HandAlarmDO> newAlarmsToCreate = new ArrayList<>(); List<HandAlarmDO> newAlarmsToCreate = new ArrayList<>();
Map<String, HandDataVo> devicesToUpdateInRedis = new HashMap<>();
for (Map.Entry<Object, Object> entry : deviceDataMap.entrySet()) { for (Map.Entry<Object, Object> entry : deviceDataMap.entrySet()) {
try { try {
@ -91,6 +90,9 @@ public class OfflineAlarmJob implements JobHandler {
// c. 准备要插入数据库的报警记录 // c. 准备要插入数据库的报警记录
HandAlarmDO handAlarmDO = buildAlarmRecord(tenantId, handData); HandAlarmDO handAlarmDO = buildAlarmRecord(tenantId, handData);
newAlarmsToCreate.add(handAlarmDO); newAlarmsToCreate.add(handAlarmDO);
// 使用SN作为唯一Key,因为它在报警对象和设备对象中都存在
devicesToUpdateInRedis.put(handAlarmDO.getSn(), handData);
} }
} }
@ -105,6 +107,16 @@ public class OfflineAlarmJob implements JobHandler {
log.info("租户 {} 发现 {} 条新的设备离线报警,准备批量写入数据库...", tenantId, newAlarmsToCreate.size()); log.info("租户 {} 发现 {} 条新的设备离线报警,准备批量写入数据库...", tenantId, newAlarmsToCreate.size());
try { try {
handAlarmService.insertBatch(newAlarmsToCreate); handAlarmService.insertBatch(newAlarmsToCreate);
for (HandAlarmDO alarm : newAlarmsToCreate) {
// alarm.getId() 此时应该包含了数据库生成的ID
if (alarm.getId() != null && devicesToUpdateInRedis.containsKey(alarm.getSn())) {
HandDataVo dataToUpdate = devicesToUpdateInRedis.get(alarm.getSn());
dataToUpdate.setAlarmId(alarm.getId()); // 设置 alarmId
String deviceKey = alarm.getSn(); // 或者其他能定位到设备的Key
redisUtil.hset(tenantDeviceKey, deviceKey, dataToUpdate);
}
}
log.info("批量写入 {} 条设备离线报警记录成功", newAlarmsToCreate.size()); log.info("批量写入 {} 条设备离线报警记录成功", newAlarmsToCreate.size());
} catch (Exception e) { } catch (Exception e) {
log.error("批量写入设备离线报警记录失败", e); log.error("批量写入设备离线报警记录失败", e);

22
cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/mapper/HandDetectorMapper.java

@ -4,7 +4,10 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.module.hand.dal.HandDetectorDO; import cn.iocoder.yudao.module.hand.dal.HandDetectorDO;
import cn.iocoder.yudao.module.hand.dal.PersonnelDO;
import cn.iocoder.yudao.module.hand.vo.HandDetectorPageReqVO; import cn.iocoder.yudao.module.hand.vo.HandDetectorPageReqVO;
import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.cursor.Cursor; import org.apache.ibatis.cursor.Cursor;
@ -19,6 +22,7 @@ public interface HandDetectorMapper extends BaseMapperX<HandDetectorDO> {
default PageResult<HandDetectorDO> selectPage(HandDetectorPageReqVO reqVO) { default PageResult<HandDetectorDO> selectPage(HandDetectorPageReqVO reqVO) {
return selectPage(reqVO, new LambdaQueryWrapperX<HandDetectorDO>() return selectPage(reqVO, new LambdaQueryWrapperX<HandDetectorDO>()
.eqIfPresent(HandDetectorDO::getDeptId, reqVO.getDeptId())
.eqIfPresent(HandDetectorDO::getSn, reqVO.getSn()) .eqIfPresent(HandDetectorDO::getSn, reqVO.getSn())
.likeIfPresent(HandDetectorDO::getName, reqVO.getName()) .likeIfPresent(HandDetectorDO::getName, reqVO.getName())
.eqIfPresent(HandDetectorDO::getFenceIds, reqVO.getFenceIds()) .eqIfPresent(HandDetectorDO::getFenceIds, reqVO.getFenceIds())
@ -41,4 +45,22 @@ public interface HandDetectorMapper extends BaseMapperX<HandDetectorDO> {
Cursor<HandDetectorDO> selectCursor(QueryWrapper<Object> objectQueryWrapper); Cursor<HandDetectorDO> selectCursor(QueryWrapper<Object> objectQueryWrapper);
/**
* 在所有租户中根据SN统计数量
*
* @param sn 设备SN
* @param excludeId 需要排除的设备ID (用于更新场景)
* @return 存在相同SN的设备数量
*/
@InterceptorIgnore(tenantLine = "true") // 关键注解:忽略多租户插件的租户ID过滤
default Long selectCountBySnInAllTenant(String sn, Long excludeId) {
LambdaQueryWrapper<HandDetectorDO> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(HandDetectorDO::getSn, sn);
if (excludeId != null) {
wrapper.ne(HandDetectorDO::getId, excludeId);
}
return this.selectCount(wrapper); // 调用基类的 selectCount
}
} }

1
cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/mapper/PersonnelMapper.java

@ -20,6 +20,7 @@ public interface PersonnelMapper extends BaseMapperX<PersonnelDO> {
default PageResult<PersonnelDO> selectPage(PersonnelPageReqVO reqVO) { default PageResult<PersonnelDO> selectPage(PersonnelPageReqVO reqVO) {
return selectPage(reqVO, new LambdaQueryWrapperX<PersonnelDO>() return selectPage(reqVO, new LambdaQueryWrapperX<PersonnelDO>()
.likeIfPresent(PersonnelDO::getName, reqVO.getName()) .likeIfPresent(PersonnelDO::getName, reqVO.getName())
.eqIfPresent(PersonnelDO::getDeptId, reqVO.getDeptId())
.eqIfPresent(PersonnelDO::getEmployeeId, reqVO.getEmployeeId()) .eqIfPresent(PersonnelDO::getEmployeeId, reqVO.getEmployeeId())
.eqIfPresent(PersonnelDO::getUserId, reqVO.getUserId()) .eqIfPresent(PersonnelDO::getUserId, reqVO.getUserId())
.eqIfPresent(PersonnelDO::getPhone, reqVO.getPhone()) .eqIfPresent(PersonnelDO::getPhone, reqVO.getPhone())

4
cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/service/HandDetectorService.java

@ -72,4 +72,8 @@ public interface HandDetectorService {
Map<Object, Object> getMonitor(); Map<Object, Object> getMonitor();
List<HandDetectorDO> listAll(QueryWrapper<HandDetectorDO> handDetectorDOQueryWrapper); List<HandDetectorDO> listAll(QueryWrapper<HandDetectorDO> handDetectorDOQueryWrapper);
void dataMigrate(HandDetectorSaveReqVO updateReqVO);
List<HandDetectorDO> getListAll(Long deptId,Long tenantId);
} }

2
cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/service/PersonnelService.java

@ -61,5 +61,5 @@ public interface PersonnelService {
*/ */
PageResult<PersonnelDO> getPersonnelPage(PersonnelPageReqVO pageReqVO); PageResult<PersonnelDO> getPersonnelPage(PersonnelPageReqVO pageReqVO);
List<PersonnelDO> getListAll();
List<PersonnelDO> getListAll(Long deptId);
} }

22
cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/service/impl/AlarmRuleServiceImpl.java

@ -5,12 +5,14 @@ import cn.iocoder.yudao.framework.security.core.LoginUser;
import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore; import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder; import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
import cn.iocoder.yudao.module.hand.dal.AlarmRuleDO; import cn.iocoder.yudao.module.hand.dal.AlarmRuleDO;
import cn.iocoder.yudao.module.hand.dal.GasTypeDO;
import cn.iocoder.yudao.module.hand.mapper.AlarmRuleMapper; import cn.iocoder.yudao.module.hand.mapper.AlarmRuleMapper;
import cn.iocoder.yudao.module.hand.service.AlarmRuleService; import cn.iocoder.yudao.module.hand.service.AlarmRuleService;
import cn.iocoder.yudao.module.hand.util.RedisKeyUtil; import cn.iocoder.yudao.module.hand.util.RedisKeyUtil;
import cn.iocoder.yudao.module.hand.vo.AlarmRulePageReqVO; import cn.iocoder.yudao.module.hand.vo.AlarmRulePageReqVO;
import cn.iocoder.yudao.module.hand.vo.AlarmRuleSaveReqVO; import cn.iocoder.yudao.module.hand.vo.AlarmRuleSaveReqVO;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable; import org.springframework.cache.annotation.Cacheable;
@ -43,13 +45,12 @@ import static cn.iocoder.yudao.module.hand.enums.ErrorCodeConstants.ALARM_RULE_N
@Slf4j @Slf4j
public class AlarmRuleServiceImpl implements AlarmRuleService { public class AlarmRuleServiceImpl implements AlarmRuleService {
@Resource
private AlarmRuleMapper alarmRuleMapper;
// 定义一个常量来表示缓存清除的 SpEL 表达式,避免重复和拼写错误 // 定义一个常量来表示缓存清除的 SpEL 表达式,避免重复和拼写错误
private static final String EVICT_CACHE_KEY_SPEL = private static final String EVICT_CACHE_KEY_SPEL =
"'gas_rules_map:' + T(cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder).getTenantId()"; "'gas_rules_map:' + T(cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder).getTenantId()";
@Resource
private AlarmRuleMapper alarmRuleMapper;
@Override @Override
@CacheEvict(cacheNames = RedisKeyUtil.ALARM_RULES_CACHE_NAME, @CacheEvict(cacheNames = RedisKeyUtil.ALARM_RULES_CACHE_NAME,
// 【关键修改】使用 #tenantId 来引用方法参数,确保缓存key与查询数据严格对应。 // 【关键修改】使用 #tenantId 来引用方法参数,确保缓存key与查询数据严格对应。
@ -83,7 +84,6 @@ public class AlarmRuleServiceImpl implements AlarmRuleService {
validateAlarmRuleExists(id); validateAlarmRuleExists(id);
// 删除 // 删除
alarmRuleMapper.deleteById(id); alarmRuleMapper.deleteById(id);
LoginUser loginUser = getLoginUser();
} }
@ -117,9 +117,14 @@ public class AlarmRuleServiceImpl implements AlarmRuleService {
// --- 这段代码只会在缓存未命中时执行 --- // --- 这段代码只会在缓存未命中时执行 ---
log.info("气体报警规则缓存未命中,租户ID: {},执行数据库查询和分组...", tenantId); log.info("气体报警规则缓存未命中,租户ID: {},执行数据库查询和分组...", tenantId);
QueryWrapper<AlarmRuleDO> ruleDOQueryWrapper = new QueryWrapper<>();
ruleDOQueryWrapper.lambda().eq(AlarmRuleDO::getTenantId, tenantId);
List<AlarmRuleDO> allRules = alarmRuleMapper.selectList(ruleDOQueryWrapper);
MPJLambdaWrapper<AlarmRuleDO> wrapper = new MPJLambdaWrapper<AlarmRuleDO>()
.selectAll(AlarmRuleDO.class)
.selectAs(GasTypeDO::getName, AlarmRuleDO::getGasTypeName) // 查询副表字段并映射别名
.leftJoin(GasTypeDO.class, GasTypeDO::getId, AlarmRuleDO::getGasTypeId)
.eq(AlarmRuleDO::getTenantId, tenantId)
.eq(AlarmRuleDO::getDeleted, 0);
List<AlarmRuleDO> allRules = alarmRuleMapper.selectJoinList(AlarmRuleDO.class, wrapper);
// 2. 按 GasTypeId 分组 // 2. 按 GasTypeId 分组
return allRules.stream() return allRules.stream()
@ -130,6 +135,7 @@ public class AlarmRuleServiceImpl implements AlarmRuleService {
public PageResult<AlarmRuleDO> getAlarmRulePage(AlarmRulePageReqVO pageReqVO) { public PageResult<AlarmRuleDO> getAlarmRulePage(AlarmRulePageReqVO pageReqVO) {
return alarmRuleMapper.selectPage(pageReqVO); return alarmRuleMapper.selectPage(pageReqVO);
} }
@Override @Override
public List<AlarmRuleDO> getListAll() { public List<AlarmRuleDO> getListAll() {
return alarmRuleMapper.selectList(); return alarmRuleMapper.selectList();

4
cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/service/impl/FenceAlarmServiceImpl.java

@ -1,6 +1,7 @@
package cn.iocoder.yudao.module.hand.service.impl; package cn.iocoder.yudao.module.hand.service.impl;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
import cn.iocoder.yudao.module.hand.dal.FenceAlarmDO; import cn.iocoder.yudao.module.hand.dal.FenceAlarmDO;
import cn.iocoder.yudao.module.hand.mapper.FenceAlarmMapper; import cn.iocoder.yudao.module.hand.mapper.FenceAlarmMapper;
import cn.iocoder.yudao.module.hand.service.FenceAlarmService; import cn.iocoder.yudao.module.hand.service.FenceAlarmService;
@ -34,6 +35,7 @@ public class FenceAlarmServiceImpl implements FenceAlarmService {
private FenceAlarmMapper fenceAlarmMapper; private FenceAlarmMapper fenceAlarmMapper;
@Override @Override
@TenantIgnore
public Long createFenceAlarm(FenceAlarmSaveReqVO createReqVO) { public Long createFenceAlarm(FenceAlarmSaveReqVO createReqVO) {
// 插入 // 插入
FenceAlarmDO fenceAlarm = BeanUtils.toBean(createReqVO, FenceAlarmDO.class); FenceAlarmDO fenceAlarm = BeanUtils.toBean(createReqVO, FenceAlarmDO.class);
@ -74,6 +76,7 @@ public class FenceAlarmServiceImpl implements FenceAlarmService {
} }
@Override @Override
@TenantIgnore
public FenceAlarmDO getFenceAlarm(Long id) { public FenceAlarmDO getFenceAlarm(Long id) {
return fenceAlarmMapper.selectById(id); return fenceAlarmMapper.selectById(id);
} }
@ -84,6 +87,7 @@ public class FenceAlarmServiceImpl implements FenceAlarmService {
} }
@Override @Override
@TenantIgnore
public void update(FenceAlarmDO updateReqVO) { public void update(FenceAlarmDO updateReqVO) {
fenceAlarmMapper.updateById(updateReqVO); fenceAlarmMapper.updateById(updateReqVO);

110
cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/service/impl/HandDetectorServiceImpl.java

@ -11,6 +11,7 @@ import cn.iocoder.yudao.module.hand.util.RedisUtil;
import cn.iocoder.yudao.module.hand.vo.HandDataVo; import cn.iocoder.yudao.module.hand.vo.HandDataVo;
import cn.iocoder.yudao.module.hand.vo.HandDetectorPageReqVO; import cn.iocoder.yudao.module.hand.vo.HandDetectorPageReqVO;
import cn.iocoder.yudao.module.hand.vo.HandDetectorSaveReqVO; import cn.iocoder.yudao.module.hand.vo.HandDetectorSaveReqVO;
import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import jakarta.annotation.PostConstruct; import jakarta.annotation.PostConstruct;
@ -24,10 +25,12 @@ import org.springframework.cache.annotation.CacheEvict;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import java.time.Duration; import java.time.Duration;
import java.util.*; import java.util.*;
import java.util.stream.Collectors;
import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
@ -114,7 +117,10 @@ public class HandDetectorServiceImpl implements HandDetectorService {
} }
// 校验SN是否已存在(排除自身) // 校验SN是否已存在(排除自身)
validateSnUnique(createReqVO.getSn(), null);
Long count = handDetectorMapper.selectCountBySnInAllTenant(createReqVO.getSn(), null);
if (count > 0) {
throw exception(HAND_DETECTOR_SN_EXISTS);
}
// 插入 // 插入
HandDetectorDO handDetector = BeanUtils.toBean(createReqVO, HandDetectorDO.class); HandDetectorDO handDetector = BeanUtils.toBean(createReqVO, HandDetectorDO.class);
handDetectorMapper.insert(handDetector); handDetectorMapper.insert(handDetector);
@ -128,20 +134,6 @@ public class HandDetectorServiceImpl implements HandDetectorService {
return handDetector.getId(); return handDetector.getId();
} }
private void validateSnUnique(String sn, Long excludeId) {
LambdaQueryWrapper<HandDetectorDO> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(HandDetectorDO::getSn, sn);
if (excludeId != null) {
wrapper.ne(HandDetectorDO::getId, excludeId);
}
Long count = handDetectorMapper.selectCount(wrapper);
if (count > 0) {
throw exception(HAND_DETECTOR_SN_EXISTS);
}
}
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void updateHandDetector(HandDetectorSaveReqVO updateReqVO) { public void updateHandDetector(HandDetectorSaveReqVO updateReqVO) {
@ -161,7 +153,10 @@ public class HandDetectorServiceImpl implements HandDetectorService {
boolean snChanged = !oldSn.equals(newSn); boolean snChanged = !oldSn.equals(newSn);
if (snChanged) { if (snChanged) {
// 校验SN是否已存在(排除自身) // 校验SN是否已存在(排除自身)
validateSnUnique(newSn, updateReqVO.getId());
Long count = handDetectorMapper.selectCountBySnInAllTenant(newSn, updateReqVO.getId());
if (count > 0) {
throw exception(HAND_DETECTOR_SN_EXISTS);
}
// 1. 从全局设备与租户的映射中删除旧的SN // 1. 从全局设备与租户的映射中删除旧的SN
redisUtil.hdel(RedisKeyUtil.getDeviceTenantMappingKey(), oldSn); redisUtil.hdel(RedisKeyUtil.getDeviceTenantMappingKey(), oldSn);
// 2. 从租户自己的设备信息缓存中删除旧的SN // 2. 从租户自己的设备信息缓存中删除旧的SN
@ -265,4 +260,87 @@ public class HandDetectorServiceImpl implements HandDetectorService {
return handDetectorMapper.selectList(handDetectorDOQueryWrapper); return handDetectorMapper.selectList(handDetectorDOQueryWrapper);
} }
@Override
@Transactional(rollbackFor = Exception.class)
@TenantIgnore
public void dataMigrate(HandDetectorSaveReqVO migrateReqVO) {
// 1. --- 输入校验 ---
if (CollectionUtils.isEmpty(migrateReqVO.getIdList()) || migrateReqVO.getTenantId() == null) {
// 如果没有提供设备ID或目标租户ID,则直接返回或抛出异常
return;
}
// 2. --- 数据准备 ---
// 一次性查询出所有待迁移的设备实体
List<HandDetectorDO> devicesToMigrate = handDetectorMapper.selectByIds(migrateReqVO.getIdList());
if (CollectionUtils.isEmpty(devicesToMigrate)) {
// 如果根据ID没有查到任何设备,直接返回
return;
}
// 获取旧的租户ID(假设一批迁移的设备都来自同一个租户)
Integer oldTenantId = devicesToMigrate.get(0).getTenantId();
// 新的租户ID
Integer newTenantId = migrateReqVO.getTenantId();
// 如果迁移到同一个租户,没有意义,直接返回
if (oldTenantId.equals(newTenantId)) {
return;
}
// 收集所有待迁移设备的SN
List<String> deviceSns = devicesToMigrate.stream()
.map(HandDetectorDO::getSn)
.toList();
// 3. --- 数据库更新 ---
// 遍历设备列表,更新租户ID并清空特定于旧租户的关联数据
for (HandDetectorDO device : devicesToMigrate) {
device.setTenantId(newTenantId);
// 清空与旧租户相关的业务字段
device.setFenceIds(null);
device.setFenceType(null);
device.setName(null);
device.setPersonId(null);
device.setDeptId(null);
device.setRemark(null);
device.setGasTypeId(null);
}
// 批量更新数据库
handDetectorMapper.updateBatch(devicesToMigrate);
// 4. --- Redis缓存处理 ---
// 4.1. 清理旧租户的设备信息缓存
String oldTenantDeviceKey = RedisKeyUtil.getTenantDeviceHashKey(Long.valueOf(oldTenantId));
// 从旧租户的Hash中批量删除这些设备
String[] snsAsArray = deviceSns.toArray(String[]::new);
redisUtil.hdel(oldTenantDeviceKey, (Object) snsAsArray);
// 4.2. 更新全局的 SN -> TenantID 映射缓存
// 创建一个 Map: {sn1 -> newTenantId, sn2 -> newTenantId, ...}
Map<Object, Object> globalDeviceTenantMap = deviceSns.stream()
.collect(Collectors.toMap(sn -> sn, sn -> newTenantId));
redisUtil.hmset(RedisKeyUtil.getDeviceTenantMappingKey(), globalDeviceTenantMap);
// 4.3. 添加到新租户的设备信息缓存
// 创建一个 Map: {sn1 -> deviceObj1, sn2 -> deviceObj2, ...}
Map<Object, Object> newTenantDeviceMap = devicesToMigrate.stream()
.collect(Collectors.toMap(HandDetectorDO::getSn, device -> device, (v1, v2) -> v1));
String newTenantDeviceKey = RedisKeyUtil.getTenantDeviceHashKey(Long.valueOf(newTenantId));
redisUtil.hmset(newTenantDeviceKey, newTenantDeviceMap);
}
@Override
@TenantIgnore
public List<HandDetectorDO> getListAll(Long deptId,Long tenantId) {
QueryWrapper<HandDetectorDO> queryWrapper = new QueryWrapper<>();
if (deptId != null){
queryWrapper.eq("dept_id", deptId);
}
queryWrapper.eq("tenant_id", tenantId);
return handDetectorMapper.selectList(queryWrapper);
}
} }

30
cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/service/impl/PersonnelServiceImpl.java

@ -1,11 +1,15 @@
package cn.iocoder.yudao.module.hand.service.impl; package cn.iocoder.yudao.module.hand.service.impl;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.module.hand.dal.HandDetectorDO;
import cn.iocoder.yudao.module.hand.dal.PersonnelDO; import cn.iocoder.yudao.module.hand.dal.PersonnelDO;
import cn.iocoder.yudao.module.hand.mapper.HandDetectorMapper;
import cn.iocoder.yudao.module.hand.mapper.PersonnelMapper; import cn.iocoder.yudao.module.hand.mapper.PersonnelMapper;
import cn.iocoder.yudao.module.hand.service.PersonnelService; import cn.iocoder.yudao.module.hand.service.PersonnelService;
import cn.iocoder.yudao.module.hand.vo.PersonnelPageReqVO; import cn.iocoder.yudao.module.hand.vo.PersonnelPageReqVO;
import cn.iocoder.yudao.module.hand.vo.PersonnelSaveReqVO; import cn.iocoder.yudao.module.hand.vo.PersonnelSaveReqVO;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
@ -34,6 +38,9 @@ public class PersonnelServiceImpl implements PersonnelService {
@Resource @Resource
private PersonnelMapper personnelMapper; private PersonnelMapper personnelMapper;
@Resource
private HandDetectorMapper handDetectorMapper;
@Override @Override
public Long createPersonnel(PersonnelSaveReqVO createReqVO) { public Long createPersonnel(PersonnelSaveReqVO createReqVO) {
// 插入 // 插入
@ -45,12 +52,27 @@ public class PersonnelServiceImpl implements PersonnelService {
} }
@Override @Override
@Transactional(rollbackFor = Exception.class)
public void updatePersonnel(PersonnelSaveReqVO updateReqVO) { public void updatePersonnel(PersonnelSaveReqVO updateReqVO) {
// 校验存在 // 校验存在
validatePersonnelExists(updateReqVO.getId()); validatePersonnelExists(updateReqVO.getId());
// 更新 // 更新
PersonnelDO updateObj = BeanUtils.toBean(updateReqVO, PersonnelDO.class); PersonnelDO updateObj = BeanUtils.toBean(updateReqVO, PersonnelDO.class);
personnelMapper.updateById(updateObj); personnelMapper.updateById(updateObj);
// 避免传入不相关的字段。
UpdateWrapper<HandDetectorDO> handDetectorUpdateWrapper = new UpdateWrapper<>();
handDetectorUpdateWrapper.eq("person_id", updateReqVO.getId());
handDetectorUpdateWrapper.set("name", updateReqVO.getName()); // 假设需要同步姓名
handDetectorUpdateWrapper.set("person_id", updateReqVO.getId()); // 假设需要同步部门ID
handDetectorMapper.update(null, handDetectorUpdateWrapper);
} }
@Override @Override
@ -85,8 +107,12 @@ public class PersonnelServiceImpl implements PersonnelService {
} }
@Override @Override
public List<PersonnelDO> getListAll() {
return personnelMapper.selectList();
public List<PersonnelDO> getListAll(Long deptId) {
QueryWrapper<PersonnelDO> queryWrapper = new QueryWrapper<>();
if (deptId != null){
queryWrapper.eq("dept_id", deptId);
}
return personnelMapper.selectList(queryWrapper);
} }
} }

16
cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/service/impl/TdengineServiceImpl.java

@ -1,6 +1,7 @@
package cn.iocoder.yudao.module.hand.service.impl; package cn.iocoder.yudao.module.hand.service.impl;
import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.security.core.LoginUser;
import cn.iocoder.yudao.module.hand.mapper.TdengineMapper; import cn.iocoder.yudao.module.hand.mapper.TdengineMapper;
import cn.iocoder.yudao.module.hand.service.TdengineService; import cn.iocoder.yudao.module.hand.service.TdengineService;
import cn.iocoder.yudao.module.hand.vo.HandOriginalLog; import cn.iocoder.yudao.module.hand.vo.HandOriginalLog;
@ -20,6 +21,8 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUser;
@Service @Service
@Validated @Validated
@DS("tdengine") @DS("tdengine")
@ -73,7 +76,10 @@ public class TdengineServiceImpl implements TdengineService {
@Override @Override
public PageResult<TdengineDataVo> getHandDataLog(HandTdenginePageVO pageReqVO) { public PageResult<TdengineDataVo> getHandDataLog(HandTdenginePageVO pageReqVO) {
IPage<TdengineDataVo> page = new Page<>(pageReqVO.getPageNo(), pageReqVO.getPageSize()); IPage<TdengineDataVo> page = new Page<>(pageReqVO.getPageNo(), pageReqVO.getPageSize());
LoginUser loginUser = getLoginUser();
if (loginUser != null){
pageReqVO.setTenantId(loginUser.getTenantId());
}
IPage<TdengineDataVo> resultPage = tdengineMapper.selectPage(page, pageReqVO); IPage<TdengineDataVo> resultPage = tdengineMapper.selectPage(page, pageReqVO);
List<TdengineDataVo> doList = resultPage.getRecords(); List<TdengineDataVo> doList = resultPage.getRecords();
@ -89,6 +95,10 @@ public class TdengineServiceImpl implements TdengineService {
public PageResult<HandOriginalLog> getOriginalLogPage(HandTdenginePageVO pageReqVO) { public PageResult<HandOriginalLog> getOriginalLogPage(HandTdenginePageVO pageReqVO) {
IPage<HandOriginalLog> page = new Page<>(pageReqVO.getPageNo(), pageReqVO.getPageSize()); IPage<HandOriginalLog> page = new Page<>(pageReqVO.getPageNo(), pageReqVO.getPageSize());
LoginUser loginUser = getLoginUser();
if (loginUser != null){
pageReqVO.setTenantId(loginUser.getTenantId());
}
IPage<HandOriginalLog> resultPage = tdengineMapper.selectOriginalPage(page, pageReqVO); IPage<HandOriginalLog> resultPage = tdengineMapper.selectOriginalPage(page, pageReqVO);
List<HandOriginalLog> doList = resultPage.getRecords(); List<HandOriginalLog> doList = resultPage.getRecords();
@ -102,6 +112,10 @@ public class TdengineServiceImpl implements TdengineService {
@Override @Override
public List<TdengineDataVo> HistoricalSn(HandTdenginePo po) { public List<TdengineDataVo> HistoricalSn(HandTdenginePo po) {
LoginUser loginUser = getLoginUser();
if (loginUser != null){
po.setTenantId(loginUser.getTenantId());
}
return tdengineMapper.HistoricalSn(po); return tdengineMapper.HistoricalSn(po);
} }
} }

8
cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/util/RedisUtil.java

@ -283,9 +283,15 @@ public class RedisUtil {
* @param item 可以使多个 不能为null * @param item 可以使多个 不能为null
*/ */
public void hdel(String key, Object... item) { public void hdel(String key, Object... item) {
// 关键检查:判断是否收到了一个被包装的数组
if (item != null && item.length == 1 && item[0] instanceof Object[]) {
// 如果是,则解开内层数组进行传递
redisTemplate.opsForHash().delete(key, (Object[]) item[0]);
} else {
// 否则,按原样传递
redisTemplate.opsForHash().delete(key, item); redisTemplate.opsForHash().delete(key, item);
} }
}
/** /**
* 判断hash表中是否有该项的值 * 判断hash表中是否有该项的值
* *

3
cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/vo/AlarmRulePageReqVO.java

@ -59,4 +59,7 @@ public class AlarmRulePageReqVO extends PageParam {
@Schema(description = "更新者") @Schema(description = "更新者")
private String updater; private String updater;
@Schema(description = "部门id")
private Long deptId;
} }

3
cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/vo/AlarmRuleRespVO.java

@ -69,5 +69,8 @@ public class AlarmRuleRespVO {
@ExcelProperty("创建时间") @ExcelProperty("创建时间")
private LocalDateTime createTime; private LocalDateTime createTime;
@Schema(description = "部门id")
@ExcelProperty("部门id")
private Long deptId;
} }

2
cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/vo/AlarmRuleSaveReqVO.java

@ -49,5 +49,7 @@ public class AlarmRuleSaveReqVO {
@Schema(description = "备注", example = "你说的对") @Schema(description = "备注", example = "你说的对")
private String remark; private String remark;
@Schema(description = "部门id")
private Long deptId;
} }

2
cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/vo/AlarmTypePageReqVO.java

@ -39,5 +39,7 @@ public class AlarmTypePageReqVO extends PageParam {
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime; private LocalDateTime[] createTime;
@Schema(description = "部门id")
private Long deptId;
} }

2
cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/vo/AlarmTypeRespVO.java

@ -48,5 +48,7 @@ public class AlarmTypeRespVO {
@ExcelProperty("创建时间") @ExcelProperty("创建时间")
private LocalDateTime createTime; private LocalDateTime createTime;
@Schema(description = "部门id")
private Long deptId;
} }

4
cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/vo/AlarmTypeSaveReqVO.java

@ -30,8 +30,10 @@ public class AlarmTypeSaveReqVO {
@Schema(description = "排序", requiredMode = Schema.RequiredMode.REQUIRED) @Schema(description = "排序", requiredMode = Schema.RequiredMode.REQUIRED)
private Integer sortOrder; private Integer sortOrder;
@Schema(description = "备注", example = "随便") @Schema(description = "备注", example = "随便")
private String remark; private String remark;
@Schema(description = "部门id")
private Long deptId;
} }

3
cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/vo/FactoryPageReqVO.java

@ -65,4 +65,7 @@ public class FactoryPageReqVO extends PageParam {
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime; private LocalDateTime[] createTime;
@Schema(description = "部门id")
private Long deptId;
} }

4
cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/vo/FactoryRespVO.java

@ -83,4 +83,8 @@ public class FactoryRespVO {
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("创建时间") @ExcelProperty("创建时间")
private LocalDateTime createTime; private LocalDateTime createTime;
@Schema(description = "部门id")
private Long deptId;
} }

3
cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/vo/FactorySaveReqVO.java

@ -65,4 +65,7 @@ public class FactorySaveReqVO {
@Schema(description = "备注", example = "你猜") @Schema(description = "备注", example = "你猜")
private String remark; private String remark;
@Schema(description = "部门id")
private Long deptId;
} }

3
cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/vo/FenceAlarmPageReqVO.java

@ -54,4 +54,7 @@ public class FenceAlarmPageReqVO extends PageParam {
@ExcelProperty("创建时间") @ExcelProperty("创建时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime; private LocalDateTime[] createTime;
@Schema(description = "部门id")
private Long deptId;
} }

6
cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/vo/FenceAlarmRespVO.java

@ -16,9 +16,6 @@ public class FenceAlarmRespVO {
@ExcelProperty("主键ID") @ExcelProperty("主键ID")
private Long id; private Long id;
/**
* 手持表SN
*/
@Schema(description = "手持表SN", requiredMode = Schema.RequiredMode.REQUIRED, example = "123456") @Schema(description = "手持表SN", requiredMode = Schema.RequiredMode.REQUIRED, example = "123456")
private String sn; private String sn;
@ -69,4 +66,7 @@ public class FenceAlarmRespVO {
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("创建时间") @ExcelProperty("创建时间")
private LocalDateTime createTime; private LocalDateTime createTime;
@Schema(description = "部门id")
private Long deptId;
} }

3
cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/vo/FenceAlarmSaveReqVO.java

@ -66,4 +66,7 @@ public class FenceAlarmSaveReqVO {
* 创建时间 * 创建时间
*/ */
private LocalDateTime createTime; private LocalDateTime createTime;
@Schema(description = "部门id")
private Long deptId;
} }

3
cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/vo/FencePageReqVO.java

@ -33,4 +33,7 @@ public class FencePageReqVO extends PageParam {
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("创建时间") @ExcelProperty("创建时间")
private LocalDateTime[] createTime; private LocalDateTime[] createTime;
@Schema(description = "部门id")
private Long deptId;
} }

3
cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/vo/FenceRespVO.java

@ -39,4 +39,7 @@ public class FenceRespVO {
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("创建时间") @ExcelProperty("创建时间")
private LocalDateTime createTime; private LocalDateTime createTime;
@Schema(description = "部门id")
private Long deptId;
} }

3
cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/vo/FenceSaveReqVO.java

@ -27,5 +27,6 @@ public class FenceSaveReqVO {
@Schema(description = "备注", example = "你说的对") @Schema(description = "备注", example = "你说的对")
private String remark; private String remark;
@Schema(description = "部门id")
private Long deptId;
} }

3
cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/vo/GasTypePageReqVO.java

@ -33,4 +33,7 @@ public class GasTypePageReqVO extends PageParam {
@ExcelProperty("创建时间") @ExcelProperty("创建时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime; private LocalDateTime[] createTime;
@Schema(description = "部门id")
private Long deptId;
} }

3
cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/vo/GasTypeRespVO.java

@ -39,4 +39,7 @@ public class GasTypeRespVO {
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("创建时间") @ExcelProperty("创建时间")
private LocalDateTime createTime; private LocalDateTime createTime;
@Schema(description = "部门id")
private Long deptId;
} }

3
cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/vo/GasTypeSaveReqVO.java

@ -30,5 +30,6 @@ public class GasTypeSaveReqVO {
@Schema(description = "备注", example = "你说的对") @Schema(description = "备注", example = "你说的对")
private String remark; private String remark;
@Schema(description = "部门id")
private Long deptId;
} }

3
cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/vo/HandAlarmPageReqVO.java

@ -67,4 +67,7 @@ public class HandAlarmPageReqVO extends PageParam {
@ExcelProperty("创建时间") @ExcelProperty("创建时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime; private LocalDateTime[] createTime;
@Schema(description = "部门id")
private Long deptId;
} }

3
cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/vo/HandAlarmRespVO.java

@ -83,4 +83,7 @@ public class HandAlarmRespVO {
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("创建时间") @ExcelProperty("创建时间")
private LocalDateTime createTime; private LocalDateTime createTime;
@Schema(description = "部门id")
private Long deptId;
} }

3
cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/vo/HandAlarmSaveReqVO.java

@ -83,4 +83,7 @@ public class HandAlarmSaveReqVO {
* 创建时间 * 创建时间
*/ */
private LocalDateTime createTime; private LocalDateTime createTime;
@Schema(description = "部门id")
private Long deptId;
} }

6
cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/vo/HandDataVo.java

@ -106,4 +106,10 @@ public class HandDataVo {
@Schema(description = "租户id") @Schema(description = "租户id")
private Long tenantId; private Long tenantId;
@Schema(description = "部门id")
private Long deptId;
@Schema(description = "最后推送数据")
private Double lastPushValue;
} }

3
cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/vo/HandDetectorPageReqVO.java

@ -91,4 +91,7 @@ public class HandDetectorPageReqVO extends PageParam {
@ExcelProperty("创建时间") @ExcelProperty("创建时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime; private LocalDateTime[] createTime;
@Schema(description = "部门id")
private Long deptId;
} }

3
cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/vo/HandDetectorRespVO.java

@ -111,5 +111,6 @@ public class HandDetectorRespVO {
@ExcelProperty("创建时间") @ExcelProperty("创建时间")
private LocalDateTime createTime; private LocalDateTime createTime;
@Schema(description = "部门id")
private Long deptId;
} }

8
cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/vo/HandDetectorSaveReqVO.java

@ -5,6 +5,7 @@ import lombok.*;
import jakarta.validation.constraints.*; import jakarta.validation.constraints.*;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.List;
@Schema(description = "管理后台 - GAS手持探测器新增/修改 Request VO") @Schema(description = "管理后台 - GAS手持探测器新增/修改 Request VO")
@Data @Data
@ -79,7 +80,14 @@ public class HandDetectorSaveReqVO {
@Schema(description = "备注", example = "你猜") @Schema(description = "备注", example = "你猜")
private String remark; private String remark;
@Schema(description = "部门id")
private Long deptId;
@Schema(description = "id列表")
private List<Long> idList;
@Schema(description = "租户id")
private Integer tenantId;
} }

2
cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/vo/PersonnelPageReqVO.java

@ -35,4 +35,6 @@ public class PersonnelPageReqVO extends PageParam {
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime; private LocalDateTime[] createTime;
@Schema(description = "部门id")
private Long deptId;
} }

2
cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/vo/PersonnelRespVO.java

@ -44,4 +44,6 @@ public class PersonnelRespVO {
@ExcelProperty("创建时间") @ExcelProperty("创建时间")
private LocalDateTime createTime; private LocalDateTime createTime;
@Schema(description = "部门id")
private Long deptId;
} }

2
cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/vo/PersonnelSaveReqVO.java

@ -32,4 +32,6 @@ public class PersonnelSaveReqVO {
@NotNull(message = "状态 (1-在职, 0-离职)不能为空") @NotNull(message = "状态 (1-在职, 0-离职)不能为空")
private Integer status; private Integer status;
@Schema(description = "部门id")
private Long deptId;
} }

12
cc-admin-master/yudao-module-hand/src/main/java/cn/iocoder/yudao/module/hand/vo/personnelAlarmVo.java

@ -0,0 +1,12 @@
package cn.iocoder.yudao.module.hand.vo;
import lombok.Data;
@Data
public class personnelAlarmVo {
private String name;
private String alarmName;
private String unitName;
}

7
cc-admin-master/yudao-module-hand/src/main/resources/mapper/TdengineMapper.xml

@ -44,7 +44,7 @@
AND sn = #{vo.sn} AND sn = #{vo.sn}
</if> </if>
<if test="vo.tenantId != null"> <if test="vo.tenantId != null">
AND tenant_id = #{vo.tenantId}
AND tenantId = #{vo.tenantId}
</if> </if>
<if test="vo.startTime != null"> <if test="vo.startTime != null">
AND ts >= #{vo.startTime} AND ts >= #{vo.startTime}
@ -69,7 +69,7 @@
AND sn = #{vo.sn} AND sn = #{vo.sn}
</if> </if>
<if test="vo.tenantId != null"> <if test="vo.tenantId != null">
AND tenant_id = #{vo.tenantId}
AND tenantId = #{vo.tenantId}
</if> </if>
<if test="vo.startTime != null"> <if test="vo.startTime != null">
AND ts >= #{vo.startTime} AND ts >= #{vo.startTime}
@ -86,6 +86,7 @@
SELECT SELECT
_wstart as ts, _wstart as ts,
LAST(`value`) as `value`, LAST(`value`) as `value`,
LAST(`battery`) as `battery`,
LAST(longitude) as longitude, LAST(longitude) as longitude,
LAST(latitude) as latitude LAST(latitude) as latitude
FROM FROM
@ -109,6 +110,6 @@
</if> </if>
</where> </where>
INTERVAL(1m) INTERVAL(1m)
ORDER BY ts DESC
ORDER BY ts ASC
</select> </select>
</mapper> </mapper>

2
cc-admin-master/yudao-server/pom.xml

@ -81,7 +81,7 @@
<build> <build>
<!-- 设置构建的 jar 包名 --> <!-- 设置构建的 jar 包名 -->
<finalName>cc-admin-mobile</finalName>
<finalName>mobile-server</finalName>
<plugins> <plugins>
<!-- 打包 --> <!-- 打包 -->
<plugin> <plugin>

34
cc-admin-master/yudao-server/src/main/resources/application-dev.yaml

@ -48,11 +48,17 @@ spring:
primary: master primary: master
datasource: datasource:
master: master:
url: jdbc:mysql://127.0.0.1:3306/hand_alarm?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true&rewriteBatchedStatements=true # MySQL Connector/J 8.X 连接的示例
url: jdbc:mysql://192.168.0.180:3306/hand_alarm?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true&rewriteBatchedStatements=true # MySQL Connector/J 8.X 连接的示例
username: root username: root
password: roomasd111
password: Gsking164411
driver-class-name: com.mysql.cj.jdbc.Driver # MySQL Connector/J 8.X 连接的示例 driver-class-name: com.mysql.cj.jdbc.Driver # MySQL Connector/J 8.X 连接的示例
tdengine:
url: jdbc:TAOS-RS://192.168.0.207:6041/hand_alarm
username: root
password: Gsking164411
driver-class-name: com.taosdata.jdbc.rs.RestfulDriver # TDengine 连接的示例
druid:
validation-query: SELECT 1 # TDengine 的验证 SQL
# Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优 # Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优
data: data:
@ -108,11 +114,11 @@ spring:
password: rabbit # RabbitMQ 服务的密码 password: rabbit # RabbitMQ 服务的密码
# Kafka 配置项,对应 KafkaProperties 配置类 # Kafka 配置项,对应 KafkaProperties 配置类
kafka: kafka:
bootstrap-servers: zdmq.zdhlcn.com:9092 # 或者内网地址 172.21.16.6:9091
properties:
security.protocol: SASL_PLAINTEXT
sasl.mechanism: SCRAM-SHA-512
sasl.jaas.config: 'org.apache.kafka.common.security.scram.ScramLoginModule required username="zdkafka" password="Zdhl@2025";'
bootstrap-servers: 127.0.0.1:9092 # 或者内网地址 172.21.16.6:9091,或者测试地址video.zdhlcn.com:9092,zdmq.zdhlcn.com:9092
# properties:
# security.protocol: SASL_PLAINTEXT
# sasl.mechanism: SCRAM-SHA-512
# sasl.jaas.config: 'org.apache.kafka.common.security.scram.ScramLoginModule required username="zdkafka" password="Zdhl@2025";'
--- #################### 服务保障相关配置 #################### --- #################### 服务保障相关配置 ####################
# Lock4j 配置项 # Lock4j 配置项
@ -156,7 +162,7 @@ logging:
cn.iocoder.yudao.module.pay.dal.mysql: debug cn.iocoder.yudao.module.pay.dal.mysql: debug
cn.iocoder.yudao.module.pay.dal.mysql.notify.PayNotifyTaskMapper: INFO # 配置 PayNotifyTaskMapper 的日志级别为 info cn.iocoder.yudao.module.pay.dal.mysql.notify.PayNotifyTaskMapper: INFO # 配置 PayNotifyTaskMapper 的日志级别为 info
cn.iocoder.yudao.module.system.dal.mysql: debug cn.iocoder.yudao.module.system.dal.mysql: debug
cn.iocoder.yudao.module.mqtt: WARN
cn.iocoder.yudao.module.mqtt: info
org.springframework.context.support.PostProcessorRegistrationDelegate: ERROR # TODO 芋艿:先禁用,Spring Boot 3.X 存在部分错误的 WARN 提示 org.springframework.context.support.PostProcessorRegistrationDelegate: ERROR # TODO 芋艿:先禁用,Spring Boot 3.X 存在部分错误的 WARN 提示
# 打开 dynamic-datasource 框架的 DEBUG 日志 # 打开 dynamic-datasource 框架的 DEBUG 日志
#com.baomidou.dynamic.datasource: DEBUG #com.baomidou.dynamic.datasource: DEBUG
@ -216,9 +222,9 @@ pf4j:
mqtt: mqtt:
enable: true enable: true
url: tcp://zdmq.zdhlcn.com:2883
username: mobileqt
password: DVSwxQwY<x
url: tcp://127.0.0.1:1883
username: root
password: roomasd111
client: client:
id: cc-admin-qg-dev44 id: cc-admin-qg-dev44
connectionTimeout: 10 connectionTimeout: 10
@ -226,8 +232,8 @@ mqtt:
cleanSession: true cleanSession: true
subscribe: subscribe:
# $share/hand_alarm/+/zds_up //MQTT 共享订阅,不是多台服务器的情况下不要开启 # $share/hand_alarm/+/zds_up //MQTT 共享订阅,不是多台服务器的情况下不要开启
topic: +/up,+/ups,+/will,+/zds_up
qos: 1,1,1,1
topic: +/zds_up,+/zds_down
qos: 1,1
default: default:
publishQos: 1 publishQos: 1
offlineTime: 180 # 超过 180 秒无数据则判为数据超时 offlineTime: 180 # 超过 180 秒无数据则判为数据超时

4
cc-admin-master/yudao-server/src/main/resources/application-local.yaml

@ -232,8 +232,8 @@ mqtt:
cleanSession: true cleanSession: true
subscribe: subscribe:
# $share/hand_alarm/+/zds_up //MQTT 共享订阅,不是多台服务器的情况下不要开启 # $share/hand_alarm/+/zds_up //MQTT 共享订阅,不是多台服务器的情况下不要开启
topic: +/up,+/ups,+/will,+/zds_up
qos: 1,1,1,1
topic: +/zds_up,+/zds_down
qos: 1,1
default: default:
publishQos: 1 publishQos: 1
offlineTime: 180 # 超过 180 秒无数据则判为数据超时 offlineTime: 180 # 超过 180 秒无数据则判为数据超时

7
cc-admin-master/yudao-server/src/main/resources/application-prod.yaml

@ -114,7 +114,7 @@ spring:
password: rabbit # RabbitMQ 服务的密码 password: rabbit # RabbitMQ 服务的密码
# Kafka 配置项,对应 KafkaProperties 配置类 # Kafka 配置项,对应 KafkaProperties 配置类
kafka: kafka:
bootstrap-servers: 172.21.16.6:9091 # 或者内网地址 172.21.16.6:9091
bootstrap-servers: 172.21.16.6:9092 # 或者内网地址 172.21.16.6:9091
properties: properties:
security.protocol: SASL_PLAINTEXT security.protocol: SASL_PLAINTEXT
sasl.mechanism: SCRAM-SHA-512 sasl.mechanism: SCRAM-SHA-512
@ -174,6 +174,7 @@ logging:
cn.iocoder.yudao.module.iot.dal.mysql: debug cn.iocoder.yudao.module.iot.dal.mysql: debug
cn.iocoder.yudao.module.iot.dal.tdengine: DEBUG cn.iocoder.yudao.module.iot.dal.tdengine: DEBUG
cn.iocoder.yudao.module.ai.dal.mysql: debug cn.iocoder.yudao.module.ai.dal.mysql: debug
cn.iocoder.yudao.module.mqtt: error
org.springframework.context.support.PostProcessorRegistrationDelegate: ERROR # TODO 芋艿:先禁用,Spring Boot 3.X 存在部分错误的 WARN 提示 org.springframework.context.support.PostProcessorRegistrationDelegate: ERROR # TODO 芋艿:先禁用,Spring Boot 3.X 存在部分错误的 WARN 提示
debug: false debug: false
@ -242,8 +243,8 @@ mqtt:
cleanSession: true cleanSession: true
subscribe: subscribe:
# $share/hand_alarm/+/zds_up //MQTT 共享订阅,不是多台服务器的情况下不要开启 # $share/hand_alarm/+/zds_up //MQTT 共享订阅,不是多台服务器的情况下不要开启
topic: +/up,+/ups,+/will,+/zds_up
qos: 1,1,1,1
topic: +/zds_up,+/zds_down
qos: 1,1
default: default:
publishQos: 1 publishQos: 1
offlineTime: 180 # 超过 180 秒无数据则判为数据超时 offlineTime: 180 # 超过 180 秒无数据则判为数据超时

3
cc-admin-master/yudao-server/src/main/resources/application.yaml

@ -1,9 +1,8 @@
spring: spring:
application: application:
name: gas_mobile name: gas_mobile
profiles: profiles:
active: local
active: prod
main: main:
allow-circular-references: true # 允许循环依赖,因为项目是三层架构,无法避免这个情况。 allow-circular-references: true # 允许循环依赖,因为项目是三层架构,无法避免这个情况。

Loading…
Cancel
Save