From e65ed967249aa68809fc8205a8dc082ec8025396 Mon Sep 17 00:00:00 2001
From: yanderong <307678080@qq.com>
Date: 星期五, 26 六月 2026 19:50:46 +0800
Subject: [PATCH] feat: 专车价格计算逻辑修改

---
 DriverYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/specialTrain/server/impl/OrderPrivateCarServiceImpl.java |  178 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 177 insertions(+), 1 deletions(-)

diff --git a/DriverYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/specialTrain/server/impl/OrderPrivateCarServiceImpl.java b/DriverYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/specialTrain/server/impl/OrderPrivateCarServiceImpl.java
index 2ebe385..b6e009e 100644
--- a/DriverYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/specialTrain/server/impl/OrderPrivateCarServiceImpl.java
+++ b/DriverYKDTravel/guns-admin/src/main/java/com/stylefeng/guns/modular/specialTrain/server/impl/OrderPrivateCarServiceImpl.java
@@ -1285,6 +1285,181 @@
         return orderPrivateCar;
     }
 
+    /**
+     * sky
+     * 公共费用计算
+     * @param orderPrivateCar
+     * @param rule  计费规则
+     * @param wait  规则-等待时长
+     * @param waitMoney 规则-等待单价
+     * @param parkingFee    停车费
+     * @param crossingFee   过路费
+     * @return
+     * @throws Exception
+     */
+    public OrderPrivateCar calculationPrice(OrderPrivateCar orderPrivateCar, JSONObject rule,
+                                            long wait, Double waitMoney,
+                                            Double parkingFee, Double crossingFee) throws Exception {
+        orderPrivateCar.setChargeRule(rule.toJSONString());
+
+        Date date = new Date();
+        if (orderPrivateCar.getEndServiceTime() == null) {
+            orderPrivateCar.setEndServiceTime(date);
+        }
+
+        double d  = (orderPrivateCar.getMileage() == null ? 0D : orderPrivateCar.getMileage()) / 1000;
+        double t  = ((orderPrivateCar.getEndServiceTime().getTime()
+                - orderPrivateCar.getStartServiceTime().getTime()) / 60000) + 1;
+        double d1 = Math.max(0, d - rule.getDouble("num2"));
+        double t1 = Math.max(0, t - rule.getDouble("num3"));
+
+        double w  = ((orderPrivateCar.getStartServiceTime().getTime()
+                - orderPrivateCar.getArriveTime().getTime()) / 60000) + 1;
+        double w1 = (w - wait) < 0 ? 0
+                : new BigDecimal(w - wait).setScale(0, BigDecimal.ROUND_UP).doubleValue();
+
+        // 从 num14 开始,每 7 个为一组:numI=时间区间, +1=起步价, +2=里程费率,
+        //   +3=时长费率, +4=远途1费率, +5=远途2费率, +6=远途3费率
+        int startIndex = 14;
+        boolean matched = false;
+
+        while (rule.containsKey("num" + startIndex)) {
+            // 必须保证后续 6 个参数都存在
+            if (!rule.containsKey("num" + (startIndex + 6))) {
+                break;
+            }
+
+            String timeRange = rule.getString("num" + startIndex);
+            // 兼容 "HH:mm - HH:mm" 和 "HH:mm-HH:mm" 两种格式
+            String[] parts = timeRange.split("\\s*-\\s*");
+            if (parts.length != 2) {
+                startIndex += 7;
+                continue;
+            }
+
+            try {
+                Calendar rangeStart = parseTimeToCalendar(date, parts[0].trim());
+                Calendar rangeEnd   = parseTimeToCalendar(date, parts[1].trim());
+                // 跨天处理(如 "20:00 - 02:00")
+                if (rangeStart.getTimeInMillis() > rangeEnd.getTimeInMillis()) {
+                    rangeEnd.add(Calendar.DAY_OF_YEAR, 1);
+                }
+
+                boolean inRange = date.getTime() > rangeStart.getTimeInMillis()
+                        && date.getTime() < rangeEnd.getTimeInMillis();
+
+                if (inRange) {
+                    double qibujia  = rule.getDouble("num" + (startIndex + 1));
+                    double lchengLv = rule.getDouble("num" + (startIndex + 2));
+                    double schangLv = rule.getDouble("num" + (startIndex + 3));
+                    double yt1Lv    = rule.getDouble("num" + (startIndex + 4));
+                    double yt2Lv    = rule.getDouble("num" + (startIndex + 5));
+                    double yt3Lv    = rule.getDouble("num" + (startIndex + 6));
+
+                    applyPricing(orderPrivateCar, rule, d, d1, t1, w1,
+                            waitMoney, parkingFee, crossingFee,
+                            qibujia, lchengLv, schangLv, yt1Lv, yt2Lv, yt3Lv);
+                    matched = true;
+                    break;
+                }
+            } catch (Exception e) {
+                // 时间解析异常时跳过该组,继续匹配下一组
+            }
+
+            startIndex += 7;
+        }
+
+        // 无任何时间组匹配,使用基础费率(num1 ~ num13)
+        if (!matched) {
+            applyPricing(orderPrivateCar, rule, d, d1, t1, w1,
+                    waitMoney, parkingFee, crossingFee,
+                    rule.getDouble("num1"),
+                    rule.getDouble("num4"),
+                    rule.getDouble("num5"),
+                    rule.getDouble("num8"),
+                    rule.getDouble("num11"),
+                    rule.getDouble("num13"));
+        }
+
+        return orderPrivateCar;
+    }
+
+    /**
+     * sky
+     * 将 "HH:mm" 解析为基于 baseDate 当天的 Calendar
+     */
+    private Calendar parseTimeToCalendar(Date baseDate, String hhmm) {
+        String[] hm = hhmm.split(":");
+        Calendar cal = Calendar.getInstance();
+        cal.setTime(baseDate);
+        cal.set(Calendar.HOUR_OF_DAY, Integer.parseInt(hm[0]));
+        cal.set(Calendar.MINUTE,      Integer.parseInt(hm[1]));
+        cal.set(Calendar.SECOND,      0);
+        cal.set(Calendar.MILLISECOND, 0);
+        return cal;
+    }
+
+    /**
+     * sky
+     * 按指定费率计算远途费、各项费用,并写入 orderPrivateCar
+     *
+     * 远途分段逻辑(与原代码保持一致):
+     *   段1:num6 < d < num7  → yt1 = yt1Lv * d
+     *   段2:num9 < d < num10 → yt1 = yt1Lv * num7,  yt2 = yt2Lv * (d - num9)
+     *   段3:d > num12        → yt1 = yt1Lv * num7,  yt2 = yt2Lv * (num10 - num9),  yt3 = yt3Lv * (d - num12)
+     */
+    private void applyPricing(OrderPrivateCar orderPrivateCar, JSONObject rule,
+                              double d, double d1, double t1, double w1,
+                              Double waitMoney, Double parkingFee, Double crossingFee,
+                              double qibujia, double lchengLv, double schangLv,
+                              double yt1Lv, double yt2Lv, double yt3Lv) {
+
+        double num6  = rule.getDouble("num6");
+        double num7  = rule.getDouble("num7");
+        double num9  = rule.getDouble("num9");
+        double num10 = rule.getDouble("num10");
+        double num12 = rule.getDouble("num12");
+
+        double yt1 = 0, yt2 = 0, yt3 = 0;
+
+        if (d > num6 && d < num7) {
+            yt1 = yt1Lv * d;
+        }
+        if (d > num9 && d < num10) {
+            yt1 = yt1Lv * num7;
+            yt2 = yt2Lv * (d - num9);
+        }
+        if (d > num12) {
+            yt1 = yt1Lv * num7;
+            yt2 = yt2Lv * (num10 - num9);
+            yt3 = yt3Lv * (d - num12);
+        }
+
+        double mileageMoney  = new BigDecimal(d1 * lchengLv).setScale(2, BigDecimal.ROUND_DOWN).doubleValue();
+        double durationMoney = new BigDecimal(t1 * schangLv).setScale(2, BigDecimal.ROUND_DOWN).doubleValue();
+        double waitMoneyAmt  = new BigDecimal(w1 * waitMoney).setScale(2, BigDecimal.ROUND_DOWN).doubleValue();
+        double longDistMoney = new BigDecimal(yt1 + yt2 + yt3).setScale(2, BigDecimal.ROUND_DOWN).doubleValue();
+
+        orderPrivateCar.setStartMileage(rule.getDouble("num2"));
+        orderPrivateCar.setStartMoney(qibujia);
+        orderPrivateCar.setMileageKilometers(new BigDecimal(d1).setScale(2, BigDecimal.ROUND_HALF_EVEN).doubleValue());
+        orderPrivateCar.setMileageMoney(mileageMoney);
+        orderPrivateCar.setDuration(new BigDecimal(t1).setScale(2, BigDecimal.ROUND_HALF_EVEN).doubleValue());
+        orderPrivateCar.setDurationMoney(durationMoney);
+        orderPrivateCar.setWait(new BigDecimal(w1).setScale(2, BigDecimal.ROUND_HALF_EVEN).doubleValue());
+        orderPrivateCar.setWaitMoney(waitMoneyAmt);
+        orderPrivateCar.setLongDistance(new BigDecimal(d > num6 ? d - num6 : 0).setScale(2, BigDecimal.ROUND_HALF_EVEN).doubleValue());
+        orderPrivateCar.setLongDistanceMoney(longDistMoney);
+        orderPrivateCar.setParkMoney(parkingFee);
+        orderPrivateCar.setRoadTollMoney(crossingFee);
+        orderPrivateCar.setRedPacketMoney(0D);
+        orderPrivateCar.setCouponMoney(0D);
+        orderPrivateCar.setDiscount(0D);
+        orderPrivateCar.setPayMoney(0D);
+
+        double amount = qibujia + mileageMoney + durationMoney + waitMoneyAmt + longDistMoney;
+        orderPrivateCar.setOrderMoney(amount + parkingFee + crossingFee);
+    }
 
     /**
      * 公共费用计算
@@ -1297,7 +1472,8 @@
      * @return
      * @throws Exception
      */
-    public OrderPrivateCar  calculationPrice(OrderPrivateCar orderPrivateCar,JSONObject rule, long wait,Double waitMoney, Double parkingFee, Double crossingFee) throws Exception {
+    @Deprecated
+    public OrderPrivateCar  calculationPriceBack(OrderPrivateCar orderPrivateCar,JSONObject rule, long wait,Double waitMoney, Double parkingFee, Double crossingFee) throws Exception {
         orderPrivateCar.setChargeRule(rule.toJSONString());
         double amount = 0.0;
         //等待费

--
Gitblit v1.7.1