Procházet zdrojové kódy

工作计划导出修改

yusm před 2 dny
rodič
revize
d37e8c16a9

+ 101 - 54
fhKeeper/formulahousekeeper/management-platform-mld/src/main/java/com/management/platform/controller/TaskController.java

@@ -15,6 +15,7 @@ import com.management.platform.service.*;
 import com.management.platform.service.impl.WxCorpInfoServiceImpl;
 import com.management.platform.util.HttpRespMsg;
 import com.management.platform.util.MessageUtils;
+import com.management.platform.util.WorkDayCalculateUtils;
 import lombok.extern.slf4j.Slf4j;
 import net.sourceforge.tess4j.ITessAPI;
 import org.apache.commons.collections.CollectionUtils;
@@ -34,10 +35,13 @@ import javax.annotation.Resource;
 import javax.servlet.http.HttpServletRequest;
 import java.io.FileOutputStream;
 import java.io.IOException;
+import java.math.BigDecimal;
+import java.math.RoundingMode;
 import java.time.Duration;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.time.format.DateTimeFormatter;
+import java.time.temporal.TemporalAdjusters;
 import java.util.*;
 import java.util.stream.Collectors;
 
@@ -1687,79 +1691,122 @@ public class TaskController {
         CompanyDingding dingding = companyDingdingService.getOne(new LambdaQueryWrapper<CompanyDingding>().eq(CompanyDingding::getCompanyId, companyId));
         HttpRespMsg respMsg = listByPage(status, viewId, null, null, type, dateType, startDate, endDate, deptId, projectId, groupId, targetUserId);
         Map<String, Object> msgData = (Map<String, Object>) respMsg.getData();
-        List<Task> taskList = (List<Task>) msgData.get("records");
+        List<TaskWithAuditor> taskList = (List<TaskWithAuditor>) msgData.get("records");
         List<Integer> projectIds = taskList.stream().map(Task::getProjectId).distinct().collect(Collectors.toList());
         projectIds.add(-1);
         List<Project> projectList = projectService.list(new LambdaQueryWrapper<Project>().in(Project::getId, projectIds));
+        List<String> inchargeIdList = projectList.stream().filter(p -> p.getInchargerId() != null).distinct().map(Project::getInchargerId).collect(Collectors.toList());
+        inchargeIdList.add("-1");
+        List<User> userList = userMapper.selectList(new QueryWrapper<User>().in("id", inchargeIdList));
+        List<Integer> taskGroupIdList = taskList.stream().filter(t -> t.getGroupId() != null).distinct().map(Task::getGroupId).collect(Collectors.toList());
+        taskGroupIdList.add(-1);
+        List<TaskGroup> taskGroupList = taskGroupService.list(new QueryWrapper<TaskGroup>().in("id", taskGroupIdList));
+        if (org.apache.commons.lang3.StringUtils.isEmpty(startDate)||org.apache.commons.lang3.StringUtils.isEmpty(endDate)) {
+            LocalDate now = LocalDate.now();
+            // 本月第一天
+            LocalDate firstDayOfMonth = now.withDayOfMonth(1);
+            startDate=firstDayOfMonth.format(df);
+
+            // 本月最后一天
+            LocalDate lastDayOfMonth = now.with(TemporalAdjusters.lastDayOfMonth());
+            endDate=lastDayOfMonth.format(df);
+        }
+        int days = WorkDayCalculateUtils.getWorkDaysListInRange(startDate, endDate, 0).size();
+        TimeType allDay = timeTypeMapper.selectOne(new QueryWrapper<TimeType>().eq("company_id", companyId));
+        Float monthTime = days * allDay.getAllday();
         List<List<String>> dataList=new ArrayList<>();
         List<String> titleList=new ArrayList<>();
         titleList.add("序号");
-        titleList.add("项目名称");
-        titleList.add("任务阶段");
-        titleList.add("优先级");
-        titleList.add("计划名称");
-        titleList.add("执行人");
-        titleList.add("文件审核状态");
-        titleList.add("开始时间");
-        titleList.add("截止时间");
-        boolean anyMatch = projectList.stream().anyMatch(p -> p.getDeptId() != null && !StringUtils.isEmpty(p.getDeptId()));
-        if(anyMatch){
-            titleList.add("所属部门");
-        }
+        titleList.add("项目分类");
+        titleList.add("项目经理");
+        titleList.add("研究中心");
+        titleList.add("任务分组");
+        titleList.add("投入阶段");
+        titleList.add("工作内容");
+        titleList.add("一级审核人");
+        titleList.add("二级审核人");
+        titleList.add("计划工时(H)");
+        titleList.add("FTE(计划工时/当月计划工时基数)");
+        titleList.add("审核状态");
         dataList.add(titleList);
         int no=0;
-        for (Task task : taskList) {
+        for (TaskWithAuditor task : taskList) {
             no++;
             List<String> item=new ArrayList<>();
             item.add(no+"");
             Optional<Project> first = projectList.stream().filter(p -> p.getId().equals(task.getProjectId())).findFirst();
             if(first.isPresent()){
-                item.add(first.get().getProjectName());
-            }else {
-                item.add("");
-            }
-            item.add(task.getStagesName());
-            switch (task.getTaskLevel()){
-                case 0:item.add("一般");
-                    break;
-                case 1:item.add("重要");
-                    break;
-                case 2:item.add("紧急");
-                    break;
-            }
-            item.add(task.getName());
-            List<TaskExecutor> executorList = task.getExecutorList();
-            String executorString = executorList.stream().map(t->{
-                if(wxCorpInfo!=null&&wxCorpInfo.getSaasSyncContact()==1){
-                    return "$userName="+t.getExecutorName()+"$";
-                }else if(dingding!=null&&dingding.getContactNeedTranslate()==1){
-                    return "$userName="+t.getExecutorName()+"$";
-                }else {
-                    return t.getExecutorName();
-                }
-            }).collect(Collectors.joining(","));
-            item.add(executorString);
-            item.add(task.getFinalChargeStatusText());
-            item.add(task.getStartDate()==null?"":df.format(task.getStartDate()));
-            item.add(task.getEndDate()==null?"":df.format(task.getEndDate()));
-            if(anyMatch){
-                if(first.isPresent()){
-                    Project project = first.get();
-                    Optional<Department> department = departmentList.stream().filter(d -> d.getDepartmentId().equals(project.getDeptId())).findFirst();
-                    if(department.isPresent()){
-                        if(wxCorpInfo!=null&&wxCorpInfo.getSaasSyncContact()==1){
-                            item.add("$departmentName="+department.get().getCorpwxDeptid()+"$");
-                        }else if(dingding!=null&&dingding.getContactNeedTranslate()==1){
-                            item.add("$departmentName="+department.get().getDdDeptid()+"$");
-                        } else {
-                            item.add(department.get().getDepartmentName());
-                        }
+                Project project = first.get();
+                item.add(org.apache.commons.lang3.StringUtils.isEmpty(project.getCategoryName())?"":first.get().getCategoryName());
+                if (org.apache.commons.lang3.StringUtils.isNotEmpty(project.getInchargerId())){
+                    Optional<User> userOptional = userList.stream().filter(u -> u.getId().equals(project.getInchargerId())).findFirst();
+                    if(userOptional.isPresent()){
+                        item.add(userOptional.get().getName());
                     }else {
                         item.add("");
                     }
                 }else {
                     item.add("");
                 }
+                item.add(org.apache.commons.lang3.StringUtils.isEmpty(project.getAssociateDegreeNames())?"":first.get().getAssociateDegreeNames());
+            }else {
+                item.add("");
+                item.add("");
+                item.add("");
+            }
+
+            Optional<TaskGroup> groupOptional = taskGroupList.stream().filter(g -> task.getGroupId() != null && g.getId().equals(task.getGroupId())).findFirst();
+            if (groupOptional.isPresent()){
+                TaskGroup group = groupOptional.get();
+                item.add(group.getName());
+            }else {
+                item.add("");
+            }
+
+            item.add(task.getStagesName());
+            item.add(task.getName());
+            item.add(task.getFirstAuditorName());
+            item.add(task.getSecondAuditorName());
+            item.add(task.getPlanHours()==null?"": String.valueOf(new BigDecimal(task.getPlanHours().toString()).setScale(2,BigDecimal.ROUND_HALF_UP))==null?"": String.valueOf(new BigDecimal(task.getPlanHours().toString()).setScale(2,BigDecimal.ROUND_HALF_UP)));
+            item.add(
+                    task.getPlanHours() == null ? "" :
+                            new BigDecimal(task.getPlanHours().toString())
+                                    .divide(
+                                            BigDecimal.valueOf(monthTime),
+                                            2,                  // 保留2位小数
+                                            RoundingMode.HALF_UP // 四舍五入
+                                    )
+                                    .toString()
+            );
+
+
+            Integer taskStatus = task.getTaskStatus();
+            if (taskStatus == null) {
+                item.add("");
+            }else {
+                switch (taskStatus) {
+                    case 0:
+                        item.add("进行中");
+                        break;
+                    case 1:
+                        item.add("已完成");
+                        break;
+                    case 2:
+                        item.add("已撤销");
+                        break;
+                    case 3:
+                        item.add("待第一审核人审核");
+                        break;
+                    case 4:
+                        item.add("待第二审核人审核");
+                        break;
+                    case 5:
+                        item.add("第一审核人驳回");
+                        break;
+                    case 6:
+                        item.add("第二审核人驳回");
+                        break;
+                }
             }
             dataList.add(item);
         }

+ 8 - 0
fhKeeper/formulahousekeeper/management-platform-mld/src/main/java/com/management/platform/entity/TaskWithAuditor.java

@@ -13,4 +13,12 @@ public class TaskWithAuditor extends Task {
     private String secondAuditorId;
     @TableField(exist = false)
     private String secondAuditorName;
+    @TableField(exist = false)
+    private String  projectCategoryName;//项目分类
+    @TableField(exist = false)
+    private String  inchargerName;//项目经理
+    @TableField(exist = false)
+    private String  associateDegreeNames;//研究中心
+    @TableField(exist = false)
+    private String  taskGroupName;//任务分组
 }

+ 1 - 1
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/ReportController.java

@@ -3205,7 +3205,7 @@ public class ReportController {
     @RequestMapping("/getReportRateOfTask")
     public HttpRespMsg getReportRateOfTask(Integer projectId,String userIds,Integer type) {
         User user = userMapper.selectById(request.getHeader("TOKEN"));
-        return reportService.getReportRateOfTask(projectId,userIds,user.getCompanyId(),type);
+        return reportService.getReportRateOfTaskNew(projectId,userIds,user.getCompanyId(),type);
     }
 
 

+ 3 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/vo/ReportRateTaskVO.java

@@ -37,4 +37,7 @@ public class ReportRateTaskVO{
 
     private Integer companyId;
 
+    private String averagePercentage;
+    private String averageLeavePercentage;
+
 }

+ 1 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/ReportService.java

@@ -180,6 +180,7 @@ public interface ReportService extends IService<Report> {
     HttpRespMsg rejectAbnormalReportTime(HttpServletRequest request, String ymonth);
 
     HttpRespMsg getReportRateOfTask(Integer projectId, String userId, Integer companyId, Integer type);
+    HttpRespMsg getReportRateOfTaskNew(Integer projectId, String userId, Integer companyId, Integer type);
 
     HttpRespMsg exportReportRateOfTask(Integer projectId, String userIds, Integer companyId, Integer type);
 }

+ 316 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ReportServiceImpl.java

@@ -60,6 +60,7 @@ import java.util.concurrent.Executor;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.Function;
 import java.util.stream.Collectors;
 
 /**
@@ -10955,6 +10956,321 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
         return msg;
     }
 
+    @Override
+    public HttpRespMsg getReportRateOfTaskNew(Integer projectId, String userIds, Integer companyId, Integer type) {
+        HttpRespMsg msg = new HttpRespMsg();
+        DecimalFormat dft =  new DecimalFormat("0%");
+        List<String> collect=new ArrayList<>();
+        if (userIds!=null&&!userIds.isEmpty()){
+            String[] strings = userIds.split(",");
+            collect = Arrays.stream(strings).collect(Collectors.toList());
+        }
+        List<ReportRateTaskVO> reportRateTaskVOList= reportMapper.getReportRateOfTask(projectId, collect, type,companyId);
+
+
+        List<Department> departmentList = departmentMapper.selectList(new QueryWrapper<Department>().eq("company_id", companyId));
+        List<User> userList = userMapper.selectList(new QueryWrapper<User>().eq("company_id", companyId));
+
+        List<Integer> taskIds = reportRateTaskVOList.stream().distinct().map(r -> r.getTaskId()).collect(Collectors.toList());
+        System.out.println(taskIds.toString());
+        taskIds.add(-1);
+        List<Map<String,Object>> reportList=reportMapper.getUserReportTimelinessRateWithTask(companyId,taskIds);
+        Map<Object, List<Map<String, Object>>> listMap = reportList.stream().filter(item->!StringUtils.isEmpty(item.get("userName"))).collect(Collectors.groupingBy(rp -> rp.get("userName")));
+        //获取到公司设置的特殊节假日设置
+        List<HolidaySetting> holidaySettingList = holidaySettingService.list(new LambdaQueryWrapper<HolidaySetting>().eq(HolidaySetting::getCompanyId, companyId).isNotNull(HolidaySetting::getHolidayDate));
+        List<HolidaySetting> allUsersSetting = holidaySettingList.stream().filter(h -> h.getRangeType() == 0).collect(Collectors.toList());
+        List<HolidaySetting> targetUserOrDeptSetting = holidaySettingList.stream().filter(h -> h.getRangeType() == 1).collect(Collectors.toList());
+        TimeType timeType = timeTypeMapper.selectById(companyId);
+        Integer timeliness = timeType.getTimeliness();
+
+        for (ReportRateTaskVO rateTaskVO : reportRateTaskVOList) {
+            Optional<User> first = userList.stream().filter(u -> u.getId().equals(rateTaskVO.getUserId())).findFirst();
+            if (first.isPresent()){
+                User user = first.get();
+                rateTaskVO.setJobNumber(user.getJobNumber());
+                Optional<Department> firstDept = departmentList.stream().filter(d->d.getDepartmentId().equals(user.getDepartmentId())).findFirst();
+                if(firstDept.isPresent()){
+                    Department dept= firstDept.get();
+                    rateTaskVO.setDepartmentName(dept.getDepartmentName());
+                }
+
+                List<Map<String, Object>> mapList = listMap.get(user.getName());
+                LocalDate startDate = rateTaskVO.getStartDate();
+                LocalDate endDate = rateTaskVO.getEndDate();
+                AtomicReference<List<LocalDate>> listAtomicReference = new AtomicReference<>(getDays(startDate, endDate));
+                long days = listAtomicReference.get().size();
+                for (LocalDate localDateTime : listAtomicReference.get()) {
+                    if(mapList!=null){
+                        //在非工作日下 填报了的情况下 及时填报了就算作及时率计算的基数
+                        if(localDateTime!=null&& !WorkDayCalculateUtils.isWorkDay(localDateTime)&&!mapList.stream().anyMatch(ml->{
+                            Integer taskId=ml.get("taskId")!=null?Integer.parseInt(ml.get("taskId").toString()):null;
+                            if (taskId == null || !taskId.equals(rateTaskVO.getTaskId())) {
+                                return false;
+                            }
+                            Date date = (Date) ml.get("createDate");
+                            LocalDate createDate = date != null ? date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate() : null;
+                            return createDate.isEqual(localDateTime);
+                        })){
+                            days-=1;
+                        }
+                    }else {
+                        if(localDateTime!=null&&!WorkDayCalculateUtils.isWorkDay(localDateTime)){
+                            days-=1;
+                        }
+                    }
+                }
+                //获取请假数据
+                List<LeaveSheet> leaveSheetList = leaveSheetMapper.selectList(new LambdaQueryWrapper<LeaveSheet>()
+                        .eq(LeaveSheet::getCompanyId, companyId).le(endDate!=null,LeaveSheet::getStartDate,endDate)
+                        .ge(startDate!=null,LeaveSheet::getEndDate,startDate));
+                List<LeaveSheet> leaveSheets = leaveSheetList.stream().filter(ls -> ls.getOwnerId().equals(user.getId())
+                                &&(endDate!=null &&startDate!=null)
+                                &&((ls.getStartDate().isBefore(ChronoLocalDate.from(endDate))||ls.getStartDate().isEqual(ChronoLocalDate.from(endDate))))
+                                &&((ls.getEndDate().isAfter(ChronoLocalDate.from(startDate))||ls.getEndDate().isEqual(ChronoLocalDate.from(startDate)))))
+                        .collect(Collectors.toList());
+                long daysWithLeave =days;
+                if(leaveSheets.size()>0){
+                    for (LeaveSheet leaveSheet : leaveSheets) {
+                        AtomicReference<List<LocalDateTime>> leaveDateList = new AtomicReference<>(getDays(leaveSheet.getStartDate().atTime(LocalTime.MIN), leaveSheet.getEndDate().atTime(LocalTime.MIN)));
+                        AtomicReference<List<LocalDateTime>> list = new AtomicReference<>(getDays(leaveSheet.getStartDate().atTime(LocalTime.MIN), leaveSheet.getEndDate().atTime(LocalTime.MIN)));
+                        if(allUsersSetting.size()>0){
+                            List<LocalDateTime> holidayDateList = allUsersSetting.stream().map(h->h.getHolidayDate().atTime(LocalTime.MIN)).collect(Collectors.toList());
+                            leaveDateList.set(leaveDateList.get().stream().filter(d -> !holidayDateList.contains(d)).collect(Collectors.toList()));
+                            list.set(list.get().stream().filter(d -> !holidayDateList.contains(d)).collect(Collectors.toList()));
+                        }
+                        if(targetUserOrDeptSetting.size()>0){
+                            targetUserOrDeptSetting.forEach(t->{
+                                LocalDateTime holidayDate = t.getHolidayDate().atTime(LocalTime.MIN);
+                                if(!StringUtils.isEmpty(t.getTargetUsers())&&!t.getTargetUsers().equals("")){
+                                    String[] userSplit = t.getTargetUsers().split(",");
+                                    List<String> userAsList = Arrays.asList(userSplit);
+                                    if(userAsList.contains(user.getId())){
+                                        leaveDateList.set(leaveDateList.get().stream().filter(d -> !d.isEqual(holidayDate)).collect(Collectors.toList()));
+                                        list.set(list.get().stream().filter(d -> !d.isEqual(holidayDate)).collect(Collectors.toList()));
+                                    }
+                                }
+                                if(!StringUtils.isEmpty(t.getTargetDepts())&&!t.getTargetDepts().equals("")){
+                                    String[] deptSplit = t.getTargetDepts().split(",");
+                                    List<String> deptAsList = Arrays.asList(deptSplit);
+                                    for (String deptId : deptAsList) {
+                                        List<Integer> subDeptIds = getBranchDepartment(Integer.valueOf(deptId), departmentList);
+                                        if(deptId.equals(user.getDepartmentId())||subDeptIds.contains(user.getDepartmentId())){
+                                            leaveDateList.set(leaveDateList.get().stream().filter(d -> !d.isEqual(holidayDate)).collect(Collectors.toList()));
+                                            list.set(list.get().stream().filter(d -> !d.isEqual(holidayDate)).collect(Collectors.toList()));
+                                        }
+                                    }
+                                }
+                            });
+                        }
+                        if(list.get().size()>1){
+                            days-= list.get().size();
+                        }else {
+                            days-=1;
+                        }
+                        for (LocalDateTime localDateTime : leaveDateList.get()) {
+                            //todo: 请假区间当中有非工作日在之前被当作 不需填报 所以要加上 保证基数正确
+                            if(localDateTime!=null&&!WorkDayCalculateUtils.isWorkDay(localDateTime.toLocalDate())){
+                                days+=1;
+                                continue;
+                            }
+                            if((startDate!=null&&endDate!=null)&&localDateTime.isBefore(startDate.atStartOfDay())||localDateTime.isAfter(endDate.atStartOfDay().plusDays(1))){
+                                days++;
+                                continue;
+                            }
+                            if(mapList!=null&&mapList.stream().anyMatch(ml->{
+                                Integer taskId=ml.get("taskId")!=null?Integer.parseInt(ml.get("taskId").toString()):null;
+                                if (taskId == null || !taskId.equals(rateTaskVO.getTaskId())) {
+                                    return false;
+                                }
+                                Date date = (Date) ml.get("createDate");
+                                LocalDate createDate = date != null ? date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate() : null;
+                                return createDate.isEqual(localDateTime.toLocalDate());
+                            })){
+                                days++;
+                            }
+                        }
+                    }
+                }
+
+                int num=0;
+                if(mapList!=null){
+                    for (Map<String, Object> map : mapList) {
+                        if (map.get("createDate")!=null && map.get("createTime")!=null) {
+                            Map<String, Object> objectMap = new HashMap<>();
+                            Date date = (Date) map.get("createDate");
+                            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
+                            //去掉sql返回的毫秒值
+                            java.sql.Date createTime = (java.sql.Date) map.get("createTime");
+                            LocalDate createDate = date != null ? date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate() : null;
+                            // 针对美莱德 去除2024-02-09
+                            if (user.getCompanyId() == 876) {
+                                if (createDate.isEqual(LocalDate.parse("2024-02-09"))) {
+                                    continue;
+                                }
+                            }
+                            LocalDate createTimeDate = createTime.toLocalDate();
+                            //根据设置
+                            switch (timeliness) {
+                                case 1:
+                                    createDate = createDate.plusDays(1);
+                                    while (createDate!=null&&!WorkDayCalculateUtils.isWorkDay(createDate)) {
+                                        createDate = createDate.plusDays(1);
+                                    }
+                                    break;
+                                case 2:
+                                    Integer a = 0;
+                                    while (a != 2) {
+                                        createDate = createDate.plusDays(1);
+                                        if (createDate!=null&&WorkDayCalculateUtils.isWorkDay(createDate)) {
+                                            a++;
+                                        }
+                                    }
+                                    break;
+                            }
+                            if (createTimeDate.isBefore(createDate) || createTimeDate.isEqual(createDate)) {
+                                num++;
+                                objectMap.put(simpleDateFormat.format(date), MessageUtils.message("entry.timely") + "/" + MessageUtils.message("entry.SubTime") + createTimeDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
+                            } else {
+                                objectMap.put(simpleDateFormat.format(date), MessageUtils.message("entry.NoTimely") + "/" + MessageUtils.message("entry.SubTime") + createTimeDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
+                            }
+                        }
+
+                    }
+                    //处理漏填的情况,漏填的也算不及时
+                    boolean hasMissReport = false;
+                    for (LocalDate localDateTime : listAtomicReference.get()) {
+                        if(localDateTime!=null&&!WorkDayCalculateUtils.isWorkDay(localDateTime)){
+                            continue;
+                        }
+                        hasMissReport = true;
+                    }
+                    BigDecimal bigDecimal=new BigDecimal(num);
+                    BigDecimal bigDecimalWithLeave=new BigDecimal(num+(daysWithLeave-days));
+                    BigDecimal divide;
+                    BigDecimal divideWithLeave;
+                    if(days!=0){
+                        divide = bigDecimal.divide(BigDecimal.valueOf(days), 2, BigDecimal.ROUND_HALF_UP);
+                    }else if(days==0){
+                        divide=new BigDecimal(1);
+                        //查看当天有请假直接算100%
+                    }else if (days==0&&num!=0&&leaveSheetList.size()>0){
+                        divide=new BigDecimal(1);
+                    }else{
+                        divide=new BigDecimal(0);
+                    }
+                    if(divide.compareTo(new BigDecimal(1))==1){
+                        divide=new BigDecimal(1);
+                        log.error("填报及时率数据异常:==="+user.getName());
+                    }
+                    if(daysWithLeave!=0){
+                        divideWithLeave = bigDecimalWithLeave.divide(BigDecimal.valueOf(daysWithLeave), 2, BigDecimal.ROUND_HALF_UP);
+                    }else if(daysWithLeave==0){
+                        divideWithLeave=new BigDecimal(1);
+                        //查看当天有请假直接算100%
+                    }else if (daysWithLeave==0&&num!=0&&leaveSheetList.size()>0){
+                        divideWithLeave=new BigDecimal(1);
+                    }else{
+                        divideWithLeave=new BigDecimal(0);
+                    }
+                    if(divideWithLeave.compareTo(new BigDecimal(1))==1){
+                        divideWithLeave=new BigDecimal(1);
+                        log.error("填报及时率数据异常:==="+user.getName());
+                    }
+                    String number = dft.format(divide);
+                    String numberWithLeave = dft.format(divideWithLeave);
+                    rateTaskVO.setTimelinessRate(String.valueOf(number));
+                    rateTaskVO.setTimelinessRateWithLeave(String.valueOf(numberWithLeave));
+                }else {
+                    BigDecimal bigDecimal=new BigDecimal(num);
+                    BigDecimal bigDecimalWithLeave=new BigDecimal(num+(daysWithLeave-days));
+                    BigDecimal divide;
+                    BigDecimal divideWithLeave;
+                    if(days!=0){
+                        System.out.println("及时日=="+num+","+days);
+                        divide = bigDecimal.divide(BigDecimal.valueOf(days), 2, BigDecimal.ROUND_HALF_UP);
+                    }else if(days==0){
+                        divide=new BigDecimal(1);
+                        //查看当天有请假直接算100%
+                    }else if (days==0&&num!=0&&leaveSheetList.size()>0){
+                        divide=new BigDecimal(1);
+                    }else if(leaveSheets.size()>0){
+                        divide=new BigDecimal(1);
+                    }else{
+                        divide=new BigDecimal(0);
+                    }
+                    if(divide.compareTo(new BigDecimal(1))==1){
+                        divide=new BigDecimal(1);
+                        log.error("填报及时率数据异常:==="+user.getName());
+                    }
+                    if(daysWithLeave!=0){
+                        divideWithLeave = bigDecimalWithLeave.divide(BigDecimal.valueOf(daysWithLeave), 2, BigDecimal.ROUND_HALF_UP);
+                    }else if(daysWithLeave==0){
+                        divideWithLeave=new BigDecimal(1);
+                        //查看当天有请假直接算100%
+                    }else if (daysWithLeave==0&&num!=0&&leaveSheetList.size()>0){
+                        divideWithLeave=new BigDecimal(1);
+                    }else if(leaveSheets.size()>0){
+                        divideWithLeave=new BigDecimal(1);
+                    }else{
+                        divideWithLeave=new BigDecimal(0);
+                    }
+                    if(divideWithLeave.compareTo(new BigDecimal(1))==1){
+                        divideWithLeave=new BigDecimal(1);
+                        log.error("填报及时率数据异常:==="+user.getName());
+                    }
+                    String number = dft.format(divide);
+                    String numberWithLeave = dft.format(divideWithLeave);
+                    rateTaskVO.setTimelinessRate(String.valueOf(number));
+                    rateTaskVO.setTimelinessRateWithLeave(String.valueOf(numberWithLeave));
+                }
+            }
+        }
+
+        if (type==1) {
+            // 3. 主处理逻辑
+            Map<String, List<ReportRateTaskVO>> groupedByTaskId = reportRateTaskVOList.stream()
+                    .filter(task -> task.getUserId() != null)
+                    .collect(Collectors.groupingBy(ReportRateTaskVO::getUserId));
+
+            groupedByTaskId.forEach((userId, list) -> {
+                String avgPercentage = calculateAverage(list, ReportRateTaskVO::getTimelinessRate);
+                String avgLeavePercentage = calculateAverage(list, ReportRateTaskVO::getTimelinessRateWithLeave);
+
+                // 直接更新当前分组中的对象,避免二次遍历
+                list.forEach(task -> {
+                    task.setAveragePercentage(avgPercentage);
+                    task.setAverageLeavePercentage(avgLeavePercentage);
+                });
+            });
+            msg.setData(reportRateTaskVOList);
+        }else {
+            msg.setData(reportRateTaskVOList);
+        }
+        return msg;
+    }
+
+    // 2. 定义计算平均值方法
+    private String calculateAverage(List<ReportRateTaskVO> list, Function<ReportRateTaskVO, String> rateExtractor) {
+        double average = list.stream()
+                .map(rateExtractor)
+                .filter(rate -> rate != null && !rate.isEmpty())
+                .map(this::convertPercentage)
+                .filter(Objects::nonNull)
+                .mapToDouble(Double::doubleValue)
+                .average()
+                .orElse(0.0);
+        DecimalFormat dft =  new DecimalFormat("0%");
+        return dft.format(average);
+    }
+    // 1. 先定义百分比转换方法
+    private Double convertPercentage(String percentageStr) {
+        if (percentageStr == null || percentageStr.isEmpty()) {
+            return null;
+        }
+        String rateStr = percentageStr.replace("%", "");
+        return Double.parseDouble(rateStr) / 100.0;
+    }
+
     @Override
     public HttpRespMsg getReportRateOfTask(Integer projectId, String userIds, Integer companyId, Integer type) {
         HttpRespMsg msg = new HttpRespMsg();