曾富康
2026-06-22 e4f50565f585ac3bb7355fe7b9da794bb855113f
UserYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/specialTrain/server/impl/OrderPrivateCarServiceImpl.java
@@ -197,12 +197,19 @@
    */
   @Override
   public synchronized ResultUtil<BaseWarpper> saveOrderPrivateCar(Integer serverCarModelId, Date travelTime, Integer reservation, Integer instead, String placementLon, String placementLat, String startLon, String startLat,
                                                                   String startAddress, String endLon, String endLat, String endAddress, String name, String phone, Integer orderSource, Integer driverId, Integer type, Integer uid, Integer peopleNum, Integer rideType) throws Exception {
                                                                   String startAddress, String endLon, String endLat, String endAddress, String name, String phone, Integer orderSource, Integer driverId, Integer type, Integer uid, Integer peopleNum, Integer rideType, Integer callType) throws Exception {
      BaseWarpper baseWarpper = new BaseWarpper();
      if (lock.tryLock()) {
         try {
            if (callType == null) {
               callType = 1;
            }
            boolean quickCall = Integer.valueOf(2).equals(callType);
            // 快捷叫车允许用户下单时没有终点,订单必须作为实时单处理。
            //如果出行时间大于当前10分钟则默认为预约单
            if (travelTime.getTime() > (System.currentTimeMillis() + 600000)) {
            if (quickCall) {
               reservation = 1;
            } else if (travelTime.getTime() > (System.currentTimeMillis() + 600000)) {
               reservation = 2;
            }
            /**
@@ -267,8 +274,14 @@
            
            startAddress = startAddress.replaceAll("& #40;", "(");
            startAddress = startAddress.replaceAll("& #41;", ")");
            endAddress = endAddress.replaceAll("& #40;", "(");
            endAddress = endAddress.replaceAll("& #41;", ")");
            // 普通叫车仍沿用原终点必填校验,快捷叫车由司机服务中补充终点。
            if (!quickCall) {
               if (ToolUtil.isEmpty(endLon) || ToolUtil.isEmpty(endLat) || ToolUtil.isEmpty(endAddress)) {
                  return ResultUtil.error("请设置终点");
               }
               endAddress = endAddress.replaceAll("& #40;", "(");
               endAddress = endAddress.replaceAll("& #41;", ")");
            }
            if ((orderSource == 1 || orderSource == 3) && null == serverCarModelId) {
               return ResultUtil.error("请选择服务车型");
            }
@@ -288,16 +301,23 @@
            orderPrivateCar.setStartLon(Double.valueOf(startLon));
            orderPrivateCar.setStartLat(Double.valueOf(startLat));
            orderPrivateCar.setStartAddress(startAddress);
            orderPrivateCar.setEndLon(Double.valueOf(endLon));
            orderPrivateCar.setEndLat(Double.valueOf(endLat));
            orderPrivateCar.setEndAddress(endAddress);
            orderPrivateCar.setCallType(callType);
            // 快捷叫车没有终点,不写入终点坐标和地址。
            if (!quickCall) {
               orderPrivateCar.setEndLon(Double.valueOf(endLon));
               orderPrivateCar.setEndLat(Double.valueOf(endLat));
               orderPrivateCar.setEndAddress(endAddress);
            }
            orderPrivateCar.setSubstitute(instead);
            orderPrivateCar.setPassengers(name);
            orderPrivateCar.setPassengersPhone(phone);
            // TODO: 2023/11/4 无法修改
            Map<String, String> distanceMap = gdMapElectricFenceUtil.getDistance(orderPrivateCar.getStartLon() + "," + orderPrivateCar.getStartLat(), orderPrivateCar.getEndLon() + "," + orderPrivateCar.getEndLat(), 1);
            orderPrivateCar.setEstimateMileage(Double.valueOf(distanceMap.get("distance")));
            orderPrivateCar.setEstimateTime(Double.valueOf(distanceMap.get("duration")) / 60);
            // 原逻辑保留:普通叫车下单时计算预估里程和时间。
            // 快捷叫车无终点,不能在下单时计算预估里程和预估时间。
            if (!quickCall) {
               Map<String, String> distanceMap = gdMapElectricFenceUtil.getDistance(orderPrivateCar.getStartLon() + "," + orderPrivateCar.getStartLat(), orderPrivateCar.getEndLon() + "," + orderPrivateCar.getEndLat(), 1);
               orderPrivateCar.setEstimateMileage(Double.valueOf(distanceMap.get("distance")));
               orderPrivateCar.setEstimateTime(Double.valueOf(distanceMap.get("duration")) / 60);
            }
            if (instead == 0 || ToolUtil.isEmpty(orderPrivateCar.getPassengers())) {
               UserInfo userInfo = userInfoService.selectById(uid);
               if (ToolUtil.isEmpty(userInfo.getPhone())) {
@@ -307,6 +327,12 @@
               orderPrivateCar.setPassengersPhone(userInfo.getPhone());
            }
            orderPrivateCar.setState(1);
            Integer saveOrderSource = orderSource;
            // 快捷叫车按后付处理,跳过先付金额预估和待支付状态。
            if (quickCall) {
               orderSource = 2;
               orderPrivateCar.setPaymentMode(2);
            }
            // ===== 先付/后付模式判断 =====
            if (orderSource != 2) { // 扫码下单跳过先付判断(扫码下单已有固定司机)
               TSysPaymentMode paymentMode = tSysPaymentModeService.selectOne(
@@ -373,6 +399,7 @@
            orderPrivateCar.setInsertTime(new Date());
            orderPrivateCar.setTravelTime(travelTime);
            orderPrivateCar.setOrderType(reservation);
            orderSource = saveOrderSource;
            orderPrivateCar.setOrderSource(orderSource);
            if (orderSource == 2) {//扫码下单
               Driver driver = driverService.selectById(driverId);
@@ -433,7 +460,8 @@
            //判断独享,一口价,拼车
            if (orderPrivateCar.getRideType() != 3) {
            // 快捷叫车无终点,不能参与拼车合单匹配,统一走普通派单流程。
            if (quickCall || orderPrivateCar.getRideType() != 3) {
               orderPrivateCar.setTotalPeopleNum(peopleNum);
               orderPrivateCar.setIsReassign(1);
               orderPrivateCar.setIsDelete(1);
@@ -474,7 +502,7 @@
                     if (travelTime.getTime() >= order.getTravelTime().getTime() - jsonObject.getInteger("num5") * 60000L && travelTime.getTime() <= order.getTravelTime().getTime() + jsonObject.getInteger("num6") * 60000L) {
                        //                        Double dis1 = Double.valueOf(gdMapElectricFenceUtil.getDistance(orderPrivateCar.getStartLon() + "," + orderPrivateCar.getStartLat(), order.getStartLon() + "," + order.getStartLat(), 1).get("distance").toString());
                        //                        Double dis2 = Double.valueOf(gdMapElectricFenceUtil.getDistance(orderPrivateCar.getEndLon() + "," + orderPrivateCar.getEndLat(), order.getEndLon() + "," + order.getEndLat(), 1).get("distance").toString());
                        // TODO: 2023/11/4  已改成计算直线距离
                        // 待处理:2023/11/4  已改成计算直线距离
                        Double dis1 = geodesyUtil.getDistance(orderPrivateCar.getStartLon() + "," + orderPrivateCar.getStartLat(), order.getStartLon() + "," + order.getStartLat()).get("WGS84");
                        Double dis2 = geodesyUtil.getDistance(orderPrivateCar.getEndLon() + "," + orderPrivateCar.getEndLat(), order.getEndLon() + "," + order.getEndLat()).get("WGS84");
                        //判断距离
@@ -497,7 +525,7 @@
                           //                            Double dis1 = Double.valueOf(gdMapElectricFenceUtil.getDistance(orderPrivateCar.getStartLon() + "," + orderPrivateCar.getStartLat(), value, 1).get("distance").toString());
                           //                            Double dis2 = Double.valueOf(gdMapElectricFenceUtil.getDistance(orderPrivateCar.getEndLon() + "," + orderPrivateCar.getEndLat(), order.getEndLon() + "," + order.getEndLat(), 1).get("distance").toString());
                           
                           // TODO: 2023/11/4  已改成计算直线距离
                           // 待处理:2023/11/4  已改成计算直线距离
                           Double dis1 = geodesyUtil.getDistance(orderPrivateCar.getStartLon() + "," + orderPrivateCar.getStartLat(), value).get("WGS84");
                           Double dis2 = geodesyUtil.getDistance(orderPrivateCar.getEndLon() + "," + orderPrivateCar.getEndLat(), order.getEndLon() + "," + order.getEndLat()).get("WGS84");
                           //判断距离
@@ -588,15 +616,22 @@
    */
   @Override
   public ResultUtil<BaseWarpper> saveOrderPrivateCars(String serverCarModel, Date travelTime, Integer reservation, Integer instead, String placementLon, String placementLat, String startLon, String startLat, String startAddress, String endLon,
                                                       String endLat, String endAddress, String name, String phone, Integer orderSource, Integer driverId, Integer uid, Integer peopleNum) throws Exception {
                                                       String endLat, String endAddress, String name, String phone, Integer orderSource, Integer driverId, Integer uid, Integer peopleNum, Integer callType) throws Exception {
      BaseWarpper baseWarpper = new BaseWarpper();
      String key = "saveOrderPrivateCar:" + uid;
      Boolean hasKey = redisTemplate.hasKey(key);
      if (!hasKey) {
         redisTemplate.opsForValue().set(key, uid, 30, TimeUnit.SECONDS);
         try {
            if (callType == null) {
               callType = 1;
            }
            boolean quickCall = Integer.valueOf(2).equals(callType);
            // 快捷叫车允许用户下单时没有终点,订单必须作为实时单处理。
            //如果出行时间大于当前10分钟则默认为预约单
            if (travelTime.getTime() > (System.currentTimeMillis() + 600000)) {
            if (quickCall) {
               reservation = 1;
            } else if (travelTime.getTime() > (System.currentTimeMillis() + 600000)) {
               reservation = 2;
            }
            
@@ -663,8 +698,14 @@
            
            startAddress = startAddress.replaceAll("& #40;", "(");
            startAddress = startAddress.replaceAll("& #41;", ")");
            endAddress = endAddress.replaceAll("& #40;", "(");
            endAddress = endAddress.replaceAll("& #41;", ")");
            // 普通叫车仍沿用原终点必填校验,快捷叫车由司机服务中补充终点。
            if (!quickCall) {
               if (ToolUtil.isEmpty(endLon) || ToolUtil.isEmpty(endLat) || ToolUtil.isEmpty(endAddress)) {
                  return ResultUtil.error("请设置终点");
               }
               endAddress = endAddress.replaceAll("& #40;", "(");
               endAddress = endAddress.replaceAll("& #41;", ")");
            }
            if (ToolUtil.isEmpty(serverCarModel)) {
               return ResultUtil.error("请选择服务车型");
            }
@@ -682,16 +723,22 @@
            orderPrivateCar.setStartLon(Double.valueOf(startLon));
            orderPrivateCar.setStartLat(Double.valueOf(startLat));
            orderPrivateCar.setStartAddress(startAddress);
            orderPrivateCar.setEndLon(Double.valueOf(endLon));
            orderPrivateCar.setEndLat(Double.valueOf(endLat));
            orderPrivateCar.setEndAddress(endAddress);
            orderPrivateCar.setCallType(callType);
            // 快捷叫车没有终点,不写入终点坐标和地址。
            if (!quickCall) {
               orderPrivateCar.setEndLon(Double.valueOf(endLon));
               orderPrivateCar.setEndLat(Double.valueOf(endLat));
               orderPrivateCar.setEndAddress(endAddress);
            }
            orderPrivateCar.setSubstitute(instead);
            orderPrivateCar.setPassengers(name);
            orderPrivateCar.setPassengersPhone(phone);
            // TODO: 2023/11/4 无法修改
            Map<String, String> distanceMap = gdMapElectricFenceUtil.getDistance(orderPrivateCar.getStartLon() + "," + orderPrivateCar.getStartLat(), orderPrivateCar.getEndLon() + "," + orderPrivateCar.getEndLat(), 1);
            orderPrivateCar.setEstimateMileage(Double.valueOf(distanceMap.get("distance")));
            orderPrivateCar.setEstimateTime(Double.valueOf(distanceMap.get("duration")) / 60);
            // 快捷叫车无终点,不能在下单时计算预估里程和预估时间。
            if (!quickCall) {
               Map<String, String> distanceMap = gdMapElectricFenceUtil.getDistance(orderPrivateCar.getStartLon() + "," + orderPrivateCar.getStartLat(), orderPrivateCar.getEndLon() + "," + orderPrivateCar.getEndLat(), 1);
               orderPrivateCar.setEstimateMileage(Double.valueOf(distanceMap.get("distance")));
               orderPrivateCar.setEstimateTime(Double.valueOf(distanceMap.get("duration")) / 60);
            }
            UserInfo userInfo = userInfoService.selectById(uid);
            if (instead == 0 || ToolUtil.isEmpty(orderPrivateCar.getPassengers())) {
@@ -702,7 +749,11 @@
               orderPrivateCar.setPassengersPhone(userInfo.getPhone());
            }
            orderPrivateCar.setState(1);
            if (orderSource != 2) {
            if (quickCall) {
               // 快捷叫车固定后付,跳过先付金额预估和待支付状态。
               orderPrivateCar.setPaymentMode(2);
               baseWarpper.setPaymentMode(2);
            } else if (orderSource != 2) {
               TSysPaymentMode paymentMode = tSysPaymentModeService.selectOne(
                     new EntityWrapper<TSysPaymentMode>().last("LIMIT 1"));
               if (paymentMode != null && paymentMode.getPrivateType() != null) {
@@ -775,6 +826,9 @@
                  
                  if (rideType != 3) {
                     //推单操作-独享
                     this.pushOrder(orderPrivateCar.getId(), rideType, serverCarModelId, orderPrivateCar.getStartLon(), orderPrivateCar.getStartLat());
                  } else if (quickCall) {
                     // 快捷叫车不参与拼车合单,拼车车型也按普通派单处理。
                     this.pushOrder(orderPrivateCar.getId(), rideType, serverCarModelId, orderPrivateCar.getStartLon(), orderPrivateCar.getStartLat());
                  } else {
                     OrderPrivateCar orderPrivateCar1 = null;
@@ -998,7 +1052,7 @@
                  if (orderPrivateCar.getTravelTime().getTime() >= order.getTravelTime().getTime() - jsonObject.getInteger("num5") * 60000L && orderPrivateCar.getTravelTime().getTime() <= order.getTravelTime().getTime() + jsonObject.getInteger("num6") * 60000L) {
//                            Double dis1 = Double.valueOf(gdMapElectricFenceUtil.getDistance(orderPrivateCar.getStartLon() + "," + orderPrivateCar.getStartLat(), order.getStartLon() + "," + order.getStartLat(), 1).get("distance").toString());
//                            Double dis2 = Double.valueOf(gdMapElectricFenceUtil.getDistance(orderPrivateCar.getEndLon() + "," + orderPrivateCar.getEndLat(), order.getEndLon() + "," + order.getEndLat(), 1).get("distance").toString());
                     // TODO: 2023/11/4 已改成计算直线距离
                     // 待处理:2023/11/4 已改成计算直线距离
                     Double dis1 = geodesyUtil.getDistance(orderPrivateCar.getStartLon() + "," + orderPrivateCar.getStartLat(), order.getStartLon() + "," + order.getStartLat()).get("WGS84");
                     Double dis2 = geodesyUtil.getDistance(orderPrivateCar.getEndLon() + "," + orderPrivateCar.getEndLat(), order.getEndLon() + "," + order.getEndLat()).get("WGS84");
                     //判断距离
@@ -1020,7 +1074,7 @@
                        String value = (String) redisTemplate.opsForValue().get("dache:DRIVER" + String.valueOf(order.getDriverId()));
//                                Double dis1 = Double.valueOf(gdMapElectricFenceUtil.getDistance(orderPrivateCar.getStartLon() + "," + orderPrivateCar.getStartLat(), value, 1).get("distance").toString());
//                                Double dis2 = Double.valueOf(gdMapElectricFenceUtil.getDistance(orderPrivateCar.getEndLon() + "," + orderPrivateCar.getEndLat(), order.getEndLon() + "," + order.getEndLat(), 1).get("distance").toString());
                        // TODO: 2023/11/4 已改成计算直线距离
                        // 待处理:2023/11/4 已改成计算直线距离
                        Double dis1 = geodesyUtil.getDistance(orderPrivateCar.getStartLon() + "," + orderPrivateCar.getStartLat(), value).get("WGS84");
                        Double dis2 = geodesyUtil.getDistance(orderPrivateCar.getEndLon() + "," + orderPrivateCar.getEndLat(), order.getEndLon() + "," + order.getEndLat()).get("WGS84");
                        //判断距离
@@ -1397,7 +1451,7 @@
      orderServerWarpper.setLat(null != value ? value.split(",")[1] : "0.0");
      orderServerWarpper.setReassignNotice(orderPrivateCar.getReassignNotice());
      if(orderPrivateCar.getState() == 2 || orderPrivateCar.getState() == 3){//前往预约地
         // TODO: 2023/11/4 无法修改
         // 待处理:2023/11/4 无法修改
         Map<String, String> distance = gdMapElectricFenceUtil.getDistance(value, orderPrivateCar.getStartLon() + "," + orderPrivateCar.getStartLat(), 1);
         String d = "0";
         String t = "0";
@@ -1415,7 +1469,7 @@
         orderServerWarpper.setLaveTime("0");
      }
      if(orderPrivateCar.getState() == 5 || orderPrivateCar.getState() == 6){//服务中
         // TODO: 2023/11/4 无法修改
         // 待处理:2023/11/4 无法修改
         Map<String, String> distance = gdMapElectricFenceUtil.getDistance(value, orderPrivateCar.getEndLon() + "," + orderPrivateCar.getEndLat(), 1);
         String d = "0";
         String t = "0";
@@ -2104,7 +2158,7 @@
            orderPrivateCar.setSplitAllocation(JSON.toJSONString(map));
         }
         
         // TODO: 2020/5/24 这里需要给司机和用户推送订单状态
         // 待处理:2020/5/24 这里需要给司机和用户推送订单状态
         new Thread(new Runnable() {
            @Override
            public void run() {
@@ -2427,7 +2481,7 @@
         promotion(orderPrivateCar.getId());
         // TODO: 2020/5/24 这里需要给司机和用户推送订单状态
         // 待处理:2020/5/24 这里需要给司机和用户推送订单状态
         new Thread(new Runnable() {
            @Override
            public void run() {
@@ -2583,7 +2637,7 @@
         
         this.deleteTask(orderPrivateCar.getId());//删除定时任务
         
         // TODO: 2020/5/24 这里需要给司机和用户推送订单状态
         // 待处理:2020/5/24 这里需要给司机和用户推送订单状态
//            new Thread(new Runnable() {
//                @Override
//                public void run() {
@@ -3189,7 +3243,7 @@
         this.updateById(orderPrivateCar);
         promotion(orderPrivateCar.getId());
         
         // TODO: 2020/5/24 这里需要给司机和用户推送订单状态
         // 待处理:2020/5/24 这里需要给司机和用户推送订单状态
         new Thread(new Runnable() {
            @Override
            public void run() {
@@ -3433,6 +3487,8 @@
                  integers = JSON.parseArray(vehicle).toJavaList(Integer.class);
               }
               OpenCity openCity = openCityService.openCity1(startLon.toString(), startLat.toString());
               OrderPrivateCar priorityOrder = orderPrivateCarMapper.selectById(id);
               boolean priorityDispatch = isNewUserPriorityDispatch(openCity, priorityOrder == null ? null : priorityOrder.getUserId());
               List<PushOrder> querys = pushOrderService.querys(null, 1, openCity.getId());//获取需要推送的次数
               //整轮派单结束,若无司机接单,系统自动增加派单5轮,若增加5轮后任无司机接单,则系统结束派单,乘客端显示无司机接单、是否再次打车
               int num = 0;
@@ -3455,7 +3511,11 @@
                     //获取空闲司机
                     List<Driver> list = driverService.queryIdleDriver(orderType, serverCarModelId, startLon, startLat, pushOrder.getPushDistance(), null);//所有附近空闲司机
                     //随机排序
                     Collections.shuffle(list);
                     if (priorityDispatch) {
                        sortDriversForNewUserPriority(list);
                     } else {
                        Collections.shuffle(list);
                     }
                     if (list.size() > 0) {
                        double driverProportion = pushOrder.getDriverProportion() / 100;//推送占比计算成小数
                        int lastIndex = Double.valueOf(list.size() * driverProportion).intValue();//计算占比转成整数(下标截取)
@@ -3533,6 +3593,7 @@
               OpenCity openCity = openCityService.openCity1(orderPrivateCar.getStartLon().toString(), orderPrivateCar.getStartLat().toString());
               // 判断是否为派单模式
               boolean priorityDispatch = isNewUserPriorityDispatch(openCity, orderPrivateCar.getUserId());
               TSysPushType sysPushType = tSysPushTypeService.selectOne(new EntityWrapper<TSysPushType>().eq("openCityId", openCity.getId()));
               if(sysPushType!=null && sysPushType.getPushType()==2){
                  System.out.println( "派单模式");
@@ -3541,7 +3602,7 @@
                     // 固定5公里进行派单
                     List<Driver> list = driverService.queryIdleDriver(orderType, orderPrivateCar.getServerCarModelId(), orderPrivateCar.getStartLon(), orderPrivateCar.getStartLat(), 5.0, null);//所有附近空闲司机
                     if (list.size() > 0) {
                        Driver driver1 = list.stream().sorted(Comparator.comparingDouble(Driver::getDistance).reversed()).findFirst().get();
                        Driver driver1 = selectDispatchDriver(list, priorityDispatch);
                        if(orderPrivateCar.getType() == 3){
                           //批量订单
                           CarService carService = new CarService();
@@ -3664,6 +3725,9 @@
                        }
                        //获取空闲司机
                        List<Driver> list = driverService.queryIdleDriver(orderType, orderPrivateCar.getServerCarModelId(), orderPrivateCar.getStartLon(), orderPrivateCar.getStartLat(), pushOrder.getPushDistance(), null);//所有附近空闲司机
                        if (priorityDispatch) {
                           sortDriversForNewUserPriority(list);
                        }
                        System.out.println(list.toString()+"XXXXXXXX");
                        if (list.size() > 0) {
                           double driverProportion = pushOrder.getDriverProportion() / 100;//推送占比计算成小数
@@ -3712,6 +3776,53 @@
      }).start();
   }
   
   /**
    * 判断当前订单是否需要按新用户优先派单。
    */
   private boolean isNewUserPriorityDispatch(OpenCity openCity, Integer userId) {
      if (openCity == null || userId == null) {
         return false;
      }
      Company company = companyService.selectById(openCity.getId());
      if (company == null || !Integer.valueOf(1).equals(company.getNewUserPriorityDispatch())) {
         return false;
      }
      return isNewUserForDispatch(userId);
   }
   /**
    * 新用户定义:专车、出租车、跨城均不存在完成态订单。
    */
   private boolean isNewUserForDispatch(Integer userId) {
      if (userId == null) {
         return false;
      }
      int privateCarCount = orderPrivateCarMapper.selectCount(new EntityWrapper<OrderPrivateCar>().eq("userId", userId).in("state", Arrays.asList(8, 9)));
      int taxiCount = orderTaxiMapper.selectCount(new EntityWrapper<OrderTaxi>().eq("userId", userId).in("state", Arrays.asList(8, 9)));
      int crossCityCount = orderCrossCityMapper.selectCount(new EntityWrapper<OrderCrossCity>().eq("userId", userId).in("state", Arrays.asList(8, 9)));
      return privateCarCount + taxiCount + crossCityCount == 0;
   }
   /**
    * 新用户优先派单时,候选司机按距离从近到远排序。
    */
   private void sortDriversForNewUserPriority(List<Driver> drivers) {
      if (drivers == null || drivers.isEmpty()) {
         return;
      }
      drivers.sort(Comparator.comparingDouble(driver -> driver.getDistance() == null ? Double.MAX_VALUE : driver.getDistance()));
   }
   /**
    * 智能指派模式下,新用户选择最近司机;普通订单保持原有选择方式。
    */
   private Driver selectDispatchDriver(List<Driver> drivers, boolean priorityDispatch) {
      if (priorityDispatch) {
         return drivers.stream().sorted(Comparator.comparingDouble(driver -> driver.getDistance() == null ? Double.MAX_VALUE : driver.getDistance())).findFirst().get();
      }
      return drivers.stream().sorted(Comparator.comparingDouble(Driver::getDistance).reversed()).findFirst().get();
   }