“mitao”
2026-03-21 71c72f125bc10a5bd39317e51b7ee5a41035ee92
fix:运营后台工单、点位、围栏问题修改
7个文件已修改
234 ■■■■■ 已修改文件
xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/maintenance/XpTask.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/maintenance/XpVehicleRepair.java 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/service/impl/XpTaskServiceImpl.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-map-boot/src/main/java/com/xiaopeng/map/controller/XpElectronicFenceManagementController.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-map-boot/src/main/java/com/xiaopeng/map/service/serviceimpl/XpElectronicFenceServiceImpl.java 189 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/job/jobs/DynamicPricingCheckJob.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-operation-boot/src/main/resources/mapper/operation/XpWhitelistMapper.xml 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/maintenance/XpTask.java
@@ -94,5 +94,6 @@
    @ApiModelProperty(value = "状态 0=待到达 1=待处理 2=已完成 3=已取消")
    private Integer status;
    @ApiModelProperty(value = "任务来源 1-运维APP 2-管理后台")
    private Integer taskSource;
}
xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/maintenance/XpVehicleRepair.java
@@ -43,11 +43,11 @@
    private Long vehicleId;
    @ApiModelProperty(value = "开始时间")
    @JsonFormat(pattern = "yyyy年MM月dd日", timezone = "GMT+8")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private LocalDate startTime;
    @ApiModelProperty(value = "结束时间")
    @JsonFormat(pattern = "yyyy年MM月dd日", timezone = "GMT+8")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private LocalDate endTime;
    @ApiModelProperty(value = "维修原因")
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/service/impl/XpTaskServiceImpl.java
@@ -6,6 +6,7 @@
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.xiaopeng.api.dto.pushMessage.AliPushMessageDTO;
import com.xiaopeng.api.feignClient.account.SysUserClient;
import com.xiaopeng.api.feignClient.account.XpOperationUserClient;
@@ -14,6 +15,7 @@
import com.xiaopeng.api.feignClient.vehicleConvoy.XpFleetOperationsClient;
import com.xiaopeng.api.feignClient.vehicleConvoy.XpFleetVehicleClient;
import com.xiaopeng.api.feignClient.vehicleConvoy.XpVehicleClient;
import com.xiaopeng.api.model.account.SysUser;
import com.xiaopeng.api.model.account.XpOperationsRole;
import com.xiaopeng.api.model.account.XpOperationsUser;
import com.xiaopeng.api.model.account.XpOperationsUserNotification;
@@ -1576,6 +1578,7 @@
            task.setReportTime(LocalDateTime.now());
            task.setExpiredNoticeSent(0);
            task.setWillTimeoutNoticeSent(0);
            task.setTaskSource(2);
            saveTask.add(task);
        }
        this.saveBatch(saveTask);
