xp-robotaxi-account-boot/src/main/java/com/xiaopeng/account/service/impl/XpOperationsUserServiceImpl.java
@@ -150,17 +150,17 @@ // 7. 查询是否上班中 try { R<Boolean> workStatusResult = xpClockInClient.checkWorkStatus(userId); R<Integer> workStatusResult = xpClockInClient.checkWorkStatus(userId); if (workStatusResult != null && workStatusResult.getCode() == 200) { vo.setWorkFlag(workStatusResult.getData()); } else { // 调用失败,默认 false vo.setWorkFlag(false); vo.setWorkFlag(1); log.warn("查询用户上班状态失败, userId={}, result={}", userId, workStatusResult); } } catch (Exception e) { // 异常情况,默认 false vo.setWorkFlag(false); vo.setWorkFlag(1); log.error("查询用户上班状态异常, userId={}", userId, e); } @@ -491,6 +491,6 @@ if (StringUtils.isBlank(phoneNumber)) { return Collections.emptyList(); } return lambdaQuery().eq(XpOperationsUser::getPhoneNumber, phoneNumber).list(); return lambdaQuery().like(XpOperationsUser::getPhoneNumber, phoneNumber).list(); } } xp-robotaxi-api/src/main/java/com/xiaopeng/api/dto/operation/ElectronicFenceUpdateDto.java
@@ -54,4 +54,13 @@ @ApiModelProperty(value = "电子围栏区域") @NotEmpty(message = "电子围栏区域不能为空") private List<XpElectronicFenceArea> electronicFenceAreas; @ApiModelProperty(value = "范围扩大 需要新增的点位ID列表") private List<Long> addPointIdList; @ApiModelProperty(value = "范围缩小 需要改为失效状态的点位ID列表") private List<Long> delPointIdList; @ApiModelProperty(value = "禁行区覆盖点位 需要改为停用状态的点位ID列表") private List<Long> disablePointIdList; } xp-robotaxi-api/src/main/java/com/xiaopeng/api/factory/maintenance/XpClockInClientFallbackFactory.java
@@ -20,11 +20,11 @@ public XpClockInClient create(Throwable cause) { return new XpClockInClient() { @Override public R<Boolean> checkWorkStatus(Long appUserId) { public R<Integer> checkWorkStatus(Long appUserId) { log.error("调用打卡服务检查上班状态失败, appUserId={}, 异常: {}", appUserId, cause.getMessage(), cause); // 降级策略: 返回 false (未上班状态) return R.ok(false); // 降级策略: 返回 (未上班状态) return R.ok(1); } }; } xp-robotaxi-api/src/main/java/com/xiaopeng/api/feignClient/maintenance/XpClockInClient.java
@@ -26,5 +26,5 @@ * @return true=上班中, false=未上班或已下班 */ @GetMapping("/inner/clock-in/checkWorkStatus") R<Boolean> checkWorkStatus(@RequestParam("appUserId") Long appUserId); R<Integer> checkWorkStatus(@RequestParam("appUserId") Long appUserId); } xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/operation/XpBanner.java
@@ -69,8 +69,13 @@ @ApiModelProperty(value = "广告图片") @TableField("banner_pictures") private String bannerPictures; @ApiModelProperty(value = "广告标题") @TableField("banner_title") private String bannerTitle; @ApiModelProperty(value = "排序") @TableField("sort") private Integer sort; } xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/operation/XpCruisePlanVehicle.java
@@ -30,6 +30,10 @@ private static final long serialVersionUID = 1L; @ApiModelProperty(value = "自增id") @TableId(value = "id", type = IdType.AUTO) private Long id; @ApiModelProperty(value = "巡游计划ID") private Long cruisePlanId; xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/operation/XpPoint.java
@@ -34,10 +34,9 @@ private Long id; @ApiModelProperty(value = "电子围栏区域id") @TableField(value = "electronic_area_id", updateStrategy = FieldStrategy.NEVER) private Long electronicAreaId; @TableField("fp_electronic_area_id") @TableField(value = "fp_electronic_area_id", updateStrategy = FieldStrategy.NEVER) private Long fpElectronicAreaId; @ApiModelProperty(value = "点位名称") xp-robotaxi-api/src/main/java/com/xiaopeng/api/vo/account/XpOperationsUserProfileVO.java
@@ -83,8 +83,8 @@ @ApiModelProperty(value = "角色列表") private List<RoleInfoVO> roles; @ApiModelProperty("是否上班中") private Boolean workFlag; @ApiModelProperty("打卡状态 1-未打卡 2-上班中 3-休息") private Integer workFlag; @ApiModelProperty(value = "登录设备类型 1-Android 2-iOS") private Integer deviceType; xp-robotaxi-api/src/main/java/com/xiaopeng/api/vo/maintenance/TaskRuleDetailVO.java
@@ -22,7 +22,7 @@ @ApiModelProperty(value = "车辆日常监测 频次") private Integer vehicleInspectionFrequency; @ApiModelProperty(value = "车辆日常检测 任务下放时间") @JsonFormat(pattern = "HH:mm:ss", timezone = "GMT+8") @JsonFormat(pattern = "HH:mm", timezone = "GMT+8") private LocalTime vehicleInspectionTime; @ApiModelProperty(value = "车辆日常监测 紧急程度 0=P0 1=P1 2=P2 3=P3") @@ -32,7 +32,7 @@ private Boolean vehicleCollection; @ApiModelProperty(value = "车辆收车每日时间") @JsonFormat(pattern = "HH:mm:ss", timezone = "GMT+8") @JsonFormat(pattern = "HH:mm", timezone = "GMT+8") private LocalTime vehicleCollectionTime; @ApiModelProperty(value = "车辆保养周期是否启用") @@ -45,7 +45,7 @@ private Integer maintenanceCycleTimeType; @ApiModelProperty(value = "车辆保养周期 任务下放时间") @JsonFormat(pattern = "HH:mm:ss", timezone = "GMT+8") @JsonFormat(pattern = "HH:mm", timezone = "GMT+8") private LocalTime maintenanceCycleTaskTime; @ApiModelProperty(value = "车辆保养周期 紧急程度 0=P0 1=P1 2=P2 3=P3") @@ -64,7 +64,7 @@ private Integer vehicleCleanCycle; @ApiModelProperty(value = "车身清洁保养任务下放时间") @JsonFormat(pattern = "HH:mm:ss", timezone = "GMT+8") @JsonFormat(pattern = "HH:mm", timezone = "GMT+8") private LocalTime vehicleCleanTime; @ApiModelProperty(value = "车身清洁保养周期X 1=天 2=月") @@ -77,7 +77,7 @@ private Integer routineMaintenanceCycle; @ApiModelProperty(value = "日常整备保养任务下放时间") @JsonFormat(pattern = "HH:mm:ss", timezone = "GMT+8") @JsonFormat(pattern = "HH:mm", timezone = "GMT+8") private LocalTime routineMaintenanceTime; @ApiModelProperty(value = "日常整备保养周期X 1=天 2=月") xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/controller/XpClockInController.java
@@ -58,9 +58,9 @@ */ @GetMapping("/inner/clock-in/checkWorkStatus") @ApiOperation(value = "检查用户是否上班中", tags = {"内部接口"}) public R<Boolean> checkWorkStatus(@RequestParam("appUserId") Long appUserId) { public R<Integer> checkWorkStatus(@RequestParam("appUserId") Long appUserId) { log.info("检查用户上班状态, appUserId={}", appUserId); Boolean workFlag = xpClockInService.checkWorkStatus(appUserId); Integer workFlag = xpClockInService.checkWorkStatus(appUserId); return R.ok(workFlag); } xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/dto/TaskRuleDetailDto.java
@@ -23,7 +23,7 @@ @ApiModelProperty(value = "车辆日常监测 频次") private Integer vehicleInspectionFrequency; @ApiModelProperty(value = "车辆日常检测 任务下放时间") @JsonFormat(pattern = "HH:mm:ss", timezone = "GMT+8") @JsonFormat(pattern = "HH:mm", timezone = "GMT+8") private LocalTime vehicleInspectionTime; @ApiModelProperty(value = "车辆日常监测 紧急程度 0=P0 1=P1 2=P2 3=P3") @@ -33,7 +33,7 @@ private Boolean vehicleCollection; @ApiModelProperty(value = "车辆收车每日时间") @JsonFormat(pattern = "HH:mm:ss", timezone = "GMT+8") @JsonFormat(pattern = "HH:mm", timezone = "GMT+8") private LocalTime vehicleCollectionTime; @ApiModelProperty(value = "车辆保养周期是否启用") @@ -46,7 +46,7 @@ private Integer maintenanceCycleTimeType; @ApiModelProperty(value = "车辆保养周期 任务下放时间") @JsonFormat(pattern = "HH:mm:ss", timezone = "GMT+8") @JsonFormat(pattern = "HH:mm", timezone = "GMT+8") private LocalTime maintenanceCycleTaskTime; @ApiModelProperty(value = "车辆保养周期 紧急程度 0=P0 1=P1 2=P2 3=P3") @@ -65,7 +65,7 @@ private Integer vehicleCleanCycle; @ApiModelProperty(value = "车身清洁保养任务下放时间") @JsonFormat(pattern = "HH:mm:ss", timezone = "GMT+8") @JsonFormat(pattern = "HH:mm", timezone = "GMT+8") private LocalTime vehicleCleanTime; @ApiModelProperty(value = "车身清洁保养周期X 1=天 2=月") @@ -78,7 +78,7 @@ private Integer routineMaintenanceCycle; @ApiModelProperty(value = "日常整备保养任务下放时间") @JsonFormat(pattern = "HH:mm:ss", timezone = "GMT+8") @JsonFormat(pattern = "HH:mm", timezone = "GMT+8") private LocalTime routineMaintenanceTime; @ApiModelProperty(value = "日常整备保养周期X 1=天 2=月") xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/mapper/XpClockInMapper.java
@@ -23,20 +23,6 @@ public interface XpClockInMapper extends BaseMapper<XpClockIn> { /** * 查询用户当天的打卡记录 * @param appUserId 用户ID * @param startTime 开始时间 (当天00:00:00) * @param endTime 结束时间 (当天23:59:59) * @return 打卡记录列表 */ List<XpClockIn> selectTodayClockInRecords( @Param("appUserId") Long appUserId, @Param("startTime") LocalDateTime startTime, @Param("endTime") LocalDateTime endTime ); /** * 获取打卡统计 * @param pageInfo * @return xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/service/IXpClockInService.java
@@ -49,7 +49,7 @@ * @param appUserId 用户ID * @return true=上班中(只打了上班卡), false=未上班或已下班 */ Boolean checkWorkStatus(Long appUserId); Integer checkWorkStatus(Long appUserId); /** xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/service/impl/XpClockInServiceImpl.java
@@ -1,6 +1,7 @@ package com.xiaopeng.maintenance.service.impl; import cn.hutool.core.collection.CollUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.conditions.query.QueryChainWrapper; @@ -186,10 +187,10 @@ } @Override public Boolean checkWorkStatus(Long appUserId) { public Integer checkWorkStatus(Long appUserId) { if (appUserId == null) { log.warn("检查上班状态失败: appUserId 为空"); return false; return 1; } try { @@ -198,29 +199,23 @@ LocalDateTime endTime = LocalDateTime.of(LocalDate.now(), LocalTime.MAX); // 23:59:59 // 2. 查询当天打卡记录 List<XpClockIn> records = baseMapper.selectTodayClockInRecords( appUserId, startTime, endTime ); XpClockIn xpClockIn = baseMapper.selectOne(new LambdaQueryWrapper<XpClockIn>() .eq(XpClockIn::getAppUserId, appUserId) .between(XpClockIn::getClockInTime, startTime, endTime) .last("limit 1")); // 3. 判断上班状态 if (records == null || records.isEmpty()) { // 无打卡记录 = 未上班 log.debug("用户 {} 今日无打卡记录, workFlag=false", appUserId); return false; } else if (records.size() == 1) { // 1条记录 = 已上班未下班 log.debug("用户 {} 今日打卡1次, workFlag=true", appUserId); return true; // 有上班打卡状态,无下班打卡状态 if (Objects.isNull(xpClockIn)) { return 1; } else if (Objects.nonNull(xpClockIn.getClockInResult()) && Objects.isNull(xpClockIn.getClockOutResult())) { return 2; } else { // 2条及以上记录 = 已下班 log.debug("用户 {} 今日打卡{}次, workFlag=false", appUserId, records.size()); return false; return 3; } } catch (Exception e) { log.error("检查用户上班状态异常, appUserId={}", appUserId, e); // 异常情况返回 false return false; return 1; } } xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/service/impl/XpTaskServiceImpl.java
@@ -453,6 +453,9 @@ I18nKeyConstant.VEHICLE_NOT_EXIST ); } //查询任务处理记录 XpTaskHandleDetailRoutine xpTaskHandleDetailRoutine = xpTaskHandleDetailRoutineMapper.selectOne(new LambdaQueryWrapper<XpTaskHandleDetailRoutine>() .eq(XpTaskHandleDetailRoutine::getTaskId, id).last("limit 1")); res.setId(id); res.setTaskUrgencyLevel(task.getTaskUrgencyLevel()); res.setEndTime(task.getEndTime()); @@ -474,6 +477,12 @@ res.setTaskImage(task.getTaskImage()); res.setHandleUserId(task.getHandleUserId()); res.setHandleTime(task.getHandleTime()); if (Objects.nonNull(xpTaskHandleDetailRoutine)) { res.setTaskDescription(xpTaskHandleDetailRoutine.getTaskDescription()); task.setHandleUserId(xpTaskHandleDetailRoutine.getOperationsUserId().toString()); res.setHandleTime(xpTaskHandleDetailRoutine.getCreateTime()); res.setTaskImage(xpTaskHandleDetailRoutine.getTaskImage()); } if (Objects.nonNull(task.getHandleUserId()) && task.getHandleUserId().split(",").length == 1) { XpOperationsUser data = xpOperationUserClient.queryById(Long.valueOf(task.getHandleUserId())).getData(); if (Objects.nonNull(data)) { xp-robotaxi-maintenance-boot/src/main/resources/mapper/maintenance/XpClockInMapper.xml
@@ -18,29 +18,6 @@ <result column="update_time" property="updateTime"/> </resultMap> <!-- 查询用户当天的打卡记录 --> <select id="selectTodayClockInRecords" resultMap="BaseResultMap"> SELECT id, app_user_id, clock_in_time, clock_out_time, shift_id, clock_in_result, clock_out_result, clock_in_lon, clock_in_lat, clock_out_lon, clock_out_lat, create_time, update_time FROM xp_clock_in WHERE app_user_id = #{appUserId} AND clock_in_time BETWEEN #{startTime} AND #{endTime} AND clock_in_result IN (1, 2) ORDER BY clock_in_time ASC </select> <select id="getClockInStatistics" resultType="com.xiaopeng.maintenance.dto.ClockInStatisticsDto"> select aa.app_user_id as appUserId, xp-robotaxi-map-boot/src/main/java/com/xiaopeng/map/controller/XpElectronicFenceManagementController.java
@@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.xiaopeng.api.dto.operation.ElectronicFenceAddDto; import com.xiaopeng.api.dto.operation.ElectronicFenceAreaUpdateStatusDto; import com.xiaopeng.api.dto.operation.ElectronicFenceOperationStrategyValidateDto; import com.xiaopeng.api.dto.operation.ElectronicFenceUpdateDto; import com.xiaopeng.api.feignClient.operation.XpElectronicClient; import com.xiaopeng.api.model.operation.XpElectronicFence; @@ -21,7 +22,9 @@ import com.xiaopeng.map.constant.I18nKeyConstant; import com.xiaopeng.map.service.XpElectronicFenceAreaService; import com.xiaopeng.map.service.XpElectronicFenceService; import com.xiaopeng.map.service.XpPointService; import com.xiaopeng.map.service.XpRegionService; import com.xiaopeng.map.utils.OperationStrategyIndex; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; @@ -34,10 +37,12 @@ import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; import javax.validation.Valid; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.stream.Collectors; import static com.xiaopeng.map.service.serviceimpl.XpElectronicFenceServiceImpl.getPinyinInitials; @@ -66,6 +71,9 @@ private XpRegionService regionService; @Autowired private XpRegionService xpRegionService; @Autowired private XpPointService xpPointService; /** * 查询省市管理 */ @@ -146,11 +154,76 @@ */ @PostMapping("/edit") @ApiOperation(value = "编辑电子围栏") @Transactional @ShardingSphereTransactionType(TransactionType.BASE) public R edit(@Validated @RequestBody ElectronicFenceUpdateDto dto) { return xpElectronicFenceService.editElectronic(dto); } /** * 校验编辑围栏时运营时间段缩短影响的点位数量 * <p> * 统计:围栏下 operation_type=2(自定义运营时间段) 的点位中, * 当围栏运营时间范围发生缩短时,不在新运营时间范围(Union)内的点位数量(需要停用)。 * </p> */ @PostMapping("/validateOperationStrategyShorten") @ApiOperation(value = "校验围栏运营时间段缩短影响点位数量") public R<Integer> validateOperationStrategyShorten(@Valid @RequestBody ElectronicFenceOperationStrategyValidateDto dto) { XpElectronicFence fence = xpElectronicFenceService.getById(dto.getId()); if (fence == null) { throw new ServiceException("围栏不存在", I18nKeyConstant.FENCE_NOT_EXIST); } OperationStrategyIndex oldIndex = OperationStrategyIndex.parse(fence.getOperationStrategy()); OperationStrategyIndex newIndex = OperationStrategyIndex.parse(dto.getOperationStrategy()); if (oldIndex.equalsNormalized(newIndex)) { return R.ok(0); } if (!oldIndex.hasAnyShrinkComparedTo(newIndex)) { return R.ok(0); } List<Long> fenceAreaIds = xpElectronicFenceAreaService.lambdaQuery() .eq(XpElectronicFenceArea::getElectronicId, dto.getId()) .list() .stream() .map(XpElectronicFenceArea::getId) .filter(Objects::nonNull) .distinct() .collect(Collectors.toList()); if (CollUtil.isEmpty(fenceAreaIds)) { return R.ok(0); } List<XpPoint> customPoints = xpPointService.lambdaQuery() .in(XpPoint::getElectronicAreaId, fenceAreaIds) .eq(XpPoint::getPointType, 1) .eq(XpPoint::getOperationType, 2) .list(); if (CollUtil.isEmpty(customPoints)) { return R.ok(0); } int disableCount = 0; for (XpPoint point : customPoints) { if (point == null || point.getEffectiveTimePeriod() == null || point.getEffectiveTimePeriod().isEmpty()) { continue; } List<OperationStrategyIndex.TimeInterval> pointIntervals = OperationStrategyIndex.parsePointEffectiveTimePeriod(point.getEffectiveTimePeriod()); if (pointIntervals.isEmpty()) { continue; } boolean shouldDisable = !newIndex.isPointScheduleWithin(pointIntervals); if (shouldDisable) { disableCount++; } } return R.ok(disableCount); } /** * 复制电子围栏 */ @PostMapping("/copy") xp-robotaxi-map-boot/src/main/java/com/xiaopeng/map/controller/XpPointManagementController.java
@@ -186,7 +186,7 @@ throw new ServiceException("系统异常", I18nKeyConstant.SYSTEM_EXCEPTION); } if (Boolean.TRUE.equals(existsResult.getData())) { throw new ServiceException("操作失败,该点位有关联的巡游点位", I18nKeyConstant.POINT_DELETE_HAS_CRUISE_PLAN_POINT); throw new ServiceException("操作失败,该点位有关联的巡游计划点位", I18nKeyConstant.POINT_DELETE_HAS_CRUISE_PLAN_POINT); } xpPointService.removeBatchByIds(pointIds); return R.ok(); @@ -201,25 +201,12 @@ @ShardingSphereTransactionType(TransactionType.BASE) public R edit(@Validated @RequestBody PointUpdateDto pointAddDto) { XpPoint xpPoint = xpPointService.getById(pointAddDto.getId()); if (!xpPoint.getElectronicAreaId().equals(pointAddDto.getElectronicAreaId())) { BeanUtils.copyProperties(pointAddDto, xpPoint); if (xpGeoFencingPolygonService.isInFence(pointAddDto.getPointLon(), pointAddDto.getPointLat(), pointAddDto.getFenceId(), "prohibited_area")) { return R.ok("in_prohibited_area"); } xpPointService.updateById(xpPoint); } else { if (xpGeoFencingPolygonService.isInFence(pointAddDto.getPointLon(), pointAddDto.getPointLat(), pointAddDto.getFenceId(), "prohibited_area")) { return R.ok("in_prohibited_area"); } //先删除原有的数据,因为会存在点位的从属区域变化的情况,所以先删除原有的数据后添加新的数据重新分片到新的库中 BeanUtils.copyProperties(pointAddDto, xpPoint); xpPointService.removeById(pointAddDto.getId()); xpPoint.setId(null); xpPointService.save(xpPoint); BeanUtils.copyProperties(pointAddDto, xpPoint); if (xpGeoFencingPolygonService.isInFence(pointAddDto.getPointLon(), pointAddDto.getPointLat(), pointAddDto.getFenceId(), "prohibited_area")) { return R.ok("in_prohibited_area"); } xpPointService.updateById(xpPoint); return R.ok(); } xp-robotaxi-map-boot/src/main/java/com/xiaopeng/map/service/serviceimpl/XpElectronicFenceServiceImpl.java
@@ -1,6 +1,7 @@ package com.xiaopeng.map.service.serviceimpl; import cn.hutool.core.collection.CollUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; @@ -27,6 +28,8 @@ import com.xiaopeng.map.mapper.XpRegionMapper; import com.xiaopeng.map.service.XpElectronicFenceAreaService; import com.xiaopeng.map.service.XpElectronicFenceService; import com.xiaopeng.map.service.XpPointService; import com.xiaopeng.map.utils.OperationStrategyIndex; import com.xiaopeng.map.utils.GDMapGeocodingUtil; import com.xiaopeng.map.utils.PolygonOverlapService; import lombok.extern.slf4j.Slf4j; @@ -72,6 +75,10 @@ private MongoTemplate mongoTemplate; @Autowired private XpPointMapper xpPointMapper; @Autowired private XpPointService xpPointService; @Autowired private XpRegionMapper xpRegionMapper; @Autowired @@ -427,6 +434,8 @@ XpElectronicFence electronicFence = this.getById(dto.getId()); Integer status = electronicFence.getStatus(); String oldOperationStrategy = electronicFence.getOperationStrategy(); String newOperationStrategy = dto.getOperationStrategy(); // 更新主表数据 @@ -666,9 +675,109 @@ xpPointMapper.updateById(xpPoint); } } OperationStrategyIndex oldIndex = OperationStrategyIndex.parse(oldOperationStrategy); OperationStrategyIndex newIndex = OperationStrategyIndex.parse(newOperationStrategy); boolean needAutoDisableByUnion = !oldIndex.equalsNormalized(newIndex) && oldIndex.hasAnyShrinkComparedTo(newIndex); List<Long> addPointIds = normalizePointIds(dto.getAddPointIdList()); List<Long> delPointIds = normalizePointIds(dto.getDelPointIdList()); List<Long> disablePointIds = normalizePointIds(dto.getDisablePointIdList()); boolean needPointHandling = CollUtil.isNotEmpty(addPointIds) || CollUtil.isNotEmpty(delPointIds) || CollUtil.isNotEmpty(disablePointIds); boolean needFenceAreaIds = needPointHandling || needAutoDisableByUnion; XpElectronicFenceArea operationArea = needFenceAreaIds ? xpElectronicFenceAreaService.lambdaQuery() .eq(XpElectronicFenceArea::getElectronicId, dto.getId()) .eq(XpElectronicFenceArea::getAreaType, 1) .orderByDesc(XpElectronicFenceArea::getId) .last("limit 1") .one() : null; Long operationAreaId = operationArea == null ? null : operationArea.getId(); if (needPointHandling && operationAreaId == null) { throw new ServiceException("运营区域不存在", I18nKeyConstant.POINT_ELECTRONIC_AREA_NOT_EXIST); } if (CollUtil.isNotEmpty(addPointIds)) { if (operationAreaId == null) { throw new ServiceException("运营区域不存在", I18nKeyConstant.POINT_ELECTRONIC_AREA_NOT_EXIST); } xpPointService.lambdaUpdate() .in(XpPoint::getId, addPointIds) .set(XpPoint::getElectronicAreaId, operationAreaId) .set(XpPoint::getVerificationStatus, 1) .update(); } if (CollUtil.isNotEmpty(disablePointIds)) { // operation_status: 3=已停用 xpPointService.lambdaUpdate() .in(XpPoint::getId, disablePointIds) .eq(XpPoint::getElectronicAreaId, operationAreaId) .set(XpPoint::getOperationStatus, 3) .update(); } if (CollUtil.isNotEmpty(delPointIds)) { // operation_status: 4=已失效 xpPointService.lambdaUpdate() .in(XpPoint::getId, delPointIds) .eq(XpPoint::getElectronicAreaId, operationAreaId) .set(XpPoint::getOperationStatus, 4) .update(); } // 围栏运营时间缩短校验:若缩短后点位时间段不在新范围内,则更新为已停用(operation_status=3) if (needAutoDisableByUnion && operationAreaId != null) { LambdaQueryWrapper<XpPoint> pointQuery = new LambdaQueryWrapper<>(); pointQuery.eq(XpPoint::getElectronicAreaId, operationAreaId) .eq(XpPoint::getPointType, 1) .eq(XpPoint::getOperationType, 2); List<XpPoint> points = xpPointMapper.selectList(pointQuery); if (points != null && !points.isEmpty()) { List<Long> disablePointIdList = new ArrayList<>(); for (XpPoint pointItem : points) { if (pointItem == null) { continue; } if (pointItem.getOperationStatus() != null && pointItem.getOperationStatus() == 4) { continue; } String effectiveTimePeriod = pointItem.getEffectiveTimePeriod(); if (effectiveTimePeriod == null || effectiveTimePeriod.isEmpty()) { continue; } List<OperationStrategyIndex.TimeInterval> pointIntervals = OperationStrategyIndex.parsePointEffectiveTimePeriod(effectiveTimePeriod); if (pointIntervals.isEmpty()) { continue; } boolean shouldDisable = !newIndex.isPointScheduleWithin(pointIntervals); if (shouldDisable && pointItem.getId() != null) { disablePointIdList.add(pointItem.getId()); } } if (!disablePointIdList.isEmpty()) { XpPoint updatePoint = new XpPoint(); updatePoint.setOperationStatus(3); UpdateWrapper<XpPoint> updateWrapper = new UpdateWrapper<>(); updateWrapper.in("id", disablePointIdList); updateWrapper.and(w -> w.isNull("operation_status").or().ne("operation_status", 4)); xpPointMapper.update(updatePoint, updateWrapper); log.info("围栏运营时间缩短停用点位完成 fenceId={}, disableCount={}", dto.getId(), disablePointIdList.size()); } } } return R.ok(); } private static List<Long> normalizePointIds(List<Long> ids) { if (CollUtil.isEmpty(ids)) { return Collections.emptyList(); } return ids.stream().filter(Objects::nonNull).distinct().collect(Collectors.toList()); } /** * 判断点是否在多边形内 xp-robotaxi-map-boot/src/main/resources/i18n/messages.properties
@@ -39,4 +39,4 @@ point.city.not.exist=城市信息不存在 point.number.lock.fail=点位编号生成繁忙,请稍后重试 point.number.parse.fail=点位编号生成失败(历史编号格式异常) point.delete.has.cruise.plan.point=操作失败,该点位有关联的巡游点位 point.delete.has.cruise.plan.point=操作失败,该点位有关联的巡游计划点位 xp-robotaxi-map-boot/src/main/resources/i18n/messages_zh_CN.properties
@@ -32,4 +32,4 @@ point.city.not.exist=城市信息不存在 point.number.lock.fail=点位编号生成繁忙,请稍后重试 point.number.parse.fail=点位编号生成失败(历史编号格式异常) point.delete.has.cruise.plan.point=操作失败,该点位有关联的巡游点位 point.delete.has.cruise.plan.point=操作失败,该点位有关联的巡游计划点位 xp-robotaxi-map-boot/src/main/resources/mapper/XpPointMapper.xml
@@ -91,7 +91,7 @@ <when test="st == 5">OR (t1.verification_status = 5 and t1.operation_status = 1)</when> <when test="st == 6">OR t1.operation_status = 2</when> <when test="st == 7">OR t1.operation_status = 3</when> <when test="st == 8">OR t1.operation_status = 4</when> <when test="st == 8">OR (t1.verification_status = 5 and t1.operation_status = 4)</when> <otherwise>OR 1 = 0</otherwise> </choose> </foreach> @@ -157,7 +157,7 @@ <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> <when test="st == 8">OR (xp.verification_status = 5 and xp.operation_status = 4)</when> <otherwise>OR 1 = 0</otherwise> </choose> </foreach> xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/impl/XpAppVersionServiceImpl.java
@@ -62,7 +62,7 @@ if (Objects.isNull(latestVersion)) { log.warn("未找到App版本信息"); throw new ServiceException("App版本信息不存在"); return null; } // 转换为 VO