puzhibing
2026-05-11 b7bb5daa5f4ffe1764a363a051a5d6f868168cf9
xp-robotaxi-map-boot/src/main/java/com/xiaopeng/map/service/serviceimpl/XpPointServiceImpl.java
@@ -9,6 +9,7 @@
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xiaopeng.api.dto.operation.PointAddDto;
import com.xiaopeng.api.dto.operation.PointMapQuery;
import com.xiaopeng.api.dto.operation.PointUpdateDto;
import com.xiaopeng.api.dto.order.HistoryEndPointsDto;
import com.xiaopeng.api.dto.order.HistoryStartPointsDto;
import com.xiaopeng.api.feignClient.account.XpAppUserCollectAddrClient;
@@ -39,6 +40,7 @@
import com.xiaopeng.map.mapper.XpSystemSettingMapper;
import com.xiaopeng.map.query.PointByNameQuery;
import com.xiaopeng.map.service.XpElectronicFenceAreaService;
import com.xiaopeng.map.service.XpElectronicFenceService;
import com.xiaopeng.map.service.XpPointService;
import com.xiaopeng.map.service.XpStationService;
import com.xiaopeng.map.utils.holiday.HolidayUtil;
@@ -79,6 +81,7 @@
public class XpPointServiceImpl extends ServiceImpl<XpPointMapper, XpPoint> implements XpPointService {
    private static final String POINT_BIZ_TYPE = "PUD";
    private static final int MAX_POINTS_PER_FENCE = 15;
    private static final int SERIAL_WIDTH = 6;
    private static final int LOCK_WAIT_SECONDS = 5;
    private static final int LOCK_LEASE_SECONDS = 30;
@@ -116,6 +119,53 @@
    @Lazy
    @Autowired
    private BootCommonService bootCommonService;
    @Lazy
    @Resource
    private XpElectronicFenceService xpElectronicFenceService;
    @Override
    public void validateAdd(PointAddDto dto) {
        XpElectronicFenceArea electronicFenceArea = xpElectronicFenceAreaService.getById(dto.getElectronicAreaId());
        if(electronicFenceArea == null){
            throw new ServiceException("所属运营区id错误");
        }
        XpElectronicFence electronicFence = xpElectronicFenceService.getById(electronicFenceArea.getElectronicId());
        //场站的自定义时间必须在 围栏运营时间内
        if(dto.getOperationType() != null && dto.getOperationType() == 2){
//            ["06:00-12:00", "13:00-21:00"]
            if(StrUtil.isBlank(dto.getEffectiveTimePeriod())){
                throw new ServiceException("自定义时间段不能为空");
            }
            boolean stationTimeFenceOperationStrategy = bootCommonService.getStationTime_fenceOperationStrategy(dto.getEffectivePeriod(), dto.getEffectiveTimePeriod(), electronicFence.getOperationStrategy());
            if(!stationTimeFenceOperationStrategy){
                throw new ServiceException("自定义时间必须在围栏运营时间内");
            }
        }
    }
    @Override
    public void validateUpdate(PointUpdateDto dto) {
        XpElectronicFenceArea electronicFenceArea = xpElectronicFenceAreaService.getById(dto.getElectronicAreaId());
        if(electronicFenceArea == null){
            throw new ServiceException("所属运营区id错误");
        }
        XpElectronicFence electronicFence = xpElectronicFenceService.getById(electronicFenceArea.getElectronicId());
        //场站的自定义时间必须在 围栏运营时间内
        if(dto.getOperationType() != null && dto.getOperationType() == 2){
//            ["06:00-12:00", "13:00-21:00"]
            if(StrUtil.isBlank(dto.getEffectiveTimePeriod())){
                throw new ServiceException("自定义时间段不能为空");
            }
            boolean stationTimeFenceOperationStrategy = bootCommonService.getStationTime_fenceOperationStrategy(dto.getEffectivePeriod(), dto.getEffectiveTimePeriod(), electronicFence.getOperationStrategy());
            if(!stationTimeFenceOperationStrategy){
                throw new ServiceException("自定义时间必须在围栏运营时间内");
            }
        }
    }
    @Override
    @Transactional
@@ -181,6 +231,7 @@
            if (!locked) {
                throw new ServiceException("点位编号生成繁忙,请稍后重试", I18nKeyConstant.POINT_NUMBER_LOCK_FAIL);
            }
            validateFencePointCountLimit(electronicAreaId);
            String maxPointNumber = this.baseMapper.selectMaxPointNumber(cityPrefix, POINT_BIZ_TYPE);
            int nextSerial = 1;
            if (StringUtils.hasText(maxPointNumber)) {
@@ -301,6 +352,36 @@
        return getPinyinInitials(prefix).toUpperCase();
    }
    private void validateFencePointCountLimit(Long electronicAreaId) {
        if (electronicAreaId == null || electronicAreaId == 0L) {
            return;
        }
        XpElectronicFenceArea currentArea = xpElectronicFenceAreaService.getById(electronicAreaId);
        if (currentArea == null) {
            throw new ServiceException("运营区域不存在", I18nKeyConstant.POINT_ELECTRONIC_AREA_NOT_EXIST);
        }
        Long fenceId = currentArea.getElectronicId();
        if (fenceId == null) {
            throw new ServiceException("运营区域不存在", I18nKeyConstant.POINT_ELECTRONIC_AREA_NOT_EXIST);
        }
        List<Long> areaIds = xpElectronicFenceAreaService.lambdaQuery()
                .eq(XpElectronicFenceArea::getElectronicId, fenceId)
                .list()
                .stream()
                .map(XpElectronicFenceArea::getId)
                .filter(Objects::nonNull)
                .collect(Collectors.toList());
        if (areaIds.isEmpty()) {
            return;
        }
        long pointCount = this.lambdaQuery()
                .in(XpPoint::getElectronicAreaId, areaIds)
                .count();
        if (pointCount >= MAX_POINTS_PER_FENCE) {
            throw new ServiceException("当前围栏最多只能添加15个点位", I18nKeyConstant.POINT_FENCE_POINT_LIMIT_EXCEEDED);
        }
    }
    private static String buildPointNumberLockKey(String cityPrefix, String bizType) {
        return "xp:point:number:" + cityPrefix + ":" + bizType;
    }