xp-robotaxi-account-boot/src/main/java/com/xiaopeng/account/controller/XpOperationsUserController.java
@@ -262,16 +262,17 @@ XpOperationsUserVO xpOperationsUserVO = xpOperationsUserService.detailById(id); if (xpOperationsUserVO.getAvatar() != null) { JSONObject jsonObject = JSONObject.parseObject(xpOperationsUserVO.getAvatar()); String downloadUrl = null; try { // 1 String downloadUrl1 = aliOssService.getDownloadUrl(jsonObject.getString("id"), jsonObject.getString("name"), true); downloadUrl = downloadUrl1; } catch (Exception e) { e.printStackTrace(); if(jsonObject!=null){ String downloadUrl = null; try { // 1 downloadUrl= aliOssService.getDownloadUrl(jsonObject.getString("id"), jsonObject.getString("name"), true); } catch (Exception e) { e.printStackTrace(); } jsonObject.put("url", downloadUrl); xpOperationsUserVO.setAvatar(jsonObject.toJSONString()); } jsonObject.put("url", downloadUrl); xpOperationsUserVO.setAvatar(jsonObject.toJSONString()); } return R.ok(xpOperationsUserVO); xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/operation/XpTestPoint.java
New file @@ -0,0 +1,120 @@ package com.xiaopeng.api.model.operation; import com.baomidou.mybatisplus.annotation.*; import com.xiaopeng.common.core.web.domain.BaseModel; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.experimental.Accessors; import java.math.BigDecimal; /** * <p> * 测试demo-点位管理 * </p> * * @author mitao * @since 2026-02-03 */ @Data @EqualsAndHashCode(callSuper = false) @Accessors(chain = true) @TableName("xp_test_point") @ApiModel(value="XpTestPoint对象", description="点位管理") public class XpTestPoint extends BaseModel { private static final long serialVersionUID = 1L; @TableId(value = "id", type = IdType.NONE) private Long id; @ApiModelProperty(value = "电子围栏区域id") private Long electronicAreaId; @TableField(value = "fp_electronic_area_id", updateStrategy = FieldStrategy.NEVER) private Long fpElectronicAreaId; @ApiModelProperty(value = "点位名称") private String pointName; @ApiModelProperty(value = "点位poi") private String pointPoi; @ApiModelProperty(value = "点位编号唯一") private String pointNumber; @ApiModelProperty(value = "运营状态 1=待启用 2=启用中 3=已停用 4=已失效") private Integer operationStatus; @ApiModelProperty(value = "点位类型 1=运营点位 2=测试点位") private Integer pointType; @ApiModelProperty(value = "验证状态 1=待验证、2=验证中、3=已验证 4验证失败 5待生效") private Integer verificationStatus; @ApiModelProperty(value = "限停时长") private Integer parkingTimeLimit; @ApiModelProperty(value = "运营类型 1=与运营区同步 2=自定义时间段") private Integer operationType; @ApiModelProperty(value = "生效周期 1=“每日生效”、2=“仅工作日生效”、3=“仅非工作日生效”、4=“仅节假日生效”") private Integer effectivePeriod; @ApiModelProperty(value = "生效时间段") private String effectiveTimePeriod; @ApiModelProperty(value = "点位地址") @TableField("point_address") private String pointAddress; @ApiModelProperty(value = "备注") private String remarks; @ApiModelProperty(value = "点位照片") private String pointPictures; @ApiModelProperty(value = "经度") private Double pointLon; @ApiModelProperty(value = "纬度") private Double pointLat; @ApiModelProperty(value = "距离 单位米") @TableField(exist = false) private BigDecimal distance; @ApiModelProperty(value = "0否 1是充电点位") @TableField("charge_point") private Integer chargePoint; @ApiModelProperty(value = "0否 1是收车点位") @TableField("parking_point") private Integer parkingPoint; @ApiModelProperty(value = "省份名称") @TableField("province_name") private String provinceName; @ApiModelProperty(value = "省份code") @TableField("province_code") private String provinceCode; @ApiModelProperty(value = "城市名称") @TableField("city_name") private String cityName; @ApiModelProperty(value = "城市code") @TableField("city_code") private String cityCode; @ApiModelProperty(value = "区县名称") @TableField("district_name") private String districtName; @ApiModelProperty(value = "区县code") @TableField("district_code") private String districtCode; } xp-robotaxi-automatic-pilot-boot/src/main/java/com/xiaopeng/automaticPilot/service/KafkaConsumerService.java
@@ -874,6 +874,14 @@ case ORDER_CANCELLED: //已取消 if(!orderId.contains("XU")){ //判断订单状态,已经取消的不作处理 Object cacheObject = redisService.getCacheObject("ORDER_STATUS:" + orderId); if(null != cacheObject){ int order_status = Integer.parseInt(cacheObject.toString()); if(0 == order_status){ return; } } //行程中取消订单,按照行程结束处理 buildPushOrderStatus(orderId, OrderStatusEnum.SEE_OFF_GUESTS, sequence); xpOrderClient.updateOrderStatus(Long.parseLong(orderId), OrderStatusEnum.SEE_OFF_GUESTS.getCode()); @@ -904,9 +912,6 @@ public void buildPushOrderStatus(String orderId, OrderStatusEnum status, Long sequence){ if(orderId.contains("XU")){ //巡游单 //响应消息 // TODO 1.处理结束当前巡游订单 2.创建新的巡游订单 返航 3.调用xpu车机接口 (判断是返航还是正常 返航需要存储之前的订单id) responseMessage(sequence, ""); //到达目的地 if(OrderStatusEnum.COMPLETED.equals(status)){ // 返程找到目前的订单 -》之前的订单 查询生成一个 正常巡游 找到下一个点位 若到达最后点位 则反向找点位 每次判断是否收车状态 是则不进行处理了 @@ -919,6 +924,8 @@ xpCruiseOrderClient.completeCruiseOrder(Long.parseLong(orderId.substring(2))); R<XpVehicle> xpVehicleR = xpVehicleClient.queryById(vehicleId); XpVehicle xpVehicle = xpVehicleR.getData(); //响应消息 responseMessage(sequence, xpVehicle.getVehicleVin()); // 运营中 继续执行 if(xpVehicle.getOperatingStatus()==1 && xpVehicle.getState()==0){ log.info("巡游单到达终点,继续执行下一笔巡游单"); xp-robotaxi-itinerary-boot/src/main/java/com/xiaopeng/itinerary/utils/XpPricingUtil.java
@@ -89,7 +89,7 @@ String timeStr = dynamicPriceObj.toString(); // 判断当前距离这个时间范围的新增订单数(排除取消) / 上浮数量 算出应该增加的价格率 R<Integer> r = xpOrderClient.getOrderNum(new GetOrderNumDto(timeStr,openCityId)); if(r.getData()==200){ if(r.getCode()==200){ int num = r.getData(); // X单上升一次调价 Integer orderNum = getOrderNum(jsonObject, 4); @@ -140,8 +140,8 @@ xpPricingCardVo.setDurationPrice(durationPrice); xpPricingCardVo.setTotalPrice(new BigDecimal(startPrice + distancePrice + durationPrice).setScale(2,RoundingMode.HALF_UP).doubleValue()); // 里程 xpPricingCardVo.setDistance(realDistance); xpPricingCardVo.setDuration(realTime); xpPricingCardVo.setDistance(realDistance*1000); xpPricingCardVo.setDuration(realTime*60); return xpPricingCardVo; } @@ -180,7 +180,7 @@ String timeStr = dynamicPriceObj.toString(); // 判断当前距离这个时间范围的新增订单数(排除取消) / 上浮数量 算出应该增加的价格率 R<Integer> r = xpOrderClient.getOrderNum(new GetOrderNumDto(timeStr,openCityId)); if(r.getData()==200){ if(r.getCode()==200){ int num = r.getData(); // X单上升一次调价 Integer orderNum = getOrderNum(jsonObject, 4); @@ -361,6 +361,9 @@ // 时长费 xpPricingCardVo.setDurationPrice((exceedTime * rule.getDouble("num17"))); xpPricingCardVo.setDistancePriceNormal(rule.getDouble("num2")*1000); xpPricingCardVo.setDurationPriceNormal(rule.getDouble("num3")*60); } else { @@ -423,6 +426,9 @@ xpPricingCardVo.setTime(rule.getString("num22")); } xpPricingCardVo.setDistancePriceNormal(rule.getDouble("num2")*1000); xpPricingCardVo.setDurationPriceNormal(rule.getDouble("num3")*60); // 里程 xpPricingCardVo.setDistance(realDistance); @@ -502,6 +508,7 @@ amount=new BigDecimal(amount).setScale(2,RoundingMode.HALF_UP).doubleValue(); // 先减去起步价重新计算 amount = amount - startPrice; // 动态计算费用 startPrice= new BigDecimal(startPrice).multiply(new BigDecimal(priceRate)).setScale(2, RoundingMode.HALF_UP).doubleValue(); amount = amount+startPrice; @@ -510,6 +517,8 @@ xpPricingCardVo.setDistance(xpPricingCardVo.getDistance()*1000); xpPricingCardVo.setDuration(xpPricingCardVo.getDuration()*60); return xpPricingCardVo; xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/service/impl/XpSchedulingDetailServiceImpl.java
@@ -53,6 +53,7 @@ import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; /** * <p> @@ -489,8 +490,14 @@ } } //批量保存排班明细数据 if (!schedulingDetails.isEmpty()) { this.saveOrUpdateBatch(schedulingDetails); //找出需要删除的数据 Set<Long> collect = schedulingDetails.stream().filter(s -> s.getId() != null).collect(Collectors.toList()).stream().map(XpSchedulingDetail::getId).collect(Collectors.toSet()); List<XpSchedulingDetail> collect1 = list.stream().filter(s -> !collect.contains(s.getId())).collect(Collectors.toList()); collect1.forEach(s -> s.setDeleted(true)); collect1.addAll(schedulingDetails); if (!collect1.isEmpty()) { this.saveOrUpdateBatch(collect1); } //异步处理消息通知数据 pushMessage(pushMessage, notifications); xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/controller/XpPricingController.java
@@ -85,7 +85,7 @@ @GetMapping("/base/v1/mini-program/pricing/rules/{openCityId}") @ApiOperation(value = "获取费用规则(弃用)", tags = {"小程序-根据开通城市获取费用规则(弃用)"}, response = String.class) public R<?> getPricingRules(@PathVariable Long openCityId) { XpPricing xpPricing = xpPricingService.getOne(new LambdaQueryWrapper<XpPricing>().eq(XpPricing::getCityId, openCityId).eq(XpPricing::getPricingType, 1).last("limit 1")); XpPricing xpPricing = xpPricingService.getOne(new LambdaQueryWrapper<XpPricing>().eq(XpPricing::getCityId, openCityId).last("limit 1")); if (xpPricing != null) { return R.ok(xpPricing.getPriceRule()); } xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/controller/XpTestPointManagementController.java
New file @@ -0,0 +1,205 @@ package com.xiaopeng.operation.controller; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.xiaopeng.api.dto.map.XpPointExportExcelQuery; import com.xiaopeng.api.dto.operation.PointAddDto; import com.xiaopeng.api.dto.operation.PointUpdateDto; import com.xiaopeng.api.dto.operation.XpPointEnableDisableDto; import com.xiaopeng.api.model.operation.XpElectronicFence; import com.xiaopeng.api.model.operation.XpElectronicFenceArea; import com.xiaopeng.api.model.operation.XpTestPoint; import com.xiaopeng.api.query.operation.PointListQuery; import com.xiaopeng.api.query.operation.PointPageListListQuery; import com.xiaopeng.common.core.domain.R; import com.xiaopeng.common.core.web.controller.BaseController; import com.xiaopeng.common.core.web.page.PageInfo; import com.xiaopeng.operation.dto.XpPointSpecialDto; import com.xiaopeng.operation.service.IXpElectronicFenceAreaService; import com.xiaopeng.operation.service.IXpElectronicFenceService; import com.xiaopeng.operation.service.XpPointService; import com.xiaopeng.operation.service.XpTestPointService; import com.xiaopeng.operation.vo.SpecialPointListVo; import com.xiaopeng.operation.vo.SpecialPointVo; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.BeanUtils; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; @Slf4j @RestController @RequestMapping("/api/v1/testPoint") @Api(tags = "测试demo-点位管理") public class XpTestPointManagementController extends BaseController { @Resource private XpTestPointService xpTestPointService; @Resource private IXpElectronicFenceAreaService xpElectronicFenceAreaService; @Resource private IXpElectronicFenceService xpElectronicFenceService; @ApiOperation(value = "获取所有运营中的区域", response = XpElectronicFenceArea.class) @PostMapping("/listElectronicFenceArea") public R<List<XpElectronicFenceArea>> listElectronicFenceArea() { // 获取所有启用的电子围栏 List<XpElectronicFence> electronicFences = xpElectronicFenceService.lambdaQuery().eq(XpElectronicFence::getStatus, 2).list(); List<Long> electronicFenceIds = electronicFences.stream().map(XpElectronicFence::getId).collect(Collectors.toList()); if (electronicFenceIds.isEmpty()) { return R.ok(new ArrayList<XpElectronicFenceArea>()); } // 获取电子围栏下启用的运营区域 List<XpElectronicFenceArea> electronicFenceAreaList = xpElectronicFenceAreaService.lambdaQuery().in(XpElectronicFenceArea::getElectronicId, electronicFenceIds) .eq(XpElectronicFenceArea::getAreaStatus, 1).list(); return R.ok(electronicFenceAreaList); } @ApiOperation(value = "点位管理列表", response = XpTestPoint.class) @PostMapping("/listPoint") public R<List<XpTestPoint>> list(@RequestBody PointListQuery query) { List<XpTestPoint> pageList = xpTestPointService.listAll(query); return R.ok(pageList); } @ApiOperation(value = "点位管理分页列表", response = XpTestPoint.class) @PostMapping("/pageList") public R<PageInfo<XpTestPoint>> pageList(@RequestBody PointPageListListQuery query) { PageInfo<XpTestPoint> pageList = xpTestPointService.pageList(query); return R.ok(pageList); } @PostMapping("/getByIds") public R<List<XpTestPoint>> getByIds(@RequestBody XpPointExportExcelQuery query) { List<XpTestPoint> list = xpTestPointService.lambdaQuery().in(XpTestPoint::getId, query.getPointIds()).list(); return R.ok(list); } /** * 新增点位 */ @PostMapping("/addPoint") @ResponseBody @ApiOperation(value = "新增点位") public R add(@Validated @RequestBody PointAddDto pointAddDto) { XpTestPoint xpPoint = new XpTestPoint(); BeanUtils.copyProperties(pointAddDto, xpPoint); xpPoint.setFpElectronicAreaId(xpPoint.getElectronicAreaId()); xpTestPointService.save(xpPoint); return R.ok(); } /** * 批量删除点位 */ @GetMapping("/deletePoint") @ResponseBody @ApiOperation(value = "删除点位") public R deletePoint(@RequestParam("ids") String ids) { xpTestPointService.removeBatchByIds(Arrays.stream(ids.split(",")) .map(Long::parseLong).collect(Collectors.toList())); return R.ok(); } /** * 编辑点位 */ @PostMapping("/editPoint") @ApiOperation(value = "编辑点位") public R edit(@Validated @RequestBody PointUpdateDto pointAddDto) { XpTestPoint xpPoint = new XpTestPoint(); BeanUtils.copyProperties(pointAddDto, xpPoint); xpPoint.setFpElectronicAreaId(null); xpTestPointService.updateById(xpPoint); return R.ok(); } /** * 点位详情 */ @GetMapping("/queryPointById") @ApiOperation(value = "点位详情") public R<XpTestPoint> queryById(@RequestParam Long id) { return R.ok(xpTestPointService.getById(id)); } /** * 启用/禁用 */ @PostMapping("/enableDisablePoint") @ApiOperation(value = "启用/禁用") public R enableDisable(@RequestBody XpPointEnableDisableDto dto) { XpTestPoint xpPoint = xpTestPointService.getById(dto.getId()); xpPoint.setOperationStatus(dto.getOperationStatus()); xpPoint.setFpElectronicAreaId(null); xpTestPointService.updateById(xpPoint); return R.ok(); } /** * 设置特殊点位 */ @PostMapping("/setSpecialPoint") @ApiOperation(value = "设置特殊点位", tags = "后台管理-特殊点位") public R setSpecialPoint(@RequestBody XpPointSpecialDto dto) { xpTestPointService.update(new LambdaUpdateWrapper<XpTestPoint>().set(XpTestPoint::getChargePoint, 0) .set(XpTestPoint::getParkingPoint, 0)); List<XpTestPoint> list = xpTestPointService.list(new LambdaQueryWrapper<XpTestPoint>() .in(XpTestPoint::getId, dto.getChargePoints())); list.forEach(e -> { e.setChargePoint(1); e.setFpElectronicAreaId(null); }); xpTestPointService.updateBatchById(list); List<XpTestPoint> list1 = xpTestPointService.list(new LambdaQueryWrapper<XpTestPoint>() .in(XpTestPoint::getId, dto.getParkingPoints())); list1.forEach(e -> { e.setParkingPoint(1); e.setFpElectronicAreaId(null); }); xpTestPointService.updateBatchById(list1); return R.ok(); } @GetMapping("/listSpecialPoint") @ApiOperation(value = "获取特殊点位", tags = "后台管理-特殊点位") public R<SpecialPointVo> getSpecialPoint() { List<XpTestPoint> chargePoints = xpTestPointService.list(new LambdaQueryWrapper<XpTestPoint>().eq(XpTestPoint::getChargePoint, 1)); List<XpTestPoint> parkingPoints = xpTestPointService.list(new LambdaQueryWrapper<XpTestPoint>().eq(XpTestPoint::getParkingPoint, 1)); SpecialPointVo specialPointVo = new SpecialPointVo(); ArrayList<SpecialPointListVo> chargePointsList = new ArrayList<>(); for (XpTestPoint chargePoint : chargePoints) { SpecialPointListVo specialPointListVo = new SpecialPointListVo(); specialPointListVo.setPointName(chargePoint.getPointName()); specialPointListVo.setPointAddress(chargePoint.getPointAddress()); specialPointListVo.setPointId(chargePoint.getId()); chargePointsList.add(specialPointListVo); } specialPointVo.setChargePoints(chargePointsList); ArrayList<SpecialPointListVo> parkingPointsList = new ArrayList<>(); for (XpTestPoint parkingPoint : parkingPoints) { SpecialPointListVo specialPointListVo = new SpecialPointListVo(); specialPointListVo.setPointName(parkingPoint.getPointName()); specialPointListVo.setPointAddress(parkingPoint.getPointAddress()); specialPointListVo.setPointId(parkingPoint.getId()); parkingPointsList.add(specialPointListVo); } specialPointVo.setParkingPoints(parkingPointsList); return R.ok(specialPointVo); } } xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/mapper/XpTestPointMapper.java
New file @@ -0,0 +1,35 @@ package com.xiaopeng.operation.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.xiaopeng.api.dto.operation.PointMapQuery; import com.xiaopeng.api.model.operation.XpPoint; import com.xiaopeng.api.model.operation.XpTestPoint; import com.xiaopeng.api.query.operation.PointListQuery; import com.xiaopeng.api.query.operation.PointPageListListQuery; import com.xiaopeng.api.vo.order.XpPointsListVo; import com.xiaopeng.common.core.web.page.PageInfo; import com.xiaopeng.operation.query.PointByNameQuery; import org.apache.ibatis.annotations.Param; import java.util.List; /** * <p> * 测试demo-点位管理 Mapper 接口 * </p> * * @author liu * @author WuGuanFengYue * @since 2026-02-03 */ public interface XpTestPointMapper extends BaseMapper<XpTestPoint> { List<XpTestPoint> pointMap(@Param("query") PointMapQuery query); List<XpTestPoint> listAll(@Param("query") PointListQuery query); List<XpPointsListVo> queryPointByName(@Param("query") PointByNameQuery query); List<XpTestPoint> pageList(@Param("pageInfo") PageInfo<XpPoint> pageInfo, @Param("query") PointPageListListQuery query); } xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/XpTestPointService.java
New file @@ -0,0 +1,93 @@ package com.xiaopeng.operation.service; import com.baomidou.mybatisplus.extension.service.IService; import com.xiaopeng.api.dto.operation.PointMapQuery; import com.xiaopeng.api.dto.order.HistoryEndPointsDto; import com.xiaopeng.api.dto.order.HistoryStartPointsDto; import com.xiaopeng.api.model.operation.XpTestPoint; import com.xiaopeng.api.query.operation.PointListQuery; import com.xiaopeng.api.query.operation.PointPageListListQuery; import com.xiaopeng.api.vo.order.XpHistoryEndPointsVo; import com.xiaopeng.api.vo.order.XpHistoryStartPointsVo; import com.xiaopeng.api.vo.order.XpPointsSearchVo; import com.xiaopeng.common.core.web.page.PageInfo; import com.xiaopeng.operation.dto.NearestDto; import com.xiaopeng.operation.query.PointByNameQuery; import com.xiaopeng.operation.vo.NearestVo; import com.xiaopeng.operation.vo.OrderDistanceVo; import javax.validation.Valid; import java.time.LocalTime; import java.util.List; /** * <p> * 测试demo-点位管理 服务类 * </p> * * @author liu * @author WuGuanFengYue * @since 2026-02-03 */ public interface XpTestPointService extends IService<XpTestPoint> { /** * 获取附近上车站点 */ NearestVo nearest(@Valid NearestDto dto); /** * 判断点位是否时间段内 * @param now * @return */ boolean getInTime(LocalTime now, Integer effectivePeriod, String effectiveTimePeriod); List<XpTestPoint> pointMap(PointMapQuery query); List<XpTestPoint> listAll(PointListQuery query); /** * 获取历史上车站点 * @param historyStartPointsDto * @return */ List<XpHistoryStartPointsVo> getHistoryStartPoints(HistoryStartPointsDto historyStartPointsDto); /** * 获取历史上车站点 * @param historyEndPointsDto * @return */ List<XpHistoryEndPointsVo> getHistoryEndPoints(HistoryEndPointsDto historyEndPointsDto); /** * 根据名称获取点位列表 * @param query * @return */ XpPointsSearchVo queryPointByName(@Valid PointByNameQuery query); /** * 获取可下单距离 * @return */ OrderDistanceVo getOrderDistance(); PageInfo<XpTestPoint> pageList(PointPageListListQuery query); /** * 判断点位是否在当前时间范围内有效 * @param pointId * @return */ Boolean nowInTimePoint(Long pointId); } xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/impl/XpTestPointServiceImpl.java
New file @@ -0,0 +1,502 @@ package com.xiaopeng.operation.service.impl; import cn.hutool.core.collection.CollUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.xiaopeng.api.dto.operation.PointMapQuery; import com.xiaopeng.api.dto.order.HistoryEndPointsDto; import com.xiaopeng.api.dto.order.HistoryStartPointsDto; import com.xiaopeng.api.model.operation.*; import com.xiaopeng.api.query.operation.PointListQuery; import com.xiaopeng.api.query.operation.PointPageListListQuery; import com.xiaopeng.api.vo.order.XpHistoryEndPointsVo; import com.xiaopeng.api.vo.order.XpHistoryStartPointsVo; import com.xiaopeng.api.vo.order.XpPointsListVo; import com.xiaopeng.api.vo.order.XpPointsSearchVo; import com.xiaopeng.common.core.constant.CacheConstants; import com.xiaopeng.common.core.web.page.PageInfo; import com.xiaopeng.common.redis.service.RedisService; import com.xiaopeng.operation.dto.NearestDto; import com.xiaopeng.operation.mapper.XpSystemSettingMapper; import com.xiaopeng.operation.mapper.XpTestPointMapper; import com.xiaopeng.operation.query.PointByNameQuery; import com.xiaopeng.operation.service.IXpElectronicFenceAreaService; import com.xiaopeng.operation.service.IXpElectronicFenceService; import com.xiaopeng.operation.service.XpTestPointService; import com.xiaopeng.operation.utils.TimeRangeChecker; import com.xiaopeng.operation.utils.holiday.HolidayUtil; import com.xiaopeng.operation.utils.map.FastDistanceCalculator; import com.xiaopeng.operation.vo.NearestNextVo; import com.xiaopeng.operation.vo.NearestVo; import com.xiaopeng.operation.vo.OrderDistanceVo; import org.springframework.stereotype.Service; import org.springframework.util.StringUtils; import javax.annotation.Resource; import java.math.BigDecimal; import java.math.RoundingMode; import java.time.LocalDateTime; import java.time.LocalTime; import java.util.ArrayList; import java.util.Comparator; import java.util.List; import java.util.stream.Collectors; /** * <p> * 点位管理 服务实现类 * </p> * * @author liu * @author WuGuanFengYue * @since 2026-02-03 */ @Service public class XpTestPointServiceImpl extends ServiceImpl<XpTestPointMapper, XpTestPoint> implements XpTestPointService { @Resource private XpSystemSettingMapper xpSystemSettingMapper; @Resource private RedisService redisService; @Resource private HolidayUtil holidayUtil; @Resource private IXpElectronicFenceAreaService xpElectronicFenceAreaService; @Resource private IXpElectronicFenceService xpElectronicFenceService; @Override public NearestVo nearest(NearestDto dto) { // 走缓存 Object orderDistanceObj = redisService.getCacheObject(CacheConstants.NEAR_POINT_DISTANCE); Integer orderDistance; if (orderDistanceObj != null) { orderDistance = Integer.valueOf(orderDistanceObj.toString()); } else { XpSystemSetting xpSystemSetting = xpSystemSettingMapper.selectOne(null); orderDistance = xpSystemSetting.getNearPointDistance(); } List<XpTestPoint> list1 = list(new LambdaQueryWrapper<XpTestPoint>().eq(XpTestPoint::getOperationStatus, 2).eq(XpTestPoint::getPointType,1).isNotNull(XpTestPoint::getElectronicAreaId)); if(list1.size()<2){ return new NearestVo(); } // 获取所有的站点信息 List<XpTestPoint> list = list(new LambdaQueryWrapper<XpTestPoint>().eq(XpTestPoint::getOperationStatus, 2).eq(XpTestPoint::getPointType,1).isNotNull(XpTestPoint::getElectronicAreaId) // 添加距离计算字段 .apply("ST_Distance_Sphere(point({0}, {1}), point(point_lon, point_lat)) <= {2}", dto.getLongitude(), dto.getLatitude(), orderDistance)); list = list.stream().filter(e->e.getElectronicAreaId().equals(dto.getElectronicAreaId())).collect(Collectors.toList()); NearestVo nearestVo = new NearestVo(); if(list.isEmpty()){ nearestVo.setPoints(new ArrayList<>()); nearestVo.setTotal(0); return nearestVo; } List<NearestNextVo> nearestNextVos = new ArrayList<>(); LocalTime now = LocalTime.now(); List<Long> areaIds = list.stream().map(XpTestPoint::getElectronicAreaId).collect(Collectors.toList()); List<XpElectronicFenceArea> xpElectronicFenceAreas = xpElectronicFenceAreaService.listByIds(areaIds); List<Long> fenceIds = xpElectronicFenceAreas.stream().map(XpElectronicFenceArea::getElectronicId).collect(Collectors.toList()); List<XpElectronicFence> xpElectronicFences = new ArrayList<>(); if (CollUtil.isNotEmpty(fenceIds)) { xpElectronicFences = xpElectronicFenceService.listByIds(fenceIds); } //判断当前点位是否在运营时间范围内 for (XpTestPoint xpPoint : list) { Integer operationType = xpPoint.getOperationType(); if(1 == operationType){ //与运营区同步 XpElectronicFenceArea xpElectronicFenceArea = xpElectronicFenceAreas.stream().filter(s -> s.getId().equals(xpPoint.getElectronicAreaId())).findFirst().orElse(null); if(null == xpElectronicFenceArea){ continue; } XpElectronicFence xpElectronicFence = xpElectronicFences.stream().filter(s -> s.getId().equals(xpElectronicFenceArea.getElectronicId())).findFirst().orElse(null); if(null == xpElectronicFence){ continue; } //失效类型 1=永不失效 2=定时失效 Integer failureType = xpElectronicFence.getFailureType(); //永不失效,但是还未到开始时间 if(1 == failureType && LocalDateTime.now().isBefore(xpElectronicFence.getEffectTime())){ continue; }else if(2 == failureType && (LocalDateTime.now().isBefore(xpElectronicFence.getEffectTime()) || LocalDateTime.now().isAfter(xpElectronicFence.getFailureTime()))){ //定时失效,但是当前时间不在时间范围内 continue; } }else{ //自定义时间段 // 判断是否在时间段内 boolean intime = getInTime(now, xpPoint.getEffectivePeriod(), xpPoint.getEffectiveTimePeriod()); if (!intime) { continue; } } // 计算距离 小于的站点 double v = FastDistanceCalculator.distanceFast(dto.getLatitude(), dto.getLongitude(), xpPoint.getPointLat(), xpPoint.getPointLon()); // m做判断 if ((v) < orderDistance) { NearestNextVo nearestNextVo = new NearestNextVo(); nearestNextVo.setId(xpPoint.getId()); nearestNextVo.setName(xpPoint.getPointName()); nearestNextVo.setLatitude(xpPoint.getPointLat()); nearestNextVo.setLongitude(xpPoint.getPointLon()); nearestNextVo.setDistance(new BigDecimal(v).setScale(2, RoundingMode.HALF_UP).doubleValue()); nearestNextVo.setAddress(xpPoint.getPointAddress()); nearestNextVo.setTime(xpPoint.getParkingTimeLimit()); nearestNextVo.setElectronicAreaId(xpPoint.getElectronicAreaId()); nearestNextVos.add(nearestNextVo); } } if (!nearestNextVos.isEmpty()) { nearestNextVos = nearestNextVos.stream().sorted(Comparator.comparing(NearestNextVo::getDistance)).collect(Collectors.toList()); } nearestVo.setPoints(nearestNextVos); nearestVo.setTotal(nearestNextVos.size()); return nearestVo; } public boolean getInTime(LocalTime now, Integer effectivePeriod, String effectiveTimePeriod){ // 2非工作日 0工作日 1节假日 3调休日 Integer holidayToday = holidayUtil.isHolidayToday(); if(effectivePeriod==1){ boolean inTime = TimeRangeChecker.isCurrentTimeInRanges(now,effectiveTimePeriod); if (!inTime) { return false; } }else if(effectivePeriod==2){ if(holidayToday!=0){ return false; } boolean inTime = TimeRangeChecker.isCurrentTimeInRanges(now,effectiveTimePeriod); if (!inTime) { return false; } }else if(effectivePeriod==3){ if(holidayToday!=2){ return false; } boolean inTime = TimeRangeChecker.isCurrentTimeInRanges(now,effectiveTimePeriod); if (!inTime) { return false; } }else if(effectivePeriod==4){ if(holidayToday!=1){ return false; } boolean inTime = TimeRangeChecker.isCurrentTimeInRanges(now,effectiveTimePeriod); if (!inTime) { return false; } } return true; } @Override public List<XpTestPoint> pointMap(PointMapQuery query) { List<XpTestPoint> list = this.baseMapper.pointMap(query); return list; } @Override public List<XpTestPoint> listAll(PointListQuery query) { if(StringUtils.hasLength(query.getOperationStatus())){ String[] split = query.getOperationStatus().split(","); List<Integer> statusIds = new ArrayList<>(); for (String s : split) { statusIds.add(Integer.valueOf(s)); } query.setOperationStatusIds(statusIds); } List<XpTestPoint> list = this.baseMapper.listAll(query); return list; } @Override public List<XpHistoryStartPointsVo> getHistoryStartPoints(HistoryStartPointsDto historyStartPointsDto) { List<XpTestPoint> xpPoints = this.baseMapper.selectBatchIds(historyStartPointsDto.getPointIds()); ArrayList<XpHistoryStartPointsVo> resultList = new ArrayList<>(10); LocalTime now = LocalTime.now(); List<Long> areaIds = xpPoints.stream().map(XpTestPoint::getElectronicAreaId).collect(Collectors.toList()); List<XpElectronicFenceArea> xpElectronicFenceAreas = xpElectronicFenceAreaService.listByIds(areaIds); List<Long> fenceIds = xpElectronicFenceAreas.stream().map(XpElectronicFenceArea::getElectronicId).collect(Collectors.toList()); List<XpElectronicFence> xpElectronicFences = new ArrayList<>(); if (CollUtil.isNotEmpty(fenceIds)) { xpElectronicFences = xpElectronicFenceService.listByIds(fenceIds); } for (XpTestPoint xpPoint : xpPoints) { if(xpPoint.getOperationStatus()!=2){ continue; } Integer operationType = xpPoint.getOperationType(); if(1 == operationType){ //与运营区同步 XpElectronicFenceArea xpElectronicFenceArea = xpElectronicFenceAreas.stream().filter(s -> s.getId().equals(xpPoint.getElectronicAreaId())).findFirst().orElse(null); if(null == xpElectronicFenceArea){ // 不在运营段 continue; } XpElectronicFence xpElectronicFence = xpElectronicFences.stream().filter(s -> s.getId().equals(xpElectronicFenceArea.getElectronicId())).findFirst().orElse(null); if(null == xpElectronicFence){ // 不在运营段 continue; } //失效类型 1=永不失效 2=定时失效 Integer failureType = xpElectronicFence.getFailureType(); //永不失效,但是还未到开始时间 if(1 == failureType && LocalDateTime.now().isBefore(xpElectronicFence.getEffectTime())){ continue; }else if(2 == failureType && (LocalDateTime.now().isBefore(xpElectronicFence.getEffectTime()) || LocalDateTime.now().isAfter(xpElectronicFence.getFailureTime()))){ //定时失效,但是当前时间不在时间范围内 continue; } }else{ //自定义时间段 // 判断是否在时间段内 boolean intime = getInTime(now, xpPoint.getEffectivePeriod(), xpPoint.getEffectiveTimePeriod()); if (!intime) { // 不在运营段 continue; } } XpHistoryStartPointsVo xpHistoryStartPointsVo = new XpHistoryStartPointsVo(); xpHistoryStartPointsVo.setOperationStatus(1); xpHistoryStartPointsVo.setName(xpPoint.getPointName()); xpHistoryStartPointsVo.setAddress(xpPoint.getPointAddress()); xpHistoryStartPointsVo.setLatitude(xpPoint.getPointLat()); xpHistoryStartPointsVo.setLongitude(xpPoint.getPointLon()); xpHistoryStartPointsVo.setId(xpPoint.getId()); double distanced = FastDistanceCalculator.distanceFast(historyStartPointsDto.getLat(), historyStartPointsDto.getLon(), xpPoint.getPointLat(), xpPoint.getPointLon()); xpHistoryStartPointsVo.setDistance(distanced); xpHistoryStartPointsVo.setTime(xpPoint.getParkingTimeLimit()); xpHistoryStartPointsVo.setElectronicAreaId(xpPoint.getElectronicAreaId()); resultList.add(xpHistoryStartPointsVo); } return resultList; } @Override public List<XpHistoryEndPointsVo> getHistoryEndPoints(HistoryEndPointsDto historyEndPointsDto) { List<XpTestPoint> xpPoints = this.baseMapper.selectBatchIds(historyEndPointsDto.getPointIds()); ArrayList<XpHistoryEndPointsVo> resultList = new ArrayList<>(10); LocalTime now = LocalTime.now(); List<Long> areaIds = xpPoints.stream().map(XpTestPoint::getElectronicAreaId).collect(Collectors.toList()); List<XpElectronicFenceArea> xpElectronicFenceAreas = xpElectronicFenceAreaService.listByIds(areaIds); List<Long> fenceIds = xpElectronicFenceAreas.stream().map(XpElectronicFenceArea::getElectronicId).collect(Collectors.toList()); List<XpElectronicFence> xpElectronicFences = new ArrayList<>(); if (CollUtil.isNotEmpty(fenceIds)) { xpElectronicFences = xpElectronicFenceService.listByIds(fenceIds); } for (XpTestPoint xpPoint : xpPoints) { if(xpPoint.getOperationStatus()!=2){ continue; } Integer operationType = xpPoint.getOperationType(); if(1 == operationType){ //与运营区同步 XpElectronicFenceArea xpElectronicFenceArea = xpElectronicFenceAreas.stream().filter(s -> s.getId().equals(xpPoint.getElectronicAreaId())).findFirst().orElse(null); if(null == xpElectronicFenceArea){ // 不在运营段 continue; } XpElectronicFence xpElectronicFence = xpElectronicFences.stream().filter(s -> s.getId().equals(xpElectronicFenceArea.getElectronicId())).findFirst().orElse(null); if(null == xpElectronicFence){ // 不在运营段 continue; } //失效类型 1=永不失效 2=定时失效 Integer failureType = xpElectronicFence.getFailureType(); //永不失效,但是还未到开始时间 if(1 == failureType && LocalDateTime.now().isBefore(xpElectronicFence.getEffectTime())){ continue; }else if(2 == failureType && (LocalDateTime.now().isBefore(xpElectronicFence.getEffectTime()) || LocalDateTime.now().isAfter(xpElectronicFence.getFailureTime()))){ //定时失效,但是当前时间不在时间范围内 continue; } }else{ //自定义时间段 // 判断是否在时间段内 boolean intime = getInTime(now, xpPoint.getEffectivePeriod(), xpPoint.getEffectiveTimePeriod()); if (!intime) { // 不在运营段 continue; } } XpHistoryEndPointsVo xpHistoryEndPointsVo = new XpHistoryEndPointsVo(); xpHistoryEndPointsVo.setOperationStatus(1); xpHistoryEndPointsVo.setName(xpPoint.getPointName()); xpHistoryEndPointsVo.setAddress(xpPoint.getPointAddress()); xpHistoryEndPointsVo.setLatitude(xpPoint.getPointLat()); xpHistoryEndPointsVo.setLongitude(xpPoint.getPointLon()); xpHistoryEndPointsVo.setId(xpPoint.getId()); double distanced = FastDistanceCalculator.distanceFast(historyEndPointsDto.getLat(), historyEndPointsDto.getLon(), xpPoint.getPointLat(), xpPoint.getPointLon()); xpHistoryEndPointsVo.setDistance(distanced); xpHistoryEndPointsVo.setTime(xpPoint.getParkingTimeLimit()); xpHistoryEndPointsVo.setElectronicAreaId(xpPoint.getElectronicAreaId()); resultList.add(xpHistoryEndPointsVo); } return resultList; } @Override public XpPointsSearchVo queryPointByName(PointByNameQuery query) { XpPointsSearchVo searchVo = new XpTestPointsSearchVo(); List<XpPointsListVo> list = this.baseMapper.queryPointByName(query); if (list.isEmpty()) { return searchVo; } LocalTime now = LocalTime.now(); List<Long> areaIds = list.stream().map(XpPointsListVo::getElectronicAreaId).collect(Collectors.toList()); List<XpElectronicFenceArea> xpElectronicFenceAreas = xpElectronicFenceAreaService.listByIds(areaIds); List<Long> fenceIds = xpElectronicFenceAreas.stream().map(XpElectronicFenceArea::getElectronicId).collect(Collectors.toList()); List<XpElectronicFence> xpElectronicFences = new ArrayList<>(); if (CollUtil.isNotEmpty(fenceIds)) { xpElectronicFences = xpElectronicFenceService.listByIds(fenceIds); } for (XpPointsListVo xpPointsListVo : list) { Integer operationType = xpPointsListVo.getOperationType(); if(1 == operationType){ //与运营区同步 XpElectronicFenceArea xpElectronicFenceArea = xpElectronicFenceAreas.stream().filter(s -> s.getId().equals(xpPointsListVo.getElectronicAreaId())).findFirst().orElse(null); if(null == xpElectronicFenceArea){ // 不在运营段 xpPointsListVo.setState(0); } XpElectronicFence xpElectronicFence = xpElectronicFences.stream().filter(s -> s.getId().equals(xpElectronicFenceArea.getElectronicId())).findFirst().orElse(null); if(null == xpElectronicFence){ // 不在运营段 xpPointsListVo.setState(0); } //失效类型 1=永不失效 2=定时失效 Integer failureType = xpElectronicFence.getFailureType(); //永不失效,但是还未到开始时间 if(1 == failureType && LocalDateTime.now().isBefore(xpElectronicFence.getEffectTime())){ xpPointsListVo.setState(0); }else if(2 == failureType && (LocalDateTime.now().isBefore(xpElectronicFence.getEffectTime()) || LocalDateTime.now().isAfter(xpElectronicFence.getFailureTime()))){ //定时失效,但是当前时间不在时间范围内 xpPointsListVo.setState(0); } }else{ //自定义时间段 // 判断是否在时间段内 boolean intime = getInTime(now, xpPointsListVo.getEffectivePeriod(), xpPointsListVo.getEffectiveTimePeriod()); if (!intime) { // 不在运营段 xpPointsListVo.setState(0); } } } // 组装数据 并排序 剔除不在运营段的 数据 List<XpPointsListVo> resultList = list.stream() .peek(vo -> vo.setDistance(BigDecimal.valueOf(FastDistanceCalculator.distanceFast(query.getLat(), query.getLon(), vo.getLatitude(), vo.getLongitude())).setScale(2, RoundingMode.HALF_UP).doubleValue())) .filter(vo -> vo.getState() == 1).collect(Collectors.toList()); // 可用点位 List<XpPointsListVo> availablePoints = resultList.stream().filter(e -> query.getElectronicAreaId() != null && e.getElectronicAreaId().equals(query.getElectronicAreaId())).sorted(Comparator.comparing(XpPointsListVo::getDistance)).collect(Collectors.toList());// // 不可用点位 List<XpPointsListVo> unavailablePoints = resultList.stream().filter(e -> query.getElectronicAreaId() == null || !e.getElectronicAreaId().equals(query.getElectronicAreaId())).sorted(Comparator.comparing(XpPointsListVo::getDistance)).collect(Collectors.toList()); searchVo.setAvailablePoints(availablePoints); searchVo.setUnavailablePoints(unavailablePoints); return searchVo; } @Override public OrderDistanceVo getOrderDistance() { OrderDistanceVo orderDistanceVo = new OrderDistanceVo(); XpSystemSetting xpSystemSetting = xpSystemSettingMapper.selectOne(null); if (xpSystemSetting != null) { orderDistanceVo.setMaxDistance(xpSystemSetting.getOrderDistance()); orderDistanceVo.setMinDistance(xpSystemSetting.getMinOrderDistance()); orderDistanceVo.setAdsorptionDistance(xpSystemSetting.getAdsorptionDistance()); orderDistanceVo.setNearPointDistance(xpSystemSetting.getNearPointDistance()); return orderDistanceVo; } return orderDistanceVo; } @Override public PageInfo<XpTestPoint> pageList(PointPageListListQuery query) { PageInfo<XpTestPoint> pageInfo = new PageInfo<>(query.getPageNum(),query.getPageSize()); List<XpTestPoint> list = this.baseMapper.pageList(pageInfo,query); pageInfo.setRecords(list); return pageInfo; } @Override public Boolean nowInTimePoint(Long pointId) { XpTestPoint xpPoint = this.getById(pointId); if(null == xpPoint){ return false; } Integer operationType = xpPoint.getOperationType(); if(1 == operationType){ //与运营区同步 XpElectronicFenceArea xpElectronicFenceArea = xpElectronicFenceAreaService.getById(xpPoint.getElectronicAreaId()); if(null == xpElectronicFenceArea){ return false; } XpElectronicFence xpElectronicFence = xpElectronicFenceService.getById(xpElectronicFenceArea.getElectronicId()); if(null == xpElectronicFence){ return false; } //失效类型 1=永不失效 2=定时失效 Integer failureType = xpElectronicFence.getFailureType(); //永不失效,但是还未到开始时间 if(1 == failureType && LocalDateTime.now().isBefore(xpElectronicFence.getEffectTime())){ return false; }else if(2 == failureType && (LocalDateTime.now().isBefore(xpElectronicFence.getEffectTime()) || LocalDateTime.now().isAfter(xpElectronicFence.getFailureTime()))){ //定时失效,但是当前时间不在时间范围内 return false; } }else{ //自定义时间段 // 判断是否在时间段内 boolean intime = getInTime(LocalTime.now(), xpPoint.getEffectivePeriod(), xpPoint.getEffectiveTimePeriod()); if (!intime) { return false; } } return true; } } xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/utils/XpPricingUtil.java
@@ -87,7 +87,7 @@ String timeStr = dynamicPriceObj.toString(); // 判断当前距离这个时间范围的新增订单数(排除取消) / 上浮数量 算出应该增加的价格率 R<Integer> r = xpOrderClient.getOrderNum(new GetOrderNumDto(timeStr,openCityId)); if(r.getData()==200){ if(r.getCode()==200){ int num = r.getData(); // X单上升一次调价 Integer orderNum = getOrderNum(jsonObject, 4); @@ -178,7 +178,7 @@ String timeStr = dynamicPriceObj.toString(); // 判断当前距离这个时间范围的新增订单数(排除取消) / 上浮数量 算出应该增加的价格率 R<Integer> r = xpOrderClient.getOrderNum(new GetOrderNumDto(timeStr,openCityId)); if(r.getData()==200){ if(r.getCode()==200){ int num = r.getData(); // X单上升一次调价 Integer orderNum = getOrderNum(jsonObject, 4); xp-robotaxi-operation-boot/src/main/resources/mapper/operation/XpTestPointMapper.xml
New file @@ -0,0 +1,158 @@ <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.xiaopeng.operation.mapper.XpTestPointMapper"> <!-- 通用查询映射结果 --> <resultMap id="BaseResultMap" type="com.xiaopeng.api.model.operation.XpTestPoint"> <id column="id" property="id" /> <result column="point_name" property="pointName" /> <result column="point_poi" property="pointPoi" /> <result column="point_number" property="pointNumber" /> <result column="operation_status" property="operationStatus" /> <result column="point_type" property="pointType" /> <result column="verification_status" property="verificationStatus" /> <result column="parking_time_limit" property="parkingTimeLimit" /> <result column="operation_type" property="operationType" /> <result column="effective_period" property="effectivePeriod" /> <result column="effective_time_period" property="effectiveTimePeriod" /> <result column="remarks" property="remarks" /> <result column="point_pictures" property="pointPictures" /> <result column="point_lon" property="pointLon" /> <result column="point_lat" property="pointLat" /> <result column="is_deleted" property="deleted" /> <result column="create_time" property="createTime" /> <result column="update_time" property="updateTime" /> <result column="create_by" property="createBy" /> <result column="update_by" property="updateBy" /> </resultMap> <!-- 通用查询结果列 --> <sql id="Base_Column_List"> id,electronic_area_id, point_name, point_poi, point_number, operation_status, point_type, verification_status, parking_time_limit, operation_type, effective_period, effective_time_period, remarks, point_pictures, point_lon, point_lat, is_deleted, create_time, update_time, create_by, update_by </sql> <select id="pointMap" resultType="com.xiaopeng.api.model.operation.XpTestPoint"> select t1.*, ROUND( 6378.138 * 2 * ASIN( SQRT( POW( SIN( ( #{query.lat} * PI() / 180 - t1.point_lat * PI() / 180 ) / 2 ), 2 ) + COS(#{query.lat} * PI() / 180) * COS(t1.point_lat * PI() / 180) * POW( SIN( ( #{query.lon} * PI() / 180 - t1.point_lon * PI() / 180 ) / 2 ), 2 ) ) ) * 1000 ) AS distance from xp_test_point t1 where t1.is_deleted = 0 <if test="query.pointName != null and query.pointName != ''"> and t1.point_name like concat('%',#{query.pointName},'%') </if> <if test="query.pointType != null"> and t1.point_type = #{query.pointType} </if> <if test="query.operationStatus != null"> and t1.operation_status = #{query.operationStatus} </if> order by distance asc </select> <select id="listAll" resultType="com.xiaopeng.api.model.operation.XpTestPoint"> select t1.* from xp_test_point t1 where t1.is_deleted = 0 <if test="query.queryParams != null and query.queryParams != ''"> and ( t1.point_name like concat('%',#{query.queryParams},'%') or t1.point_poi like concat('%',#{query.queryParams},'%') or t1.point_number like concat('%',#{query.queryParams},'%') ) </if> <if test="query.pointType != null"> and t1.point_type = #{query.pointType} </if> <if test="query.cityCode != null and query.cityCode != ''"> and t1.city_code = #{query.cityCode} </if> <if test="query.operationStatusIds != null and query.operationStatusIds.size()>0"> AND t1.operation_status IN <foreach collection="query.operationStatusIds" separator="," item="id" open="(" close=")"> #{id} </foreach> </if> order by t1.create_time desc </select> <select id="queryPointByName" resultType="com.xiaopeng.api.vo.order.XpPointsListVo"> select p.id,p.operation_type as operationType ,p.electronic_area_id as electronicAreaId,p.point_name as name,p.point_address as address,p.point_lon as longitude,p.point_lat as latitude,p.effective_period,p.effective_time_period from xp_electronic_fence_area xefa left join xp_test_point p on p.electronic_area_id = xefa.id where p.is_deleted = 0 and p.operation_status =2 and xefa.is_deleted = 0 and xefa.area_status = 1 and p.electronic_area_id is not null and xefa.city_code = #{query.cityCode} <if test="query.pointPoi != null and query.pointPoi != ''"> and ( p.point_address like concat('%',#{query.pointPoi},'%') or p.point_name like concat('%',#{query.pointPoi},'%') ) </if> <if test="query.electronicAreaId != null"> and p.electronic_area_id = #{query.electronicAreaId} </if> </select> <select id="pageList" resultType="com.xiaopeng.api.model.operation.XpTestPoint"> select xp.id,xp.point_number as pointNumber,xp.point_name as pointName,xp.point_poi as pointPoi, xp.point_address as pointAddress, xp.point_lon as pointLon,xp.point_lat as pointLat,xp.create_time as createTime,xp.create_by as createBy ,xp.parking_time_limit as parkingTimeLimit,xp.verification_status as verificationStatus,xp.operation_status as operationStatus from xp_test_point xp where xp.is_deleted = 0 <if test="query.pointName != null and query.pointName != ''"> and xp.point_name like concat('%',#{query.pointName},'%') </if> <if test="query.pointNumber != null and query.pointNumber != ''"> and xp.point_number like concat('%',#{query.pointNumber},'%') </if> <if test="query.createBy != null and query.createBy != ''"> and xp.create_by like concat('%',#{query.createBy},'%') </if> <if test="query.parkingTimeLimit != null"> and xp.parking_time_limit = #{query.parkingTimeLimit} </if> <if test="query.pointLonAndLat != null and query.pointLonAndLat != ''"> and #{query.pointLonAndLat} like concat('%',xp.point_lon,'%') and #{query.pointLonAndLat} like concat('%',xp.point_lat,'%') </if> <if test="query.startTime != null and query.startTime != '' and query.endTime != null and query.endTime != ''"> and xp.create_time between #{query.startTime} and #{query.endTime} </if> <if test="query.operationStatusList != null and query.operationStatusList.size() > 0"> <trim prefix="and (" suffix=")" prefixOverrides="OR"> <foreach collection="query.operationStatusList" item="st"> <choose> <when test="st == 1">OR xp.verification_status = 1</when> <when test="st == 2">OR xp.verification_status = 2</when> <when test="st == 3">OR xp.verification_status = 4</when> <when test="st == 4">OR (xp.verification_status = 3 and xp.operation_status = 1)</when> <when test="st == 5">OR (xp.verification_status = 5 and xp.operation_status = 1)</when> <when test="st == 6">OR xp.operation_status = 2</when> <when test="st == 7">OR xp.operation_status = 3</when> <when test="st == 8">OR xp.operation_status = 4</when> <otherwise>OR 1 = 0</otherwise> </choose> </foreach> </trim> </if> order by xp.create_time desc </select> </mapper> xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/job/jobs/AddCruiseMissionJob.java
@@ -41,12 +41,15 @@ cancelTaxiPassengerVo.setOrderNo(xpOrder.getOrderNumber()); cancelTaxiPassengerVo.setAppId(appid); userVehicleClient.cancelTaxiPassenger(cancelTaxiPassengerVo); log.info("车辆到达终点后的定时任务解绑用户和车辆关系 {}", xpOrder.getOrderNumber()); // 修改车辆接单状态 vehicle.setState(0); xpVehicleClient.updateVehicleById(vehicle); log.info("车辆到达终点后的定时任务回滚车辆状态为空闲 {}", xpOrder.getOrderNumber()); } xpOrderService.addCruiseMission(vehicle, xpOrder); log.info("车辆到达终点后的定时任务给车辆派巡游单 {}", xpOrder.getOrderNumber()); } } xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/service/impl/XpOrderServiceImpl.java
@@ -1260,12 +1260,13 @@ try { redisService.removeByPattern(order.getQueueName(), order.getOrderNumber()); } catch (Exception e) { e.printStackTrace(); } //判断还原车辆状态 if (null == order.getVehicleId()) { Object cacheObject1 = redisService.getCacheObject("CREATE_ORDER:" + order.getId().toString()); if (null != cacheObject1) { com.alibaba.fastjson2.JSONObject jsonObject = com.alibaba.fastjson2.JSON.parseObject(cacheObject1.toString()); JSONObject jsonObject = JSON.parseObject(cacheObject1.toString()); String vin = jsonObject.getString("vin"); XpVehicle vehicle = xpVehicleClient.findByVehicleVin(vin).getData(); if (null != vehicle && 0 != vehicle.getState()) { @@ -1302,21 +1303,6 @@ Integer i = Integer.valueOf(cacheObject.toString()); redisService.setCacheCancelOrder("CANCEL_ORDER_" + uid, i + 1); } // 消息推送 // Map<String, Object> params = new HashMap<>(); // Map<String, Object> content = new HashMap<>(); // content.put("orderId", order.getId().toString()); // content.put("status", OrderStatusEnum.CANCELED.getCode()); // params.put("type", PushMessageTypeEnum.ORDER_STATUS.getDesc()); // params.put("content", JSONObject.toJSONString(content)); // params.put("timestamp", new Date().getTime() + ""); // String message = JSONObject.toJSONString(params); // SendMessageDTO sendMessageDTO = new SendMessageDTO(); // sendMessageDTO.setMessage(message); // sendMessageDTO.setAppUserId(uid); // xpPushMessageClient.sendStatus(sendMessageDTO); // log.info("订单取消消息推送完毕"); // 移除mongo数据 xpPricingClient.deleteXpGeoQueryEntity(order.getId().toString()); @@ -1481,6 +1467,9 @@ if(xpOrder.getStatus() >= 8){ return R.fail("订单已结束"); } Long appUserId = xpOrder.getAppUserId(); // 查询车辆 XpVehicle xpVehicle = xpVehicleClient.queryById(xpOrder.getVehicleId()).getData(); switch (status) { case 4: // 查询起点点位 @@ -1505,6 +1494,8 @@ LocalDateTime now = LocalDateTime.now(); xpOrder.setBoardingTime(now); xpOrder.setRideTime(now); //推送行起点到终点的驶轨迹给乘客端 sendRoute(appUserId.toString(), orderId, "ORDER_NAVIGATION_END_DATA", xpVehicle.getVehicleVin()); // 删除定时任务job QuartzManager.removeJob((OrderCancelJob.name + xpOrder.getId()).toUpperCase(), TimeJobType.ORDER_CANCEL); break; @@ -1515,8 +1506,6 @@ case 7: xpOrder.setGetoffTime(LocalDateTime.now()); // 解析下车地点 // 查询车辆 XpVehicle xpVehicle = xpVehicleClient.queryById(xpOrder.getVehicleId()).getData(); VehiclePosition vehiclePosition = mongoTemplate.findOne(new Query(Criteria.where("vin").is(xpVehicle.getVehicleVin())), VehiclePosition.class); if(Objects.nonNull(vehiclePosition)){ GeoJsonPoint point = vehiclePosition.getPoint(); @@ -1582,7 +1571,7 @@ endTripJobMaps ); // 添加车辆到达终点后限停时间到后驶离的定时任务 //时间到后添加巡游订单,解绑车辆关系,车辆驶离点位 //时间到后将车辆状态回滚到空闲、添加巡游订单,解绑用户和车辆关系,车辆驶离点位 XpPoint point = xpPointClient.queryById(xpOrder.getEndPointId()).getData(); Map<String, ? extends Object> jobMaps = new ImmutableMap.Builder<String, String>() @@ -1627,11 +1616,6 @@ order.setStatus(8); order.setAppUserId(null); order.setTripEnd(LocalDateTime.now()); double exactMinutes = Duration.between(order.getBoardingTime(), order.getTripEnd()).toMillis() / (1000.0 * 60); exactMinutes = new BigDecimal(exactMinutes).setScale(2, RoundingMode.HALF_UP).doubleValue(); order.setDuration(exactMinutes); baseMapper.updateById(order); redisService.setCacheObject("ORDER_STATUS:" + order.getId(), 8, 24L, TimeUnit.HOURS); @@ -1678,6 +1662,8 @@ xpOrderDetail.setOrderId(orderId); xpOrderDetail.setType(1); xpOrderDetail.setMileage(new BigDecimal(mileageKilometers).setScale(2, RoundingMode.HALF_UP)); String currentTimeSlot = DateUtils.getCurrentTimeSlot(); xpOrderDetail.setTime(currentTimeSlot); xpOrderDetail.setDuration(duration1); xpOrderDetail.setMoney(new BigDecimal(xpPricingCardVo.getStartPrice()).setScale(2, RoundingMode.HALF_UP)); xpOrderDetails.add(xpOrderDetail); @@ -1685,7 +1671,6 @@ xpOrderDetail.setDetailType(2); xpOrderDetail.setOrderId(orderId); xpOrderDetail.setType(1); xpOrderDetail.setMileage(new BigDecimal(mileageKilometers).setScale(2, RoundingMode.HALF_UP)); xpOrderDetail.setMoney(new BigDecimal(xpPricingCardVo.getDistancePrice()).setScale(2,RoundingMode.HALF_UP)); xpOrderDetails.add(xpOrderDetail); xpOrderDetail = new XpOrderDetail(); @@ -2424,16 +2409,8 @@ @Override public R<FareBreakdownVo> fareBreakdown(Long orderId, String uid) { XpOrder order = this.getById(orderId); order.setAppUserId(null); // 查询订单轨迹 List<OrderTrajectory> trajectories = mongoTemplate.find( new Query(Criteria.where("orderId").is(orderId)) .with(Sort.by(Sort.Direction.ASC, "locatetime")), OrderTrajectory.class ); FareBreakdownVo res = new FareBreakdownVo(); res.setChangeMoneyFlag(order.getChangeMoneyFlag()); @@ -2461,22 +2438,6 @@ } } // if (order.getDuration() != null && order.getDuration() > 0) { // FareBreakdownDetailVo durationDetail = new FareBreakdownDetailVo(); // durationDetail.setType(order.getDurationType()); // durationDetail.setDuration(order.getDuration()); // durationDetail.setMoney(order.getDurationMoney()); // duration.add(durationDetail); // } // // if (order.getLongDistance() != null && order.getLongDistance() > 0) { // FareBreakdownDetailVo longDistanceDetail = new FareBreakdownDetailVo(); // longDistanceDetail.setType(order.getLongDistanceType()); // longDistanceDetail.setMileage(BigDecimal.valueOf(order.getLongDistance())); // longDistanceDetail.setMoney(order.getLongDistancemoney()); // longDistance.add(longDistanceDetail); // } res.setStart(start); res.setMileage(mileage); res.setDuration(duration); @@ -2492,9 +2453,7 @@ order.setTripEnd(tripEnd); this.updateById(order); } double exactMinutes = Duration.between(order.getBoardingTime(), order.getTripEnd()).toMillis() / (1000.0 * 60); res.setTime(new BigDecimal(exactMinutes).setScale(2, RoundingMode.HALF_UP)); res.setTime(new BigDecimal(order.getDuration() == null ? 0 : order.getDuration()).multiply(new BigDecimal(60)).setScale(0, RoundingMode.HALF_UP)); return R.ok(res); } @@ -2573,7 +2532,7 @@ public void saveVehicleLocation(OrderTrajectory orderTrajectory) { // 查询订单信息 Integer status = redisService.getCacheObject("ORDER_STATUS:" + orderTrajectory.getOrderId()); if(status != 6){ if(status < 6){ return; } @@ -2585,7 +2544,7 @@ // 存储mongo数据 mongoTemplate.save(orderTrajectory); // 存储首次定位 redisService.setCacheObject(CacheConstants.ORDER_OLD_LOCATION + orderTrajectory.getOrderId(), orderTrajectory.getLocation()); redisService.setCacheObject(CacheConstants.ORDER_OLD_LOCATION + orderTrajectory.getOrderId(), orderTrajectory.getLocation(), 1L, TimeUnit.HOURS); } else { Map<String, Double> distance = GeodesyUtil.getDistance(orderTrajectory.getLocation(), oldLocation); if (null != distance) { @@ -2595,7 +2554,7 @@ // 存储mongo数据 mongoTemplate.save(orderTrajectory); // 更新定位 redisService.setCacheObject(CacheConstants.ORDER_OLD_LOCATION + orderTrajectory.getOrderId(), orderTrajectory.getLocation()); redisService.setCacheObject(CacheConstants.ORDER_OLD_LOCATION + orderTrajectory.getOrderId(), orderTrajectory.getLocation(), 1L, TimeUnit.HOURS); } else { log.error("调用高德计算距离出错"); } @@ -2788,27 +2747,55 @@ } // 存mongo数据 xpPricingClient.updateXpGeoQueryEntity(order.getId().toString()); // 修改车辆信息 vehicle.setState(1); xpVehicleClient.updateVehicleById(vehicle); //绑定用户和车辆关系 addTaxiPassengerVo.setUid(appUserId.toString()); order.setAppUserId(null); this.updateById(order); //构建推送消息 Map<String, Object> params = new HashMap<>(); Map<String, Object> content = new HashMap<>(); content.put("orderId", orderId.toString()); content.put("status", 2); params.put("type", PushMessageTypeEnum.ORDER_STATUS.getDesc()); params.put("content", JSONObject.toJSONString(content)); params.put("timestamp", System.currentTimeMillis() + ""); String message = JSONObject.toJSONString(params); SendMessageDTO dto1 = new SendMessageDTO(); dto1.setAppUserId(appUserId + ""); dto1.setMessage(message); R<String> stringR = xpPushMessageClient.sendStatus(dto1); //推送失败,重试3次 if(stringR.getCode() != Constants.SUCCESS){ ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>()); executor.execute(() -> { for (int i = 0; i < 3; i++) { R<String> stringR1 = xpPushMessageClient.sendStatus(dto1); if(stringR1.getCode() == Constants.SUCCESS){ break; } try { Thread.sleep(1000); } catch (InterruptedException e) { throw new RuntimeException(e); } log.info("推送订单状态消息失败:{} {} {}", stringR1.getMsg(), JSON.toJSONString(dto), order.getOrderNumber()); } }); } redisService.setCacheObject("ORDER_STATUS:" + order.getId(), 2, 24L, TimeUnit.HOURS); addTaxiPassengerVo.setOrderNo(order.getOrderNumber()); // TODO appid addTaxiPassengerVo.setAppId(appid); userVehicleClient.addTaxiPassenger(addTaxiPassengerVo); //推送乘客车辆到达预约点的导航数据 sendRoute(addTaxiPassengerVo.getUid(), orderId, "ORDER_NAVIGATION_START_DATA", dto.getXpVehicleVin()); } else { //推送行起点到终点的驶轨迹给乘客端 sendRoute(appUserId.toString(), orderId, "ORDER_NAVIGATION_END_DATA", dto.getXpVehicleVin()); } } } @@ -2900,16 +2887,16 @@ XpPoint endPoint = xpPointR1.getData(); xpOrderDetailVO.setEndParkingTimeLimit(endPoint.getParkingTimeLimit()); } // 算时间 if (xpOrder.getStatus() == 1) { R<Integer> r = xpPricingClient.getWaitTime(new LonLatDto(xpOrder.getStartLon(), xpOrder.getStartLat())); if (r.getCode() == R.SUCCESS) { xpOrderDetailVO.setEstimatedTime(r.getData()); } else { throw new RuntimeException(r.getMsg()); } } // // 算时间 // if (xpOrder.getStatus() == 1) { // R<Integer> r = xpPricingClient.getWaitTime(new LonLatDto(xpOrder.getStartLon(), xpOrder.getStartLat())); // if (r.getCode() == R.SUCCESS) { // xpOrderDetailVO.setEstimatedTime(r.getData()); // } else { // throw new RuntimeException(r.getMsg()); // } // // } if (xpOrder.getVehicleId() != null) { R<XpVehicle> xpVehicleR = xpVehicleClient.queryById(xpOrder.getVehicleId()); xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/utils/TrajectoryGenerator.java
File was deleted xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/utils/XpPricingUtil.java
@@ -88,7 +88,7 @@ String timeStr = dynamicPriceObj.toString(); // 判断当前距离这个时间范围的新增订单数(排除取消) / 上浮数量 算出应该增加的价格率 R<Integer> r = xpOrderClient.getOrderNum(new GetOrderNumDto(timeStr,openCityId)); if(r.getData()==200){ if(r.getCode()==200){ int num = r.getData(); // X单上升一次调价 Integer orderNum = getOrderNum(jsonObject, 4); @@ -179,7 +179,7 @@ String timeStr = dynamicPriceObj.toString(); // 判断当前距离这个时间范围的新增订单数(排除取消) / 上浮数量 算出应该增加的价格率 R<Integer> r = xpOrderClient.getOrderNum(new GetOrderNumDto(timeStr,openCityId)); if(r.getData()==200){ if(r.getCode()==200){ int num = r.getData(); // X单上升一次调价 Integer orderNum = getOrderNum(jsonObject, 4); xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/controller/XpVehicleController.java
@@ -628,7 +628,7 @@ String jsonString = jsonObject.toJSONString(); vehicleDetail.setVehiclePictures(jsonString); } return R.ok(); return R.ok(vehicleDetail); } /** xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/service/impl/XpVehicleServiceImpl.java
@@ -248,30 +248,30 @@ if (Objects.isNull(xpVehicle)) { throw new ServiceException("未查询到有效车辆信息", I18nKeyConstant.VEHICLE_NOT_EXISTS); } // 判断距离是否在范围之内 4米 // VehiclePosition vehiclePosition = mongoTemplate.findOne(new Query(Criteria.where("vin").is(xpVehicle.getVehicleVin())), VehiclePosition.class); // if (Objects.nonNull(vehiclePosition)) { // GeoJsonPoint point = vehiclePosition.getPoint(); // if(Objects.nonNull(point)){ // Map<String, Double> distance = GeodesyUtil.getDistance(dto.getLongitude()+ "," + dto.getLatitude(), point.getX()+","+point.getY()); // if (null != distance) { // Double distance1 = distance.get("WGS84"); // if (distance1 > 4) { // throw new ServiceException("距离过远,无法打开", I18nKeyConstant.VEHICLE_DISTANCE_TOO_LONG); // } // }else { // throw new ServiceException("距离过远,无法打开", I18nKeyConstant.VEHICLE_DISTANCE_TOO_LONG); // } // }else { // throw new ServiceException("距离过远,无法打开", I18nKeyConstant.VEHICLE_DISTANCE_TOO_LONG); // } // } // 判断距离是否在范围之内 15米 VehiclePosition vehiclePosition = mongoTemplate.findOne(new Query(Criteria.where("vin").is(xpVehicle.getVehicleVin())), VehiclePosition.class); if (Objects.nonNull(vehiclePosition)) { GeoJsonPoint point = vehiclePosition.getPoint(); if(Objects.nonNull(point)){ Map<String, Double> distance = GeodesyUtil.getDistance(dto.getLongitude()+ "," + dto.getLatitude(), point.getX()+","+point.getY()); if (null != distance) { Double distance1 = distance.get("WGS84"); if (distance1 > 10) { throw new ServiceException("距离过远,无法打开", I18nKeyConstant.VEHICLE_DISTANCE_TOO_LONG); } }else { throw new ServiceException("距离过远,无法打开", I18nKeyConstant.VEHICLE_DISTANCE_TOO_LONG); } }else { throw new ServiceException("距离过远,无法打开", I18nKeyConstant.VEHICLE_DISTANCE_TOO_LONG); } } // 车门解锁、后备箱解锁 VehiclesCommandVo vehiclesCommandVo = new VehiclesCommandVo(); vehiclesCommandVo.setVin(xpVehicle.getVehicleVin()); if ("door".equals(dto.getDoorType())) { // 开启车门 判断是否为P档 Integer gearLevel = redisService.getCacheObject(CacheConstants.GEAR_LEVEL + xpVehicle.getVehicleVin()); Integer gearLevel = redisService.getCacheObject(CacheConstants.GEAR_LEVEL + xpVehicle.getXpuId()); if (gearLevel == null || gearLevel != 4) { throw new ServiceException("车辆非P档,无法开启车门", I18nKeyConstant.VEHICLE_NOT_P_GEAR); } @@ -286,23 +286,8 @@ if(xpOrder.getOpenTrunk()==0){ xpOrder.setOpenTrunk(1); } if(xpOrder.getOpenTrunk()==1){ if(xpOrder.getOpenTrunk()==1) { xpOrder.setOpenTrunk(2); // 添加定时任务 // xpOrderClient.updateOrderStatus(xpOrder.getId(),7); // // 推送倒计时消息 消息推送 // Map<String, Object> params = new HashMap<>(); // Map<String, Object> content = new HashMap<>(); // content.put("orderId", xpOrder.getId().toString()); // content.put("isOpen", 1); // params.put("type", PushMessageTypeEnum.OPEN_TRUNK.getDesc()); // params.put("content", JSONObject.toJSONString(content)); // params.put("timestamp", new Date().getTime() + ""); // String message = JSONObject.toJSONString(params); // SendMessageDTO sendMessageDTO = new SendMessageDTO(); // sendMessageDTO.setMessage(message); // sendMessageDTO.setAppUserId(String.valueOf(xpOrder.getAppUserId())); // xpPushMessageClient.sendStatus(sendMessageDTO); } } try {