|
@@ -1,6 +1,7 @@
|
|
|
package org.dromara.system.controller;
|
|
package org.dromara.system.controller;
|
|
|
|
|
|
|
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
|
|
+import java.time.Duration;
|
|
|
import java.util.*;
|
|
import java.util.*;
|
|
|
import java.util.concurrent.atomic.AtomicInteger;
|
|
import java.util.concurrent.atomic.AtomicInteger;
|
|
|
import java.util.stream.Collectors;
|
|
import java.util.stream.Collectors;
|
|
@@ -146,144 +147,163 @@ public class TblDzbcPathSchedulingController extends BaseController {
|
|
|
@RequestParam(required = true) Long fromareaId,
|
|
@RequestParam(required = true) Long fromareaId,
|
|
|
@RequestParam(required = true) Long toareaId,
|
|
@RequestParam(required = true) Long toareaId,
|
|
|
@RequestParam(required = false) Integer type) {
|
|
@RequestParam(required = false) Integer type) {
|
|
|
- //优先从缓存中获取车量信息 缓存没有则初始化缓存
|
|
|
|
|
- Date date = new Date();
|
|
|
|
|
|
|
+ Date date;
|
|
|
try{
|
|
try{
|
|
|
date = DateUtil.parseDate(searchDate);
|
|
date = DateUtil.parseDate(searchDate);
|
|
|
}catch (Exception e){
|
|
}catch (Exception e){
|
|
|
return R.fail("日期格式不正确 eg:2025-02-01");
|
|
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();
|
|
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.setTicket(0);
|
|
|
carTicket.setCarStatus("已售罄");
|
|
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{
|
|
}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.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)
|
|
@Log(title = "定制班车-多站点路线排班余票", businessType = BusinessType.FORCE)
|