puzhibing
2026-02-28 e8cd57fc46fa84b0c095f7e93cb348c014d06eb4
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/service/impl/XpSchedulingDetailServiceImpl.java
@@ -1,15 +1,19 @@
package com.xiaopeng.maintenance.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xiaopeng.api.feignClient.account.XpOperationUserClient;
import com.xiaopeng.api.feignClient.maintenance.XpCheckLocationClient;
import com.xiaopeng.api.feignClient.vehicleConvoy.XpFleetClient;
import com.xiaopeng.api.model.maintenance.XpCheckLocation;
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.feignClient.vehicleConvoy.XpFleetOperationsClient;
import com.xiaopeng.api.model.account.XpOperationsUser;import com.xiaopeng.api.model.maintenance.*;
import com.xiaopeng.api.model.vehicleConvoy.XpFleet;
import com.xiaopeng.common.core.domain.R;
import com.xiaopeng.common.core.utils.poi.ExcelUtil;
import com.xiaopeng.common.core.web.page.PageInfo;
import com.xiaopeng.maintenance.dto.ExportSchedulingDetailDto;
import com.xiaopeng.maintenance.dto.SchedulingDetailDto;
import com.xiaopeng.maintenance.dto.ShiftAttendanceDTO;
import com.xiaopeng.maintenance.mapper.XpCheckLocationMapper;
@@ -17,12 +21,21 @@
import com.xiaopeng.maintenance.mapper.XpSchedulingDetailMapper;
import com.xiaopeng.maintenance.mapper.XpShiftMapper;
import com.xiaopeng.maintenance.service.IXpSchedulingDetailService;
import com.xiaopeng.maintenance.vo.SchedulingDetailVo;
import com.xiaopeng.maintenance.vo.ShiftAttendanceVO;
import com.xiaopeng.maintenance.service.IXpSchedulingService;
import com.xiaopeng.maintenance.service.IXpShiftService;
import com.xiaopeng.maintenance.vo.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Objects;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.TextStyle;
import java.time.temporal.TemporalAdjusters;
import java.util.*;
/**
 * <p>
@@ -35,14 +48,22 @@
@Service
public class XpSchedulingDetailServiceImpl extends ServiceImpl<XpSchedulingDetailMapper, XpSchedulingDetail> implements IXpSchedulingDetailService {
    @Autowired
    @Resource
    private XpFleetClient xpFleetClient;
    @Autowired
    @Resource
    private XpCheckLocationMapper xpCheckLocationMapper;
    @Autowired
    @Resource
    private XpShiftMapper xpShiftMapper;
    @Autowired
    @Resource
    private XpClockInMapper xpClockInMapper;
    @Resource
    private IXpSchedulingService xpSchedulingService;
    @Resource
    private IXpShiftService xpShiftService;
    @Resource
    private XpFleetOperationsClient xpFleetOperationsClient;
    @Resource
    private XpOperationUserClient xpOperationUserClient;
    @Override
    public ShiftAttendanceVO shiftAttendance(ShiftAttendanceDTO dto) {
@@ -78,10 +99,10 @@
                .eq(XpClockIn::getAppUserId, dto.getOperationsUserId())
                .likeRight(XpClockIn::getClockInTime, dto.getSchedulingDate())
                .last("LIMIT 1"));
        if(Objects.isNull(xpClockIn)){
        if (Objects.isNull(xpClockIn)) {
            shiftAttendanceVO.setClockIn(false);
            shiftAttendanceVO.setClockOut(false);
        }else {
        } else {
            shiftAttendanceVO.setXpClockIn(xpClockIn);
            shiftAttendanceVO.setClockIn(true);
            shiftAttendanceVO.setClockOut(xpClockIn.getClockOutTime() != null);
@@ -92,15 +113,438 @@
    /**
     * 排班明细分页列表
     *
     * @param query
     * @return
     */
    @Override
    public PageInfo<SchedulingDetailDto> pageList(SchedulingDetailVo query) {
        PageInfo<SchedulingDetailDto> pageInfo = new PageInfo<>(query.getPageNum(), query.getPageSize());
        List<SchedulingDetailDto> schedulingDetailDtos = this.baseMapper.pageList(pageInfo, query.getMonth());
        LocalDate parse1 = LocalDate.parse(query.getMonth(), DateTimeFormatter.ofPattern("yyyy-MM"));
        //找出月份的最大天
        int dayOfMonth = parse1.with(TemporalAdjusters.lastDayOfMonth()).getDayOfMonth();
        for (SchedulingDetailDto schedulingDetailDto : schedulingDetailDtos) {
            String days = schedulingDetailDto.getDays();
            if (StringUtils.isNotBlank(days)) {
                String[] split = days.split(",");
                List<String> list = Arrays.asList(split);
                for (int i = 1; i <= dayOfMonth; i++) {
                    Map<String, String> map1 = new HashMap<>();
                    for (String s : split) {
                        String[] split1 = s.split("_");
                        if (i == Integer.parseInt(split1[0])) {
                            map1.put("shiftId", split1[1]);
                            map1.put("shiftName", split1[2]);
                            map1.put("shiftColor", split1[3]);
                            break;
                        }
                    }
                    setEnglishDay(i, schedulingDetailDto, map1);
                }
                long allDay = list.stream().filter(s -> s.contains("全天")).count();
                long morning = list.stream().filter(s -> s.contains("早")).count();
                long midDay = list.stream().filter(s -> s.contains("中")).count();
                long evening = list.stream().filter(s -> s.contains("晚")).count();
                schedulingDetailDto.setAllDay(allDay);
                schedulingDetailDto.setMorning(morning);
                schedulingDetailDto.setMidDay(midDay);
                schedulingDetailDto.setEvening(evening);
            }
        }
        pageInfo.setRecords(schedulingDetailDtos);
        return pageInfo;
    }
    /**
     * 给每天的字段赋值
     * @param day
     * @param dto
     * @param map
     */
    private void setEnglishDay(int day, SchedulingDetailDto dto, Map<String, String> map) {
        switch (day) {
            case 1:
                dto.setOne(map);
                break;
            case 2:
                dto.setTwo(map);
                break;
            case 3:
                dto.setThree(map);
                break;
            case 4:
                dto.setFour(map);
                break;
            case 5:
                dto.setFive(map);
                break;
            case 6:
                dto.setSix(map);
                break;
            case 7:
                dto.setSeven(map);
                break;
            case 8:
                dto.setEight(map);
                break;
            case 9:
                dto.setNine(map);
                break;
            case 10:
                dto.setTen(map);
                break;
            case 11:
                dto.setEleven(map);
                break;
            case 12:
                dto.setTwelve(map);
                break;
            case 13:
                dto.setThirteen(map);
                break;
            case 14:
                dto.setFourteen(map);
                break;
            case 15:
                dto.setFifteen(map);
                break;
            case 16:
                dto.setSixteen(map);
                break;
            case 17:
                dto.setSeventeen(map);
                break;
            case 18:
                dto.setEighteen(map);
                break;
            case 19:
                dto.setNineteen(map);
                break;
            case 20:
                dto.setTwenty(map);
                break;
            case 21:
                dto.setTwentyOne(map);
                break;
            case 22:
                dto.setTwentyTwo(map);
                break;
            case 23:
                dto.setTwentyThree(map);
                break;
            case 24:
                dto.setTwentyFour(map);
                break;
            case 25:
                dto.setTwentyFive(map);
                break;
            case 26:
                dto.setTwentySix(map);
                break;
            case 27:
                dto.setTwentySeven(map);
                break;
            case 28:
                dto.setTwentyEight(map);
                break;
            case 29:
                dto.setTwentyNine(map);
                break;
            case 30:
                dto.setThirty(map);
                break;
            case 31:
                dto.setThirtyOne(map);
                break;
        }
    }
        return null;
    /**
     * 给每天的字段赋值
     * @param day
     * @param dto
     * @param shiftName
     */
    private void setEnglishDay(int day, ExportSchedulingDetailDto dto, String shiftName) {
        switch (day) {
            case 1:
                dto.setOne(shiftName);
                break;
            case 2:
                dto.setTwo(shiftName);
                break;
            case 3:
                dto.setThree(shiftName);
                break;
            case 4:
                dto.setFour(shiftName);
                break;
            case 5:
                dto.setFive(shiftName);
                break;
            case 6:
                dto.setSix(shiftName);
                break;
            case 7:
                dto.setSeven(shiftName);
                break;
            case 8:
                dto.setEight(shiftName);
                break;
            case 9:
                dto.setNine(shiftName);
                break;
            case 10:
                dto.setTen(shiftName);
                break;
            case 11:
                dto.setEleven(shiftName);
                break;
            case 12:
                dto.setTwelve(shiftName);
                break;
            case 13:
                dto.setThirteen(shiftName);
                break;
            case 14:
                dto.setFourteen(shiftName);
                break;
            case 15:
                dto.setFifteen(shiftName);
                break;
            case 16:
                dto.setSixteen(shiftName);
                break;
            case 17:
                dto.setSeventeen(shiftName);
                break;
            case 18:
                dto.setEighteen(shiftName);
                break;
            case 19:
                dto.setNineteen(shiftName);
                break;
            case 20:
                dto.setTwenty(shiftName);
                break;
            case 21:
                dto.setTwentyOne(shiftName);
                break;
            case 22:
                dto.setTwentyTwo(shiftName);
                break;
            case 23:
                dto.setTwentyThree(shiftName);
                break;
            case 24:
                dto.setTwentyFour(shiftName);
                break;
            case 25:
                dto.setTwentyFive(shiftName);
                break;
            case 26:
                dto.setTwentySix(shiftName);
                break;
            case 27:
                dto.setTwentySeven(shiftName);
                break;
            case 28:
                dto.setTwentyEight(shiftName);
                break;
            case 29:
                dto.setTwentyNine(shiftName);
                break;
            case 30:
                dto.setThirty(shiftName);
                break;
            case 31:
                dto.setThirtyOne(shiftName);
                break;
        }
    }
    /**
     * 保存排班明细
     *
     * @param vo
     * @return
     */
    @Override
    public R saveSchedulingDetail(SaveSchedulingVo vo, Long userId) {
        String month = vo.getMonth();
        List<XpSchedulingDetail> list = this.list(new QueryWrapper<XpSchedulingDetail>().eq("is_deleted", 0).last(" and DATE_FORMAT(planTime,'%Y-%m') = '" + month + "'"));
        //保存排班数据
        XpScheduling xpScheduling = xpSchedulingService.getOne(new QueryWrapper<XpScheduling>().eq("is_deleted", 0).last(" and DATE_FORMAT(schedulingDate,'%Y-%m') = '" + month + "'"));
        if(null == xpScheduling){
            xpScheduling = new XpScheduling();
            xpScheduling.setDeleted(false);
            xpScheduling.setCreateTime(LocalDateTime.now());
            xpScheduling.setUpdateTime(LocalDateTime.now());
            xpScheduling.setCreateBy(userId.toString());
            xpScheduling.setUpdateBy(userId.toString());
        }
        xpScheduling.setSchedulingDate(LocalDate.parse(month, DateTimeFormatter.ofPattern("yyyy-MM")));
        xpScheduling.setCommitUserId(userId);
        xpSchedulingService.saveOrUpdate(xpScheduling);
        List<XpShift> xpShifts = xpShiftService.list(new QueryWrapper<XpShift>().eq("is_deleted", 0));
        //构建排班明细数据
        List<SaveSchedulingDetailVo> datas = vo.getDatas();
        List<XpSchedulingDetail> schedulingDetails = new ArrayList<>();
        for (SaveSchedulingDetailVo data : datas) {
            Long fleetId = data.getFleetId();
            List<SaveSchedulingDetailDay> days = data.getDays();
            for (SaveSchedulingDetailDay day : days) {
                Long shiftId = day.getShiftId();
                LocalDate parse = LocalDate.parse(day.getDayTime(), DateTimeFormatter.ofPattern("yyyy-MM-dd"));
                //查询判断数据是否存在
                XpSchedulingDetail schedulingDetail = list.stream().filter(s -> s.getFleetId().equals(fleetId)
                        && s.getShiftId().equals(shiftId)
                        && s.getPlanTime().equals(parse)
                ).findAny().orElse(null);
                //构建存储对象
                if(null == schedulingDetail){
                    schedulingDetail = new XpSchedulingDetail();
                    schedulingDetail.setCreateBy(userId.toString());
                    schedulingDetail.setCreateTime(LocalDateTime.now());
                    schedulingDetail.setUpdateBy(userId.toString());
                    schedulingDetail.setUpdateTime(LocalDateTime.now());
                    schedulingDetail.setDeleted(false);
                }else{
                    //构建通知消息
                    Long old_shiftId = schedulingDetail.getShiftId();
                    if(!old_shiftId.equals(shiftId)){
                        //获取车队的所有人员
                        XpShift xpShift1 = xpShifts.stream().filter(s -> s.getId().equals(old_shiftId)).findAny().orElse(null);
                        XpShift xpShift2 = xpShifts.stream().filter(s -> s.getId().equals(shiftId)).findAny().orElse(null);
                        List<Long> operationsIds = xpFleetOperationsClient.getOperationsIdsByFleetId(fleetId).getData();
                        if(null != operationsIds && !operationsIds.isEmpty()){
                            List<XpOperationsUser> data1 = xpOperationUserClient.listByIds(operationsIds).getData();
                            for (XpOperationsUser xpOperationsUser : data1) {
                                String nickName = xpOperationsUser.getNickName();
                                String message = nickName + "请注意," + month + "你的排班由" + xpShift1.getShiftName() + "变更为了" + xpShift2.getShiftName() + "。详情请联系平台管理员。";
                            }
                        }
                    }
                }
                schedulingDetail.setSchedulingId(xpScheduling.getId());
                schedulingDetail.setFleetId(fleetId);
                schedulingDetail.setShiftId(shiftId);
                XpShift xpShift = xpShifts.stream().filter(s -> s.getId().equals(shiftId)).findAny().orElse(null);
                schedulingDetail.setIsAllDay(xpShift.getShiftName().contains("全天"));
                schedulingDetail.setPlanTime(parse);
                schedulingDetails.add(schedulingDetail);
            }
        }
        //批量保存排班明细数据
        if(schedulingDetails.isEmpty()){
            this.saveOrUpdateBatch(schedulingDetails);
        }
        return R.ok();
    }
    /**
     * 导出排班数据
     * @param month
     * @param response
     */
    @Override
    public void exportExcel(String month, HttpServletResponse response) {
        PageInfo<SchedulingDetailDto> pageInfo = new PageInfo<>(0, 10000);
        List<SchedulingDetailDto> schedulingDetailDtos = this.baseMapper.pageList(pageInfo, month);
        List<ExportSchedulingDetailDto> exportSchedulingDetailDtos = new ArrayList<>();
        //获取月份的最大天数
        LocalDate parse1 = LocalDate.parse(month, DateTimeFormatter.ofPattern("yyyy-MM"));
        int dayOfMonth = parse1.with(TemporalAdjusters.lastDayOfMonth()).getDayOfMonth();
        //构建表头第二行数据
        ExportSchedulingDetailDto exportSchedulingDetailDto = new ExportSchedulingDetailDto();
        exportSchedulingDetailDto.setFleetName("");
        for (int i = 1; i <= dayOfMonth; i++) {
            LocalDate parse = LocalDate.parse(month + "-" + i, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
            String week = "";
            switch (parse.getDayOfWeek()){
                case MONDAY:
                    week = "一";
                    break;
                case TUESDAY:
                    week = "二";
                    break;
                case WEDNESDAY:
                    week = "三";
                    break;
                case THURSDAY:
                    week = "四";
                    break;
                case FRIDAY:
                    week = "五";
                    break;
                case SATURDAY:
                    week = "六";
                    break;
                case SUNDAY:
                    week = "日";
                    break;
            }
            setEnglishDay(i, exportSchedulingDetailDto, week);
        }
        exportSchedulingDetailDto.setAllDay("全天");
        exportSchedulingDetailDto.setMorning("早");
        exportSchedulingDetailDto.setMidDay("中");
        exportSchedulingDetailDto.setEvening("晚");
        exportSchedulingDetailDtos.add(exportSchedulingDetailDto);
        //构建数据部分的内容
        for (SchedulingDetailDto schedulingDetailDto : schedulingDetailDtos) {
            exportSchedulingDetailDto = new ExportSchedulingDetailDto();
            exportSchedulingDetailDto.setFleetName(schedulingDetailDto.getFleetName());
            String days = schedulingDetailDto.getDays();
            if (StringUtils.isNotBlank(days)) {
                String[] split = days.split(",");
                List<String> list = Arrays.asList(split);
                for (int i = 1; i <= dayOfMonth; i++) {
                    String shiftName = "休";
                    for (String s : split) {
                        String[] split1 = s.split("_");
                        if (i == Integer.parseInt(split1[0])) {
                            shiftName = split1[2];
                            break;
                        }
                    }
                    setEnglishDay(i, exportSchedulingDetailDto, shiftName);
                }
                long allDay = list.stream().filter(s -> s.contains("全天")).count();
                long morning = list.stream().filter(s -> s.contains("早")).count();
                long midDay = list.stream().filter(s -> s.contains("中")).count();
                long evening = list.stream().filter(s -> s.contains("晚")).count();
                exportSchedulingDetailDto.setAllDay(allDay + "");
                exportSchedulingDetailDto.setMorning(morning + "");
                exportSchedulingDetailDto.setMidDay(midDay + "");
                exportSchedulingDetailDto.setEvening(evening + "");
            }else{
                for (int i = 1; i <= 31; i++) {
                    String shiftName = "休";
                    setEnglishDay(i, exportSchedulingDetailDto, shiftName);
                }
                exportSchedulingDetailDto.setAllDay("0");
                exportSchedulingDetailDto.setMorning("0");
                exportSchedulingDetailDto.setMidDay("0");
                exportSchedulingDetailDto.setEvening("0");
            }
            exportSchedulingDetailDtos.add(exportSchedulingDetailDto);
        }
        String[] split = month.split("-");
        ExcelUtil<ExportSchedulingDetailDto> excelUtil = new ExcelUtil<>(ExportSchedulingDetailDto.class);
        excelUtil.exportExcel(response, exportSchedulingDetailDtos, "排班计划", "日期:" + split[0] + "年" + split[1] + "月");
    }
}