From fe97e3191aaa5f5db104541946f6ac7937e46e15 Mon Sep 17 00:00:00 2001
From: zouyu <2723363702@qq.com>
Date: 星期四, 30 四月 2026 16:10:17 +0800
Subject: [PATCH] 人员考勤统计调整&原材料下单导出检验项详情

---
 performance-server/src/main/java/com/ruoyi/performance/service/impl/PerformanceShiftServiceImpl.java |  886 ++++++++++++++++++++++++++++++----------------------------
 1 files changed, 464 insertions(+), 422 deletions(-)

diff --git a/performance-server/src/main/java/com/ruoyi/performance/service/impl/PerformanceShiftServiceImpl.java b/performance-server/src/main/java/com/ruoyi/performance/service/impl/PerformanceShiftServiceImpl.java
index 507af3f..64228e2 100644
--- a/performance-server/src/main/java/com/ruoyi/performance/service/impl/PerformanceShiftServiceImpl.java
+++ b/performance-server/src/main/java/com/ruoyi/performance/service/impl/PerformanceShiftServiceImpl.java
@@ -2,34 +2,59 @@
 
 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.ObjectUtils;
+import org.springframework.util.CollectionUtils;
 
-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;
 
 /**
  * <p>
@@ -39,81 +64,68 @@
  * @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;
 
+    private DateTimeFormatter yyyyMMdd = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+
+    private DateTimeFormatter yyyyMMddHHmmss = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+
+    private DateTimeFormatter yyyMMStr = DateTimeFormatter.ofPattern("yyyy骞碝M鏈坉d鏃�");
+
+    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();
-
-
-        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
-        String formattedDateTime = performanceShiftAddDto.getStartWeek().format(formatter);
-        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(formatter);
-                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){
+    private List<PerformanceShift> saveMonth (LocalDateTime week,String userId,List<PerformanceShift> list){
         LocalDate firstDayOfMonth = week.toLocalDate().withDayOfMonth(1);
         LocalDate lastDayOfMonth = week.toLocalDate().with(TemporalAdjusters.lastDayOfMonth());
         List<LocalDateTime> localDateTimesBetween = getLocalDateTimesBetween(firstDayOfMonth.atStartOfDay(), lastDayOfMonth.atStartOfDay());
@@ -132,114 +144,115 @@
     }
 
     @Override
-    public Map<String, Object> performanceShiftPage(Page<Object> page, 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.equals("")) {
-            String[] split = departLimsId.split(",");
-            //鏌ヨ瀵瑰簲鏋舵瀯鍚嶇О(閫氫俊瀹為獙瀹�,鐢靛姏瀹為獙瀹�,妫�娴嬪姙)
-            String departLims = baseMapper.seldepLimsId(Integer.parseInt(split[split.length - 1]));
-            if (departLims.contains("瀹為獙瀹�")) {
-                laboratory = departLims;
-            }
-        }
-        // 鑾峰彇header鏃堕棿
-        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
-        DateTimeFormatter formatters = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
-        // 灏嗗瓧绗︿覆鏃堕棿杞崲涓� LocalDateTime 绫诲瀷鏃堕棿
-        LocalDateTime localDateTime = LocalDateTime.parse(time, formatters);
+    public Map<String, Object> performanceShift( String time, String userName, String laboratory) {
+        //鏌ヨ浜哄憳鏋舵瀯
+        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);
         LocalDate lastDayOfMonth = localDateTime.toLocalDate().withDayOfMonth(25);
+        //浜哄憳鎺掔彮璇︽儏
+        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);
+                }
+            });
+            //缁熻鍚勭彮娆″ぉ鏁�
+            Map<String, Long> countShift = countShift(shiftMapDtos);
+            shiftMapDto.setMonthlyAttendance(countShift);
+            shiftMapDto.setMonthlyAttendanceStr(formateMap(countShift));
+            shiftMapDto.setList(newShiftMapDtos);
 
-        IPage<PerformanceShiftMapDto> mapIPage = baseMapper.performanceShiftPage(page, firstDayOfMonth,lastDayOfMonth, userName, laboratory);
-
-        List<SysDictData> shiftType = dictTypeService.selectDictDataByName("鐝绫诲瀷");
-        List<Map<String, Object>> mapYearIPage = baseMapper.performanceShiftYearPage(time, userName, laboratory);
-        mapIPage.getRecords().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("2") || shiftTimeAndShift[1].equals("3") || shiftTimeAndShift[1].equals("4")) {
-                    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);
-            }
-            double totalYearAttendance = 0;
-            Map<String, Object> hashMap = new HashMap<>();
-            for (Map<String, Object> record : mapYearIPage) {
-                if (record.get("user_id").toString().equals(i.getUserId())) {
-                    for (SysDictData enums : shiftType) {
-                        if (!hashMap.containsKey(enums.getDictLabel())) {
-                            hashMap.put(enums.getDictLabel(), 0);
-                        }
-                        if (enums.getDictValue().equals(record.get("shift"))) {
-                            BigDecimal num = new BigDecimal(hashMap.get(enums.getDictLabel()).toString());
-                            hashMap.put(enums.getDictLabel(), num.add(new BigDecimal("1")));
-                        }
-                        // 鍗婏紝鍙﹀鍗婂ぉ绠楃粰鏃�
-//                        if (record.get("shift").equals("5") && enums.getDictValue().equals("0")) {
-//                            BigDecimal bigDecimal = new BigDecimal(hashMap.get(enums.getDictLabel()).toString());
-//                            hashMap.put(enums.getDictLabel(), bigDecimal.add(new BigDecimal("0.5")));
-//                        }
-                    }
-                    if (record.get("shift").equals("2") || record.get("shift").equals("3") || record.get("shift").equals("4")) {
-                        hashMap.put("totalAttendance", totalYearAttendance += 1);
-                    }
-                    // 鍗�
-//                    if (record.get("shift").equals("5")) {
-//                        hashMap.put("totalAttendance", totalYearAttendance += 0.5);
-//                    }
-                }
-            }
-            i.setSidebarAnnualAttendance(hashMap);
-            i.setList(map);
-            i.setShiftTime(null);
+            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;
+    }
+
+    public String formateMap(Map<String, Long> map){
+        List<String> stringList = new ArrayList<>();
+        map.forEach((k,v)->{
+            if(shiftSoreList.contains(k)){
+                stringList.add(k+":"+v);
+            }
+        });
+        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;
+    }
+
+    /**
+     * 鐝鍒嗛〉鏌ヨ锛氳幏鍙栨湀搴︽棩鏈熻〃澶村垪琛�
+     * @param firstDayOfMonth
+     * @param lastDayOfMonth
+     * @return
+     */
+    private List<Object> getYearHeaderTimeList(LocalDate firstDayOfMonth,LocalDate lastDayOfMonth){
         List<LocalDateTime> localDateTimesBetween = getLocalDateTimesBetween(firstDayOfMonth.atStartOfDay(), lastDayOfMonth.atStartOfDay());
-        List<Object> list1 = new ArrayList<>();
+        List<Object> list = new ArrayList<>();
         for (LocalDateTime dateTime : localDateTimesBetween) {
             Map<Object, Object> hashMap = new HashMap<>();
-            DateTime parse = DateUtil.parse(dateTime.format(formatter));
+            DateTime parse = DateUtil.parse(dateTime.format(yyyyMMdd));
             hashMap.put("weekly", DateUtil.weekOfYear(DateUtil.offsetDay(parse, 1)));
-            hashMap.put("headerTime", getWeek(dateTime.format(formatters)));
-            list1.add(hashMap);
+            hashMap.put("headerTime", getWeek(dateTime.format(yyyyMMddHHmmss)));
+            list.add(hashMap);
         }
-        Map<String, Object> resultMap = new HashMap<>();
-        resultMap.put("page", mapIPage);
-        resultMap.put("headerList", list1);
-        return resultMap;
+        return list;
     }
 
     @Override
