liujie
2026-02-12 e6364fb72bf036d3af583b334626b3aee48697eb
小程序接口  动态价格修改
3个文件已修改
206 ■■■■■ 已修改文件
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/impl/XpPricingServiceImpl.java 142 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/utils/XpPricingUtil.java 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/utils/holiday/HolidayUtil.java 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/impl/XpPricingServiceImpl.java
@@ -1,6 +1,7 @@
package com.xiaopeng.operation.service.impl;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
@@ -33,6 +34,7 @@
import com.xiaopeng.operation.service.IXpGeoQueryEntityService;
import com.xiaopeng.operation.service.XpPricingService;
import com.xiaopeng.operation.utils.XpPricingUtil;
import com.xiaopeng.operation.utils.holiday.HolidayUtil;
import com.xiaopeng.operation.utils.map.FastDistanceCalculator;
import com.xiaopeng.operation.vo.XpPricingCardVo;
import org.springframework.beans.factory.annotation.Autowired;
@@ -100,14 +102,19 @@
    @Resource
    private XpAppUserClient xpAppUserClient;
    @Resource
    private HolidayUtil holidayUtil;
    @Autowired
    private IXpGeoQueryEntityService geoQueryEntityService;
    @Autowired
    private XpElectronicFenceMapper xpElectronicFenceMapper;
    // 自定义线程池用于并行执行任务
    private final ExecutorService executorService;
    // 初始化自定义线程池
    public XpPricingServiceImpl() {
@@ -170,7 +177,7 @@
                + "-" + routeAndFareDto.getDestination().getLongitude() + "-" + routeAndFareDto.getDestination().getLatitude() + "-" + getCurrentTimeSlot() + "-" + userId;
        if (redisService.hasKey(key)) {
            String jsonStr = Objects.requireNonNull(redisService.getCacheObject( key)).toString();
            String jsonStr = Objects.requireNonNull(redisService.getCacheObject(key)).toString();
            RouteAndFareVo RouteAndFareVo = JSONObject.parseObject(jsonStr, RouteAndFareVo.class);
            return (RouteAndFareVo);
        }
@@ -215,11 +222,11 @@
        // 优惠券
        CompletableFuture<R<UserCouponVo>> couponFuture = CompletableFuture.supplyAsync(
                () -> {
                        // 优惠券
                        return xpAppUserCouponClient.getUserCoupon(
                    // 优惠券
                    return xpAppUserCouponClient.getUserCoupon(
//                                new GetUserCouponDto(Long.valueOf(userId), xpPricingCardVo.getTotalPrice(),routeAndFareDto.getOpenCityId())
                                new GetUserCouponDto(Long.valueOf(userId), 1d,routeAndFareDto.getOpenCityId())
                        );
                            new GetUserCouponDto(Long.valueOf(userId), 1d, routeAndFareDto.getOpenCityId())
                    );
                },
                executorService
        );
@@ -285,7 +292,7 @@
        // 10. 检查等待时间
        Integer waitTime = getWaitTime(routeAndFareDto.getOrigin().getLongitude(), routeAndFareDto.getOrigin().getLatitude());
        if(waitTime>3){
        if (waitTime > 3) {
            throw new ServiceException("当前区域正在等待中,请耐心等待", I18nKeyConstant.WAITING_TIME);
        }
        fareVo.setWaitingTime(waitTime);
@@ -315,7 +322,7 @@
     * @return
     */
    @Override
    public Integer getWaitTime(double lon,double lat) {
    public Integer getWaitTime(double lon, double lat) {
        List<XpGeoQueryEntity> entities = geoQueryEntityService.findByLocationWithin500MetersAndLastWeekAndStatusGreater(
                lon,
                lat,
@@ -324,7 +331,7 @@
        if (entities.isEmpty()) {
           return 1;
            return 1;
        } else {
            // 已完成接单的数据
            List<XpGeoQueryEntity> validEntities = entities.stream().filter(e -> e.getStatus() > 1).collect(Collectors.toList());
@@ -336,7 +343,7 @@
                // 未完成接单的数量
                int count = entities.size() - validEntities.size();
                if (count == 0) {
                   return 1;
                    return 1;
                } else {
                    double waitMinutes = (average * count) / 60;
                    if (waitMinutes > 3) {
@@ -345,19 +352,28 @@
                    return (int) waitMinutes;
                }
            } else {
                return  1;
                return 1;
            }
        }
    }
    @Override
    public Long saveOrder(XpOrderDto dto, String uid) {
        // 是否在运营区域时间内
        XpElectronicFenceArea xpElectronicFenceArea = xpElectronicFenceAreaMapper.selectById(dto.getXpElectronicFenceAreaId());
        XpElectronicFence xpElectronicFence = xpElectronicFenceMapper.selectById(xpElectronicFenceArea.getElectronicId());
        String operationStrategy = xpElectronicFence.getOperationStrategy();
        Boolean inOperationTime = isInOperationTime(operationStrategy);
        if (!inOperationTime) {
            throw new ServiceException("当前区域未开通服务", I18nKeyConstant.NO_CURRENT_REGION);
        }
        Integer cancelCount = xpTradingStrategyMapper.selectOne(null).getCancleCount();
        // 判断是否有进行的订单
        R<Long> r = xpOrderClient.hasUnPaodOrder(uid);
        if(r.getData()>0){
        if (r.getData() > 0) {
            throw new RuntimeException("有正在进行的订单");
        }
@@ -369,30 +385,40 @@
        // 判断当天取消的次数 后台配置 redis 查询
        Object cancelOrder = redisService.getCacheObject("CANCEL_ORDER_" + uid);
        if(cancelOrder!=null){
        if (cancelOrder != null) {
            Integer num = Integer.valueOf(cancelOrder.toString());
            if(num>=cancelCount){
            if (num >= cancelCount) {
                return 0l;
            }
        }
        // 获取起步里程
        XpPricing xpPricing = this.baseMapper.selectOne(new LambdaQueryWrapper<XpPricing>().eq(XpPricing::getCityId, dto.getOpenCityId()));
        Integer startMileage = XpPricingUtil.getStartMileage(xpPricing.getStartingFareJson());
        if (startMileage == null) {
            throw new ServiceException("当前区域未开通服务", I18nKeyConstant.NO_CURRENT_REGION);
        }
        // 根据id获取手机号
        Boolean isPriorityDispatch=false;
        Boolean isPriorityDispatch = false;
        R<XpAppUser> xpAppUserR = xpAppUserClient.queryOperationsUserById(Long.valueOf(uid));
        if(xpAppUserR.getCode()==R.SUCCESS){
        if (xpAppUserR.getCode() == R.SUCCESS) {
            Long count = xpWhitelistMapper.selectCount(new LambdaQueryWrapper<XpWhitelist>().eq(XpWhitelist::getAccount, xpAppUserR.getData().getPhoneNumber()).eq(XpWhitelist::getIsPriorityDispatch, 1));
            if(count>0){
                isPriorityDispatch=true;
            if (count > 0) {
                isPriorityDispatch = true;
            }
        }
        // 生成订单数据
        XpOrder xpOrder = new XpOrder();
        xpOrder.setStartMileage(Double.valueOf(startMileage));
        xpOrder.setAppUserId(Long.valueOf(uid));
        xpOrder.setOrderNumber("XP"+System.currentTimeMillis());
        xpOrder.setOrderNumber("XP" + System.currentTimeMillis());
        xpOrder.setPlacementLon(dto.getPlacementLon());
        xpOrder.setPlacementLat(dto.getPlacementLat());
        xpOrder.setPlacementAddress(dto.getPlacementAddress());
@@ -444,27 +470,27 @@
        R<RouteVo> distanceAndDuration = xpMapClient.getDistanceAndDuration(routeAndFareDto);
        Integer distance = 0;
        Integer duration = 0;
        if(distanceAndDuration.getCode()!=200){
        if (distanceAndDuration.getCode() != 200) {
            //静默处理
            return 0l;
        }
        distance=distanceAndDuration.getData().getDistance();
        duration=distanceAndDuration.getData().getDuration();
        distance = distanceAndDuration.getData().getDistance();
        duration = distanceAndDuration.getData().getDuration();
        // 产生订单
        R<Long> addOrderR = xpOrderClient.addOrder(xpOrder);
        if(addOrderR.getCode()!=R.SUCCESS){
        if (addOrderR.getCode() != R.SUCCESS) {
            throw new ServiceException("订单生成失败", I18nKeyConstant.ORDER_CREATE_FAIL);
        }
        Long orderId = addOrderR.getData();
        // 最大距离
        Object maxPushDistanceObj = redisService.getCacheObject(CacheConstants.MAX_PUSH_DISTANCE);
        Double maxPushDistance= 0.0;
        if(maxPushDistanceObj!=null){
             maxPushDistance = Double.valueOf(maxPushDistanceObj.toString());
        }else {
             maxPushDistance = xpTradingStrategyMapper.selectOne(null).getThreePushDistance();
        Double maxPushDistance = 0.0;
        if (maxPushDistanceObj != null) {
            maxPushDistance = Double.valueOf(maxPushDistanceObj.toString());
        } else {
            maxPushDistance = xpTradingStrategyMapper.selectOne(null).getThreePushDistance();
        }
        // 找出现在所有的队列 通过计算距离 算出目前应该放在那个队列  如果没有符合的新增一个队列  符合后看是否白名单账号 是则直接放在队列前端
@@ -474,20 +500,20 @@
            String lonLat = s.split("-")[2];
            // 和上车点进行判断是否<maxPushDistance
            double v = FastDistanceCalculator.distanceFast(Double.parseDouble(lonLat.split(",")[1]), Double.parseDouble(lonLat.split(",")[0]), xpPoint.getPointLat(), xpPoint.getPointLon());
            if(v<maxPushDistance){
                if(isPriorityDispatch){
            if (v < maxPushDistance) {
                if (isPriorityDispatch) {
                    // 头部  value 订单_经纬度_状态_用户id_订单编号_距离_时间
                    redisService.addToTail(s,orderId+"_"+xpPoint.getPointLon()+","+xpPoint.getPointLat()+"_0"+"_"+uid+"_"+xpOrder.getOrderNumber()+"_"+distance+"_"+duration+"_"+routeAndFareDto.getRoutePlanRule());
                }else {
                    redisService.addToTail(s, orderId + "_" + xpPoint.getPointLon() + "," + xpPoint.getPointLat() + "_0" + "_" + uid + "_" + xpOrder.getOrderNumber() + "_" + distance + "_" + duration + "_" + routeAndFareDto.getRoutePlanRule());
                } else {
                    // 尾部
                    redisService.addToTail(s,orderId+"_"+xpPoint.getPointLon()+","+xpPoint.getPointLat()+"_0"+"_"+uid+"_"+xpOrder.getOrderNumber()+"_"+distance+"_"+duration+"_"+routeAndFareDto.getRoutePlanRule());
                    redisService.addToTail(s, orderId + "_" + xpPoint.getPointLon() + "," + xpPoint.getPointLat() + "_0" + "_" + uid + "_" + xpOrder.getOrderNumber() + "_" + distance + "_" + duration + "_" + routeAndFareDto.getRoutePlanRule());
                }
                return orderId;
            }
        }
        String key = CacheConstants.QUEUE_POINT_ID+"-"+ xpPoint.getId()+"-"+xpPoint.getPointLon()+","+xpPoint.getPointLat();
        redisService.setCacheList(key,Arrays.asList(orderId+"_"+xpPoint.getPointLon()+","+xpPoint.getPointLat()+"_0"+"_"+uid+"_"+xpOrder.getOrderNumber()+"_"+distance+"_"+duration+"_"+routeAndFareDto.getRoutePlanRule()));
        String key = CacheConstants.QUEUE_POINT_ID + "-" + xpPoint.getId() + "-" + xpPoint.getPointLon() + "," + xpPoint.getPointLat();
        redisService.setCacheList(key, Arrays.asList(orderId + "_" + xpPoint.getPointLon() + "," + xpPoint.getPointLat() + "_0" + "_" + uid + "_" + xpOrder.getOrderNumber() + "_" + distance + "_" + duration + "_" + routeAndFareDto.getRoutePlanRule()));
        return orderId;
//
@@ -497,12 +523,54 @@
//
        // 产生订单  存订单数据  // 下发指令  消息推送用户端
//        return null;
    }
    private Boolean isInOperationTime(String operationStrategy) {
        JSONArray jsonArray = JSONArray.parseArray(operationStrategy);
        Integer holidayToday = holidayUtil.isHolidayToday();
        for (Object o : jsonArray) {
            JSONObject jsonObject = JSONObject.parseObject(o.toString());
            String type = jsonObject.getString("type");
            if (type.equals(holidayToday.toString())) {
                JSONArray time = jsonObject.getJSONArray("time");
                // 判断当前时间 是否在time时间段中
                for (Object object : time) {
                    String[] timeArray = object.toString().split("-");
                    String startTime = timeArray[0];
                    String endTime = timeArray[1];
                    boolean currentTimeInRange = DateUtils.isCurrentTimeInRange(startTime, endTime);
                    if (currentTimeInRange) {
                        return true;
                    }
                }
            } else if (type.equals("3")) {
                // 判断是什么类型 0每天  1-7 想起
                String typeStr = jsonObject.getString("typeStr");
                // 查看今天周几
                Integer week = DateUtils.getWeek();
                // 包含每天 或者  包含当天
                if (typeStr.contains("0") || typeStr.contains(week.toString())) {
                    JSONArray time = jsonObject.getJSONArray("time");
                    // 判断当前时间 是否在time时间段中
                    for (Object object : time) {
                        String[] timeArray = object.toString().split("-");
                        String startTime = timeArray[0];
                        String endTime = timeArray[1];
                        boolean currentTimeInRange = DateUtils.isCurrentTimeInRange(startTime, endTime);
                        if (currentTimeInRange) {
                            return true;
                        }
                    }
                }
            }
        }
        return false;
    }
}
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/utils/XpPricingUtil.java
@@ -35,6 +35,35 @@
    /**
     * 获取起步里程
     * @param startingFareJsonStr
     * @return
     */
    public static Integer getStartMileage(String startingFareJsonStr) {
        Date date = new Date();
        JSONArray startingFareJson = JSONObject.parseArray(startingFareJsonStr);
        for (Object o : startingFareJson) {
            JSONObject startingFare = (JSONObject) o;
            Calendar calendarStart = Calendar.getInstance();
            calendarStart.setTime(date);
            calendarStart.set(Calendar.HOUR_OF_DAY, Integer.valueOf(startingFare.getString("num1").split(":")[0]));
            calendarStart.set(Calendar.MINUTE, Integer.valueOf(startingFare.getString("num1").split(":")[1]));
            Calendar calendarEnd = Calendar.getInstance();
            calendarEnd.setTime(date);
            calendarEnd.set(Calendar.HOUR_OF_DAY, Integer.valueOf(startingFare.getString("num2").split(":")[0]));
            calendarEnd.set(Calendar.MINUTE, Integer.valueOf(startingFare.getString("num2").split(":")[1]));
            // 找到符合条件的直接跳出循环
            if (date.getTime() > calendarStart.getTimeInMillis() && date.getTime() < calendarEnd.getTimeInMillis()) {
                Integer mileage = startingFare.getInteger("num4");
                return mileage;
            }
        }
        return null;
    }
    /**
     *  计算基础价格
     * @param rule 基础规则
     * @param distance 里程
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/utils/holiday/HolidayUtil.java
@@ -4,6 +4,7 @@
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.xiaopeng.common.core.constant.CacheConstants;
import com.xiaopeng.common.core.utils.HttpUtils;
import com.xiaopeng.common.redis.service.RedisService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
@@ -43,4 +44,38 @@
        return false;
    }
    /**
     * 2非工作日  0工作日  1节假日 3调休日
     * @return
     */
    public  Integer isHolidayToday() {
        LocalDate now = LocalDate.now();
        Object cacheObject = redisService.getCacheObject(CacheConstants.IS_DAY + now);
        // 判断缓存里面是否有节假日算法
        if (cacheObject!=null) {
            return Integer.valueOf(cacheObject.toString());
        }
        String result = HttpUtils.sendGet("https://publicapi.xiaoai.me/holiday/day?date=" +now);
//        String result = HttpUtils.sendGet("https://publicapi.xiaoai.me/holiday/day?date=2026-01-04");
        JSONObject jsonObject = JSONObject.parseObject(result);
        Object data = jsonObject.get("data");
        JSONArray parse = JSONArray.parse(data.toString());
        for (int i = 0; i < parse.size(); i++) {
            JSONObject jsonObject1 = parse.getJSONObject(i);
            String daytype = jsonObject1.get("daytype").toString();
            if (daytype.equals("0")) {
                redisService.setCacheObject(CacheConstants.IS_DAY + now, "0", 1l, TimeUnit.DAYS);
                return 0;
            } else if (daytype.equals("1")) {
                redisService.setCacheObject(CacheConstants.IS_DAY + now, "1", 1l, TimeUnit.DAYS);
                return 1;
            } else if (daytype.equals("2")) {
                redisService.setCacheObject(CacheConstants.IS_DAY + now, "0", 1l, TimeUnit.DAYS);
                return 0;
            }
        }
        return 0;
    }
}