yusm 2 недель назад
Родитель
Сommit
5c94d484c0

+ 408 - 41
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/UserCorpwxTimeController.java

@@ -16,6 +16,7 @@ import com.management.platform.util.*;
 import org.apache.poi.EncryptedDocumentException;
 import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
 import org.apache.poi.ss.usermodel.*;
+import org.apache.poi.xssf.streaming.SXSSFWorkbook;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.util.StringUtils;
@@ -2534,16 +2535,10 @@ public class UserCorpwxTimeController {
     }
 
 
-    @RequestMapping("/getUserFictitiousAttendanceList")
-    public HttpRespMsg getUserFictitiousAttendanceList(String month, Integer pageIndex, Integer pageSize){
+    @RequestMapping("/getUserCorpwvTimeList")
+    public HttpRespMsg getUserCorpwvTimeList(String month, Integer pageIndex, Integer pageSize){
         HttpRespMsg httpRespMsg = new HttpRespMsg();
         try {
-            if (pageIndex == null || pageIndex < 1) {
-                pageIndex = 1;
-            }
-            if (pageSize == null || pageSize < 1) {
-                pageSize = 20;
-            }
             String token = request.getHeader("TOKEN");
             User loginUser = userMapper.selectById(token);
             if (loginUser == null) {
@@ -2556,10 +2551,13 @@ public class UserCorpwxTimeController {
             LocalDate monthStart = LocalDate.parse(month + "-01", DateTimeFormatter.ofPattern("yyyy-MM-dd"));
             LocalDate monthEnd = monthStart.plusMonths(1).minusDays(1);
             int daysInMonth = monthStart.lengthOfMonth();
-            List<SysRichFunction> functionList = sysFunctionMapper.getRoleFunctions(loginUser.getRoleId(), "全部员工假勤数据");
+            List<SysRichFunction> functionList = sysFunctionMapper.getRoleFunctions(loginUser.getRoleId(), "全部员工考勤数据");
+            QueryWrapper<User> userWrapper = new QueryWrapper<User>()
+                    .eq("company_id", loginUser.getCompanyId());
             QueryWrapper<UserCorpwxTime> monthQuery = new QueryWrapper<UserCorpwxTime>()
                     .eq("company_id", loginUser.getCompanyId())
                     .between("create_date", monthStart, monthEnd);
+            monthQuery.orderByAsc("create_date", "name");
             if (functionList == null || functionList.isEmpty()) {
                 Integer manageDeptId = loginUser.getManageDeptId();
                 List<Integer> deptIds = new ArrayList<>();
@@ -2568,27 +2566,32 @@ public class UserCorpwxTimeController {
                     deptIds = departmentService.getAllManagedDeptIdList(loginUser, allDeptList);
                 }
                 if (deptIds.isEmpty()) {
-                    monthQuery.in("corpwx_userid", Collections.singletonList("__NONE__"));
+                    userWrapper.in("corpwx_userid", Collections.singletonList("__NONE__"));
                 } else {
                     List<User> deptUserList = userMapper.selectList(new QueryWrapper<User>().eq("company_id", loginUser.getCompanyId()).in("department_id", deptIds));
                     List<String> deptCorpwxUserIds = deptUserList.stream().map(User::getCorpwxUserid).filter(org.springframework.util.StringUtils::hasText).collect(Collectors.toList());
                     List<String> deptNames = deptUserList.stream().map(User::getName).filter(org.springframework.util.StringUtils::hasText).collect(Collectors.toList());
                     if (!deptCorpwxUserIds.isEmpty() && !deptNames.isEmpty()) {
-                        monthQuery.and(q -> q.in("corpwx_userid", deptCorpwxUserIds).or().in("name", deptNames));
+                        userWrapper.and(q -> q.in("corpwx_userid", deptCorpwxUserIds).or().in("name", deptNames));
                     } else if (!deptCorpwxUserIds.isEmpty()) {
-                        monthQuery.in("corpwx_userid", deptCorpwxUserIds);
+                        userWrapper.in("corpwx_userid", deptCorpwxUserIds);
                     } else if (!deptNames.isEmpty()) {
-                        monthQuery.in("name", deptNames);
+                        userWrapper.in("name", deptNames);
                     } else {
-                        monthQuery.in("corpwx_userid", Collections.singletonList("__NONE__"));
+                        userWrapper.in("corpwx_userid", Collections.singletonList("__NONE__"));
                     }
                 }
             }
-            monthQuery.orderByAsc("create_date", "name");
-            Page<UserCorpwxTime> page = new Page<>(pageIndex, pageSize);
-            IPage<UserCorpwxTime> monthPage = userCorpwxTimeMapper.selectPage(page, monthQuery);
-            List<UserCorpwxTime> monthList = monthPage.getRecords();
 
+            Page<User> userPage = new Page<>(pageIndex, pageSize);
+            IPage<User> userIPage = userMapper.selectPage(userPage, userWrapper);
+            List<User> userList = userIPage.getRecords();
+            List<String> userIds = userList.stream().map(User::getCorpwxUserid).distinct().collect(Collectors.toList());
+            if(userIds.size()>0){
+                monthQuery.in("corpwx_userid",userIds);
+            }
+            monthQuery.orderByAsc("create_date", "name");
+            List<UserCorpwxTime> monthList  = userCorpwxTimeMapper.selectList(monthQuery);
             List<LocalDate> restDayDates = WorkDayCalculateUtils.getNonWorkDaysListInRange(
                     monthStart.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")),
                     monthEnd.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"))
@@ -2596,39 +2599,404 @@ public class UserCorpwxTimeController {
             List<String> restDayList = restDayDates.stream().map(d -> d.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"))).collect(Collectors.toList());
 
             Map<String, List<UserCorpwxTime>> grouped = monthList.stream()
-                    .collect(Collectors.groupingBy(item -> item.getCorpwxUserid() != null ? item.getCorpwxUserid() : item.getName(), LinkedHashMap::new, Collectors.toList()));
+                    .collect(Collectors.groupingBy(item -> {
+                        if (item.getCorpwxUserid() != null && !item.getCorpwxUserid().isEmpty()) {
+                            return item.getCorpwxUserid();
+                        }
+                        return item.getName();
+                    }, LinkedHashMap::new, Collectors.toList()));
 
             List<Map<String, Object>> attendanceList = new ArrayList<>();
             DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+            for (User sysUser : userList) {
+                Map<String, Object> row = new HashMap<>();
+                List<UserCorpwxTime> userTimes = monthList.stream().filter(i->i.getCorpwxUserid().equals(sysUser.getCorpwxUserid())).collect(Collectors.toList());
+                row.put("userId", sysUser.getId());
+                row.put("employeeName", sysUser.getCorpwxUserid());
+                row.put("jobNumber", sysUser.getJobNumber());
+                row.put("departmentName",sysUser.getCorpwxDeptid());
+                Map<String, UserCorpwxTime> dayMap = userTimes.stream()
+                        .collect(Collectors.toMap(t -> t.getCreateDate().format(df), t -> t, (a, b) -> a));
+                List<String> attendanceArray = new ArrayList<>();
+                double legalHolidayCount = 0D;
+                double yearLeaveCount = 0D;
+                double marriageLeaveCount = 0D;
+                double paternityLeaveCount = 0D;
+                double maternityLeaveCount = 0D;
+                double bereavementLeaveCount = 0D;
+                double transferLeaveCount = 0D;
+                double sickLeaveCount = 0D;
+                double personalLeaveCount = 0D;
+                int lateCount = 0;
+                int missingCardCount = 0;
+                Set<String> nonWorkDaySet = new HashSet<>(restDayList);
+                legalHolidayCount=nonWorkDaySet.size();
+                for (int i = 1; i <= daysInMonth; i++) {
+                    LocalDate date = monthStart.withDayOfMonth(i);
+                    String dateStr = date.format(df);
+                    UserCorpwxTime time = dayMap.get(dateStr);
+                    String value = "";
+                    if (time != null) {
+                        String leaveType = StringUtils.hasText(time.getAskLeaveType()) ? time.getAskLeaveType().trim() : "";
+                        if (time.getAskLeaveTime() != null && time.getAskLeaveTime() > 0) {
+                            if ("年假".equals(leaveType)) {
+                                yearLeaveCount +=1;
+                            } else if ("婚假".equals(leaveType)) {
+                                marriageLeaveCount +=1;
+                            } else if ("陪产假".equals(leaveType)) {
+                                paternityLeaveCount +=1;
+                            } else if ("产假".equals(leaveType)) {
+                                maternityLeaveCount +=1;
+                            } else if ("丧假".equals(leaveType)) {
+                                bereavementLeaveCount +=1;
+                            } else if ("T".equals(leaveType)) {
+                                transferLeaveCount +=1;
+                            } else if ("B".equals(leaveType)) {
+                                sickLeaveCount +=1;
+                            } else if ("事假".equals(leaveType)) {
+                                personalLeaveCount +=1;
+                            }
+                            value = leaveType+time.getAskLeaveTime();
+                        } else if (time.getWorkHours() != null && time.getWorkHours() > 0) {
+                            value ="√";
+                        } else if (time.getCardTime() != null && time.getCardTime() > 0) {
+                            value = String.valueOf(time.getCardTime());
+                        }
+                        if (time.getOtStatus() != null && time.getOtStatus() == 2) {
+                            missingCardCount += 1;
+                        }
+                        if (time.getCardTime() != null && time.getCardTime() > 0 && time.getCardTime() < 1.0) {
+                            lateCount += 1;
+                        }
+                    }
+                    attendanceArray.add(value);
+                }
+                row.put("attendanceArray", attendanceArray);
+                row.put("legalHolidayCount", legalHolidayCount);
+                row.put("yearLeaveCount", yearLeaveCount);
+                row.put("marriageLeaveCount", marriageLeaveCount);
+                row.put("paternityLeaveCount", paternityLeaveCount);
+                row.put("maternityLeaveCount", maternityLeaveCount);
+                row.put("bereavementLeaveCount", bereavementLeaveCount);
+                row.put("transferLeaveCount", transferLeaveCount);
+                row.put("sickLeaveCount", sickLeaveCount);
+                row.put("personalLeaveCount", personalLeaveCount);
+                row.put("lateCount", lateCount);
+                row.put("missingCardCount", missingCardCount);
+                row.put("shouldAttendCount", daysInMonth - restDayList.size());
+                row.put("actualAttendanceCount", attendanceArray.stream().filter(s -> s != null && !s.isEmpty() && "√".equals(s)).count());
+                row.put("daysCount", daysInMonth);
+                attendanceList.add(row);
+            }
             for (Map.Entry<String, List<UserCorpwxTime>> entry : grouped.entrySet()) {
                 List<UserCorpwxTime> userTimes = entry.getValue();
                 if (userTimes.isEmpty()) {
                     continue;
                 }
-                UserCorpwxTime first = userTimes.get(0);
-                Map<String, Object> row = new HashMap<>();
-                row.put("userId", first.getCorpwxUserid());
-                row.put("employeeName", first.getName());
-                row.put("jobNumber", null);
-                User sysUser = null;
-                if (first.getCorpwxUserid() != null) {
-                    sysUser = userMapper.selectOne(new QueryWrapper<User>().eq("corpwx_userid", first.getCorpwxUserid()).eq("company_id", loginUser.getCompanyId()));
+
+            }
+
+            Map<String, Object> result = new HashMap<>();
+            List<String> dateList = new ArrayList<>();
+            List<String> weekList = new ArrayList<>();
+            for (int i = 1; i <= daysInMonth; i++) {
+                LocalDate date = monthStart.withDayOfMonth(i);
+                dateList.add(String.valueOf(i));
+                weekList.add(date.getDayOfWeek().getDisplayName(TextStyle.SHORT, Locale.CHINESE).replace("星期", ""));
+            }
+            result.put("dateList", dateList);
+            result.put("weekList", weekList);
+            result.put("restDayList", restDayList);
+            result.put("list", attendanceList);
+            result.put("records", attendanceList);
+            result.put("total", userPage.getTotal());
+            httpRespMsg.data = result;
+        } catch (Exception e) {
+            e.printStackTrace();
+            httpRespMsg.setError("获取员工考勤数据失败:" + e.getMessage());
+        }
+        return httpRespMsg;
+    }
+
+    @RequestMapping("/exportEmployeeHolidayExcel")
+    public HttpRespMsg exportEmployeeHolidayExcel(String month) throws Exception {
+        HttpRespMsg msg = new HttpRespMsg();
+        String token = request.getHeader("TOKEN");
+        User loginUser = userMapper.selectById(token);
+        if (loginUser == null) {
+            msg.setError("未获取到登录用户");
+            return msg;
+        }
+        if (month == null || month.trim().isEmpty()) {
+            month = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM"));
+        }
+        HttpRespMsg ret = getUserFictitiousAttendanceList(month, -1, -1);
+        if (ret == null || ret.data == null) {
+            msg.setError("获取员工假勤数据失败");
+            return msg;
+        }
+        HashMap map = (HashMap) ret.data;
+        List<Map<String, Object>> list = (List<Map<String, Object>>) map.get("list");
+        List<String> dateList = (List<String>) map.get("dateList");
+        List<String> weekList = (List<String>) map.get("weekList");
+        List<String> restDayList = (List<String>) map.get("restDayList");
+        String fileName = System.currentTimeMillis() + "员工假勤表_" + month;
+        WxCorpInfo wxCorpInfo = wxCorpInfoMapper.selectOne(new LambdaQueryWrapper<WxCorpInfo>().eq(WxCorpInfo::getCompanyId, loginUser.getCompanyId()));
+        CompanyDingding dingding = companyDingdingMapper.selectOne(new LambdaQueryWrapper<CompanyDingding>().eq(CompanyDingding::getCompanyId, loginUser.getCompanyId()));
+        String fileUrl = exportAttendanceWithMergedHeader(wxCorpInfo,fileName, month, dateList, weekList, restDayList, list, false);
+        if (loginUser.getCompanyId() != null) {
+            if ((wxCorpInfo != null && wxCorpInfo.getSaasSyncContact() == 1) || (dingding != null && dingding.getContactNeedTranslate() == 1)) {
+                msg.data = excelExportService.exportTranForwx(wxCorpInfo, dingding, fileName).data;
+                return msg;
+            }
+        }
+        msg.data = fileUrl;
+        return msg;
+    }
+
+    @RequestMapping("/exportEmployeeCorpTimeExcel")
+    public HttpRespMsg exportEmployeeCorpTimeExcel(String month) throws Exception {
+        HttpRespMsg msg = new HttpRespMsg();
+        String token = request.getHeader("TOKEN");
+        User loginUser = userMapper.selectById(token);
+        if (loginUser == null) {
+            msg.setError("未获取到登录用户");
+            return msg;
+        }
+        if (month == null || month.trim().isEmpty()) {
+            month = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM"));
+        }
+        HttpRespMsg ret = getUserCorpwvTimeList(month, -1, -1);
+        if (ret == null || ret.data == null) {
+            msg.setError("获取员工考勤数据失败");
+            return msg;
+        }
+        HashMap map = (HashMap) ret.data;
+        List<Map<String, Object>> list = (List<Map<String, Object>>) map.get("list");
+        List<String> dateList = (List<String>) map.get("dateList");
+        List<String> weekList = (List<String>) map.get("weekList");
+        List<String> restDayList = (List<String>) map.get("restDayList");
+        String fileName = System.currentTimeMillis() + "员工考勤表_" + month;
+        WxCorpInfo wxCorpInfo = wxCorpInfoMapper.selectOne(new LambdaQueryWrapper<WxCorpInfo>().eq(WxCorpInfo::getCompanyId, loginUser.getCompanyId()));
+        CompanyDingding dingding = companyDingdingMapper.selectOne(new LambdaQueryWrapper<CompanyDingding>().eq(CompanyDingding::getCompanyId, loginUser.getCompanyId()));
+        String fileUrl = exportAttendanceWithMergedHeader(wxCorpInfo,fileName, month, dateList, weekList, restDayList, list, true);
+        if (loginUser.getCompanyId() != null) {
+            if ((wxCorpInfo != null && wxCorpInfo.getSaasSyncContact() == 1) || (dingding != null && dingding.getContactNeedTranslate() == 1)) {
+                msg.data = excelExportService.exportTranForwx(wxCorpInfo, dingding, fileName).data;
+                return msg;
+            }
+        }
+        msg.data = fileUrl;
+        return msg;
+    }
+
+    private String exportAttendanceWithMergedHeader(WxCorpInfo wxCorpInfo,String fileName, String month, List<String> dateList, List<String> weekList, List<String> restDayList, List<Map<String, Object>> rows, boolean isCorpTime) throws Exception {
+        SXSSFWorkbook workBook = new SXSSFWorkbook();
+        Sheet sheet = workBook.createSheet();
+        sheet.setDefaultColumnWidth(14);
+        sheet.createFreezePane(0, 2);
+        Font headFont = workBook.createFont();
+        headFont.setBold(true);
+        headFont.setFontHeightInPoints((short) 10);
+        headFont.setFontName("黑体");
+        Font font = workBook.createFont();
+        font.setFontHeightInPoints((short) 10);
+        font.setFontName("宋体");
+        CellStyle headStyle = workBook.createCellStyle();
+        headStyle.setFont(headFont);
+        headStyle.setAlignment(HorizontalAlignment.CENTER);
+        headStyle.setVerticalAlignment(VerticalAlignment.CENTER);
+        headStyle.setWrapText(true);
+        headStyle.setBorderBottom(BorderStyle.THIN);
+        headStyle.setBorderLeft(BorderStyle.THIN);
+        headStyle.setBorderTop(BorderStyle.THIN);
+        headStyle.setBorderRight(BorderStyle.THIN);
+        CellStyle cellStyle = workBook.createCellStyle();
+        cellStyle.setFont(font);
+        cellStyle.setAlignment(HorizontalAlignment.CENTER);
+        cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
+        cellStyle.setWrapText(true);
+        cellStyle.setBorderBottom(BorderStyle.THIN);
+        cellStyle.setBorderLeft(BorderStyle.THIN);
+        cellStyle.setBorderTop(BorderStyle.THIN);
+        cellStyle.setBorderRight(BorderStyle.THIN);
+
+        CellStyle restDayStyle = workBook.createCellStyle();
+        restDayStyle.cloneStyleFrom(cellStyle);
+        restDayStyle.setFillForegroundColor(IndexedColors.BRIGHT_GREEN.getIndex());
+        restDayStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
+
+        Row header1 = sheet.createRow(0);
+        Row header2 = sheet.createRow(1);
+        header1.setHeightInPoints(24);
+        header2.setHeightInPoints(24);
+        String[] fixedHeaders = new String[]{"序号", "姓名", "部门"};
+        for (int i = 0; i < fixedHeaders.length; i++) {
+            Cell c1 = header1.createCell(i);
+            c1.setCellStyle(headStyle);
+            c1.setCellValue(fixedHeaders[i]);
+            Cell c2 = header2.createCell(i);
+            c2.setCellStyle(headStyle);
+            c2.setCellValue("");
+            sheet.addMergedRegion(new org.apache.poi.ss.util.CellRangeAddress(0, 1, i, i));
+        }
+        int col = 3;
+        for (int i = 0; i < dateList.size(); i++) {
+            Cell c1 = header1.createCell(col);
+            c1.setCellStyle(headStyle);
+            c1.setCellValue(dateList.get(i));
+            Cell c2 = header2.createCell(col);
+            c2.setCellStyle(headStyle);
+            c2.setCellValue(weekList != null && i < weekList.size() ? weekList.get(i) : "");
+            col++;
+        }
+        String[] tailHeaders = isCorpTime ? new String[]{"法定假/天", "年休假/天", "婚假/天", "陪产假/天", "产假/天", "丧假/天", "调休假/天", "病假/天", "事假/天", "迟到", "缺卡", "本月应出勤天数", "本月实际出勤天数"} : new String[]{"本月请假工时(h)"};
+        for (String tailHeader : tailHeaders) {
+            Cell c1 = header1.createCell(col);
+            c1.setCellStyle(headStyle);
+            c1.setCellValue(tailHeader);
+            Cell c2 = header2.createCell(col);
+            c2.setCellStyle(headStyle);
+            c2.setCellValue("");
+            sheet.addMergedRegion(new org.apache.poi.ss.util.CellRangeAddress(0, 1, col, col));
+            col++;
+        }
+
+        for (int r = 0; r < rows.size(); r++) {
+            Map<String, Object> row = rows.get(r);
+            Row dataRow = sheet.createRow(r + 2);
+            dataRow.setHeightInPoints(24);
+            int c = 0;
+            setCell(dataRow, c++, String.valueOf(r + 1), cellStyle);
+            if(wxCorpInfo != null && wxCorpInfo.getSaasSyncContact() == 1){
+                setCell(dataRow, c++, String.valueOf(row.get("employeeName") == null ? "" :("$userName="+row.get("employeeName")+"$")) , cellStyle);
+                setCell(dataRow, c++, String.valueOf(row.get("departmentName") == null ? "" : ("$departmentName="+row.get("departmentName")+"$")), cellStyle);
+            }else {
+                setCell(dataRow, c++, String.valueOf(row.get("employeeName") == null ? "" : row.get("employeeName")), cellStyle);
+                setCell(dataRow, c++, String.valueOf(row.get("departmentName") == null ? "" : row.get("departmentName")), cellStyle);
+            }
+            List<?> arr = (List<?>) row.get(isCorpTime ? "attendanceArray" : "fictitiousAttendanceArray");
+            Set<String> restDaySet = restDayList == null ? new HashSet<>() : new HashSet<>(restDayList);
+            for (int i = 0; i < dateList.size(); i++) {
+                Object v = arr != null && i < arr.size() ? arr.get(i) : "";
+                boolean isRestDay = restDaySet.contains(monthToDateString(dateList.get(i), month));
+                setCell(dataRow, c++, v == null ? "" : String.valueOf(v), isRestDay ? restDayStyle : cellStyle);
+            }
+            if (isCorpTime) {
+                String[] keys = new String[]{"legalHolidayCount", "yearLeaveCount", "marriageLeaveCount", "paternityLeaveCount", "maternityLeaveCount", "bereavementLeaveCount", "transferLeaveCount", "sickLeaveCount", "personalLeaveCount", "lateCount", "missingCardCount", "shouldAttendCount", "actualAttendanceCount"};
+                for (String key : keys) {
+                    Object v = row.get(key);
+                    setCell(dataRow, c++, v == null ? "0" : String.valueOf(v), cellStyle);
                 }
-                if (sysUser == null && first.getName() != null) {
-                    sysUser = userMapper.selectOne(new QueryWrapper<User>().eq("name", first.getName()).eq("company_id", loginUser.getCompanyId()));
+            } else {
+                Object v = row.get("holidayCount");
+                setCell(dataRow, c++, v == null ? "0" : String.valueOf(v), cellStyle);
+            }
+        }
+
+        File dir = new File(path);
+        if (!dir.exists()) {
+            dir.mkdirs();
+        }
+        FileOutputStream os = new FileOutputStream(path + fileName + ".xlsx");
+        workBook.write(os);
+        os.flush();
+        os.close();
+        workBook.dispose();
+        return "/upload/" + fileName + ".xlsx";
+    }
+
+    private void setCell(Row row, int index, String value, CellStyle style) {
+        Cell cell = row.createCell(index);
+        cell.setCellStyle(style);
+        cell.setCellValue(value == null ? "" : value);
+    }
+
+    private String monthToDateString(String dayText, String month) {
+        if (dayText == null || dayText.trim().isEmpty() || month == null || month.trim().isEmpty()) {
+            return "";
+        }
+        try {
+            int day = Integer.parseInt(dayText.trim());
+            return month + "-" + String.format("%02d", day);
+        } catch (Exception e) {
+            return "";
+        }
+    }
+
+    @RequestMapping("/getUserFictitiousAttendanceList")
+    public HttpRespMsg getUserFictitiousAttendanceList(String month, Integer pageIndex, Integer pageSize){
+        HttpRespMsg httpRespMsg = new HttpRespMsg();
+        try {
+            String token = request.getHeader("TOKEN");
+            User loginUser = userMapper.selectById(token);
+            if (loginUser == null) {
+                httpRespMsg.setError("未获取到登录用户");
+                return httpRespMsg;
+            }
+            if (month == null || month.trim().isEmpty()) {
+                month = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM"));
+            }
+            LocalDate monthStart = LocalDate.parse(month + "-01", DateTimeFormatter.ofPattern("yyyy-MM-dd"));
+            LocalDate monthEnd = monthStart.plusMonths(1).minusDays(1);
+            int daysInMonth = monthStart.lengthOfMonth();
+            List<SysRichFunction> functionList = sysFunctionMapper.getRoleFunctions(loginUser.getRoleId(), "全部员工假勤数据");
+            QueryWrapper<User> userWrapper = new QueryWrapper<User>()
+                    .eq("company_id", loginUser.getCompanyId());
+            QueryWrapper<UserCorpwxTime> monthQuery = new QueryWrapper<UserCorpwxTime>()
+                    .eq("company_id", loginUser.getCompanyId())
+                    .between("create_date", monthStart, monthEnd);
+            if (functionList == null || functionList.isEmpty()) {
+                Integer manageDeptId = loginUser.getManageDeptId();
+                List<Integer> deptIds = new ArrayList<>();
+                if (manageDeptId != null && manageDeptId != 0) {
+                    List<Department> allDeptList = departmentMapper.selectList(new QueryWrapper<Department>().eq("company_id", loginUser.getCompanyId()));
+                    deptIds = departmentService.getAllManagedDeptIdList(loginUser, allDeptList);
                 }
-                if (sysUser != null) {
-                    row.put("userId", sysUser.getId());
-                    row.put("employeeName", sysUser.getName());
-                    row.put("jobNumber", sysUser.getJobNumber());
-                    Department dept = null;
-                    if (sysUser.getDepartmentId() != null) {
-                        dept = departmentMapper.selectById(sysUser.getDepartmentId());
-                    }
-                    row.put("departmentName", dept == null ? "" : dept.getCorpwxDeptid());
+                if (deptIds.isEmpty()) {
+                    userWrapper.in("corpwx_userid", Collections.singletonList("__NONE__"));
                 } else {
-                    row.put("departmentName", "");
+                    List<User> deptUserList = userMapper.selectList(new QueryWrapper<User>().eq("company_id", loginUser.getCompanyId()).in("department_id", deptIds));
+                    List<String> deptCorpwxUserIds = deptUserList.stream().map(User::getCorpwxUserid).filter(org.springframework.util.StringUtils::hasText).collect(Collectors.toList());
+                    List<String> deptNames = deptUserList.stream().map(User::getName).filter(org.springframework.util.StringUtils::hasText).collect(Collectors.toList());
+                    if (!deptCorpwxUserIds.isEmpty() && !deptNames.isEmpty()) {
+                        userWrapper.and(q -> q.in("corpwx_userid", deptCorpwxUserIds).or().in("name", deptNames));
+                    } else if (!deptCorpwxUserIds.isEmpty()) {
+                        userWrapper.in("corpwx_userid", deptCorpwxUserIds);
+                    } else if (!deptNames.isEmpty()) {
+                        userWrapper.in("name", deptNames);
+                    } else {
+                        userWrapper.in("corpwx_userid", Collections.singletonList("__NONE__"));
+                    }
                 }
+            }
+            monthQuery.orderByAsc("create_date", "name");
+            Page<User> userPage = new Page<>(pageIndex, pageSize);
+            IPage<User> userIPage = userMapper.selectPage(userPage, userWrapper);
+            List<User> userList = userIPage.getRecords();
+            List<String> userIds = userList.stream().map(User::getCorpwxUserid).distinct().collect(Collectors.toList());
+            if(userIds.size()>0){
+                monthQuery.in("corpwx_userid",userIds);
+            }
+            List<UserCorpwxTime> monthList = userCorpwxTimeMapper.selectList(monthQuery);
+            List<LocalDate> restDayDates = WorkDayCalculateUtils.getNonWorkDaysListInRange(
+                    monthStart.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")),
+                    monthEnd.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"))
+            );
+            List<String> restDayList = restDayDates.stream().map(d -> d.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"))).collect(Collectors.toList());
+
+            Map<String, List<UserCorpwxTime>> grouped = monthList.stream()
+                    .collect(Collectors.groupingBy(item -> item.getCorpwxUserid() != null ? item.getCorpwxUserid() : item.getName(), LinkedHashMap::new, Collectors.toList()));
+
+            List<Map<String, Object>> attendanceList = new ArrayList<>();
+            DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+            for (User sysUser : userList) {
+                List<UserCorpwxTime> userTimes = monthList.stream().filter(i->i.getCorpwxUserid().equals(sysUser.getCorpwxUserid())).collect(Collectors.toList());
+                Map<String, Object> row = new HashMap<>();
+                row.put("userId", sysUser.getCorpwxUserid());
+                row.put("employeeName", sysUser.getCorpwxUserid());
+                row.put("jobNumber", sysUser.getJobNumber());
+                row.put("departmentName", sysUser.getCorpwxDeptid());
                 Map<String, UserCorpwxTime> dayMap = userTimes.stream().collect(Collectors.toMap(t -> t.getCreateDate().format(df), t -> t, (a, b) -> a));
                 List<String> attendanceArray = new ArrayList<>();
                 double holidayCount = 0;
@@ -2656,8 +3024,7 @@ public class UserCorpwxTimeController {
                 row.put("holidayCount", holidayCount);
                 attendanceList.add(row);
             }
-
-            int total = (int) monthPage.getTotal();
+            int total = (int) userPage.getTotal();
             List<Map<String, Object>> pageList = attendanceList;
 
             Map<String, Object> result = new HashMap<>();

+ 13 - 1
fhKeeper/formulahousekeeper/management-platform/src/main/resources/sql/2024-04-27.sql

@@ -13,4 +13,16 @@ CREATE TABLE `project_approval_document` (
   `is_deleted` INT DEFAULT 0 COMMENT '是否删除 0-存在 1-删除',
   `is_folder` INT DEFAULT 0 COMMENT '是否文件夹 0-文件 1-文件夹',
   PRIMARY KEY (`id`)
-) ENGINE=INNODB DEFAULT CHARSET=utf8mb4;
+) ENGINE=INNODB DEFAULT CHARSET=utf8mb4;
+
+
+
+INSERT INTO report_form VALUES (NULL,"员工假勤表");
+INSERT INTO report_form VALUES (NULL,"员工考勤表");
+INSERT INTO company_report VALUES(5792,44);
+INSERT INTO company_report VALUES(5792,45);
+INSERT INTO sys_function VALUES(NULL,"全部员工假勤数据",NULL,NULL,7,72,0,0,1,0,0,0,0,0,0,0,0,0,"可以查看全部员工假期数据",44);
+INSERT INTO sys_function VALUES(NULL,"负责部门员工假勤数据",NULL,NULL,7,73,0,0,1,0,0,0,0,0,0,0,0,0,"可以查看负责部门员工假期数据",44);
+INSERT INTO sys_function VALUES(NULL,"全部员工考勤数据",NULL,NULL,7,74,0,0,1,0,0,0,0,0,0,0,0,0,"可以查看全部员工考勤数据",45);
+INSERT INTO sys_function VALUES(NULL,"负责部门员工考勤数据",NULL,NULL,7,74,0,0,1,0,0,0,0,0,0,0,0,0,"可以查看负责部门员工考勤数据",45);
+ALTER TABLE user_corpwx_time ADD COLUMN ask_leave_type VARCHAR(100) COMMENT '请假类型' AFTER ask_leave_time;

+ 4 - 4
fhKeeper/formulahousekeeper/timesheet/src/permissions.js

@@ -126,8 +126,8 @@ const StringUtil = {
         reportDashboard: false, // 工时分析报告
         allFictitiousAttendance: false, // 员工假勤表
         fictitiousAttendance: false, // 员工假勤表
-        allEmployeeAttendance: false, // 员工考勤表
-        employeeAttendance: false, // 员工考勤表
+        attendanceRecord: false, // 员工考勤表
+        allAttendanceRecord: false, // 员工考勤表
         // 请假模块
         leaveFil : false, // 请假填报 // 
         leaveAudit : false, // 请假审核 //
@@ -342,8 +342,8 @@ const StringUtil = {
         arr[i] == '施工进度表' ? obj.engineeringProgress = true : ''
         arr[i] == '全部员工假勤数据' ? obj.allFictitiousAttendance = true : ''
         arr[i] == '负责部门员工假勤数据' ? obj.fictitiousAttendance = true : ''
-        arr[i] == '全部员工考勤数据' ? obj.allEmployeeAttendance = true : ''
-        arr[i] == '负责部门员工考勤数据' ? obj.employeeAttendance = true : ''
+        arr[i] == '全部员工考勤数据' ? obj.allAttendanceRecord = true : ''
+        arr[i] == '负责部门员工考勤数据' ? obj.attendanceRecord = true : ''
         
     }
     return obj

+ 440 - 16
fhKeeper/formulahousekeeper/timesheet/src/views/corpreport/list.vue

@@ -342,7 +342,16 @@
                   @click="ssl(42)"
                   ><p>员工假勤表</p></el-menu-item
                 >
-                <!-- <el-menu-item index="1-44" v-if="permissions.engineeringProgress" @click="ssl(43)"><p>施工进度表</p></el-menu-item> -->
+                <el-menu-item
+                  index="1-44"
+                  v-if="
+                    permissions.allAttendanceRecord ||
+                    permissions.attendanceRecord
+                  "
+                  @click="ssl(44)"
+                  ><p>员工考勤表</p></el-menu-item
+                >
+                <!-- <el-menu-item index="1-45" v-if="permissions.engineeringProgress" @click="ssl(45)"><p>施工进度表</p></el-menu-item> -->
               </el-submenu>
             </el-menu>
           </el-col>
@@ -580,7 +589,8 @@
               <el-select
                 v-if="
                   !screeningCondition.project.includes(ins) &&
-                  !(ins == 6 && overtimeTabActive === 'project')
+                  !(ins == 6 && overtimeTabActive === 'project') &&
+                  ins != 44
                 "
                 v-model="proJuctId"
                 :placeholder="$t('defaultText.pleaseSelectSnItem')"
@@ -5873,9 +5883,9 @@
                 key="41"
                 ref="employeeAttendanceTbl"
                 border
-                :data="employeeAttendanceList"
+                :data="employeeCorpTimeList"
                 highlight-current-row
-                v-loading="employeeAttendanceLoading"
+                v-loading="employeeCorpTimeLoading"
                 :height="+tableHeight"
                 style="width: 100%"
                 :max-height="+tableHeight + 50"
@@ -6013,9 +6023,7 @@
                 >
                   <template slot="header">
                     <div class="holiday-day-header">
-                      <div class="holiday-day-header__date">
-                        {{ date }}
-                      </div>
+                      <div class="holiday-day-header__date">{{ date }}</div>
                       <div class="holiday-day-header__week">
                         {{ fictitiousAttendanceWeekList[index] }}
                       </div>
@@ -6061,6 +6069,227 @@
               </el-table>
             </template>
 
+            <!-- 员工考勤表 -->
+            <template v-if="ins == 44">
+              <div class="corp-time-report-title">
+                <div class="corp-time-report-title__main">
+                  {{
+                    user.company && user.company.companyName
+                      ? user.company.companyName
+                      : ""
+                  }}
+                  {{
+                    monthPersonnel || dayjs(new Date()).format("YYYY-MM")
+                  }}月考勤表
+                </div>
+                <div class="corp-time-report-title__sub">
+                  <span
+                    >日期范围:{{
+                      monthPersonnel || dayjs(new Date()).format("YYYY-MM")
+                    }}</span
+                  >
+                  <span>单位:天</span>
+                </div>
+              </div>
+              <div class="corp-time-table-wrap">
+                <el-table
+                  key="44"
+                  ref="employeeAttendanceNewTbl"
+                  border
+                  :data="employeeCorpTimeList"
+                  highlight-current-row
+                  v-loading="employeeCorpTimeLoading"
+                  :height="+tableHeight - 48"
+                  style="width: 100%"
+                  :max-height="+tableHeight + 50"
+                >
+                  <el-table-column
+                    prop="index"
+                    label="序号"
+                    width="50"
+                    fixed
+                    align="center"
+                    :resizable="false"
+                  >
+                    <template slot-scope="scope">{{
+                      scope.$index + 1
+                    }}</template>
+                  </el-table-column>
+                  <el-table-column
+                    prop="employeeName"
+                    label="姓名"
+                    min-width="200"
+                    align="center"
+                  >
+                    <template slot-scope="scope">
+                      <span v-if="user.userNameNeedTranslate == '1'">
+                        <TranslationOpenDataText
+                          type="userName"
+                          :openid="scope.row.employeeName"
+                        ></TranslationOpenDataText>
+                      </span>
+                      <span v-if="user.userNameNeedTranslate != '1'">
+                        {{ scope.row.employeeName }}
+                      </span>
+                    </template>
+                  </el-table-column>
+                  <el-table-column
+                    prop="departmentName"
+                    :label="$t('subordinatedepartments')"
+                    min-width="200"
+                    align="center"
+                  >
+                    <template slot-scope="scope">
+                      <span v-if="user.userNameNeedTranslate == '1'">
+                        <span
+                          v-for="(item, index) in scope.row.departmentName"
+                          :key="index"
+                        >
+                          <TranslationOpenDataText
+                            type="departmentName"
+                            :openid="item"
+                          ></TranslationOpenDataText>
+                          <span
+                            v-if="index < scope.row.departmentName.length - 1"
+                            >/</span
+                          >
+                        </span>
+                      </span>
+                      <span v-if="user.userNameNeedTranslate != '1'">
+                        {{ scope.row.departmentName }}
+                      </span>
+                    </template>
+                  </el-table-column>
+                  <el-table-column
+                    v-for="(date, index) in employeeCorpTimeDateList"
+                    :key="date"
+                    :label="date"
+                    align="center"
+                    width="58"
+                    :resizable="false"
+                    class-name="holiday-day-column"
+                  >
+                    <template slot="header">
+                      <div class="holiday-day-header">
+                        <div class="holiday-day-header__date">
+                          {{ index + 1 }}
+                        </div>
+                        <div class="holiday-day-header__week">
+                          {{ employeeCorpTimeWeekList[index] }}
+                        </div>
+                      </div>
+                    </template>
+                    <template slot-scope="scope">
+                      <div
+                        :style="getEmployeeCorpTimeCellStyle(index, scope.row)"
+                        style="
+                          position: absolute;
+                          inset: 0;
+                          display: flex;
+                          align-items: center;
+                          justify-content: center;
+                          width: 100%;
+                          height: 100%;
+                        "
+                      >
+                        <span>
+                          {{ getEmployeeCorpTimeCellText(scope.row, index) }}
+                        </span>
+                      </div>
+                    </template>
+                  </el-table-column>
+                  <el-table-column label="带薪假" align="center">
+                    <el-table-column
+                      prop="legalHolidayCount"
+                      label="法定假"
+                      width="70"
+                      align="center"
+                    />
+                    <el-table-column
+                      prop="yearLeaveCount"
+                      label="年休假"
+                      width="70"
+                      align="center"
+                    />
+                    <el-table-column
+                      prop="marriageLeaveCount"
+                      label="婚假/天"
+                      width="100"
+                      align="center"
+                    />
+                    <el-table-column
+                      prop="paternityLeaveCount"
+                      label="陪产假/天"
+                      width="100"
+                      align="center"
+                    />
+                    <el-table-column
+                      prop="maternityLeaveCount"
+                      label="产假/天"
+                      width="100"
+                      align="center"
+                    />
+                    <el-table-column
+                      prop="bereavementLeaveCount"
+                      label="丧假/天"
+                      width="100"
+                      align="center"
+                    />
+                    <el-table-column
+                      prop="transferLeaveCount"
+                      label="调休假/天"
+                      width="100"
+                      align="center"
+                    />
+                  </el-table-column>
+                  <el-table-column label="其他" align="center">
+                    <el-table-column
+                      prop="sickLeaveCount"
+                      label="病假/天"
+                      width="100"
+                      align="center"
+                    />
+                    <el-table-column
+                      prop="personalLeaveCount"
+                      label="事假/天"
+                      width="100"
+                      align="center"
+                    />
+                  </el-table-column>
+                  <el-table-column label="迟到" align="center">
+                    <el-table-column
+                      prop="sickLeaveCount"
+                      label="次"
+                      width="70"
+                      align="center"
+                    />
+                  </el-table-column>
+                  <el-table-column label="缺卡" align="center">
+                    <el-table-column
+                      prop="sickLeaveCount"
+                      label="次"
+                      width="70"
+                      align="center"
+                    />
+                  </el-table-column>
+                  <el-table-column label="汇总" align="center">
+                    <el-table-column
+                      prop="shouldAttendCount"
+                      label="本月应出勤天数"
+                      width="80"
+                      align="center"
+                    />
+                    <el-table-column
+                      prop="actualAttendanceCount"
+                      label="本月实际出勤天数"
+                      width="80"
+                      align="center"
+                    />
+                  </el-table-column>
+                </el-table>
+              </div>
+            </template>
+
             <!-- 施工进度表 -->
             <!-- <template v-if="ins == 42">
             <el-table key="42" border :data="constructionStageList" highlight-current-row v-loading="constructionStageLoading" :height="+tableHeight" style="width: 100%;" >
@@ -6139,8 +6368,7 @@
                 layout="total, sizes, prev, pager, next"
                 :total="total"
                 style="float: right"
-              ></el-pagination
-              >{{ ins }}
+              ></el-pagination>
             </el-col>
           </div>
         </div>
@@ -6951,7 +7179,7 @@ export default {
           4, 8, 9, 10, 11, 14, 15, 17, 19, 20, 21, 22, 28, 30, 31, 34, 35, 36,
           37, 38, 40, 41, 42,
         ], // 项目筛选条件 (不等于)
-        months: [14, 15, 42], // 月份筛选条件 (等于)
+        months: [14, 15, 42, 44], // 月份筛选条件 (等于)
         monthRange: [19, 30], // 月份区间筛选条件 (等于)
         staff: [
           6, 8, 9, 19, 11, 14, 18, 23, 25, 26, 28, 30, 32, 35, 36, 37, 38, 39,
@@ -7091,6 +7319,7 @@ export default {
         "员工出勤表",
         "员工假勤表",
         "施工进度表",
+        "员工考勤表",
       ],
 
       shuzArr: [
@@ -7379,8 +7608,16 @@ export default {
       // 员工出勤表
       employeeAttendanceList: [],
       employeeAttendanceDateList: [],
+      employeeAttendanceWeekList: [],
       employeeAttendanceLoading: false,
 
+      // 员工考勤表
+      employeeCorpTimeList: [],
+      employeeCorpTimeDateList: [],
+      employeeCorpTimeWeekList: [],
+      employeeCorpTimeLoading: false,
+      employeeCorpTimeRestDayList: [],
+
       // 员工假勤表
       fictitiousAttendanceDateList: [],
       fictitiousAttendanceList: [],
@@ -7831,10 +8068,20 @@ export default {
         this.ssl(41);
         this.defaultActive = "1-42";
         return;
-      } else if (this.permissions.employeeAttendance) {
+      } else if (
+        this.permissions.allFictitiousAttendance ||
+        this.permissions.responsibleFictitiousAttendance
+      ) {
         this.ssl(42);
         this.defaultActive = "1-43";
         return;
+      } else if (
+        this.permissions.attendanceRecord ||
+        this.permissions.allAttendanceRecord
+      ) {
+        this.ssl(43);
+        this.defaultActive = "1-44";
+        return;
       } else {
         this.allWrong = false;
       }
@@ -8347,6 +8594,9 @@ export default {
       if (this.ins == 43) {
         this.getConstructionStage();
       }
+      if (this.ins == 44) {
+        this.getEmployeeCorpTime();
+      }
     },
     exportExcel() {
       var url = "/project";
@@ -8738,6 +8988,11 @@ export default {
         if (this.constructionStageClassificationId) {
           sl.classificationId = this.constructionStageClassificationId;
         }
+      } else if (this.ins == 44) {
+        fName = `员工考勤表.xlsx`;
+        url = `/user_corpwv_time/export`;
+        sl.companyId = this.user.companyId;
+        sl.month = this.dayjs(new Date()).format("YYYY-MM");
       }
       this.exportReportLoading = true;
       this.http.post(
@@ -10212,7 +10467,40 @@ export default {
         this.getEmployeeHoliday();
       } else if (this.ins == 43) {
         this.getConstructionStage();
+      } else if (this.ins == 44) {
+        this.getEmployeeCorpTime();
+      }
+    },
+    exportExcel() {
+      let url = "/project";
+      let fName = "";
+      let sl = {};
+      if (this.ins == 42) {
+        fName = "员工假勤表.xlsx";
+        url = "/user-corpwx-time/exportEmployeeHolidayExcel";
+        sl.month =
+          this.monthPersonnel || this.dayjs(new Date()).format("YYYY-MM");
+      } else if (this.ins == 44) {
+        fName = "员工考勤表.xlsx";
+        url = "/user-corpwx-time/exportEmployeeCorpTimeExcel";
+        sl.month =
+          this.monthPersonnel || this.dayjs(new Date()).format("YYYY-MM");
+      } else {
+        return this.$message.info("当前报表暂无导出功能");
       }
+      this.exportReportLoading = true;
+      this.postData(url, sl)
+        .then((res) => {
+          if (res && res.data) {
+            const link = document.createElement("a");
+            link.href = res.data;
+            link.download = fName;
+            link.click();
+          }
+        })
+        .finally(() => {
+          this.exportReportLoading = false;
+        });
     },
 
     // 获取日报明细表
@@ -11543,6 +11831,39 @@ export default {
         });
     },
 
+    // 获取员工考勤表
+    getEmployeeCorpTime() {
+      this.employeeCorpTimeLoading = true;
+      const month =
+        this.monthPersonnel || this.dayjs(new Date()).format("YYYY-MM");
+      this.postData(`/user-corpwx-time/getUserCorpwvTimeList`, {
+        month,
+        pageIndex: this.ins == 44 ? this.page : -1,
+        pageSize: this.ins == 44 ? this.size : -1,
+      })
+        .then((res) => {
+          const data = res.data || {};
+          this.employeeCorpTimeDateList = data.dateList || [];
+          this.employeeCorpTimeWeekList = data.weekList || [];
+          this.employeeCorpTimeList = data.list || data.records || [];
+          this.employeeCorpTimeRestDayList = Array.isArray(data.restDayList)
+            ? data.restDayList
+            : [];
+          this.total = data.total || 0;
+          this.$nextTick(() => {
+            if (
+              this.$refs.employeeAttendanceNewTbl &&
+              this.$refs.employeeAttendanceNewTbl.doLayout
+            ) {
+              this.$refs.employeeAttendanceNewTbl.doLayout();
+            }
+          });
+        })
+        .finally(() => {
+          this.employeeCorpTimeLoading = false;
+        });
+    },
+
     // 获取员工假勤表
     getEmployeeHoliday() {
       this.fictitiousAttendanceLoading = true;
@@ -11558,7 +11879,7 @@ export default {
       }
       this.postData("/user-corpwx-time/getUserFictitiousAttendanceList", {
         month,
-        pageIndex: this.ins == 42 ? this.page : 1,
+        pageIndex: this.ins == 42 ? this.page : -1,
         pageSize: this.ins == 42 ? this.size : -1,
       })
         .then((res) => {
@@ -11607,6 +11928,42 @@ export default {
       };
     },
 
+    getEmployeeCorpTimeCellText(row, index) {
+      const val = row && row.attendanceArray ? row.attendanceArray[index] : "";
+      return val ? val : "";
+    },
+    getEmployeeCorpTimeCellStyle(index, row) {
+      const date = this.employeeCorpTimeDateList[index];
+      const fullDate = `${this.dayjs(new Date()).format("YYYY-MM")}-${String(
+        date,
+      ).padStart(2, "0")}`;
+      const isRestDay = this.employeeCorpTimeRestDayList.includes(fullDate);
+      const hasAttendance =
+        row &&
+        row.attendanceArray &&
+        row.attendanceArray[index] !== undefined &&
+        row.attendanceArray[index] !== null &&
+        String(row.attendanceArray[index]) !== "";
+      const hasLeave = row && row.leaveArray && row.leaveArray[index];
+      return {
+        display: "flex",
+        alignItems: "center",
+        justifyContent: "center",
+        minHeight: "28px",
+        borderRadius: "4px",
+        backgroundColor: hasLeave
+          ? "#d9f7be"
+          : isRestDay
+          ? "#12b54a"
+          : hasAttendance
+          ? "#12b54a"
+          : "transparent",
+        color: hasLeave || isRestDay || hasAttendance ? "#fff" : "#303133",
+        whiteSpace: "normal",
+        wordBreak: "break-all",
+      };
+    },
+
     syncFictitiousAttendanceByMonth(month) {
       this.monthPersonnel = month;
       if (this.ins == 42) {
@@ -11705,7 +12062,8 @@ export default {
   display: flex;
   flex-wrap: wrap;
 }
-.holiday-day-header {
+.holiday-day-header,
+.corp-time-day-header {
   height: 34px;
   display: flex;
   flex-direction: column;
@@ -11713,20 +12071,86 @@ export default {
   align-items: center;
   line-height: 16px;
   text-align: center;
-  background: #fff;
+  background: transparent;
 }
-.holiday-day-header__date {
+.holiday-day-header__date,
+.corp-time-day-header__date {
   width: 100%;
   font-size: 12px;
   color: #303133;
   padding-bottom: 2px;
 }
-.holiday-day-header__week {
+.holiday-day-header__week,
+.corp-time-day-header__week {
   width: 100%;
   font-size: 10px;
   color: #666;
   padding-top: 2px;
 }
+.corp-time-report-title {
+  padding: 8px 0 10px;
+}
+.corp-time-table-wrap ::v-deep .el-table__header th,
+.corp-time-table-wrap ::v-deep .el-table__body td {
+  padding: 0;
+}
+.corp-time-table-wrap ::v-deep .el-table__header th .cell {
+  line-height: 18px;
+  background: transparent;
+}
+.corp-time-table-wrap ::v-deep .el-table__header .cell {
+  padding: 0 2px;
+  background: transparent;
+}
+.corp-time-table-wrap ::v-deep .el-table__body .cell {
+  padding: 0;
+}
+.corp-time-table-wrap ::v-deep .holiday-day-header {
+  height: 36px;
+  justify-content: center;
+}
+.corp-time-table-wrap ::v-deep .holiday-day-header__date,
+.corp-time-table-wrap ::v-deep .holiday-day-header__week {
+  line-height: 1.2;
+}
+.corp-time-report-title__main {
+  font-size: 18px;
+  font-weight: 700;
+  color: #303133;
+  line-height: 1.4;
+}
+.corp-time-report-title__sub {
+  margin-top: 4px;
+  display: flex;
+  justify-content: center;
+  gap: 24px;
+  color: #606266;
+  font-size: 12px;
+}
+.corp-time-table-wrap {
+  width: 100%;
+  overflow-x: auto;
+  overflow-y: hidden;
+}
+.corp-time-table-wrap ::v-deep .el-table {
+  min-width: 2200px;
+}
+.corp-time-table-wrap ::v-deep .el-table__body-wrapper,
+.corp-time-table-wrap ::v-deep .el-table__header-wrapper {
+  overflow-x: auto;
+}
+.corp-time-table-wrap ::v-deep .el-table__body-wrapper table,
+.corp-time-table-wrap ::v-deep .el-table__header-wrapper table {
+  table-layout: fixed !important;
+}
+.holiday-day-column .cell,
+.corp-time-day-column .cell {
+  padding: 0 !important;
+}
+.holiday-day-column .cell > div,
+.corp-time-day-column .cell > div {
+  min-height: 28px;
+}
 .holiday-fixed-dept {
   border-right: 2px solid #dcdfe6;
 }