@@ -250,190 +263,304 @@
     }
 
     @Override
-    public IPage<Map<String, Object>> performanceShiftPageYear(Page<Object> page, 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.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("鏌ヨ鏃ユ湡涓嶈兘涓虹┖");
         }
-        IPage<Map<String, Object>> mapYearIPage = baseMapper.performanceShiftYear(page, time, userName, laboratory);
-        List<SysDictData> shiftType = dictTypeService.selectDictDataByName("鐝绫诲瀷");
-        mapYearIPage.setRecords(annualAttendanceProcessing(mapYearIPage.getRecords(), shiftType));
-        return mapYearIPage;
-    }
-
-    // 骞村垎椤典笌瀵煎嚭鍏卞悓浣跨敤
-    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);
+        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<>();
+        groupByUserId.keySet().forEach(userIdKey->{
+            //鎸夋湀浠藉垎缁勶紝缁熻姣忎釜鏈堢殑鐝璇︽儏
+            Map<String, Object> returnMap = new HashMap<>();
+            List<PerformanceShiftMapDto> shiftMapDtos = groupByUserId.get(userIdKey);
+            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());
+                //閬嶅巻12涓湀鐨勭彮娆′俊鎭�
+                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)){
+                        monthlyAttendanceMap.put("monthlyAttendanceStr",formateMap(countShift(new ArrayList<>())));//鏈堝害鐝缁熻
+                        monthlyAttendanceMap.put("monthlyAttendance",countShift(new ArrayList<>()));//鏈堝害鐝缁熻
+                    }else{
+                        monthlyAttendanceMap.put("monthlyAttendanceStr",formateMap(countShift(monthShiftDtos)));//鏈堝害鐝缁熻
+                        monthlyAttendanceMap.put("monthlyAttendance",countShift(monthShiftDtos));//鏈堝害鐝缁熻
                     }
-                    // 鏈�
-                    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);
-                    }
+                    monthlyAttendances.add(monthlyAttendanceMap);
                 }
-                hashMapMonth.put("totalMonthAttendance", totalMonthAttendance);
-                hashMapYear.put("totalYearAttendance", totalYearAttendance);
-                resultMap.put(i + "", hashMapMonth);
+                returnMap.put("monthlyAttendances",monthlyAttendances);
+                returnMap.put("sidebarAnnualAttendance",sidebarAnnualAttendance);
+                returnMap.put("sidebarAnnualAttendanceStr",formateMap(sidebarAnnualAttendance));
             }
-            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);
+            returnList.add(returnMap);
         });
-        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;
+        returnList.sort(Comparator.comparing(r->userIdList.indexOf(Integer.parseInt(r.get("userId").toString()))));
+        return returnList;
     }
 
     @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骞碝鏈�")));
+            }
+        }
+        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鐨勬瘡涓�澶�
@@ -483,90 +610,5 @@
             default:
                 return "鏈煡";
         }
-    }
-
-    /**
-     * 杩斿洖琛ㄥご
-     * <p>
-     * 澶栧眰List浠h〃琛屽唴灞� List浠h〃鍒�  鐩稿悓鐨勫垪鏁版嵁浼氳涓诲姩鍚堝苟
-     * 鏋勯�犲弻鍒楄〃澶�
-     *
-     * @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()));
-            }
-        }
-        // 鏈坔eader
-        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).getName());
-            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;
     }
 }

--
Gitblit v1.9.3