zouyu
2026-04-22 fbbfb006e1d745ca3b7ae9ef497c06da4128f380
performance-server/src/main/java/com/ruoyi/performance/service/impl/PerformanceShiftServiceImpl.java
@@ -2,37 +2,58 @@
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.util.concurrent.AtomicDouble;
import com.ruoyi.common.core.domain.entity.SysDictData;
import com.ruoyi.common.core.domain.entity.User;
import com.ruoyi.common.utils.JackSonUtil;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.performance.dto.PerformanceShiftAddDto;
import com.ruoyi.performance.dto.PerformanceShiftMapDto;
import com.ruoyi.performance.dto.StaffAttendanceDTO;
import com.ruoyi.performance.excel.PerformanceShiftAnnotationTextExcelData;
import com.ruoyi.performance.excel.PerformanceShiftExcelData;
import com.ruoyi.performance.excel.handler.performance.CommentWriteHandler;
import com.ruoyi.performance.mapper.PerformanceShiftMapper;
import com.ruoyi.performance.pojo.PerformanceShift;
import com.ruoyi.performance.pojo.StaffAttendanceTrackingRecord;
import com.ruoyi.performance.service.PerformanceShiftService;
import com.ruoyi.performance.service.StaffAttendanceTrackingRecordService;
import com.ruoyi.performance.vo.StaffAttendanceVO;
import com.ruoyi.system.mapper.UserMapper;
import com.ruoyi.system.service.ISysDictTypeService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.ibatis.annotations.Param;
import org.apache.poi.ss.usermodel.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import java.math.BigDecimal;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.Collectors;
/**
@@ -43,11 +64,12 @@
 * @author 江苏鵷雏网络科技有限公司
 * @since 2024-05-08 09:12:04
 */
