wenhongquan 5 месяцев назад
Родитель
Сommit
f594831c6b

+ 130 - 110
ruoyi-modules/ruoyi-dzbc/src/main/java/org/dromara/system/controller/TblDzbcPathSchedulingController.java

@@ -1,6 +1,7 @@
 package org.dromara.system.controller;
 
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import java.time.Duration;
 import java.util.*;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.stream.Collectors;
@@ -146,144 +147,163 @@ public class TblDzbcPathSchedulingController extends BaseController {
                                    @RequestParam(required = true) Long fromareaId,
                                    @RequestParam(required = true) Long toareaId,
                                    @RequestParam(required = false) Integer type) {
-        //优先从缓存中获取车量信息  缓存没有则初始化缓存
-        Date date = new Date();
+        Date date;
         try{
             date =  DateUtil.parseDate(searchDate);
         }catch (Exception e){
             return R.fail("日期格式不正确 eg:2025-02-01");
         }
 
+        // 优化:直接根据日期构建Redis Key,避免 keys * 扫描和加载所有日期数据
+        String redisKey = StrUtil.format("dzbc_path_scheduling|{}", DateUtil.formatDate(date));
+        Map<String, TblDzbcPathSchedulingVo> dataMap = RedisUtils.getCacheMap(redisKey);
 
-        Collection ret = RedisUtils.keys("dzbc_path_scheduling");
-        if (ret == null||ret.size()<1) {
+        // 如果缓存为空,则查询数据库加载当天数据
+        if (dataMap == null || dataMap.isEmpty()) {
             TblDzbcPathSchedulingBo bo = new TblDzbcPathSchedulingBo();
-            bo.getParams().put("mdate", DateUtil.today());
-            List<TblDzbcPathSchedulingVo> allTblDzbcPathScheduling = tblDzbcPathSchedulingService.queryList(bo);
-            for (TblDzbcPathSchedulingVo tblDzbcPathSchedulingVo : allTblDzbcPathScheduling) {
-               Map<String, TblDzbcPathSchedulingVo> dataMap =  RedisUtils.getCacheMap(StrUtil.format("dzbc_path_scheduling|{}", DateUtil.formatDate(tblDzbcPathSchedulingVo.getMdate())));
-               if(dataMap == null||dataMap.size()<1) dataMap =new HashMap<>();
-                dataMap.put(tblDzbcPathSchedulingVo.getId().toString(), tblDzbcPathSchedulingVo);
-                RedisUtils.setCacheMap(StrUtil.format("dzbc_path_scheduling|{}", DateUtil.formatDate(tblDzbcPathSchedulingVo.getMdate())), dataMap);
-                RedisUtils.expire(StrUtil.format("dzbc_path_scheduling|{}", DateUtil.formatDate(tblDzbcPathSchedulingVo.getMdate())), DateUtil.offset(tblDzbcPathSchedulingVo.getMdate(), DateField.HOUR_OF_DAY, 24).getTime() - DateUtil.current());
+            // 精确匹配日期
+            bo.setMdate(date);
+            List<TblDzbcPathSchedulingVo> schedulingList = tblDzbcPathSchedulingService.queryList(bo);
+
+            if (schedulingList != null && !schedulingList.isEmpty()) {
+                dataMap = new HashMap<>();
+                for (TblDzbcPathSchedulingVo vo : schedulingList) {
+                    dataMap.put(vo.getId().toString(), vo);
+                }
+                // 存入 Redis,设置过期时间
+                RedisUtils.setCacheMap(redisKey, dataMap);
+                // 默认过期时间设置为 24 小时后,或者当天的 24 小时后
+                long expireTime = DateUtil.offset(date, DateField.HOUR_OF_DAY, 24).getTime() - DateUtil.current();
+                if (expireTime > 0) {
+                    RedisUtils.expire(redisKey, Duration.ofMillis(expireTime));
+                } else {
+                    RedisUtils.expire(redisKey, Duration.ofHours(2));
+                }
             }
         }
-        Map<String, TblDzbcPathSchedulingVo> dataMap = RedisUtils.getCacheMap(StrUtil.format("dzbc_path_scheduling|{}", DateUtil.formatDate(date)));
-        //先获取
-        if(dataMap == null||dataMap.size()<1){
-            return  R.fail("没有排班信息");
-        }else{
-            Date finalDate = date;
-            List<TblDzbcPathSchedulingVo> carTickets = dataMap.values().stream().filter(item -> {
-                // 类型筛选逻辑
-                if (type != null) {
-                    // 如果指定了类型,必须匹配类型
-                    if (!Objects.equals(item.getType(), type)) {
-                        return false;
-                    }
-                } else {
-                    // 如果没指定类型,默认排除固定线路 (type=2)
-                    if (item.getType() != null && item.getType() == 2) {
-                        return false;
-                    }
+
+        if(dataMap == null || dataMap.isEmpty()){
+            return R.fail("没有排班信息");
+        }
+
+        Date finalDate = date;
+        // 过滤符合条件的排班
+        List<TblDzbcPathSchedulingVo> carTickets = dataMap.values().stream().filter(item -> {
+            if (type != null) {
+                if (!Objects.equals(item.getType(), type)) {
+                    return false;
                 }
-                if(item.getExt1()!=null){
-                   JSONObject dataObject = JSONUtil.parseObj(item.getExt1()).getJSONObject("pathInfo");
-                   if(Objects.equals(dataObject.getLong("startArea"), fromareaId) && Objects.equals(dataObject.getLong("endArea"), toareaId)){
-                       //大于1小时
-                       if(item.getMdate().getTime()- finalDate.getTime()> 3600*1000){
-                           dataMap.remove(item.getId());
-                           RedisUtils.setCacheMap(StrUtil.format("dzbc_path_scheduling|{}", DateUtil.formatDate(finalDate)), dataMap);
-                           return false;
-                       }
-
-                       return true;
-                   }
+            } else {
+                if (item.getType() != null && item.getType() == 2) {
+                    return false;
                 }
+            }
 
-                return false;
-            }).collect(Collectors.toList());
+            if(item.getExt1()!=null){
+                try {
+                    JSONObject dataObject = JSONUtil.parseObj(item.getExt1()).getJSONObject("pathInfo");
+                    if(dataObject != null &&
+                       Objects.equals(dataObject.getLong("startArea"), fromareaId) &&
+                       Objects.equals(dataObject.getLong("endArea"), toareaId)){
+
+                        // 简单的过期校验
+                        if(item.getMdate().getTime() - finalDate.getTime() > 3600*1000){
+                             return false;
+                        }
+                        return true;
+                    }
+                } catch (Exception e) {
+                    // ignore parse error
+                }
+            }
+            return false;
+        }).collect(Collectors.toList());
 
-            if(carTickets.size()<1){return  R.fail("没有排班信息");}
+        if(carTickets.isEmpty()){return R.fail("没有排班信息");}
 
-            //计算余票
-            for (TblDzbcPathSchedulingVo carTicket : carTickets) {
-                //先计算车辆座位数
-                if(carTicket.getExt1() != null){
-                    try {
-                        JSONObject data = JSONUtil.parseObj(carTicket.getExt1());
-                        JSONObject carInfo = data.getJSONObject("carInfo");
-                        Integer zw =  carInfo.getInt("carZw");
-                        carTicket.setTicket(zw);
-                    }
-                    catch (Exception e){
-                        carTicket.setTicket(0);
-                        carTicket.setCarStatus("已售罄");
-                    }
-                }else{
+        // 批量查询 Path 信息,解决 N+1 问题
+        Set<Long> pathIds = carTickets.stream()
+            .map(TblDzbcPathSchedulingVo::getPathId)
+            .filter(Objects::nonNull)
+            .collect(Collectors.toSet());
+
+        Map<Long, TblDzbcPathVo> pathMap = new HashMap<>();
+        if (!pathIds.isEmpty()) {
+            List<TblDzbcPathVo> paths = tblDzbcPathService.queryByIds(pathIds);
+            pathMap = paths.stream().collect(Collectors.toMap(TblDzbcPathVo::getId, java.util.function.Function.identity(), (k1, k2) -> k1));
+        }
+
+        // 计算余票
+        for (TblDzbcPathSchedulingVo carTicket : carTickets) {
+            //先计算车辆座位数
+            if(carTicket.getExt1() != null){
+                try {
+                    JSONObject data = JSONUtil.parseObj(carTicket.getExt1());
+                    JSONObject carInfo = data.getJSONObject("carInfo");
+                    Integer zw =  carInfo.getInt("carZw");
+                    carTicket.setTicket(zw);
+                }
+                catch (Exception e){
                     carTicket.setTicket(0);
                     carTicket.setCarStatus("已售罄");
                 }
+            }else{
+                carTicket.setTicket(0);
+                carTicket.setCarStatus("已售罄");
+            }
 
-                if(carTicket.getExt2() != null){
-                    //获取已售车票
-                    //{
-                    //   orderid:{ zw:2,userinfos:[user1,{lx:'成人','name':'张三','cardNo':'1234567890','cardType':'身份证'}]  }
-                    // }
-                    try {
-                        AtomicInteger salszw = new AtomicInteger();
-                        JSONObject data = JSONUtil.parseObj(carTicket.getExt2());
-                        data.keySet().stream().forEach( orderid -> {
-                            // 排除type字段
-                            if ("type".equals(orderid)) {
-                                return;
-                            }
-                            JSONObject order = data.getJSONObject(orderid);
-                            if (order != null && order.containsKey("zw")) {
-                                salszw.addAndGet(order.getInt("zw"));
-                            }
-                        } );
-                        carTicket.setTicket(carTicket.getTicket() - salszw.get());
-                        if(carTicket.getTicket()<1){
-                            carTicket.setCarStatus("已售罄");
+            if(carTicket.getExt2() != null){
+                try {
+                    AtomicInteger salszw = new AtomicInteger();
+                    JSONObject data = JSONUtil.parseObj(carTicket.getExt2());
+                    data.keySet().stream().forEach( orderid -> {
+                        if ("type".equals(orderid)) {
+                            return;
+                        }
+                        JSONObject order = data.getJSONObject(orderid);
+                        if (order != null && order.containsKey("zw")) {
+                            salszw.addAndGet(order.getInt("zw"));
+                        }
+                    } );
+                    carTicket.setTicket(carTicket.getTicket() - salszw.get());
+                    if(carTicket.getTicket()<1){
+                        carTicket.setCarStatus("已售罄");
+                    }else{
+                        if(carTicket.getTicket()<4){
+                            carTicket.setCarStatus("余票紧张");
                         }else{
-                            if(carTicket.getTicket()<4){
-                                carTicket.setCarStatus("余票紧张");
-                            }else{
-                                carTicket.setCarStatus("余票充足");
-                            }
+                            carTicket.setCarStatus("余票充足");
                         }
                     }
-                    catch (Exception e){
+                }
+                catch (Exception e){
+                    carTicket.setTicket(0);
+                    carTicket.setCarStatus("已售罄");
+                }
+
+            }
+            try {
+                //如果超出时间余票为0
+                if(carTicket.getMtime()==null||carTicket.getMtime().equals("")){
+                    // 使用批量查询的 Map 获取 PathVo
+                    TblDzbcPathVo pathVo = pathMap.get(carTicket.getPathId());
+                    if(pathVo != null){
+                        carTicket.setMtime(pathVo.getCostTime());
+                    }
+                }
+                if(carTicket.getMtime()!=null && !carTicket.getMtime().equals("")){
+                    Date datec =  DateUtil.parse(DateUtil.formatDate(carTicket.getMdate())+" "+carTicket.getMtime(), DatePattern.NORM_DATETIME_FORMAT);
+                    if(datec.getTime() < DateUtil.current()){
                         carTicket.setTicket(0);
-                        carTicket.setCarStatus("已售罄");
+                        carTicket.setCarStatus("已发车");
                     }
-
                 }
-               try {
-                   //如果超出时间余票为0
-                   if(carTicket.getMtime()==null||carTicket.getMtime().equals("")){
-                       TblDzbcPathVo pathVo = tblDzbcPathService.queryById(carTicket.getPathId());
-                       if(pathVo != null){
-                           carTicket.setMtime(pathVo.getCostTime());
-                       }
-                   }
-                   if(carTicket.getMtime()!=null && !carTicket.getMtime().equals("")){
-                       Date datec =  DateUtil.parse(DateUtil.formatDate(carTicket.getMdate())+" "+carTicket.getMtime(), DatePattern.NORM_DATETIME_FORMAT);
-                       if(datec.getTime() < DateUtil.current()){
-                           carTicket.setTicket(0);
-                           carTicket.setCarStatus("已发车");
-                       }
-                   }
-               } catch (Exception e) {
-
-               }
-
+            } catch (Exception e) {
 
             }
-
-            return R.ok(carTickets);
         }
+
+        return R.ok(carTickets);
     }
 
     @Log(title = "定制班车-多站点路线排班余票", businessType = BusinessType.FORCE)

+ 5 - 0
ruoyi-modules/ruoyi-dzbc/src/main/java/org/dromara/system/service/ITblDzbcPathService.java

@@ -25,6 +25,11 @@ public interface ITblDzbcPathService {
     /**
      * 查询定制班车-路线列表
      */
+    List<TblDzbcPathVo> queryByIds(Collection<Long> ids);
+
+    /**
+     * 查询定制班车-路线列表
+     */
     TableDataInfo<TblDzbcPathVo> queryPageList(TblDzbcPathBo bo, PageQuery pageQuery);
 
     /**

+ 8 - 0
ruoyi-modules/ruoyi-dzbc/src/main/java/org/dromara/system/service/impl/TblDzbcPathServiceImpl.java

@@ -40,6 +40,14 @@ public class TblDzbcPathServiceImpl implements ITblDzbcPathService {
         return baseMapper.selectVoById(id);
     }
 
+    @Override
+    public List<TblDzbcPathVo> queryByIds(Collection<Long> ids) {
+        if (ids == null || ids.isEmpty()) {
+            return List.of();
+        }
+        return baseMapper.selectVoBatchIds(ids);
+    }
+
     /**
      * 查询定制班车-路线列表
      */