puzhibing
2026-03-21 1f28c318888b4b7eb6153997218d29ab7969a53a
修改bug和优化推送消息触发的先后顺序
6个文件已添加
3个文件已修改
1188 ■■■■■ 已修改文件
xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/operation/XpTestPoint.java 120 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/service/impl/XpSchedulingDetailServiceImpl.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/controller/XpTestPointManagementController.java 205 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/mapper/XpTestPointMapper.java 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/XpTestPointService.java 93 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/impl/XpTestPointServiceImpl.java 502 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-operation-boot/src/main/resources/mapper/operation/XpTestPointMapper.xml 158 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/service/impl/XpOrderServiceImpl.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/service/impl/XpVehicleServiceImpl.java 55 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
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-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/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/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/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()) {
@@ -2531,7 +2532,7 @@
    public void saveVehicleLocation(OrderTrajectory orderTrajectory) {
        // 查询订单信息
        Integer status = redisService.getCacheObject("ORDER_STATUS:" + orderTrajectory.getOrderId());
        if(status != 6){
        if(status < 6){
            return;
        }
@@ -2543,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) {
@@ -2553,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("调用高德计算距离出错");
            }
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 {