@Slf4j
@Service
public class PerformanceShiftServiceImpl extends ServiceImpl<PerformanceShiftMapper, PerformanceShift> implements PerformanceShiftService {
    @Autowired
    private ISysDictTypeService dictTypeService;
    private StaffAttendanceTrackingRecordService trackingRecordService;
    @Autowired
    UserMapper userMapper;
@@ -56,67 +78,51 @@
    private DateTimeFormatter yyyyMMddHHmmss = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    private DateTimeFormatter yyyMMStr = DateTimeFormatter.ofPattern("yyyy年MM月dd日");
    private final int LIST_MAX_COUNT = 1000;
    private static final String morningShiftKeyword = "早";//早班班次关键字
    private static final String dayShiftKeyword = "中";//中班班次关键字
    private static final String nightShiftKeyword = "夜";//夜班班次关键字
    private static final String holidayLeaveKeyword = "休";//休假,调休假班次关键字
    private static final String officialTripKeyword = "公";//公差班次关键字
    private static final String personalLeaveKeyword = "事";//事假班次关键字
    private static final String sickLeaveKeyword = "病";//病假班次关键字
    private static final String annualLeaveKeyword = "年";//年假班次关键字
    private static final String marriageLeaveKeyword = "婚";//婚假班次关键字
    private static final String maternityLeaveKeyword = "产";//产假班次关键字
    private static final String bereavementLeaveKeyword = "丧";//丧假班次关键字
    private static final List<String> shiftSoreList = Arrays.asList("早","中","夜","休","公","事","病","年","婚","产","丧");
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void performanceShiftAdd(PerformanceShiftAddDto performanceShiftAddDto) {
        List<PerformanceShift> list = new ArrayList<>();
        LocalDateTime startWeek = performanceShiftAddDto.getStartWeek();
        LocalDateTime endWeek = performanceShiftAddDto.getEndWeek();
        String formattedDateTime = performanceShiftAddDto.getStartWeek().format(yyyyMMdd);
        String[] splitUserId = performanceShiftAddDto.getUserId().split(",");
        for (String userId : splitUserId) {
            //判断是否跨月
            boolean isMonth = startWeek.getMonthValue() != endWeek.getMonthValue();
            if (isMonth){
                //如果跨月,则两个月都判断一下看数据库是哪个月份的数据没有
                boolean exists1 = baseMapper.exists(Wrappers.<PerformanceShift>lambdaQuery()
                        .eq(PerformanceShift::getWorkTime, startWeek)
                        .eq(PerformanceShift::getUserId, userId));
                boolean exists2 = baseMapper.exists(Wrappers.<PerformanceShift>lambdaQuery()
                        .eq(PerformanceShift::getWorkTime, endWeek)
                        .eq(PerformanceShift::getUserId, userId));
                if (!exists1 && !exists2){
                    //两个月都不存在数据
                    list = saveMonth(performanceShiftAddDto.getStartWeek(), userId, list);
                    list = saveMonth(performanceShiftAddDto.getEndWeek(), userId, list);
                }else if (!exists1 && exists2){
                    //开始的月份不存在数据
                    list = saveMonth(performanceShiftAddDto.getStartWeek(), userId, list);
                }else if (exists1 && !exists2){
                    //结束的月份不存在数据
                    list = saveMonth(performanceShiftAddDto.getEndWeek(), userId, list);
        //1.查询所选周次时间范围内已排班的数据
        List<PerformanceShift> shiftList = baseMapper.selectList(Wrappers.<PerformanceShift>lambdaQuery()
                .between(ObjectUtils.allNotNull(performanceShiftAddDto.getStartTime(), performanceShiftAddDto.getEndTime()),
                        PerformanceShift::getWorkTime, performanceShiftAddDto.getStartTime(), performanceShiftAddDto.getEndTime())
                .in(!performanceShiftAddDto.getUserIdList().isEmpty(), PerformanceShift::getUserId, performanceShiftAddDto.getUserIdList())
        );
        List<LocalDateTime> timeList = getLocalDateTimesBetween(performanceShiftAddDto.getStartTime(), performanceShiftAddDto.getEndTime());
        //处理选中人员
        List<PerformanceShift> newShiftList = new ArrayList<>();
        performanceShiftAddDto.getUserIdList().forEach(userId->{
            List<PerformanceShift> oldShifts = shiftList.stream().filter(f -> Objects.equals(f.getUserId(), userId)).collect(Collectors.toList());
            timeList.forEach(time->{
                PerformanceShift performanceShift = oldShifts.stream().filter(f -> f.getWorkTime().isEqual(time)).findFirst().orElse(new PerformanceShift(userId, time));
                if(Objects.isNull(performanceShift.getId())||StringUtils.isBlank(performanceShift.getShift())){
                    performanceShift.setShift(performanceShiftAddDto.getShift());
                    newShiftList.add(performanceShift);
                }
            }else {
                //不跨月
                boolean exists = baseMapper.exists(Wrappers.<PerformanceShift>lambdaQuery()
                        .in(PerformanceShift::getWorkTime, formattedDateTime)
                        .eq(PerformanceShift::getUserId, userId));
                // 如果不存在添加数据
                if (!exists) {
                    list = saveMonth(performanceShiftAddDto.getEndWeek(), userId, list);
                }
            });
            if(newShiftList.size()>LIST_MAX_COUNT){
                this.saveBatch(newShiftList);
                newShiftList.clear();
            }
        }
        if (!list.isEmpty()) {
            baseMapper.insertBatchSomeColumn(list);
            list.clear();
        }
        // 再次更新
        List<LocalDateTime> datesBetween = getLocalDateTimesBetween(performanceShiftAddDto.getStartWeek(), performanceShiftAddDto.getEndWeek());
        for (LocalDateTime date : datesBetween) {
            for (String s : splitUserId) {
                PerformanceShift performanceShift = new PerformanceShift();
                performanceShift.setShift(performanceShiftAddDto.getShift());
                performanceShift.setUserId(Integer.valueOf(s));
                performanceShift.setWorkTime(date);
                String formatterDateTime = date.format(yyyyMMdd);
                baseMapper.update(new PerformanceShift(), Wrappers.<PerformanceShift>lambdaUpdate()
                        .set(PerformanceShift::getShift, performanceShiftAddDto.getShift())
                        .eq(PerformanceShift::getUserId, s)
                        .eq(PerformanceShift::getWorkTime, formatterDateTime));
            }
        }
        });
        if(!newShiftList.isEmpty())this.saveOrUpdateBatch(newShiftList);
    }
    private List<PerformanceShift> saveMonth (LocalDateTime week,String userId,List<PerformanceShift> list){
@@ -139,21 +145,9 @@
    @Override
    public Map<String, Object> performanceShift( String time, String userName, String laboratory) {
        //查询当前登录人员的架构
        Integer userId = SecurityUtils.getUserId().intValue();
        //判断全部,个人,组织的权限
        User user = userMapper.selectById(userId);//当前登录的人
        //获取当前人所属实验室id
        String departLimsId = user.getDepartLimsId();
        if (com.baomidou.mybatisplus.core.toolkit.ObjectUtils.isNotEmpty(departLimsId) && !departLimsId.isEmpty()) {
            String[] split = departLimsId.split(",");
            //查询对应架构名称(通信实验室,电力实验室,检测办)
            String departLims = baseMapper.seldepLimsId(Integer.parseInt(split[split.length - 1]));
            if (departLims.contains("实验室")) {
                laboratory = departLims;
            }
        }
//        List<SysDictData> shiftType = dictTypeService.selectDictDataByName("班次类型");
        //查询人员架构
        List<User> userList = userMapper.selectUserListByPerformance(false);
        List<Integer> userIdList = userList.stream().map(User::getId).collect(Collectors.toList());
        //班次时间范围为上个月的26号到本月的25号
        LocalDateTime localDateTime = LocalDateTime.parse(time, yyyyMMddHHmmss);
        LocalDate firstDayOfMonth = localDateTime.toLocalDate().minusMonths(1L).withDayOfMonth(26);
@@ -162,69 +156,84 @@
        List<PerformanceShiftMapDto> mapIPage = baseMapper.performanceShift(firstDayOfMonth,lastDayOfMonth, userName, laboratory);
        Map<Integer, List<PerformanceShiftMapDto>> groupByUserId = mapIPage.stream().collect(Collectors.groupingBy(PerformanceShiftMapDto::getUserId));
        List<PerformanceShiftMapDto> newRecords = new ArrayList<>();
        List<LocalDateTime> timeList = getLocalDateTimesBetween(LocalDateTime.of(firstDayOfMonth, LocalTime.MIN), LocalDateTime.of(lastDayOfMonth, LocalTime.MIN));
        groupByUserId.keySet().forEach(key->{
            PerformanceShiftMapDto shiftMapDto = new PerformanceShiftMapDto();
            List<PerformanceShiftMapDto> shiftMapDtos = groupByUserId.get(key);
            List<PerformanceShiftMapDto> newShiftMapDtos = new ArrayList<>();
            timeList.forEach(t->{
                PerformanceShiftMapDto mapDto = shiftMapDtos.stream().filter(s -> t.isEqual(s.getWorkTime())).findFirst().orElse(null);
                if(ObjectUtils.isNotEmpty(mapDto)){
                    newShiftMapDtos.add(mapDto);
                }else{
                    newShiftMapDtos.add(null);
                }
            });
            //统计各班次天数
            countShift(shiftMapDto.getMonthlyAttendance(),shiftMapDtos);
            shiftMapDto.setList(shiftMapDtos);
            Map<String, Long> countShift = countShift(shiftMapDtos);
            shiftMapDto.setMonthlyAttendance(countShift);
            shiftMapDto.setMonthlyAttendanceStr(formateMap(countShift));
            shiftMapDto.setList(newShiftMapDtos);
            shiftMapDto.setUserName(shiftMapDtos.isEmpty()?"":shiftMapDtos.get(0).getUserName());
            shiftMapDto.setUserId(key);
            newRecords.add(shiftMapDto);
        });
        newRecords.sort(Comparator.comparing(r->userIdList.indexOf(r.getUserId())));
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("page", newRecords);
        resultMap.put("headerList", getYearHeaderTimeList(firstDayOfMonth,lastDayOfMonth));
        return resultMap;
    }
    /**
     * 统计班次
     * @param targetMap  结果对象
     * @param shiftMapDtos 班次列表
     */
    private void countShift(Map<String,Object> targetMap,List<PerformanceShiftMapDto> shiftMapDtos){
        //汇总早班、中班、夜班、休息、请假、出差的天数,以及总出勤天数
        Map<String, List<PerformanceShiftMapDto>> groupByShift = shiftMapDtos.stream().collect(Collectors.groupingBy(PerformanceShift::getShift));
        AtomicInteger morningShift = new AtomicInteger(0);//早班
        AtomicInteger swingShift = new AtomicInteger(0);//中班
        AtomicInteger nightShift = new AtomicInteger(0);//晚班
        AtomicInteger holidayShift = new AtomicInteger(0);//休
        AtomicInteger leaveShift = new AtomicInteger(0);//请假
        groupByShift.keySet().forEach(shiftKey->{
            switch (shiftKey){
                case "0"://早12
                case "2"://早班8
                case "6"://早10
                    morningShift.addAndGet(groupByShift.get(shiftKey).size());
                    break;
                case "3"://中班8
                    swingShift.addAndGet(groupByShift.get(shiftKey).size());
                    break;
                case "1"://夜12
                case "4"://夜班8
                    nightShift.addAndGet(groupByShift.get(shiftKey).size());
                    break;
                case "5"://休
                    holidayShift.addAndGet(groupByShift.get(shiftKey).size());
                    break;
                case "7"://事
                case "8"://病
                case "9"://年
                case "10"://婚
                case "11"://调休
                case "12"://产
                case "13"://丧
                    leaveShift.addAndGet(groupByShift.get(shiftKey).size());
                    break;
    public String formateMap(Map<String, Long> map){
        List<String> stringList = new ArrayList<>();
        map.forEach((k,v)->{
            if(shiftSoreList.contains(k)){
                stringList.add(k+":"+v);
            }
        });
        targetMap.put("morningShift",morningShift.get());
        targetMap.put("swingShift",swingShift.get());
        targetMap.put("nightShift",nightShift.get());
        targetMap.put("holidayShift",holidayShift.get());
        targetMap.put("leaveShift",leaveShift.get());
        return String.join(",",stringList);
    }
    /**
     * 统计班次
     * @param shiftMapDtos 班次列表
     */
    private Map<String,Long> countShift(List<PerformanceShiftMapDto> shiftMapDtos){
        TreeMap<String, Long> targetMap = new TreeMap<>(Comparator.comparing(shiftSoreList::indexOf));
        //汇总早班、中班、夜班、休息、请假、出差的天数,以及总出勤天数
        Map<String, Long> groupByShiftName = shiftMapDtos.stream().filter(f-> StringUtils.isNotBlank(f.getShiftName())).collect(Collectors.groupingBy(PerformanceShiftMapDto::getShiftName,Collectors.counting()));
        AtomicLong morningShiftCount = new AtomicLong(0);//早班
        AtomicLong dayShiftCount = new AtomicLong(0);//中班
        AtomicLong nightShiftCount = new AtomicLong(0);//晚班
        AtomicLong holidayShiftCount = new AtomicLong(0);//休
        AtomicLong totalCount = new AtomicLong(0);//总出勤天数
        groupByShiftName.keySet().forEach(key->{
            if(key.contains(morningShiftKeyword)){
                morningShiftCount.getAndAdd(groupByShiftName.get(key));
                totalCount.getAndAdd(groupByShiftName.get(key));
            }else if(key.contains(dayShiftKeyword)){
                dayShiftCount.getAndAdd(groupByShiftName.get(key));
                totalCount.getAndAdd(groupByShiftName.get(key));
            }else if(key.contains(nightShiftKeyword)){
                nightShiftCount.getAndAdd(groupByShiftName.get(key));
                totalCount.getAndAdd(groupByShiftName.get(key));
            }else if(key.contains(holidayLeaveKeyword)){
                holidayShiftCount.getAndAdd(groupByShiftName.get(key));
            }else if(key.contains(officialTripKeyword)){
                targetMap.put(key,groupByShiftName.get(key));
                totalCount.getAndAdd(groupByShiftName.get(key));
            }else{
                targetMap.put(key,groupByShiftName.get(key));
            }
        });
        targetMap.put("早",morningShiftCount.get());
        targetMap.put("中",dayShiftCount.get());
        targetMap.put("夜",nightShiftCount.get());
        targetMap.put("休",holidayShiftCount.get());
        targetMap.put("totalCount",totalCount.get());
        return targetMap;
    }
    /**
@@ -254,23 +263,16 @@
    }
    @Override
    public List<Map<String, Object>> performanceShiftPageYear(String time, String userName, String laboratory) {
        //查询当前登录人员的架构
        Integer userId = SecurityUtils.getUserId().intValue();
        //判断全部,个人,组织的权限
        User user = userMapper.selectById(userId);//当前登录的人
        //获取当前人所属实验室id
        String departLimsId = user.getDepartLimsId();
        if (StringUtils.isNotEmpty(departLimsId) && !departLimsId.equals("")) {
            String[] split = departLimsId.split(",");
            //查询对应架构名称(通信实验室,电力实验室,检测办)
            String departLims = baseMapper.seldepLimsId(Integer.parseInt(split[split.length - 1]));
            if (departLims.contains("实验室")) {
                laboratory = departLims;
            }
    public List<Map<String, Object>> performanceShiftPageYear(LocalDateTime time, String userName, String laboratory) {
        //查询人员架构
        List<User> userList = userMapper.selectUserListByPerformance(false);
        List<Integer> userIdList = userList.stream().map(User::getId).collect(Collectors.toList());
        if(ObjectUtil.isEmpty(time)){
            throw new RuntimeException("查询日期不能为空");
        }
//        List<SysDictData> shiftType = dictTypeService.selectDictDataByName("班次类型");
        List<PerformanceShiftMapDto> shiftYearList = baseMapper.performanceShiftYear(time, userName, laboratory);
        LocalDateTime startDateTime = time.minusMonths(1L).withDayOfMonth(26);
        LocalDateTime endDateTime = time.plusMonths(11L).withDayOfMonth(25);
        List<PerformanceShiftMapDto> shiftYearList = baseMapper.performanceShiftYear(startDateTime,endDateTime, userName, laboratory);
        //按人员分组,统计每个人的年度班次
        Map<Integer, List<PerformanceShiftMapDto>> groupByUserId = shiftYearList.stream().collect(Collectors.groupingBy(PerformanceShift::getUserId));
        List<Map<String,Object>> returnList = new ArrayList<>();
@@ -278,195 +280,287 @@
            //按月份分组,统计每个月的班次详情
            Map<String, Object> returnMap = new HashMap<>();
            List<PerformanceShiftMapDto> shiftMapDtos = groupByUserId.get(userIdKey);
            Map<String, Object> sidebarAnnualAttendance = new HashMap<>();
            countShift(sidebarAnnualAttendance,shiftMapDtos);//年度班次统计
            List<Map<String,Object>> monthlyAttendance = new ArrayList<>();
            Map<String, Long> sidebarAnnualAttendance = countShift(shiftMapDtos);//年度班次统计
            List<Map<String, Object>> monthlyAttendances = new ArrayList<>();
            if(!shiftMapDtos.isEmpty()){
                returnMap.put("userName",shiftMapDtos.get(0).getUserName());
                returnMap.put("userId",shiftMapDtos.get(0).getUserId());
                Map<Integer, List<PerformanceShiftMapDto>> groupByMonthNum = shiftMapDtos.stream().collect(Collectors.groupingBy(PerformanceShiftMapDto::getMonthNum));
                //遍历12个月的班次信息
                for (int i = 1; i <= 12; i++) {
                    List<PerformanceShiftMapDto> monthShiftDtos = groupByMonthNum.get(i);
                for (int i = 0; i < 11; i++) {
                    LocalDateTime firstDayOfMonth = startDateTime.plusMonths(i);
                    LocalDateTime lastDayOfMonth = firstDayOfMonth.plusMonths(1L).withDayOfMonth(25);
                    Map<String, Object> monthlyAttendanceMap = new HashMap<>();
                    List<PerformanceShiftMapDto> monthShiftDtos = shiftMapDtos.stream().filter(f->!f.getWorkTime().isBefore(firstDayOfMonth)&&!f.getWorkTime().isAfter(lastDayOfMonth)).collect(Collectors.toList());
                    if(CollectionUtils.isEmpty(monthShiftDtos)){
                        countShift(monthlyAttendanceMap,new ArrayList<>());//月度班次统计
                        monthlyAttendanceMap.put("monthlyAttendanceStr",formateMap(countShift(new ArrayList<>())));//月度班次统计
                        monthlyAttendanceMap.put("monthlyAttendance",countShift(new ArrayList<>()));//月度班次统计
                    }else{
                        countShift(monthlyAttendanceMap,monthShiftDtos);//月度班次统计
                        monthlyAttendanceMap.put("monthlyAttendanceStr",formateMap(countShift(monthShiftDtos)));//月度班次统计
                        monthlyAttendanceMap.put("monthlyAttendance",countShift(monthShiftDtos));//月度班次统计
                    }
                    monthlyAttendance.add(monthlyAttendanceMap);
                    monthlyAttendances.add(monthlyAttendanceMap);
                }
                returnMap.put("monthlyAttendance",monthlyAttendance);
                returnMap.put("monthlyAttendances",monthlyAttendances);
                returnMap.put("sidebarAnnualAttendance",sidebarAnnualAttendance);
                returnMap.put("sidebarAnnualAttendanceStr",formateMap(sidebarAnnualAttendance));
            }
            returnList.add(returnMap);
        });
        returnList.sort(Comparator.comparing(r->userIdList.indexOf(Integer.parseInt(r.get("userId").toString()))));
        return returnList;
    }
    // 年分页与导出共同使用
    public List<Map<String, Object>> annualAttendanceProcessing(List<Map<String, Object>> mapYearList, List<SysDictData> shiftType) {
        for (Map<String, Object> map : mapYearList) {
            Map<String, Object> resultMap = new LinkedHashMap<>();
            Map<String, Object> hashMapYear = new LinkedHashMap<>();
            double totalYearAttendance = 0;
            // 一年12个月
            for (int i = 1; i < 13; i++) {
                Map<String, Object> hashMapMonth = new LinkedHashMap<>();
                double totalMonthAttendance = 0;
                for (SysDictData shift : shiftType) {
                    // 初始化赋值
                    if (!hashMapYear.containsKey(shift.getDictLabel())) {
                        hashMapYear.put(shift.getDictLabel(), 0);
                    }
                    // 月
                    if (!ObjectUtils.isEmpty(map.get("month_str"))) {
                        String charArray = map.get("month_str").toString();
                        int count = countOccurrences(charArray, i + ":" + shift.getDictValue());
                        hashMapMonth.put(shift.getDictLabel(), count);
                        hashMapYear.put(shift.getDictLabel(), new BigDecimal(hashMapYear.get(shift.getDictLabel()).toString()).add(new BigDecimal(count)));
                        // 早,中,夜,差
                        if (shift.getDictValue().equals("0") || shift.getDictValue().equals("1") || shift.getDictValue().equals("2") || shift.getDictValue().equals("6")) {
                            totalMonthAttendance += count;
                            totalYearAttendance += count;
                        }
//                      半,另外半天算给早
                        if (shift.getDictValue().equals("5")) {
                            BigDecimal multiply = new BigDecimal("0.5").multiply(new BigDecimal(count)).setScale(1, BigDecimal.ROUND_CEILING);
                            hashMapMonth.put(shiftType.get(0).getDictLabel(), new BigDecimal(hashMapMonth.get(shiftType.get(0).getDictLabel()).toString()).add(multiply));
                            hashMapYear.put(shiftType.get(0).getDictLabel(), new BigDecimal(hashMapYear.get(shiftType.get(0).getDictLabel()).toString()).add(multiply));
                            totalMonthAttendance += multiply.doubleValue();
                            totalYearAttendance += multiply.doubleValue();
                        }
                    }
                    // 空数据
                    else {
                        map.put("work_time", i);
                        hashMapMonth.put(shift.getDictLabel(), 0);
                    }
                }
                hashMapMonth.put("totalMonthAttendance", totalMonthAttendance);
                hashMapYear.put("totalYearAttendance", totalYearAttendance);
                resultMap.put(i + "", hashMapMonth);
            }
            map.remove("month_str");
            map.remove("year_str");
            map.put("year", hashMapYear);
            map.put("month", resultMap);
        }
        return mapYearList;
    }
    public static int countOccurrences(String str, String target) {
        int count = 0;
        int index = 0;
        while ((index = str.indexOf(target, index)) != -1) {
            count++;
            index += target.length();
        }
        return count;
    }
    public List<List<Object>> dataRequiredForProcessingIntoExcel(List<Map<String, Object>> list, List<SysDictData> enums) throws Exception {
        List<List<Object>> data = new ArrayList<>();
        for (int i = 0; i < list.size(); i++) {
            List<Object> excelRowList = new ArrayList<>();
            excelRowList.add(i + 1);
            excelRowList.add(list.get(i).get("account"));
            excelRowList.add(list.get(i).get("name"));
            Map<String, Object> year = JackSonUtil.unmarshal(JackSonUtil.marshal(list.get(i).get("year")), Map.class);
            excelRowList.add(year.get("totalYearAttendance"));
            enums.forEach(j -> {
                if (!j.getDictValue().equals("5")) {
                    excelRowList.add(year.get(j.getDictLabel()));
                }
            });
            Map<String, Map<String, Object>> month = JackSonUtil.unmarshal(JackSonUtil.marshal(list.get(i).get("month")), Map.class);
            for (int j = 1; j < 13; j++) {
                Object totalMonthAttendance = month.get(j + "").get("totalMonthAttendance");
                excelRowList.add(totalMonthAttendance);
                for (SysDictData anEnum : enums) {
                    if (!anEnum.getDictValue().equals("5")) {
                        excelRowList.add(month.get(j + "").get(anEnum.getDictLabel()));
                    }
                }
            }
            data.add(excelRowList);
        }
        return data;
    }
    @Override
    public Map<Object, Object> exportToYearExcel(String time, String userName, String laboratory) throws Exception {
        Map<Object, Object> map = new HashMap<>();
        List<SysDictData> shiftType = dictTypeService.selectDictDataByName("班次类型");
        DateTimeFormatter formatters = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        // 将字符串时间转换为 LocalDateTime 类型时间
        LocalDateTime localDateTime = LocalDateTime.parse(time, formatters);
        map.put("header", getYearHeader(localDateTime.getYear() + " 年", shiftType));
        List<Map<String, Object>> mapYearList = baseMapper.performanceShiftYearList(time, userName, laboratory);
        annualAttendanceProcessing(mapYearList, shiftType);
        List<List<Object>> lists = dataRequiredForProcessingIntoExcel(mapYearList, shiftType);
        map.put("data", lists);
        return map;
    }
    @Override
    public Map<Object, Object> exportToMonthExcel(String time, String userName, String laboratory) {
        List<SysDictData> shiftType = dictTypeService.selectDictDataByName("班次类型");
        List<PerformanceShiftMapDto> mapIPage = baseMapper.performanceShiftList(time, userName, laboratory);
        mapIPage.forEach(i -> {
            String[] shiftTimes = i.getShiftTime().split(";");
            double totalAttendance = 0;
            List<Map<String, Object>> map = new ArrayList<>();
            // 分割日期
            for (String shiftTime : shiftTimes) {
                Map<String, Object> hashMap = new HashMap<>();
                String[] shiftTimeAndShift = shiftTime.split(":");
                for (SysDictData enums : shiftType) {
                    if (!i.getMonthlyAttendance().containsKey(enums.getDictLabel())) {
                        i.getMonthlyAttendance().put(enums.getDictLabel(), 0);
                    }
                    if (enums.getDictValue().equals(shiftTimeAndShift[1])) {
                        BigDecimal bigDecimal = new BigDecimal(i.getMonthlyAttendance().get(enums.getDictLabel()).toString());
                        i.getMonthlyAttendance().put(enums.getDictLabel(), bigDecimal.add(new BigDecimal("1")));
                    }
                    // 半,另外半天算给早
                    if (shiftTimeAndShift[1].equals("5") && enums.getDictValue().equals("0")) {
                        BigDecimal bigDecimal = new BigDecimal(i.getMonthlyAttendance().get(enums.getDictLabel()).toString());
                        i.getMonthlyAttendance().put(enums.getDictLabel(), bigDecimal.add(new BigDecimal("0.5")));
                    }
                }
                // 早,中,夜,差
                if (shiftTimeAndShift[1].equals("1") || shiftTimeAndShift[1].equals("2") || shiftTimeAndShift[1].equals("0") || shiftTimeAndShift[1].equals("6")) {
                    i.getMonthlyAttendance().put("totalAttendance", totalAttendance += 1);
                }
                // 半
                if (shiftTimeAndShift[1].equals("5")) {
                    i.getMonthlyAttendance().put("totalAttendance", totalAttendance += 0.5);
                }
                hashMap.put("id", shiftTimeAndShift[3]);
                hashMap.put("shift", shiftTimeAndShift[1]);
                hashMap.put("time", shiftTimeAndShift[0]);
                hashMap.put("annotationText", shiftTimeAndShift[2]);
                map.add(hashMap);
            }
//            i.setList(map);
            i.setShiftTime(null);
        });
        Map<Object, Object> map = new HashMap<>();
        DateTimeFormatter formatters = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        // 将字符串时间转换为 LocalDateTime 类型时间
        LocalDateTime localDateTime = LocalDateTime.parse(time, formatters);
        map.put("header", getMonthHeader(localDateTime, shiftType));
        List<List<Object>> lists = dataRequiredForProcessingIntoExcelMonth(mapIPage, shiftType);
        map.put("data", lists);
        return map;
    }
    @Override
    public boolean editAnnotationText(PerformanceShift performanceShift) {
        return this.updateById(performanceShift);
    }
    @Override
    public void exportToExcel(LocalDateTime time, String userName, String laboratory, Boolean isMonth, HttpServletResponse response) {
        response.reset();
        try{
            String fileName = "中天耐丝质量部班次信息"+ ExcelTypeEnum.XLSX;
            fileName =  URLEncoder.encode(fileName, StandardCharsets.UTF_8.toString());
            response.setContentType("application/vnd.ms-excel");
            response.setHeader("Cache-Control", "no-cache");
            response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
            response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
            Map<Object, Object> data;
            LocalDateTime startDate;
            LocalDateTime endDate;
            if(!isMonth){
                //年度统计,时间区间取一整年
                startDate = time.minusMonths(1L).withDayOfMonth(26);
                endDate = time.plusMonths(11L).withDayOfMonth(25);
            }else{
                //月度统计,时间区间取上个月26号到本月25号
                startDate = time.minusMonths(1L).withDayOfMonth(26);
                endDate = time.withDayOfMonth(25);
            }
            List<LocalDate> performanceShiftDateList = buildPerformanceShiftDateList(startDate,endDate,isMonth);
            //批注信息坐标信息
            List<PerformanceShiftAnnotationTextExcelData> annotationTextList = new ArrayList<>();
            // 查询班次
            List<PerformanceShiftMapDto> performanceShifts = baseMapper.selectListByWorkTime(startDate, endDate, userName);
            //获取考勤数据
            StaffAttendanceDTO staffAttendanceDTO = new StaffAttendanceDTO();
            staffAttendanceDTO.setStartDate(startDate);
            staffAttendanceDTO.setEndDate(endDate);
            staffAttendanceDTO.setKeyword(userName);
            List<StaffAttendanceVO> attendanceRecords = trackingRecordService.getAttendanceRecord(performanceShifts,staffAttendanceDTO);
            //组装导出数据
            List<PerformanceShiftExcelData> excelData = new ArrayList<>();
            Map<Integer, List<PerformanceShiftMapDto>> groupByUserId = performanceShifts.stream().collect(Collectors.groupingBy(PerformanceShiftMapDto::getUserId));
            List<Integer> userIdKeys = groupByUserId.keySet().stream().sorted().collect(Collectors.toList());
            for (int i = 0; i < userIdKeys.size(); i++) {
                List<PerformanceShiftMapDto> shiftMapDtos = groupByUserId.get(userIdKeys.get(i));
                PerformanceShiftExcelData performanceShiftExcelData = new PerformanceShiftExcelData();
                List<String> shiftList = new ArrayList<>();
                performanceShiftExcelData.setPersonName(shiftMapDtos.get(0).getUserName());
                performanceShiftExcelData.setExcelIndex(i+1);
                AtomicInteger morningShiftCount = new AtomicInteger(0);//早班天数
                AtomicInteger dayShiftCount = new AtomicInteger(0);//中班天数
                AtomicInteger nightShiftCount = new AtomicInteger(0);//夜班天数
                AtomicInteger holidayCount = new AtomicInteger(0);//休息天数
                AtomicInteger personalLeaveCount = new AtomicInteger(0);//事假天数
                AtomicInteger annualLeaveCount = new AtomicInteger(0);//年假天数
                AtomicInteger officialTripCount = new AtomicInteger(0);//公差天数
                AtomicInteger marriageLeaveCount = new AtomicInteger(0);//婚假天数
                AtomicInteger bereavementLeaveCount = new AtomicInteger(0);//丧假天数
                AtomicInteger sickLeaveCount = new AtomicInteger(0);//病假天数
                AtomicInteger maternityLeaveCount = new AtomicInteger(0);//产假天数
                AtomicInteger totalCount = new AtomicInteger(0);//出勤天数
                AtomicDouble attendanceWorkHourCount = new AtomicDouble(0D);//出勤总时间
                for (int j = 0; j < shiftMapDtos.size(); j++) {
                    PerformanceShiftMapDto shiftMapDto = shiftMapDtos.get(j);
                    //统计各班次的天数
                    if(StringUtils.contains(shiftMapDto.getShiftName(),morningShiftKeyword)){
                        morningShiftCount.getAndIncrement();
                        totalCount.getAndIncrement();
                    }else if(StringUtils.contains(shiftMapDto.getShiftName(),dayShiftKeyword)){
                        dayShiftCount.getAndIncrement();
                        totalCount.getAndIncrement();
                    }else if(StringUtils.contains(shiftMapDto.getShiftName(),nightShiftKeyword)){
                        nightShiftCount.getAndIncrement();
                        totalCount.getAndIncrement();
                    }else if(StringUtils.contains(shiftMapDto.getShiftName(),holidayLeaveKeyword)){
                        holidayCount.getAndIncrement();
                    }else if(StringUtils.contains(shiftMapDto.getShiftName(),personalLeaveKeyword)){
                        personalLeaveCount.getAndIncrement();
                    }else if(StringUtils.contains(shiftMapDto.getShiftName(),annualLeaveKeyword)){
                        annualLeaveCount.getAndIncrement();
                    }else if(StringUtils.contains(shiftMapDto.getShiftName(),officialTripKeyword)){
                        officialTripCount.getAndIncrement();
                        totalCount.getAndIncrement();
                    }else if(StringUtils.contains(shiftMapDto.getShiftName(),marriageLeaveKeyword)){
                        marriageLeaveCount.getAndIncrement();
                    }else if(StringUtils.contains(shiftMapDto.getShiftName(),bereavementLeaveKeyword)){
                        bereavementLeaveCount.getAndIncrement();
                    }else if(StringUtils.contains(shiftMapDto.getShiftName(),sickLeaveKeyword)){
                        sickLeaveCount.getAndIncrement();
                    }else if(StringUtils.contains(shiftMapDto.getShiftName(),maternityLeaveKeyword)){
                        maternityLeaveCount.getAndIncrement();
                    }
                    shiftList.add(shiftMapDto.getShiftName());
                    if(!StringUtils.isAllBlank(shiftMapDto.getStartTime(),shiftMapDto.getEndTime())){
                        //过滤当前人员的班次信息
                        StaffAttendanceVO vo = attendanceRecords.stream().filter(f-> StringUtils.isNotBlank(f.getPersonCode())).filter(f -> StringUtils.equals(f.getPersonCode(), shiftMapDto.getPersonCode()) && f.getSwingDate().isEqual(shiftMapDto.getWorkTime())).findFirst().orElse(null);
                        if(ObjectUtils.isNotEmpty(vo)){
                            String actualWorkHours = Objects.toString(vo.getActualWorkHours(), "");
                            if (StringUtils.isNotBlank(actualWorkHours)) {
                                attendanceWorkHourCount.getAndAdd(Double.parseDouble(actualWorkHours));
                            }
                        }
                    }
                    //月度统计才插入批注数据
                    if(isMonth){
                        if(StringUtils.isNotBlank(shiftMapDto.getAnnotationText())){
                            annotationTextList.add(new PerformanceShiftAnnotationTextExcelData(i,j,shiftMapDto.getAnnotationText()));
                        }
                    }
                }
                if(isMonth){
                    performanceShiftExcelData.setShiftNameList(shiftList);
                }
                performanceShiftExcelData.setTotalCount(totalCount.get());
                //班次考勤天数
                performanceShiftExcelData.setMorningShiftCount(morningShiftCount.get());
                performanceShiftExcelData.setDayShiftCount(dayShiftCount.get());
                performanceShiftExcelData.setNightShiftCount(nightShiftCount.get());
                performanceShiftExcelData.setHolidayLeaveCount(holidayCount.get());
                performanceShiftExcelData.setPersonalLeaveCount(personalLeaveCount.get());
                performanceShiftExcelData.setAnnualLeaveCount(annualLeaveCount.get());
                performanceShiftExcelData.setOfficialTripCount(officialTripCount.get());
                performanceShiftExcelData.setMarriageLeaveCount(marriageLeaveCount.get());
                performanceShiftExcelData.setBereavementLeaveCount(bereavementLeaveCount.get());
                performanceShiftExcelData.setSickLeaveCount(sickLeaveCount.get());
                performanceShiftExcelData.setMaternityLeaveCount(maternityLeaveCount.get());
                performanceShiftExcelData.setTotalWorkHourCount(attendanceWorkHourCount.get());
                excelData.add(performanceShiftExcelData);
            }
            //导出
            InputStream resourceAsStream = buildPerformanceShiftTemplate(performanceShiftDateList,isMonth);
            try (ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).withTemplate(resourceAsStream).registerWriteHandler(new CommentWriteHandler(excelData, annotationTextList)).relativeHeadRowIndex(4).build()) {
                WriteSheet writeSheet = EasyExcel.writerSheet().build();
                excelWriter.fill(excelData, writeSheet);
                if(!isMonth){
                    String startDateStr = startDate.format(yyyMMStr);
                    String endDateStr = endDate.format(yyyMMStr);
                    Map<String, String> dateMap = new HashMap<>();
                    dateMap.put("startDate",startDateStr);
                    dateMap.put("endDate",endDateStr);
                    excelWriter.fill(dateMap, writeSheet);
                }
            }
        }catch (Exception e){
            throw new RuntimeException("班次导出异常");
        }
    }
    private InputStream buildPerformanceShiftTemplate(List<LocalDate> attendanceDateList,Boolean isMonth) throws IOException {
        String templateName = "/static/performance_shift_month_template.xlsx";
        if(!isMonth){
            templateName = "/static/performance_shift_year_template.xlsx";
        }
        try (InputStream templateStream = this.getClass().getResourceAsStream(templateName)) {
            assert templateStream != null;
            try (Workbook workbook = WorkbookFactory.create(templateStream);
                 ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
                Sheet sheet = workbook.getSheetAt(0);
                if(isMonth){
                    fillPerformanceShiftHeader(sheet, attendanceDateList);
                }
                workbook.write(outputStream);
                return new ByteArrayInputStream(outputStream.toByteArray());
            }
        } catch (Exception e) {
            throw new IOException("构建班次导出模板失败", e);
        }
    }
    private void fillPerformanceShiftHeader(Sheet sheet, List<LocalDate> attendanceDateList) {
        if (sheet == null || attendanceDateList == null || attendanceDateList.isEmpty()) {
            return;
        }
        Row titleRow = sheet.getRow(1);
        if (titleRow != null) {
            Cell titleCell = titleRow.getCell(0);
            if (titleCell != null) {
                titleCell.setCellValue(attendanceDateList.get(attendanceDateList.size() - 1).format(DateTimeFormatter.ofPattern("yyyy年M月")));
            }
        }
        Row weekRow = sheet.getRow(2);
        Row dayRow = sheet.getRow(3);
        if (weekRow == null || dayRow == null) {
            return;
        }
        final int startColumnIndex = 2;
        final int maxDateColumnCount = 31;
        for (int i = 0; i < maxDateColumnCount; i++) {
            Cell weekCell = getOrCreateCell(weekRow, startColumnIndex + i, startColumnIndex);
            Cell dayCell = getOrCreateCell(dayRow, startColumnIndex + i, startColumnIndex);
            if (i < attendanceDateList.size()) {
                LocalDate currentDate = attendanceDateList.get(i);
                weekCell.setCellValue(resolveWeekOfYear(currentDate));
                dayCell.setCellValue(currentDate.getDayOfMonth());
            } else {
                weekCell.setBlank();
                dayCell.setBlank();
            }
        }
    }
    private Cell getOrCreateCell(Row row, int cellIndex, int templateCellIndex) {
        Cell cell = row.getCell(cellIndex);
        if (cell != null) {
            return cell;
        }
        Cell templateCell = row.getCell(templateCellIndex);
        cell = row.createCell(cellIndex);
        if (templateCell != null && templateCell.getCellStyle() != null) {
            cell.setCellStyle(templateCell.getCellStyle());
        }
        return cell;
    }
    private String resolveWeekOfYear(LocalDate date) {
        switch (date.getDayOfWeek()) {
            case MONDAY:
                return "一";
            case TUESDAY:
                return "二";
            case WEDNESDAY:
                return "三";
            case THURSDAY:
                return "四";
            case FRIDAY:
                return "五";
            case SATURDAY:
                return "六";
            case SUNDAY:
                return "日";
            default:
                return "";
        }
    }
    private List<LocalDate> buildPerformanceShiftDateList(LocalDateTime startDateTime,LocalDateTime endDateTime,Boolean isMonth) {
        if (startDateTime == null || endDateTime == null) {
            throw new IllegalArgumentException("导出时间范围不能为空");
        }
        LocalDate startDate = startDateTime.toLocalDate();
        LocalDate endDate = endDateTime.toLocalDate();
        if (startDate.isAfter(endDate)) {
            throw new IllegalArgumentException("开始时间不能晚于结束时间");
        }
        List<LocalDate> attendanceDateList = new ArrayList<>();
        for (LocalDate currentDate = startDate; !currentDate.isAfter(endDate); currentDate = currentDate.plusDays(1)) {
            attendanceDateList.add(currentDate);
        }
        if (attendanceDateList.size() > 31 && isMonth) {
            throw new IllegalArgumentException("导出时间范围不能超过31天");
        }
        return attendanceDateList;
    }
    // 获取两个localDateTime的每一天
@@ -516,90 +610,5 @@
            default:
                return "未知";
        }
    }
    /**
     * 返回表头
     * <p>
     * 外层List代表行内层 List代表列  相同的列数据会被主动合并
     * 构造双列表头
     *
     * @return List<List < String>>
     */
    private static List<List<String>> getYearHeader(String year, List<SysDictData> enums) {
        List<List<String>> line = new ArrayList<>();
        line.add(Arrays.asList("考勤汇总", "序号", "序号"));
        line.add(Arrays.asList("考勤汇总", "工号", "工号"));
        line.add(Arrays.asList("考勤汇总", "姓名", "姓名"));
        line.add(Arrays.asList("出勤详情", year, "出勤"));
        // 年 header
        for (SysDictData anEnum : enums) {
            if (!anEnum.getDictValue().equals("5")) {
                line.add(Arrays.asList("考勤汇总", year, anEnum.getDictLabel()));
            }
        }
        // 月header
        for (int i = 1; i < 13; i++) {
            line.add(Arrays.asList("出勤详情", i + " 月", "出勤"));
            for (SysDictData anEnum : enums) {
                if (!anEnum.getDictValue().equals("5")) {
                    line.add(Arrays.asList("出勤详情", i + " 月", anEnum.getDictLabel()));
                }
            }
        }
        return line;
    }
    private static List<List<String>> getMonthHeader(LocalDateTime localDateTimeYear, List<SysDictData> enums) {
        String year = localDateTimeYear.getYear() + " 年人员班次";
        List<List<String>> line = new ArrayList<>();
        line.add(Arrays.asList(year, "序号", "序号", "序号"));
        line.add(Arrays.asList(year, "姓名", "姓名", "姓名"));
        line.add(Arrays.asList(year, "实验室", "实验室", "实验室"));
        line.add(Arrays.asList(year, localDateTimeYear.getYear() + "", localDateTimeYear.getYear() + "", "出勤"));
        line.add(Arrays.asList(year, localDateTimeYear.getYear() + "", localDateTimeYear.getYear() + "", enums.get(3).getDictLabel()));
        line.add(Arrays.asList(year, "年", "年", enums.get(4).getDictLabel()));
        line.add(Arrays.asList(year, localDateTimeYear.getMonthValue() + "", localDateTimeYear.getMonthValue() + "", enums.get(0).getDictLabel()));
        line.add(Arrays.asList(year, "月", "月", enums.get(1).getDictLabel()));
        line.add(Arrays.asList(year, "", "", enums.get(2).getDictLabel()));
        line.add(Arrays.asList(year, "周次", "星期", "出差"));
        LocalDate firstDayOfMonth = localDateTimeYear.toLocalDate().withDayOfMonth(1);
        LocalDate lastDayOfMonth = localDateTimeYear.toLocalDate().with(TemporalAdjusters.lastDayOfMonth());
        List<LocalDateTime> timeList = getLocalDateTimesBetween(firstDayOfMonth.atStartOfDay(), lastDayOfMonth.atStartOfDay());
        timeList.forEach(i -> {
            int dayOfYear = i.getDayOfMonth();
            Date from = Date.from(i.atZone(ZoneId.systemDefault()).toInstant());
            String weekDay = getWeekDay(i.getDayOfWeek().getValue());
            line.add(Arrays.asList(year, DateUtil.weekOfYear(DateUtil.offsetDay(from, 1)) + "", weekDay, dayOfYear + ""));
        });
        return line;
    }
    public List<List<Object>> dataRequiredForProcessingIntoExcelMonth(List<PerformanceShiftMapDto> list, List<SysDictData> enums) {
        List<List<Object>> data = new ArrayList<>();
        for (int i = 0; i < list.size(); i++) {
            List<Object> excelRowList = new ArrayList<>();
            excelRowList.add(i + 1);
            excelRowList.add(list.get(i).getUserName());
            excelRowList.add(list.get(i).getDepartment());
            excelRowList.add(list.get(i).getMonthlyAttendance().get("totalAttendance"));
            excelRowList.add(list.get(i).getMonthlyAttendance().get(enums.get(3).getDictLabel())); // 休
            excelRowList.add(list.get(i).getMonthlyAttendance().get(enums.get(4).getDictLabel())); // 假
            excelRowList.add(list.get(i).getMonthlyAttendance().get(enums.get(0).getDictLabel())); // 早
            excelRowList.add(list.get(i).getMonthlyAttendance().get(enums.get(1).getDictLabel())); // 中
            excelRowList.add(list.get(i).getMonthlyAttendance().get(enums.get(2).getDictLabel())); // 夜
            excelRowList.add(list.get(i).getMonthlyAttendance().get(enums.get(6).getDictLabel())); // 差
//            for (Map<String, Object> o : list.get(i).getList()) {
//                String enumLabel = "";
//                for (SysDictData anEnum : enums) {
//                    if (anEnum.getDictValue().equals(o.get("shift"))) {
//                        enumLabel = anEnum.getDictLabel();
//                    }
//                }
//                excelRowList.add(ObjectUtils.isEmpty(enumLabel) ? "-" : enumLabel);
//            }
            data.add(excelRowList);
        }
        return data;
    }
}