From 99ecb29f3c90777b3306e911c15f5a850c3aa182 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B1=88=E5=B1=95=E8=88=AA?= <2426745133@qq.com> Date: Thu, 4 Dec 2025 15:39:06 +0800 Subject: [PATCH] =?UTF-8?q?12-04-=E4=BA=BA=E5=91=98=E5=AE=9A=E4=BD=8D-?= =?UTF-8?q?=E7=BB=88=E7=89=88-=E4=BC=98=E5=8C=96=E7=89=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/RydwWebSocketServer.java | 351 ++++++------------ 1 file changed, 110 insertions(+), 241 deletions(-) diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/websocket/websocket/service/RydwWebSocketServer.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/websocket/websocket/service/RydwWebSocketServer.java index e6f5a96a..2b96d0e1 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/websocket/websocket/service/RydwWebSocketServer.java +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/websocket/websocket/service/RydwWebSocketServer.java @@ -60,6 +60,8 @@ public class RydwWebSocketServer { log.info("✅ 人员定位WebSocket 服务端已随项目启动初始化!端点路径:/websocket/rydw"); } + private static final String[] TIME_SLOTS = {"06:00", "08:00", "10:00", "12:00", "14:00", "16:00", "18:00"}; + /** * 客户端连接时触发(无需手动启动,有客户端连接时自动调用) */ @@ -329,124 +331,34 @@ public class RydwWebSocketServer { /** * 柱状图数据初始化 */ - public void zztcsh (List> allValue,List busProjectPunchranges,List persons,long expireSeconds){ + public void zztcsh(List> allValue, List busProjectPunchranges, + List persons, long expireSeconds) { for (BusProjectPunchrange busProjectPunchrange : busProjectPunchranges) { - Map map2 = new HashMap<>(); + Map map2 = new HashMap<>(); - boolean existsObject = RedisUtils.isExistsObject(busProjectPunchrange.getId() + ":" + busProjectPunchrange.getPunchName() + ":06:00"); - if (!existsObject) { - RedisUtils.setCacheObject(busProjectPunchrange.getId() + ":" + busProjectPunchrange.getPunchName() + ":06:00", 0, Duration.ofSeconds(expireSeconds)); - map2.put("06:00",0); - }else { - //如果存在 循环找到打卡的人 - Integer i = 0; - for (SubConstructionUser person : persons) { - //这个人 在6点 是否活跃过 "rydw_tj_"+busProjectPunchrange.getId() + "_" + "06:00" + "_" + constructionUser.getSysUserId() - boolean b = RedisUtils.isExistsObject("rydw_tj_"+busProjectPunchrange.getId() + "_" + "06:00" + "_" + person.getSysUserId()); - if ( b){ - i++; + for (String timeSlot : TIME_SLOTS) { + String redisKey = busProjectPunchrange.getId() + ":" + busProjectPunchrange.getPunchName() + ":" + timeSlot; + boolean existsObject = RedisUtils.isExistsObject(redisKey); + + if (!existsObject) { + RedisUtils.setCacheObject(redisKey, 0, Duration.ofSeconds(expireSeconds)); + map2.put(timeSlot, 0); + } else { + int count = 0; + String timeSlotKey = "rydw_tj_" + busProjectPunchrange.getId() + "_" + timeSlot + "_"; + int timeSlotKeyLength = timeSlotKey.length(); + + for (SubConstructionUser person : persons) { + if (RedisUtils.isExistsObject(timeSlotKey + person.getSysUserId())) { + count++; + } } + map2.put(timeSlot, count); } - map2.put("06:00",i); } - existsObject = RedisUtils.isExistsObject(busProjectPunchrange.getId() + ":" + busProjectPunchrange.getPunchName() + ":08:00"); - if (!existsObject) { - RedisUtils.setCacheObject(busProjectPunchrange.getId() + ":" + busProjectPunchrange.getPunchName() + ":08:00", 0, Duration.ofSeconds(expireSeconds)); - map2.put("08:00",0); - }else { - //如果存在 循环找到打卡的人 - Integer i = 0; - for (SubConstructionUser person : persons) { - boolean b = RedisUtils.isExistsObject("rydw_tj_"+busProjectPunchrange.getId() + "_" + "08:00" + "_" + person.getSysUserId()); - if ( b){ - i++; - } - } - map2.put("08:00",i); - } - - existsObject = RedisUtils.isExistsObject(busProjectPunchrange.getId() + ":" + busProjectPunchrange.getPunchName() + ":10:00"); - if (!existsObject) { - RedisUtils.setCacheObject(busProjectPunchrange.getId() + ":" + busProjectPunchrange.getPunchName() + ":10:00", 0, Duration.ofSeconds(expireSeconds)); - map2.put("10:00",0); - }else { - //如果存在 循环找到打卡的人 - Integer i = 0; - for (SubConstructionUser person : persons) { - boolean b = RedisUtils.isExistsObject("rydw_tj_"+busProjectPunchrange.getId() + "_" + "10:00" + "_" + person.getSysUserId()); - if ( b){ - i++; - } - } - map2.put("10:00",i); - } - - existsObject = RedisUtils.isExistsObject(busProjectPunchrange.getId() + ":" + busProjectPunchrange.getPunchName() + ":12:00"); - if (!existsObject) { - RedisUtils.setCacheObject(busProjectPunchrange.getId() + ":" + busProjectPunchrange.getPunchName() + ":12:00", 0, Duration.ofSeconds(expireSeconds)); - map2.put("12:00",0); - }else { - //如果存在 循环找到打卡的人 - Integer i = 0; - for (SubConstructionUser person : persons) { - boolean b = RedisUtils.isExistsObject("rydw_tj_"+busProjectPunchrange.getId() + "_" + "12:00" + "_" + person.getSysUserId()); - if ( b){ - i++; - } - } - map2.put("12:00",i); - } - - existsObject = RedisUtils.isExistsObject(busProjectPunchrange.getId() + ":" + busProjectPunchrange.getPunchName() + ":14:00"); - if (!existsObject) { - RedisUtils.setCacheObject(busProjectPunchrange.getId() + ":" + busProjectPunchrange.getPunchName() + ":14:00", 0, Duration.ofSeconds(expireSeconds)); - map2.put("14:00",0); - }else { - //如果存在 循环找到打卡的人 - Integer i = 0; - for (SubConstructionUser person : persons) { - boolean b = RedisUtils.isExistsObject("rydw_tj_"+busProjectPunchrange.getId() + "_" + "14:00" + "_" + person.getSysUserId()); - if ( b){ - i++; - } - } - map2.put("14:00",i); - } - - existsObject = RedisUtils.isExistsObject(busProjectPunchrange.getId() + ":" + busProjectPunchrange.getPunchName() + ":16:00"); - if (!existsObject) { - RedisUtils.setCacheObject(busProjectPunchrange.getId() + ":" + busProjectPunchrange.getPunchName() + ":16:00", 0, Duration.ofSeconds(expireSeconds)); - map2.put("16:00",0); - }else { - //如果存在 循环找到打卡的人 - Integer i = 0; - for (SubConstructionUser person : persons) { - boolean b = RedisUtils.isExistsObject("rydw_tj_"+busProjectPunchrange.getId() + "_" + "16:00" + "_" + person.getSysUserId()); - if ( b){ - i++; - } - } - map2.put("16:00",i); - } - - if (!existsObject) { - RedisUtils.setCacheObject(busProjectPunchrange.getId() + ":" + busProjectPunchrange.getPunchName() + ":18:00", 0, Duration.ofSeconds(expireSeconds)); - map2.put("18:00",0); - }else { - //如果存在 循环找到打卡的人 - Integer i = 0; - for (SubConstructionUser person : persons) { - boolean b = RedisUtils.isExistsObject("rydw_tj_"+busProjectPunchrange.getId() + "_" + "18:00" + "_" + person.getSysUserId()); - if ( b){ - i++; - } - } - map2.put("18:00",i); - } - - Map map1 = new HashMap<>(); - map1.put(busProjectPunchrange.getId()+":"+busProjectPunchrange.getPunchName(),map2); + Map map1 = new HashMap<>(); + map1.put(busProjectPunchrange.getId() + ":" + busProjectPunchrange.getPunchName(), map2); allValue.add(map1); } } @@ -454,100 +366,53 @@ public class RydwWebSocketServer { /** * 柱状图 数据 */ - public void setZztData(String key,List> allValue,GpsEquipmentSon one,BusProjectPunchrange busProjectPunchrange,SubConstructionUser constructionUser,long expireSeconds){ + public void setZztData(String key, List> allValue, GpsEquipmentSon one, + BusProjectPunchrange busProjectPunchrange, SubConstructionUser constructionUser, long expireSeconds) { + + // 先找到对应的map,避免在循环内部多次判断 + Map timeSlotMap = null; for (Map mapMap : allValue) { - //这个map为 id+名字 : 时间段 MAP - if (mapMap.containsKey(key)){ - //找到了时间段map - LocalDateTime dateTime = one.getCreateTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime(); - // 获取小时数 - int hour = dateTime.getHour(); - // 根据小时数判断所属区间并增加计数 一个人在一个时间段只能增加一次 设计一个新的redis存储 Key = 范围ID + 时间段 + 用户ID value = 0(未统计)1(已统计) 过期时间 = 今天为止 - if (hour >= 6 && hour < 8) { - //先从redis判断此人在该时间段是否已经活动过 - boolean b = RedisUtils.isExistsObject("rydw_tj_"+busProjectPunchrange.getId() + "_" + "06:00" + "_" + constructionUser.getSysUserId()); - //如果不存在 - if (!b) { - mapMap.get(key).put("06:00", (int) mapMap.get(key).get("06:00") + 1); - //将redis中该时间段人数+1 map中已经加过 - RedisUtils.setCacheObject(busProjectPunchrange.getId() + ":" + busProjectPunchrange.getPunchName() + ":06:00", (int) mapMap.get(key).get("06:00"), Duration.ofSeconds(expireSeconds)); - //判断数据添加到redis - RedisUtils.setCacheObject("rydw_tj_"+busProjectPunchrange.getId() + "_" + "06:00" + "_" + constructionUser.getSysUserId(), 1, Duration.ofSeconds(expireSeconds)); - } + if (mapMap.containsKey(key)) { + timeSlotMap = mapMap.get(key); + break; + } + } - } else if (hour >= 8 && hour < 10) { - //先从redis判断此人在该时间段是否已经活动过 - boolean b = RedisUtils.isExistsObject("rydw_tj_"+busProjectPunchrange.getId() + "_" + "08:00" + "_" + constructionUser.getSysUserId()); - //如果不存在 - if (!b) { - mapMap.get(key).put("08:00", (int) mapMap.get(key).get("08:00") + 1); - //将redis中该时间段人数+1 - RedisUtils.setCacheObject(busProjectPunchrange.getId() + ":" + busProjectPunchrange.getPunchName() + ":08:00", (int) mapMap.get(key).get("08:00"), Duration.ofSeconds(expireSeconds)); - //判断数据添加到redis - RedisUtils.setCacheObject("rydw_tj_"+busProjectPunchrange.getId() + "_" + "08:00" + "_" + constructionUser.getSysUserId(), 1, Duration.ofSeconds(expireSeconds)); - } + if (timeSlotMap == null) return; - } else if (hour >= 10 && hour < 12) { - //先从redis判断此人在该时间段是否已经活动过 - boolean b = RedisUtils.isExistsObject("rydw_tj_"+busProjectPunchrange.getId() + "_" + "10:00" + "_" + constructionUser.getSysUserId()); - //如果不存在 - if (!b) { - mapMap.get(key).put("10:00", (int) mapMap.get(key).get("10:00") + 1); - //将redis中该时间段人数+1 - RedisUtils.setCacheObject(busProjectPunchrange.getId() + ":" + busProjectPunchrange.getPunchName() + ":10:00", (int) mapMap.get(key).get("10:00"), Duration.ofSeconds(expireSeconds)); - //判断数据添加到redis - RedisUtils.setCacheObject("rydw_tj_"+busProjectPunchrange.getId() + "_" + "10:00" + "_" + constructionUser.getSysUserId(), 1, Duration.ofSeconds(expireSeconds)); - } + LocalDateTime dateTime = one.getCreateTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime(); + int hour = dateTime.getHour(); - } else if (hour >= 12 && hour < 14) { - //先从redis判断此人在该时间段是否已经活动过 - boolean b = RedisUtils.isExistsObject("rydw_tj_"+busProjectPunchrange.getId() + "_" + "12:00" + "_" + constructionUser.getSysUserId()); - //如果不存在 - if (!b) { - mapMap.get(key).put("12:00", (int) mapMap.get(key).get("12:00") + 1); - //将redis中该时间段人数+1 - RedisUtils.setCacheObject(busProjectPunchrange.getId() + ":" + busProjectPunchrange.getPunchName() + ":12:00", (int) mapMap.get(key).get("12:00"), Duration.ofSeconds(expireSeconds)); - //判断数据添加到redis - RedisUtils.setCacheObject("rydw_tj_"+busProjectPunchrange.getId() + "_" + "12:00" + "_" + constructionUser.getSysUserId(), 1, Duration.ofSeconds(expireSeconds)); - } + // 使用映射表减少if-else判断 + Map hourToTimeSlot = new HashMap<>(); + hourToTimeSlot.put(6, "06:00"); + hourToTimeSlot.put(8, "08:00"); + hourToTimeSlot.put(10, "10:00"); + hourToTimeSlot.put(12, "12:00"); + hourToTimeSlot.put(14, "14:00"); + hourToTimeSlot.put(16, "16:00"); + hourToTimeSlot.put(18, "18:00"); - } else if (hour >= 14 && hour < 16) { - //先从redis判断此人在该时间段是否已经活动过 - boolean b = RedisUtils.isExistsObject("rydw_tj_"+busProjectPunchrange.getId() + "_" + "14:00" + "_" + constructionUser.getSysUserId()); - //如果不存在 - if (!b) { - mapMap.get(key).put("14:00", (int) mapMap.get(key).get("14:00") + 1); - //将redis中该时间段人数+1 - RedisUtils.setCacheObject(busProjectPunchrange.getId() + ":" + busProjectPunchrange.getPunchName() + ":14:00", (int) mapMap.get(key).get("14:00"), Duration.ofSeconds(expireSeconds)); - //判断数据添加到redis - RedisUtils.setCacheObject("rydw_tj_"+busProjectPunchrange.getId() + "_" + "14:00" + "_" + constructionUser.getSysUserId(), 1, Duration.ofSeconds(expireSeconds)); - } + for (Map.Entry entry : hourToTimeSlot.entrySet()) { + int startHour = entry.getKey(); + if (hour >= startHour && hour < startHour + 2) { + String timeSlot = entry.getValue(); + String redisCheckKey = "rydw_tj_" + busProjectPunchrange.getId() + "_" + timeSlot + "_" + constructionUser.getSysUserId(); - } else if (hour >= 16 && hour < 18) { - //先从redis判断此人在该时间段是否已经活动过 - boolean b = RedisUtils.isExistsObject("rydw_tj_"+busProjectPunchrange.getId() + "_" + "16:00" + "_" + constructionUser.getSysUserId()); - //如果不存在 - if (!b) { - mapMap.get(key).put("16:00", (int) mapMap.get(key).get("16:00") + 1); - //将redis中该时间段人数+1 - RedisUtils.setCacheObject(busProjectPunchrange.getId() + ":" + busProjectPunchrange.getPunchName() + ":16:00", (int) mapMap.get(key).get("16:00"), Duration.ofSeconds(expireSeconds)); - //判断数据添加到redis - RedisUtils.setCacheObject("rydw_tj_"+busProjectPunchrange.getId() + "_" + "16:00" + "_" + constructionUser.getSysUserId(), 1, Duration.ofSeconds(expireSeconds)); - } + if (!RedisUtils.isExistsObject(redisCheckKey)) { + // 原子性更新,避免并发问题 + synchronized (this) { + if (!RedisUtils.isExistsObject(redisCheckKey)) { + int currentCount = (int) timeSlotMap.get(timeSlot); + timeSlotMap.put(timeSlot, currentCount + 1); - } else if (hour >= 18 && hour < 20) { - //先从redis判断此人在该时间段是否已经活动过 - boolean b = RedisUtils.isExistsObject("rydw_tj_"+busProjectPunchrange.getId() + "_" + "18:00" + "_" + constructionUser.getSysUserId()); - //如果不存在 - if (!b) { - mapMap.get(key).put("18:00", (int) mapMap.get(key).get("18:00") + 1); - //将redis中该时间段人数+1 - RedisUtils.setCacheObject(busProjectPunchrange.getId() + ":" + busProjectPunchrange.getPunchName() + ":18:00", (int) mapMap.get(key).get("18:00"), Duration.ofSeconds(expireSeconds)); - //判断数据添加到redis - RedisUtils.setCacheObject("rydw_tj_"+busProjectPunchrange.getId() + "_" + "18:00" + "_" + constructionUser.getSysUserId(), 1, Duration.ofSeconds(expireSeconds)); + String redisCountKey = busProjectPunchrange.getId() + ":" + busProjectPunchrange.getPunchName() + ":" + timeSlot; + RedisUtils.setCacheObject(redisCountKey, currentCount + 1, Duration.ofSeconds(expireSeconds)); + RedisUtils.setCacheObject(redisCheckKey, 1, Duration.ofSeconds(expireSeconds)); + } } - } + break; // 找到对应时段后退出循环 } } } @@ -555,62 +420,66 @@ public class RydwWebSocketServer { /** * 统计饼状图 数据 */ - public List> getPieData(List> value,List persons,List dkfw) { - //redis中有判断标识数据: "rydw_tj_"+busProjectPunchrange.getId() + "_" + "06:00" + "_" + constructionUser.getSysUserId() + public List> getPieData(List> value, + List persons, + List dkfw) { - //饼状图数据Map - Map map = new HashMap<>(); + // 使用Set去重,提高查找效率 + Set userRangeSet = new HashSet<>(); + // 预构建打卡范围ID到名称的映射 + Map rangeIdToName = new HashMap<>(); + for (BusProjectPunchrange fw : dkfw) { + rangeIdToName.put(fw.getId().toString(), fw.getPunchName()); + } + + // 遍历所有数据 for (Map mapMap : value) { - //打卡范围ID : 打卡范围名称 - Set keys = mapMap.keySet(); - for (String fwIdMc : keys) { - //时间段 - Set keySet = mapMap.get(fwIdMc).keySet(); - for (Object time : keySet) { - //组合key值进行查询redis: 打卡范围ID + "_" + 时间段 + "_" + 用户ID - String[] split = fwIdMc.split(":"); - //分离出范围ID - String fwId = split[0]; - //范围名称 - String fwMc = split[1]; - //组合用户id进行循环查询 + for (Map.Entry entry : mapMap.entrySet()) { + String fwIdMc = entry.getKey(); + String[] split = fwIdMc.split(":"); + if (split.length < 2) continue; + + String fwId = split[0]; + String fwName = rangeIdToName.get(fwId); + if (fwName == null) continue; + + Map timeMap = entry.getValue(); + for (String timeSlot : timeMap.keySet()) { + // 批量构建redis key + List redisKeys = new ArrayList<>(); for (SubConstructionUser person : persons) { - //在此范围 此时间 循环用户 -> 在此范围 下一个时间 循环用户 -> 在下一个范围 此时间 循环用户 - String key = "rydw_tj_"+fwId + "_" + time + "_" + person.getSysUserId(); - //针对时间去重 一个范围内只需要有一个时间段在范围内 其余不统计 - if (RedisUtils.isExistsObject( key)){ - //在map中判断 如果有 则不进行添加 - if (!map.containsKey(fwId + "_" + person.getSysUserId())) { - //如果没有 则说明该用户在 这个范围 这个时间段 有数据 可以添加 - map.put(fwId + "_" + person.getSysUserId(), 1); - } + redisKeys.add("rydw_tj_" + fwId + "_" + timeSlot + "_" + person.getSysUserId()); + } + + // 批量查询redis(假设RedisUtils支持批量操作) + // 如果RedisUtils不支持批量,可以批量获取以减少网络开销 + for (int i = 0; i < redisKeys.size(); i++) { + if (RedisUtils.isExistsObject(redisKeys.get(i))) { + String uniqueKey = fwId + "_" + persons.get(i).getSysUserId(); + userRangeSet.add(uniqueKey); } } } } } - //循环完成后 可以统计出 在此范围 此用户 是否活跃过 + // 统计结果 Map countMap = new HashMap<>(); - //再次进行循环 统计出 一个范围内 多少活跃 用一个新map进行计数 - map.forEach((key, num) -> { - for (BusProjectPunchrange fw : dkfw) { - //提取出范围ID - String fwId = key.split("_")[0]; - if (fw.getId().toString().equals(fwId)) { - if (!countMap.containsKey(fw.getId() + ":" + fw.getPunchName())){ - //如果没有则初始化为1人 - countMap.put(fw.getId() + ":" + fw.getPunchName(), 1); - }else { - //如果有则进行累加 - countMap.put(fw.getId() + ":" + fw.getPunchName(), countMap.get(fw.getId() + ":" + fw.getPunchName()) + 1); - } - } + for (String userRangeKey : userRangeSet) { + String[] parts = userRangeKey.split("_"); + if (parts.length < 2) continue; + + String fwId = parts[0]; + String fwName = rangeIdToName.get(fwId); + if (fwName != null) { + String rangeKey = fwId + ":" + fwName; + countMap.put(rangeKey, countMap.getOrDefault(rangeKey, 0) + 1); } - //放一条测试数据 - countMap.put("1000000:测试数据", 8); - }); + } + + // 测试数据 + countMap.put("1000000:测试数据", 8); return new ArrayList<>(countMap.entrySet()); }