@@ -1989,6 +1992,15 @@
                res.setReportUserPhone("111111");
                res.setReportUserAvatar("[]");
            }else{
                if (Objects.nonNull(task.getTaskSource()) && task.getTaskSource().equals(2)) {
                    List<SysUser> list = sysUserClient.listByIds(Lists.newArrayList(task.getReportUserId())).getData();
                    if (CollUtil.isNotEmpty(list)) {
                        SysUser sysUser = list.get(0);
                        res.setReportUserId(sysUser.getId());
                        res.setReportUserName(sysUser.getNickName());
                        res.setReportUserPhone(sysUser.getPhoneNumber());
                    }
                }else{
                XpOperationsUser data = xpOperationUserClient.queryById(task.getReportUserId()).getData();
                if (data != null ) {
                    res.setReportUserId(data.getId());
@@ -1997,6 +2009,7 @@
                    res.setReportUserAvatar(data.getAvatar());
                }
            }
            }
            if (task.getHandleUserId()!=null && task.getHandleUserId().split(",").length == 1) {
                XpOperationsUser operationsUser = xpOperationUserClient.queryById(Long.valueOf(task.getHandleUserId())).getData();
xp-robotaxi-map-boot/src/main/java/com/xiaopeng/map/controller/XpElectronicFenceManagementController.java
@@ -334,19 +334,23 @@
    private void validateFenceTime(@NotNull Integer status, Integer effectType, LocalDateTime effectTime,
                                   Integer failureType, LocalDateTime failureTime) {
        LocalDateTime now = LocalDateTime.now();
        // 定时生效时,生效时间不能早于当前时间
        if (null != status && status == 2 && effectType != null && effectType != 1) {
        // 发布/启用时,定时生效的生效时间不能早于当前时间
        if (requiresScheduleValidation(status) && effectType != null && effectType != 1) {
            if (effectTime == null || effectTime.isBefore(now)) {
                throw new ServiceException("围栏生效时间不合法,定时生效时生效时间不能早于当前时间",
                        I18nKeyConstant.FENCE_EFFECT_TIME_INVALID);
            }
        }
        // 定时失效时,失效时间不能早于当前时间
        if (null != status && status == 2 && failureType != null && failureType != 1) {
        // 发布/启用时,定时失效的失效时间不能早于当前时间
        if (requiresScheduleValidation(status) && failureType != null && failureType != 1) {
            if (failureTime == null || failureTime.isBefore(now)) {
                throw new ServiceException("围栏失效时间不合法,定时失效时失效时间不能早于当前时间",
                        I18nKeyConstant.FENCE_FAILURE_TIME_INVALID);
            }
        }
    }
    private boolean requiresScheduleValidation(Integer status) {
        return status != null && (status == 1 || status == 2);
    }
}
xp-robotaxi-map-boot/src/main/java/com/xiaopeng/map/service/serviceimpl/XpElectronicFenceServiceImpl.java
@@ -245,23 +245,11 @@
        // 保存主表数据
        XpElectronicFence xpElectronicFence = new XpElectronicFence();
        BeanUtils.copyProperties(dto, xpElectronicFence);
        xpElectronicFence.setStatus(0);
        if (dto.getStatus() == 0) {
            xpElectronicFence.setStatus(0);
        } else if (dto.getStatus() == 1) {
            if (dto.getEffectType() == 1) {
                // 设置为启用中
                xpElectronicFence.setStatus(2);
                xpElectronicFence.setEffectTime(LocalDateTime.now());
            } else {
                if (dto.getEffectTime().isBefore(LocalDateTime.now())) {
                    // 设置为启用中
                    xpElectronicFence.setStatus(2);
                } else {
                    xpElectronicFence.setStatus(1);
                }
            }
        LocalDateTime now = LocalDateTime.now();
        int targetStatus = resolveFenceStatus(dto.getStatus(), dto.getEffectType(), dto.getEffectTime(), now);
        xpElectronicFence.setStatus(targetStatus);
        if (targetStatus == 2 && dto.getEffectType() != null && dto.getEffectType() == 1) {
            xpElectronicFence.setEffectTime(now);
        }
        //根据经纬度获取当前城市code
@@ -291,55 +279,9 @@
        // 获取拼音首字母并大写
        String result = getPinyinInitials(prefix).toUpperCase();
        xpElectronicFence.setElectronicNumber(result + "-OP-" + String.format("%04d", xpElectronicFence.getId()));
        if (dto.getStatus() == 0) {
            xpElectronicFence.setStatus(0);
        } else if (dto.getStatus() == 1) {
            if (dto.getEffectType() == 1) {
                // 设置为启用中
                xpElectronicFence.setStatus(2);
                xpElectronicFence.setEffectTime(LocalDateTime.now());
            } else {
                if (dto.getEffectTime().isBefore(LocalDateTime.now())) {
                    // 设置为启用中
                    xpElectronicFence.setStatus(2);
                } else {
                    // 添加定时任务job type=1电子围栏生效 type=2电子围栏失效
                    Map<String, ? extends Object> maps =
                            new ImmutableMap.Builder<String, Long>().
                                    put("type", 1L)
                                    .put("id", xpElectronicFence.getId())
                                    .build();
                    QuartzManager.addJob(
                            ElectronicEffectJob.class,
                            (ElectronicEffectJob.effect + xpElectronicFence.getId()).toUpperCase(),
                            TimeJobType.ELECTRONIC_EFFECT,
                            DateUtils.localDateTimeToDate(dto.getEffectTime()),
                            maps
                    );
                    xpElectronicFence.setStatus(1);
                }
            }
            if (dto.getFailureType() != null && dto.getFailureType() == 2) {
                if (dto.getFailureTime().isBefore(LocalDateTime.now())) {
                    // 设置待启用
                    xpElectronicFence.setStatus(1);
                } else {
                    // 添加定时任务job type=1电子围栏生效 type=2电子围栏失效
                    Map<String, ? extends Object> maps =
                            new ImmutableMap.Builder<String, Long>().
                                    put("type", 2L)
                                    .put("id", xpElectronicFence.getId())
                                    .build();
                    QuartzManager.addJob(
                            ElectronicEffectJob.class,
                            (ElectronicEffectJob.failure + xpElectronicFence.getId()).toUpperCase(),
                            TimeJobType.ELECTRONIC_FAILURE,
                            DateUtils.localDateTimeToDate(dto.getFailureTime()),
                            maps
                    );
                }
            }
        if (dto.getStatus() == 1) {
            registerEffectJobIfNeeded(xpElectronicFence.getId(), targetStatus, dto.getEffectType(), dto.getEffectTime(), now);
            registerFailureJobIfNeeded(xpElectronicFence.getId(), dto.getFailureType(), dto.getFailureTime(), now);
        }
        this.updateById(xpElectronicFence);
        if (xpElectronicFence.getStatus() == 2) {
@@ -444,56 +386,17 @@
        // 更新主表数据
        XpElectronicFence xpElectronicFence = new XpElectronicFence();
        BeanUtils.copyProperties(dto, xpElectronicFence);
        if (dto.getStatus() == 0) {
            xpElectronicFence.setStatus(0);
        } else if (dto.getStatus() == 1) {
            if (dto.getEffectType() == 1) {
                // 立即生效:设置为启用中
                xpElectronicFence.setStatus(2);
                xpElectronicFence.setEffectTime(LocalDateTime.now());
        LocalDateTime now = LocalDateTime.now();
        int targetStatus = resolveFenceStatus(dto.getStatus(), dto.getEffectType(), dto.getEffectTime(), now);
        xpElectronicFence.setStatus(targetStatus);
        if (targetStatus == 2 && dto.getEffectType() != null && dto.getEffectType() == 1) {
            xpElectronicFence.setEffectTime(now);
        }
        if (dto.getStatus() == 1 || dto.getStatus() == 2) {
            registerEffectJobIfNeeded(xpElectronicFence.getId(), targetStatus, dto.getEffectType(), dto.getEffectTime(), now);
            registerFailureJobIfNeeded(xpElectronicFence.getId(), dto.getFailureType(), dto.getFailureTime(), now);
            } else {
                if (dto.getEffectTime().isBefore(LocalDateTime.now())) {
                    // 定时生效时间已过:直接设置为启用中
                    xpElectronicFence.setStatus(2);
                } else {
                    // 定时生效:注册生效定时任务
                    QuartzManager.removeJob((ElectronicEffectJob.effect + xpElectronicFence.getId()).toUpperCase(), TimeJobType.ELECTRONIC_EFFECT);
                    Map<String, ? extends Object> effectMaps =
                            new ImmutableMap.Builder<String, Long>()
                                    .put("type", 1L)
                                    .put("id", xpElectronicFence.getId())
                                    .build();
                    QuartzManager.addJob(
                            ElectronicEffectJob.class,
                            (ElectronicEffectJob.effect + xpElectronicFence.getId()).toUpperCase(),
                            TimeJobType.ELECTRONIC_EFFECT,
                            DateUtils.localDateTimeToDate(dto.getEffectTime()),
                            effectMaps
                    );
                    xpElectronicFence.setStatus(1);
                }
            }
        }
        // 失效时间处理:独立于 status 判断,只要 failureType=2 就注册失效定时任务
        if (dto.getFailureType() != null && dto.getFailureType() == 2) {
            if (dto.getFailureTime() != null && !dto.getFailureTime().isBefore(LocalDateTime.now())) {
                // 先删除以前的定时任务,再注册新的失效定时任务
                QuartzManager.removeJob((ElectronicEffectJob.failure + xpElectronicFence.getId()).toUpperCase(), TimeJobType.ELECTRONIC_FAILURE);
                Map<String, ? extends Object> failureMaps =
                        new ImmutableMap.Builder<String, Long>()
                                .put("type", 2L)
                                .put("id", xpElectronicFence.getId())
                                .build();
                QuartzManager.addJob(
                        ElectronicEffectJob.class,
                        (ElectronicEffectJob.failure + xpElectronicFence.getId()).toUpperCase(),
                        TimeJobType.ELECTRONIC_FAILURE,
                        DateUtils.localDateTimeToDate(dto.getFailureTime()),
                        failureMaps
                );
            }
        } else {
            // failureType 不是定时失效,清除可能存在的旧失效定时任务
            QuartzManager.removeJob((ElectronicEffectJob.failure + xpElectronicFence.getId()).toUpperCase(), TimeJobType.ELECTRONIC_FAILURE);
        }
        //根据经纬度获取当前城市code
@@ -852,6 +755,64 @@
        return ids.stream().filter(Objects::nonNull).distinct().collect(Collectors.toList());
    }
    private int resolveFenceStatus(Integer requestedStatus, Integer effectType, LocalDateTime effectTime, LocalDateTime now) {
        if (requestedStatus == null) {
            return 0;
        }
        if (requestedStatus == 0) {
            return 0;
        }
        if (requestedStatus == 3) {
            return 3;
        }
        if (effectType != null && effectType == 1) {
            return 2;
        }
        if (effectTime != null && !effectTime.isAfter(now)) {
            return 2;
        }
        return 1;
    }
    private void registerEffectJobIfNeeded(Long electronicId, Integer targetStatus, Integer effectType,
                                           LocalDateTime effectTime, LocalDateTime now) {
        QuartzManager.removeJob((ElectronicEffectJob.effect + electronicId).toUpperCase(), TimeJobType.ELECTRONIC_EFFECT);
        if (targetStatus != 1 || effectType == null || effectType == 1 || effectTime == null || !effectTime.isAfter(now)) {
            return;
        }
        Map<String, ? extends Object> effectMaps =
                new ImmutableMap.Builder<String, Long>()
                        .put("type", 1L)
                        .put("id", electronicId)
                        .build();
        QuartzManager.addJob(
                ElectronicEffectJob.class,
                (ElectronicEffectJob.effect + electronicId).toUpperCase(),
                TimeJobType.ELECTRONIC_EFFECT,
                DateUtils.localDateTimeToDate(effectTime),
                effectMaps
        );
    }
    private void registerFailureJobIfNeeded(Long electronicId, Integer failureType, LocalDateTime failureTime, LocalDateTime now) {
        QuartzManager.removeJob((ElectronicEffectJob.failure + electronicId).toUpperCase(), TimeJobType.ELECTRONIC_FAILURE);
        if (failureType == null || failureType != 2 || failureTime == null || failureTime.isBefore(now)) {
            return;
        }
        Map<String, ? extends Object> failureMaps =
                new ImmutableMap.Builder<String, Long>()
                        .put("type", 2L)
                        .put("id", electronicId)
                        .build();
        QuartzManager.addJob(
                ElectronicEffectJob.class,
                (ElectronicEffectJob.failure + electronicId).toUpperCase(),
                TimeJobType.ELECTRONIC_FAILURE,
                DateUtils.localDateTimeToDate(failureTime),
                failureMaps
        );
    }
    /**
     * 判断点是否在多边形内
     *
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/job/jobs/DynamicPricingCheckJob.java
@@ -1,7 +1,5 @@
package com.xiaopeng.operation.job.jobs;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.xiaopeng.api.feignClient.order.XpOrderClient;
@@ -11,10 +9,8 @@
import com.xiaopeng.api.model.operation.XpPricing;
import com.xiaopeng.api.model.vehicleConvoy.XpVehicle;
import com.xiaopeng.common.core.domain.R;
import com.xiaopeng.common.core.utils.DateUtils;
import com.xiaopeng.common.core.utils.StringUtils;
import com.xiaopeng.common.redis.service.RedisService;
import com.xiaopeng.operation.job.base.AbstractJob;
import com.xiaopeng.operation.job.base.TimeJobType;
import com.xiaopeng.operation.job.base.QuartzManager;
import com.xiaopeng.operation.job.utils.SpringContextsUtil;
@@ -22,12 +18,12 @@
import com.xiaopeng.operation.mapper.XpOpenCityMapper;
import com.xiaopeng.operation.service.XpPricingService;
import lombok.extern.slf4j.Slf4j;
import org.quartz.Job;
import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import java.time.LocalDateTime;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
@@ -45,7 +41,7 @@
 * @author mitao
 */
@Slf4j
public class DynamicPricingCheckJob extends AbstractJob {
public class DynamicPricingCheckJob implements Job {
    /**
     * 任务名称前缀
@@ -60,7 +56,6 @@
    private RedisService redisService;
    public DynamicPricingCheckJob() {
        super();
        this.xpPricingService = SpringContextsUtil.getBean(XpPricingService.class);
        this.xpOrderClient = SpringContextsUtil.getBean(XpOrderClient.class);
        this.xpVehicleClient = SpringContextsUtil.getBean(XpVehicleClient.class);
@@ -166,7 +161,7 @@
            if (activeOrderCount > orderThreshold && idleVehicleCount < vehicleThreshold) {
                String redisKey = "DYNAMIC_PRICE_" + cityId;
                // 写入当前时间字符串,与现有 XpPricingUtil 消费侧兼容
                redisService.setCacheObject(redisKey, DateUtil.format(new Date(), DatePattern.NORM_DATETIME_FORMAT));
                redisService.setCacheObject(redisKey, LocalDateTime.now().toString());
                log.info("动态调价触发:已写入 Redis key={} pricingId={}", redisKey, pricingId);
            } else {
                log.info("动态调价未触发:供需条件不满足 pricingId={}", pricingId);
xp-robotaxi-operation-boot/src/main/resources/mapper/operation/XpWhitelistMapper.xml
@@ -11,7 +11,6 @@
        ,create_time as createTime,update_time as updateTime,create_by as createBy,update_by as updateBy
        from xp_whitelist
        where is_deleted = 0
          group by account
        <if test="query.account != null and query.account != ''">
            and account like concat('%',#{query.account},'%')
        </if>
@@ -21,6 +20,7 @@
        <if test="query.whitelistSource != null">
            and whitelist_source = #{query.whitelistSource}
        </if>
        group by account
        order by create_time desc
    </select>
    <select id="exportList" resultType="com.xiaopeng.api.model.operation.XpWhitelist">