xuhy
2026-03-12 b3e9e6eb29afce516d893f17c7c99ae3dd2be4f5
处理缺卡问题
1个文件已添加
5个文件已修改
197 ■■■■■ 已修改文件
xp-robotaxi-account-boot/src/main/java/com/xiaopeng/account/config/MybatisPlusConfig.java 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-api/src/main/java/com/xiaopeng/api/factory/vehicleConvoy/XpFleetOperationsClientFallbackFactory.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-api/src/main/java/com/xiaopeng/api/feignClient/vehicleConvoy/XpFleetOperationsClient.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/schedule/ClockInScheduleTask.java 113 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/controller/XpWhitelistController.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/controller/XpFleetOperationsController.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-account-boot/src/main/java/com/xiaopeng/account/config/MybatisPlusConfig.java
New file
@@ -0,0 +1,51 @@
package com.xiaopeng.account.config;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.core.config.GlobalConfig;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
 * @author xiaochen
 * @ClassName MybatisPlusConfig
 * @Description MybatisPlus相关配置
 * @date 2020-09-22 11:22、
 * 直接以实现类作为bean的注入(有事务管理的类)
 * @EnableTransactionManagement(proxyTargetClass = true)
 */
@Configuration
public class MybatisPlusConfig {
    private final DataUpdateHandlerConfig dataUpdateHandler;
    @Autowired
    public MybatisPlusConfig(DataUpdateHandlerConfig dataUpdateHandler) {
        this.dataUpdateHandler = dataUpdateHandler;
    }
    /**
     * 新的分页插件,一缓和二缓遵循mybatis的规则,需要设置 MybatisConfiguration#useDeprecatedExecutor = false 避免缓存出现问题
     */
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;
    }
    /**
     * 自动填充功能
     *
     * @return
     */
    @Bean
    public GlobalConfig globalConfig() {
        GlobalConfig globalConfig = new GlobalConfig();
        globalConfig.setMetaObjectHandler(dataUpdateHandler);
        return globalConfig;
    }
}
xp-robotaxi-api/src/main/java/com/xiaopeng/api/factory/vehicleConvoy/XpFleetOperationsClientFallbackFactory.java
@@ -1,6 +1,7 @@
package com.xiaopeng.api.factory.vehicleConvoy;
import com.xiaopeng.api.feignClient.vehicleConvoy.XpFleetOperationsClient;
import com.xiaopeng.api.model.vehicleConvoy.XpFleetOperations;
import com.xiaopeng.common.core.domain.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.openfeign.FallbackFactory;
@@ -40,6 +41,12 @@
                log.error("根据车队ID获取人员信息失败 {}",  cause.getMessage());
                return R.fail("根据车队ID获取人员信息失败");
            }
            @Override
            public R<List<XpFleetOperations>> getOperationsIdsByFleetIds(List<Long> fleetIds) {
                log.error("根据车队ID集合查询关联的运维人员ID列表失败 {}",  cause.getMessage());
                return R.fail("根据车队ID集合查询关联的运维人员ID列表失败");
            }
        };
    }
}
xp-robotaxi-api/src/main/java/com/xiaopeng/api/feignClient/vehicleConvoy/XpFleetOperationsClient.java
@@ -2,11 +2,14 @@
import com.xiaopeng.api.factory.vehicleConvoy.XpFleetOperationsClientFallbackFactory;
import com.xiaopeng.api.factory.vehicleConvoy.XpFleetVehicleClientFallbackFactory;
import com.xiaopeng.api.model.vehicleConvoy.XpFleetOperations;
import com.xiaopeng.common.core.domain.R;
import com.xiaopeng.common.core.dto.ServiceNameConstantsEnum;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import java.util.List;
@@ -47,4 +50,12 @@
     */
    @GetMapping("/inner/fleet-operations/getOperationsIdsByFleetId/{fleetId}")
    R<List<Long>> getOperationsIdsByFleetId(@PathVariable("fleetId") Long fleetId);
    /**
     * 根据车队ID集合查询关联的运维人员ID列表
     *
     * @param fleetIds 车队ID集合
     * @return 运维人员ID列表
     */
    @PostMapping("/inner/fleet-operations/getOperationsIdsByFleetIds")
    R<List<XpFleetOperations>> getOperationsIdsByFleetIds(@RequestBody List<Long> fleetIds);
}
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/schedule/ClockInScheduleTask.java
@@ -2,15 +2,21 @@
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.xiaopeng.api.feignClient.account.XpOperationUserClient;
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.maintenance.XpClockIn;
import com.xiaopeng.api.model.maintenance.XpSchedulingDetail;
import com.xiaopeng.api.model.maintenance.XpShift;
import com.xiaopeng.api.model.vehicleConvoy.XpFleetOperations;
import com.xiaopeng.common.core.utils.DateUtils;
import com.xiaopeng.maintenance.mapper.XpClockInMapper;
import com.xiaopeng.maintenance.mapper.XpTaskMapper;
import com.xiaopeng.maintenance.mapper.XpTaskRuleMapper;
import com.xiaopeng.maintenance.mapper.XpTaskRuleRoleMapper;
import com.xiaopeng.maintenance.service.IXpClockInService;
import com.xiaopeng.maintenance.service.IXpSchedulingDetailService;
import com.xiaopeng.maintenance.service.IXpShiftService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@@ -19,6 +25,8 @@
import org.springframework.util.CollectionUtils;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
@@ -40,7 +48,10 @@
    private IXpClockInService xpClockInService;
    @Autowired
    private IXpSchedulingDetailService xpSchedulingDetailService;
    @Autowired
    private XpFleetOperationsClient xpFleetOperationsClient;
    @Autowired
    private IXpShiftService xpShiftService;
    /**
     * 每5分钟执行一次
@@ -49,20 +60,100 @@
    public void clockInScheduleTask() {
        log.info("========== 开始执行打卡检查 ==========");
        try {
            // 查询上班卡在今天的
            List<XpSchedulingDetail> clockInPlanList = xpSchedulingDetailService.list(Wrappers.lambdaQuery(XpSchedulingDetail.class)
                    .likeRight(XpSchedulingDetail::getPlanTime, LocalDate.now()));
            if(!CollectionUtils.isEmpty(clockInPlanList)){
                List<Long> fleetIds = clockInPlanList.stream().map(XpSchedulingDetail::getFleetId).collect(Collectors.toList());
                // 查询所有车队
            }
            // 查询下班卡在今天的
            List<XpSchedulingDetail> clockOutPlanList = xpSchedulingDetailService.list(Wrappers.lambdaQuery(XpSchedulingDetail.class)
                    .likeRight(XpSchedulingDetail::getPlanTime, LocalDate.now()));
            if(!CollectionUtils.isEmpty(clockOutPlanList)){
                List<Long> fleetIds = clockOutPlanList.stream().map(XpSchedulingDetail::getFleetId).collect(Collectors.toList());
                // 查询所有车队的绑定人员
                List<XpFleetOperations> xpFleetOperations = xpFleetOperationsClient.getOperationsIdsByFleetIds(fleetIds).getData();
                // 查询班次
                List<Long> shiftIds = clockOutPlanList.stream().map(XpSchedulingDetail::getShiftId).collect(Collectors.toList());
                List<XpShift> xpShifts = xpShiftService.list(Wrappers.lambdaQuery(XpShift.class)
                        .eq(XpShift::getId, shiftIds));
                log.info("========== 查询到{}个车队 ==========", xpFleetOperations.size());
                if(!CollectionUtils.isEmpty(xpShifts) && !CollectionUtils.isEmpty(xpFleetOperations)){
                    // 处理上班卡缺卡情况
                    // 过滤当前时间在班次下班打卡时间之后的数据   今日已过下班的班次
                    List<XpShift> shiftList = xpShifts.stream().filter(xpShift ->
                            DateUtils.stringToLocalDateTime(LocalDate.now() + " " + xpShift.getEndTime() + ":00").isBefore(LocalDateTime.now())).collect(Collectors.toList());
                    List<Long> ids = shiftList.stream().map(XpShift::getId).collect(Collectors.toList());
                    if(!CollectionUtils.isEmpty(ids)){
                        log.info("========== 进入上班过期的班次 ==========");
                        // 获取过期当前班次的排班明细  覆盖
                        List<XpSchedulingDetail> clockOutPlans = clockOutPlanList.stream().filter(xpSchedulingDetail -> ids.contains(xpSchedulingDetail.getShiftId())).collect(Collectors.toList());
                        List<Long> fleetIdIn = clockOutPlans.stream().map(XpSchedulingDetail::getFleetId).collect(Collectors.toList());
                        List<Long> operationsUserIds = xpFleetOperations.stream().filter(x -> fleetIdIn.contains(x.getFleetId()))
                                .map(XpFleetOperations::getOperationsUserId).distinct().collect(Collectors.toList());
                        // 批量查询人员打卡信息
                        List<XpClockIn> clockInList = xpClockInService.list(Wrappers.lambdaQuery(XpClockIn.class)
                                .eq(XpClockIn::getAppUserId, operationsUserIds));
                        // 判断有哪些人员没有打卡信息
                        List<Long> noClockInUserIds = operationsUserIds.stream().filter(id -> clockInList.stream().noneMatch(clockIn -> clockIn.getAppUserId().equals(id))).collect(Collectors.toList());
                        if(!CollectionUtils.isEmpty(noClockInUserIds)){
                            log.info("========== 获取到{}个人员没有打卡信息 ==========", noClockInUserIds.size());
                            // 添加上班缺卡信息
                            List<XpClockIn> noClockInList = new ArrayList<>();
                            for (Long noClockInUserId : noClockInUserIds) {
                                // 通过用户id找到车队id
                                List<XpFleetOperations> operations = xpFleetOperations.stream().filter(x -> x.getOperationsUserId().equals(noClockInUserId)).collect(Collectors.toList());
                                if(!CollectionUtils.isEmpty(operations)){
                                    Long fleetId = operations.get(0).getFleetId();
                                    // 通过车队id和已过期的班次获取排班明细
                                    List<XpSchedulingDetail> clockOutPlanExpiredList = clockOutPlanList.stream()
                                            .filter(xpSchedulingDetail -> xpSchedulingDetail.getFleetId().equals(fleetId)
                                                    && ids.contains(xpSchedulingDetail.getShiftId())).collect(Collectors.toList());
                                    if(!CollectionUtils.isEmpty(clockOutPlanExpiredList)){
                                        Long shiftId = clockOutPlanExpiredList.get(0).getShiftId();
                                        XpClockIn xpClockIn = new XpClockIn();
                                        xpClockIn.setAppUserId(noClockInUserId);
                                        xpClockIn.setClockInTime(LocalDateTime.now());
                                        xpClockIn.setClockInResult(3);
                                        xpClockIn.setShiftId(shiftId);
                                        noClockInList.add(xpClockIn);
                                    }
                                }
                            }
                            if (!CollectionUtils.isEmpty(noClockInList)){
                                log.info("添加上班缺卡信息:{}", noClockInList);
                                xpClockInService.saveOrUpdateBatch(noClockInList);
                            }
                        }
                    }
                    // 处理下班卡缺卡情况
                    // 过滤当前时间在班次下班打卡时间之后5小时的数据   今日已过下班打卡时间5小时后的班次
                    List<XpShift> shiftListFive = xpShifts.stream().filter(xpShift ->
                            DateUtils.stringToLocalDateTime(LocalDate.now() + " " + xpShift.getEndTime() + ":00").plusHours(5).isBefore(LocalDateTime.now())).collect(Collectors.toList());
                    List<Long> fiveIds = shiftListFive.stream().map(XpShift::getId).collect(Collectors.toList());
                    if(!CollectionUtils.isEmpty(fiveIds)){
                        log.info("========== 进入下班过期的班次 ==========");
                        // 获取过期当前班次的排班明细  覆盖
                        List<XpSchedulingDetail> fiveClockOutPlans = clockOutPlanList.stream().filter(xpSchedulingDetail -> fiveIds.contains(xpSchedulingDetail.getShiftId())).collect(Collectors.toList());
                        List<Long> fiveFleetIdIn = fiveClockOutPlans.stream().map(XpSchedulingDetail::getFleetId).collect(Collectors.toList());
                        // 查询所有车队的绑定人员
                        if(!CollectionUtils.isEmpty(xpFleetOperations)){
                            List<Long> operationsUserIdsFive = xpFleetOperations.stream().filter(x -> fiveFleetIdIn.contains(x.getFleetId()))
                                    .map(XpFleetOperations::getOperationsUserId).distinct().collect(Collectors.toList());
                            // 批量查询人员打卡信息
                            List<XpClockIn> clockInListFive = xpClockInService.list(Wrappers.lambdaQuery(XpClockIn.class)
                                    .eq(XpClockIn::getAppUserId, operationsUserIdsFive)
                                    .isNull(XpClockIn::getClockOutTime));
                            log.info("========== 获取到{}个人员没有下班打卡信息 ==========", clockInListFive.size());
                            if(!CollectionUtils.isEmpty(clockInListFive)){
                                for (XpClockIn xpClockIn : clockInListFive) {
                                    xpClockIn.setClockOutTime(LocalDateTime.now());
                                    xpClockIn.setClockOutResult(3);
                                }
                                xpClockInService.updateBatchById(clockInListFive);
                                log.info("========== 修改为下班缺卡 ==========");
                            }
                        }
                    }
                }
            }
        } catch (Exception e) {
            log.error("执行打卡检查任务执行失败", e);
        }
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/controller/XpWhitelistController.java
@@ -323,7 +323,7 @@
        xpWhitelistOperlog.setCreateBy(sysUser.getNickName());
        xpWhitelistOperlogService.save(xpWhitelistOperlog);
        return AjaxResult.success(message, message);
        return AjaxResult.success(opContent, opContent);
    }
    private static String trimToNull(String value) {
xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/controller/XpFleetOperationsController.java
@@ -92,4 +92,17 @@
                .collect(Collectors.toList());
        return R.ok(operationsIds);
    }
    /**
     * 根据车队ID集合查询关联的运维人员ID列表
     *
     * @param fleetIds 车队ID集合
     * @return 运维人员ID列表
     */
    @PostMapping("/inner/fleet-operations/getOperationsIdsByFleetIds")
    public R<List<XpFleetOperations>> getOperationsIdsByFleetIds(@RequestBody List<Long> fleetIds){
        List<XpFleetOperations> fleetOperations = xpFleetOperationsService.lambdaQuery()
                .in(XpFleetOperations::getFleetId, fleetIds)
                .list();
        return R.ok(fleetOperations);
    }
}