package com.xiaopeng.itinerary.controller; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.xiaopeng.api.dto.map.RouteAndFareDto; import com.xiaopeng.api.dto.map.RoutePreferenceSaveDto; import com.xiaopeng.api.dto.map.RouteStaleCheckDto; import com.xiaopeng.api.dto.map.SelectNavigationRouteDto; import com.xiaopeng.api.dto.order.OrderChangeDto; import com.xiaopeng.api.model.order.XpOrder; import com.xiaopeng.api.vo.operation.MultiRouteAndFareVo; import com.xiaopeng.api.vo.operation.RoutePreferenceItemVo; import com.xiaopeng.api.vo.operation.RouteStaleCheckVo; import com.xiaopeng.api.dto.operation.LonLatDto; import com.xiaopeng.api.model.operation.XpPricing; import com.xiaopeng.api.vo.operation.RouteAndFareVo; import com.xiaopeng.common.core.domain.R; import com.xiaopeng.common.core.web.controller.BaseController; import com.xiaopeng.common.redis.service.RedisService; import com.xiaopeng.itinerary.dto.XpOrderDto; import com.xiaopeng.itinerary.service.ActiveOrderService; import com.xiaopeng.itinerary.service.IXpGeoQueryEntityService; import com.xiaopeng.itinerary.service.XpPricingService; import com.xiaopeng.api.vo.HotFixInfoVo; import com.xiaopeng.itinerary.utils.ImageTagProcessor; import com.xiaopeng.itinerary.vo.QueueStatusVo; import com.xiaopeng.itinerary.vo.SaveOrderVo; import com.xiaopeng.unifiedverification.interceptor.XpClientCheck; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import javax.validation.Valid; import java.util.List; /** *

* 费项管理 前端控制器 *

* * @author mitao * @since 2026-02-03 */ @Slf4j @RestController @RequestMapping("") @Api(tags = "费用管理") public class XpPricingController extends BaseController { private final XpPricingService xpPricingService; private final IXpGeoQueryEntityService xpGeoQueryEntityService; private final RedisService redisService; private final ImageTagProcessor imageTagProcessor; public XpPricingController(XpPricingService xpPricingService, IXpGeoQueryEntityService xpGeoQueryEntityService, RedisService redisService, ImageTagProcessor imageTagProcessor) { this.xpPricingService = xpPricingService; this.xpGeoQueryEntityService = xpGeoQueryEntityService; this.redisService = redisService; this.imageTagProcessor = imageTagProcessor; } @PostMapping("/base/v1/mini-program/navigation/route-and-fare") @ApiOperation(value = "导航-获取路线和费用", tags = {"小程序-获取路线和费用"}, response = RouteAndFareVo.class) @XpClientCheck(checkToken = false, checkOtpToken = true) public R> getRouteAndFare(@RequestBody @Valid RouteAndFareDto routeAndFareDto, HttpServletRequest request) { // uid已通过拦截器otp校验,可以直接使用 String uid = request.getHeader("XP-Uid"); return R.ok(xpPricingService.getRouteAndFare(routeAndFareDto, uid)); } @GetMapping("/base/v1/mini-program/pricing/rules/{openCityId}") @ApiOperation(value = "获取费用规则", tags = {"小程序-根据开通城市获取费用规则"}, response = String.class) @XpClientCheck(checkToken = false, checkOtpToken = true) public R getPricingRules(@PathVariable Long openCityId) { XpPricing xpPricing = xpPricingService.getOne(new LambdaQueryWrapper().eq(XpPricing::getCityId, openCityId).last("limit 1")); if (xpPricing != null) { String priceRule = xpPricing.getPriceRule(); if (priceRule != null && priceRule.contains(" getWaitTime(@RequestBody LonLatDto dto) { return R.ok(xpPricingService.getWaitTime(dto.getLongitude(), dto.getLatitude())); } @PostMapping("/logan/inner/v1/pricing/getWaitTime") public R getWaitTime1(@RequestBody LonLatDto dto) { return R.ok(xpPricingService.getWaitTime(dto.getLongitude(), dto.getLatitude())); } /** * 播单 */ @PostMapping("/base/v1/mini-program/order/save") @ApiOperation(value = "保存订单", tags = {"小程序-保存订单"}) @XpClientCheck(checkToken = false, checkOtpToken = true) public R saveOrder(@RequestBody @Validated XpOrderDto dto, HttpServletRequest request) { String uid = request.getHeader("XP-Uid"); String orderId = xpPricingService.saveOrder(dto, uid); if(orderId==null){ String language = request.getHeader("language"); if(language==null){ return R.ok("站点已停止运营"); } if("1".equals( language)){ return R.ok("站点已停止运营"); } if("2".equals( language)){ return R.ok("This site has ceased operations"); } } SaveOrderVo saveOrderVo = new SaveOrderVo(); saveOrderVo.setOrderId(orderId); return R.ok(saveOrderVo); } /** * 获取热修复信息 * @param * @param * @return */ @GetMapping("/base/v1/mini-program/order/getHotFixInfo") @ApiOperation(value = "获取热修复信息", tags = {"小程序-获取热修复信息"}, response = HotFixInfoVo.class) public R getHotFixInfo() { Object cacheObject = redisService.getCacheObject("HOT_FIX_INFO"); if(cacheObject!=null){ HotFixInfoVo hotFixInfoVo = (HotFixInfoVo) cacheObject; return R.ok(hotFixInfoVo); } HotFixInfoVo hotFixInfoVo = new HotFixInfoVo(); hotFixInfoVo.setHotfixStatus(0); return R.ok(hotFixInfoVo); } @PostMapping("/base/v1/mini-program/navigation/multi-route-and-fare") @ApiOperation(value = "导航-多策略路线合并与费用", tags = {"小程序-路线选择"}, response = MultiRouteAndFareVo.class) @XpClientCheck(checkToken = false, checkOtpToken = true) public R getMultiRouteAndFare(@RequestBody @Valid RouteAndFareDto routeAndFareDto, HttpServletRequest request) { String uid = request.getHeader("XP-Uid"); return R.ok(xpPricingService.getMultiRouteAndFare(routeAndFareDto, uid)); } @PostMapping("/base/v1/mini-program/navigation/select-route") @ApiOperation(value = "选中某条路线并写入导航缓存", tags = {"小程序-路线选择"}) @XpClientCheck(checkToken = false, checkOtpToken = true) public R selectNavigationRoute(@RequestBody @Valid SelectNavigationRouteDto dto, HttpServletRequest request) { String uid = request.getHeader("XP-Uid"); xpPricingService.selectNavigationRoute(dto, uid); return R.ok(); } @PostMapping("/base/v1/mini-program/navigation/route-stale-check") @ApiOperation(value = "路线/价格过期静默校验", tags = {"小程序-路线选择"}, response = RouteStaleCheckVo.class) @XpClientCheck(checkToken = false, checkOtpToken = true) public R checkRouteStale(@RequestBody @Valid RouteStaleCheckDto dto, HttpServletRequest request) { String uid = request.getHeader("XP-Uid"); return R.ok(xpPricingService.checkRouteStale(dto, uid)); } @GetMapping("/base/v1/mini-program/navigation/route-preferences") @ApiOperation(value = "路线偏好可选项(含当前用户勾选态 selected)", tags = {"小程序-路线选择"}, response = RoutePreferenceItemVo.class) @XpClientCheck(checkToken = false, checkOtpToken = true) public R> listRoutePreferences(@RequestParam Long openCityId, HttpServletRequest request) { String uid = request.getHeader("XP-Uid"); return R.ok(xpPricingService.listRoutePreferences(openCityId, uid)); } @PostMapping("/base/v1/mini-program/navigation/route-preference") @ApiOperation(value = "保存用户路线偏好", tags = {"小程序-路线选择"}) @XpClientCheck(checkToken = false, checkOtpToken = true) public R saveUserRoutePreference(@RequestBody @Valid RoutePreferenceSaveDto dto, HttpServletRequest request) { String uid = request.getHeader("XP-Uid"); xpPricingService.saveUserRoutePreference(dto.getCode(), uid); return R.ok(); } /** * 查询排队状态 * @param orderId 订单ID * @return 排队状态信息 */ @GetMapping("/base/v1/mini-program/order/queue-status") @ApiOperation(value = "查询排队状态", tags = {"小程序-排队状态"}, response = QueueStatusVo.class) @XpClientCheck(checkToken = false, checkOtpToken = true) public R getQueueStatus(@RequestParam String orderId, HttpServletRequest request) { String uid = request.getHeader("XP-Uid"); return R.ok(xpPricingService.getQueueStatus(orderId, uid)); } /** * 当前行程可否修改 * * @param * @return 订单数量 */ @GetMapping("/api/v1/mini-program/order/queryOrderTrajectory") public R allowedModify(@RequestParam Long orderId){ // 1. 小于10分钟路程(后台配置)【取消行程】按钮应置灰;【取消行程】按钮应置灰;登录后获取系统和个人配置; // 2. 当前剩余里程 < 800米 (后台配置)或 剩余时间 < 5分钟(后台配置)(以先到者为准),禁止修改,按钮置灰。 // 3. 单次行程最多允许修改 2次 (后台配置)目的地,防恶意高频调用 // // 数据字典设置 // 取消行程 时间阈值 10 分钟 // 修改行程 时间阈值 5 分钟 // 修改行程 路程阈值 800 米 // 解除限制 时间阈值 3 分钟 // // 若系统检测到车辆在当前坐标时速 < 3km/h 且持续时间 > 3分钟(后台配置)(判定为极度拥堵或异常停滞),此时解除限制 // 通过 redis 轨迹得到路程 < 3s/60s * 3000m,则为堵车 return R.ok(); } }