Ver Fonte

读取企业微信上传转译文件的任务

seyason há 2 anos atrás
pai
commit
9127c7c16a

+ 9 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/ProjectController.java

@@ -66,6 +66,15 @@ public class ProjectController {
     private UserMapper userMapper;
     @Resource
     private OperationRecordService operationRecordService;
+    @RequestMapping("/testRead")
+    public HttpRespMsg testRead(String jobId) {
+        return projectService.testRead(jobId);
+    }
+
+    @RequestMapping("/testAdd")
+    public HttpRespMsg testAdd(String jobId) {
+        return projectService.testAdd(jobId);
+    }
 
     /**
      * 获取我参与的全部项目的负责人列表

+ 2 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/WeiXinCorpController.java

@@ -8,6 +8,7 @@ import com.management.platform.entity.*;
 import com.management.platform.entity.vo.UserVO;
 import com.management.platform.mapper.*;
 import com.management.platform.service.*;
+import com.management.platform.service.impl.ExcelExportServiceImpl;
 import com.management.platform.util.*;
 import com.qq.weixin.mp.aes.AesException;
 import com.qq.weixin.mp.aes.WXBizMsgCrypt;
@@ -413,6 +414,7 @@ public class WeiXinCorpController {
                     result.setJobId(jobId);
                     result.setJobType(jobType);
                     corpwxJobResultMapper.insert(result);
+                    ExcelExportServiceImpl.corpwxJobCenter.put(jobId, result);
                 }
             }
         } catch (Exception e) {

+ 13 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/ExcelExportService.java

@@ -0,0 +1,13 @@
+package com.management.platform.service;
+
+import com.management.platform.entity.WxCorpInfo;
+import com.management.platform.util.HttpRespMsg;
+
+import java.util.List;
+
+public interface ExcelExportService {
+    public void testRead(String jobId);
+    public HttpRespMsg exportGeneralExcelByTitleAndList(WxCorpInfo wxCorpInfo, String title, List<List<String>> list, String downloadPath) throws Exception;
+
+    void testAdd(String jobId);
+}

+ 4 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/ProjectService.java

@@ -196,4 +196,8 @@ public interface ProjectService extends IService<Project> {
     HttpRespMsg removeDuplicateParticipators(Integer companyId, HttpServletRequest request);
 
     HttpRespMsg synchronizationProject(String dataJson);
+
+    HttpRespMsg testRead(String jobId);
+
+    HttpRespMsg testAdd(String jobId);
 }

+ 102 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ExcelExportServiceImpl.java

@@ -0,0 +1,102 @@
+package com.management.platform.service.impl;
+
+import com.management.platform.entity.CorpwxJobResult;
+import com.management.platform.entity.WxCorpInfo;
+import com.management.platform.mapper.CorpwxJobResultMapper;
+import com.management.platform.service.ExcelExportService;
+import com.management.platform.service.WxCorpInfoService;
+import com.management.platform.util.ExcelUtil;
+import com.management.platform.util.HttpRespMsg;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Isolation;
+import org.springframework.transaction.annotation.Transactional;
+
+import javax.annotation.Resource;
+import java.util.HashMap;
+import java.util.List;
+
+@Service
+public class ExcelExportServiceImpl implements ExcelExportService {
+    //用于控制线程锁
+    public static HashMap<String, CorpwxJobResult> corpwxJobCenter = new HashMap();
+    @Resource
+    private WxCorpInfoService wxCorpInfoService;
+
+    @Resource
+    private CorpwxJobResultMapper corpwxJobResultMapper;
+
+    @Transactional(isolation = Isolation.READ_COMMITTED)
+    public void testRead(String jobId) {
+        System.out.println("Enter ExcelExportService testRead@@@");
+        int i = 0;
+        while (i < 10) {
+            try {
+                Thread.sleep(2000);
+            } catch (InterruptedException e) {
+                e.printStackTrace();
+            }
+//            CorpwxJobResult corpwxJobResult = corpwxJobResultMapper.selectById(jobId);
+            CorpwxJobResult corpwxJobResult = corpwxJobCenter.get(jobId);
+//            CorpwxJobResult item = new CorpwxJobResult();
+//            item.setJobId("444");
+//            corpwxJobResultMapper.insert(item);
+            if (corpwxJobResult != null) {
+                System.out.println("===读取到了====");
+                corpwxJobCenter.remove(jobId);
+                break;
+            } else {
+                System.out.println("===无匹配记录====");
+            }
+            i++;
+        }
+    }
+
+    public HttpRespMsg exportGeneralExcelByTitleAndList(WxCorpInfo wxCorpInfo, String title, List<List<String>> list, String downloadPath) throws Exception {
+        String result = "系统提示:Excel文件导出成功!";
+        String fileName = title + ".xls";
+        HttpRespMsg httpRespMsg = new HttpRespMsg();
+        String resp = ExcelUtil.exportGeneralExcelByTitleAndList(null, title, list, downloadPath);
+        String fileUrlSuffix = title + ".xls";
+        if(wxCorpInfo != null && wxCorpInfo.getSaasSyncContact() == 1){
+            String mediaId = wxCorpInfoService.getTranslationMediaId(fileUrlSuffix);
+            String jobId = wxCorpInfoService.syncTranslation(wxCorpInfo.getCorpid(),mediaId,fileUrlSuffix, null);
+            int i = 0;
+            String syncTranslationResult = null;
+            /**
+             * 异步上传转译文件的任务完成时会触发回调,在WeiXinCorpController中的commonDevCallbackPost实现了对回调的处理,存储到corpwxJobResult表中
+             * 此处轮询查询本地数据库,检测到有任务的回调数据时继续执行查询操作
+             */
+            while (i < 10) {
+                Thread.sleep(3000);
+                CorpwxJobResult corpwxJobResult = corpwxJobCenter.get(jobId);
+                if (corpwxJobResult != null) {
+                    if (corpwxJobResult.getErrCode() == 0) {
+                        syncTranslationResult = wxCorpInfoService.getSyncTranslationResult(jobId);
+                        corpwxJobCenter.remove(jobId);
+                    } else {
+                        httpRespMsg.setError(corpwxJobResult.getErrMsg());
+                        return httpRespMsg;
+                    }
+                    break;
+                }
+                i++;
+            }
+            if (syncTranslationResult != null) {
+                httpRespMsg.data = syncTranslationResult;
+            } else {
+                httpRespMsg.setError("处理超时...");
+            }
+        }else {
+            httpRespMsg.data = resp;
+        }
+        return httpRespMsg;
+    }
+
+    @Override
+    public void testAdd(String jobId) {
+        CorpwxJobResult corpwxJobResult = new CorpwxJobResult();
+        corpwxJobResult.setJobId(jobId);
+        corpwxJobCenter.put(jobId, corpwxJobResult);
+//        corpwxJobResultMapper.insert(corpwxJobResult);
+    }
+}

+ 20 - 2
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ProjectServiceImpl.java

@@ -38,6 +38,8 @@ import org.assertj.core.util.Lists;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Isolation;
+import org.springframework.transaction.annotation.Propagation;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.util.StringUtils;
 import org.springframework.web.bind.annotation.RequestParam;
@@ -77,6 +79,8 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
     @Resource
     private HttpServletRequest request;
     @Resource
+    ExcelExportService excelExportService;
+    @Resource
     private ProjectNotifyUserService projectNotifyUserService;
     @Resource
     private GroupParticipatorMapper groupParticipatorMapper;
@@ -1329,13 +1333,15 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
             //生成excel文件导出
             //String fileName = "项目成本工时统计_"+System.currentTimeMillis();
             String fileName = MessageUtils.message("fileName.projectCost")+System.currentTimeMillis();
-            String resp = ExcelUtil.exportGeneralExcelByTitleAndList(wxCorpInfo,fileName , allList, path);
-            httpRespMsg.data = resp;
+            return excelExportService.exportGeneralExcelByTitleAndList(wxCorpInfo,fileName , allList, path);
         } catch (NullPointerException e) {
             e.printStackTrace();
             //httpRespMsg.setError("验证失败");
             httpRespMsg.setError(MessageUtils.message("access.verificationError"));
             return httpRespMsg;
+        } catch (Exception exception) {
+            exception.printStackTrace();
+            httpRespMsg.setError(exception.getMessage());
         }
         return httpRespMsg;
     }
@@ -6914,6 +6920,18 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
         return msg;
     }
 
+    @Override
+    public HttpRespMsg testRead(String jobId) {
+        excelExportService.testRead(jobId);
+        return new HttpRespMsg();
+    }
+
+    @Override
+    public HttpRespMsg testAdd(String jobId) {
+        excelExportService.testAdd(jobId);
+        return new HttpRespMsg();
+    }
+
     public static void main(String[] args) {
         Map params = new HashMap<>();
         Map paramDataJson = new HashMap<>();

+ 236 - 210
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/WxCorpInfoServiceImpl.java

@@ -32,6 +32,7 @@ import java.net.URI;
 import java.text.SimpleDateFormat;
 import java.time.*;
 import java.time.format.DateTimeFormatter;
+import java.time.temporal.ChronoUnit;
 import java.util.*;
 import java.util.concurrent.Executors;
 import java.util.stream.Collectors;
@@ -538,6 +539,7 @@ public class WxCorpInfoServiceImpl extends ServiceImpl<WxCorpInfoMapper, WxCorpI
             String resp = responseEntity.getBody();
             if (showLog) System.out.println(resp);
             JSONObject json = JSONObject.parseObject(resp);
+            DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd");
             if (json.getIntValue("errcode") == 0) {
                 JSONArray datas = json.getJSONArray("datas");
                 for (int i = 0; i < datas.size(); i++) {
@@ -590,250 +592,274 @@ public class WxCorpInfoServiceImpl extends ServiceImpl<WxCorpInfoMapper, WxCorpI
                     int regular_work_sec = summary_info.getIntValue("regular_work_sec");//秒
                     Integer standard_work_sec = summary_info.getInteger("standard_work_sec");
 
-
                     ct.setStartTime(DateTimeUtil.getTimeFromSeconds(sTime));
                     ct.setEndTime(DateTimeUtil.getTimeFromSeconds(eTime));
                     //直接设置打卡时长,以企业微信的为准,不考虑漏打卡的情况
                     ct.setCardTime(DateTimeUtil.getHoursFromSeconds(regular_work_sec));
-
-                    JSONArray holidayItems = jsonObject.getJSONArray("holiday_infos");
-//                        if (eTime == sTime) {
-                    //开始时间和结束时间一样,说明下班没有打卡,需要提取请假的最晚时间作为下班打卡时间
-                    String lastestOffworkTime = null;
-                    boolean needRecaculate = false;
-                    for (int t = 0; t < holidayItems.size(); t++) {
-                        JSONObject holiday = holidayItems.getJSONObject(t);
-                        JSONObject spTitle = holiday.getJSONObject("sp_title");
-                        JSONArray data = spTitle.getJSONArray("data");
-                        for (int m = 0; m < data.size(); m++) {
-                            String leaveText = data.getJSONObject(m).getString("text");
-                            if (leaveText.startsWith("请假")) {
-                                //获取对应位置的请假时间段
-                                String string = holiday.getJSONObject("sp_description").getJSONArray("data").getJSONObject(m).getString("text");
-                                String[] s = string.split(" |\\~");
-                                boolean isOldFormat = false;
-                                if (s.length < 5) {
-                                    isOldFormat = true;
-                                }
-
-                                //获取到请假的开始时间和结束时间
-                                String leaveEnd = isOldFormat ? s[3] : s[4];
-                                String leaveStart = s[1];
-                                //请假开始的日期和结束的日期
-                                String dateStart = localDate.getYear() + "/" + s[0];
-                                String dateEnd = localDate.getYear() + "/" + (isOldFormat ? s[2] : s[3]);
-                                LocalDate sDate = LocalDate.parse(dateStart, mdFormat);
-                                LocalDate eDate = LocalDate.parse(dateEnd, mdFormat);
-                                if (sDate.isEqual(eDate)) {
-                                    //请假在一天内
-                                    if (leaveEnd.equals("下午")) {
-                                        if (leaveStart.equals("上午")) {
-                                            leaveEnd = baseAfternoonEnd;//上午和下午都请假,算全天
-                                            leaveStart = baseMorningStart;
-                                        } else {
-                                            leaveStart = "14:00";
-                                            leaveEnd = baseAfternoonEnd;//请假的下班打卡时间,算上午结束的时间
-                                        }
-                                    } else if (leaveEnd.equals("上午")) {
-                                        //上午请假
-                                        leaveEnd = baseMorningEnd;
-                                        leaveStart = baseMorningStart;
-                                    }
-                                    //开始时间是00:00要处理成正常打卡的开始时间
-                                    if ("00:00".equals(leaveStart)) {
-                                        leaveStart = baseMorningStart;
+                    ct.setAskLeaveTime(0.0);
+                    ct.setWorkHours(0.0);
+                    ct.setOutdoorTime(0.0);
+                    //工作日或者非工作日有打卡,需要校正请假,外出的时长数据
+                    if (WorkDayCalculateUtils.isWorkDay(localDate) || sTime > 0 || eTime > 0) {
+                        JSONArray holidayItems = jsonObject.getJSONArray("holiday_infos");
+                        //开始时间和结束时间一样,说明下班没有打卡,需要提取请假的最晚时间作为下班打卡时间
+                        boolean needRecaculate = false;
+                        //跨天请假的情况,中间如果有非工作日要自动补齐时间。
+                        List<LocalDate> betweenNonWorkDays = new ArrayList<>();
+                        int betweenTotalDays = 0;
+                        for (int t = 0; t < holidayItems.size(); t++) {
+                            JSONObject holiday = holidayItems.getJSONObject(t);
+                            JSONObject spTitle = holiday.getJSONObject("sp_title");
+                            JSONArray data = spTitle.getJSONArray("data");
+                            for (int m = 0; m < data.size(); m++) {
+                                String leaveText = data.getJSONObject(m).getString("text");
+                                if (leaveText.startsWith("请假")) {
+                                    //获取对应位置的请假时间段
+                                    String string = holiday.getJSONObject("sp_description").getJSONArray("data").getJSONObject(m).getString("text");
+                                    String[] s = string.split(" |\\~");
+                                    boolean isOldFormat = false;
+                                    if (s.length < 5) {
+                                        isOldFormat = true;
                                     }
-                                    System.out.println("leaveStart==" + leaveStart + ", leaveEnd=" + leaveEnd);
-                                } else {
-                                    if (showLog) System.out.println("跨天请假@@@@");
-                                    if (showLog)
-                                        System.out.println("当天==" + localDate + ", sDate=" + sDate + ", 比较=" + (localDate.isEqual(sDate)));
-                                    //跨天请假
-                                    if (localDate.isEqual(sDate)) {
-                                        //当前日期第一天,需判断上下午半天请假的情况
-                                        if (leaveStart.equals("上午")) {
-                                            leaveStart = baseMorningStart;
-                                        } else {
-                                            leaveStart = baseAfternoonStart;
-                                        }
-                                        //跨天请假的第一天,结束时间默认为18:00
-                                        leaveEnd = baseAfternoonEnd;//上午开始请假的算全天
-                                    } else if (localDate.isEqual(eDate)) {
-                                        //当前日期就是最后一天,需判断上下午半天请假的情况
+
+                                    //获取到请假的开始时间和结束时间
+                                    String leaveEnd = isOldFormat ? s[3] : s[4];
+                                    String leaveStart = s[1];
+                                    //请假开始的日期和结束的日期
+                                    String dateStart = localDate.getYear() + "/" + s[0];
+                                    String dateEnd = localDate.getYear() + "/" + (isOldFormat ? s[2] : s[3]);
+                                    LocalDate sDate = LocalDate.parse(dateStart, mdFormat);
+                                    LocalDate eDate = LocalDate.parse(dateEnd, mdFormat);
+                                    if (sDate.isEqual(eDate)) {
+                                        //请假在一天内
                                         if (leaveEnd.equals("下午")) {
-                                            leaveEnd = baseAfternoonEnd;//请假到最后一天的下午,就算是全天
+                                            if (leaveStart.equals("上午")) {
+                                                leaveEnd = baseAfternoonEnd;//上午和下午都请假,算全天
+                                                leaveStart = baseMorningStart;
+                                            } else {
+                                                leaveStart = "14:00";
+                                                leaveEnd = baseAfternoonEnd;//请假的下班打卡时间,算上午结束的时间
+                                            }
                                         } else if (leaveEnd.equals("上午")) {
                                             //上午请假
                                             leaveEnd = baseMorningEnd;
+                                            leaveStart = baseMorningStart;
+                                        }
+                                        //开始时间是00:00要处理成正常打卡的开始时间
+                                        if ("00:00".equals(leaveStart)) {
+                                            leaveStart = baseMorningStart;
                                         }
-                                        //跨天请假的最后一天,开始时间默认为9:00
-                                        leaveStart = baseMorningStart;
+                                        System.out.println("leaveStart==" + leaveStart + ", leaveEnd=" + leaveEnd);
                                     } else {
-                                        //中间日期就是全天
-                                        leaveStart = baseMorningStart;
-                                        leaveEnd = baseAfternoonEnd;
-                                        if (showLog) System.out.println("===中间天请假===");
+                                        if (showLog) System.out.println("跨天请假@@@@");
+                                        if (showLog)
+                                            System.out.println("当天==" + localDate + ", sDate=" + sDate + ", 比较=" + (localDate.isEqual(sDate)));
+                                        //跨天请假,获取期间的非工作日,加进去
+                                        List<LocalDate> localDates = WorkDayCalculateUtils.getNonWorkDaysListInRange(dtf.format(sDate) ,dtf.format(eDate));
+                                        for (LocalDate curLdate : localDates) {
+                                            if (!betweenNonWorkDays.stream().anyMatch(be->be.isEqual(curLdate))) {
+                                                if (showLog) System.out.println("含非工作日请假:"+curLdate);
+                                                betweenNonWorkDays.add(curLdate);
+                                            }
+                                        }
+                                        if (betweenNonWorkDays.size() > 0) {
+                                            betweenTotalDays = (int)sDate.until(eDate, ChronoUnit.DAYS) + 1;
+                                            if (showLog) System.out.println("总跨度请假天数为:"+betweenTotalDays);
+                                        }
+                                        if (localDate.isEqual(sDate)) {
+                                            //当前日期第一天,需判断上下午半天请假的情况
+                                            if (showLog) System.out.println("跨天请假第一天leaveStart为:"+leaveStart);
+                                            if (leaveStart.equals("上午")) {
+                                                leaveStart = baseMorningStart;
+                                            } else if (leaveStart.equals("下午")) {
+                                                leaveStart = baseAfternoonStart;
+                                            }
+                                            //跨天请假的第一天,结束时间默认为18:00
+                                            leaveEnd = baseAfternoonEnd;//上午开始请假的算全天
+                                        } else if (localDate.isEqual(eDate)) {
+                                            //当前日期就是最后一天,需判断上下午半天请假的情况
+                                            if (leaveEnd.equals("下午")) {
+                                                leaveEnd = baseAfternoonEnd;//请假到最后一天的下午,就算是全天
+                                            } else if (leaveEnd.equals("上午")) {
+                                                //上午请假
+                                                leaveEnd = baseMorningEnd;
+                                            }
+                                            //跨天请假的最后一天,开始时间默认为9:00
+                                            leaveStart = baseMorningStart;
+                                        } else {
+                                            //中间日期就是全天
+                                            leaveStart = baseMorningStart;
+                                            leaveEnd = baseAfternoonEnd;
+                                            if (showLog) System.out.println("===中间天请假===");
+                                        }
                                     }
-                                }
 
-                                //获取请假最早的开始时间和最晚的结束时间最为当天考勤的最早和最晚时间
-                                if (ct.getStartTime().equals("00:00") || ct.getStartTime().compareTo(leaveStart) > 0) {
-                                    ct.setStartTime(leaveStart);
-                                    needRecaculate = true;
-                                }
-                                if (ct.getEndTime().compareTo(leaveEnd) < 0) {
-                                    ct.setEndTime(leaveEnd);
-                                    needRecaculate = true;
-                                }
-                            } else if (leaveText.startsWith("外出")) {
-                                String string = holiday.getJSONObject("sp_description").getJSONArray("data").getJSONObject(m).getString("text");
-                                String[] s = string.split(" |\\~");
-                                //获取到外出的开始时间和结束时间
-                                boolean isOldFormat = false;
-                                if (s.length < 5) {
-                                    isOldFormat = true;
-                                }
-                                String outEnd = isOldFormat ? s[3] : s[4];
-                                String outStart = s[1];
-                                //获取外出的最早的开始时间和最晚的结束时间最为当天考勤的最早和最晚时间
-                                if (ct.getStartTime().equals("00:00") || ct.getStartTime().compareTo(outStart) > 0) {
-                                    ct.setStartTime(outStart);
-                                    needRecaculate = true;
-                                }
+                                    //获取请假最早的开始时间和最晚的结束时间最为当天考勤的最早和最晚时间
+                                    if (ct.getStartTime().equals("00:00") || ct.getStartTime().compareTo(leaveStart) > 0) {
+                                        ct.setStartTime(leaveStart);
+                                        needRecaculate = true;
+                                    }
+                                    if (ct.getEndTime().compareTo(leaveEnd) < 0) {
+                                        ct.setEndTime(leaveEnd);
+                                        needRecaculate = true;
+                                    }
+                                } else if (leaveText.startsWith("外出")) {
+                                    String string = holiday.getJSONObject("sp_description").getJSONArray("data").getJSONObject(m).getString("text");
+                                    String[] s = string.split(" |\\~");
+                                    //获取到外出的开始时间和结束时间
+                                    boolean isOldFormat = false;
+                                    if (s.length < 5) {
+                                        isOldFormat = true;
+                                    }
+                                    String outEnd = isOldFormat ? s[3] : s[4];
+                                    String outStart = s[1];
+                                    //获取外出的最早的开始时间和最晚的结束时间最为当天考勤的最早和最晚时间
+                                    if (ct.getStartTime().equals("00:00") || ct.getStartTime().compareTo(outStart) > 0) {
+                                        ct.setStartTime(outStart);
+                                        needRecaculate = true;
+                                    }
 
-                                if (ct.getEndTime().compareTo(outEnd) < 0) {
-                                    ct.setEndTime(outEnd);
-                                    needRecaculate = true;
+                                    if (ct.getEndTime().compareTo(outEnd) < 0) {
+                                        ct.setEndTime(outEnd);
+                                        needRecaculate = true;
+                                    }
                                 }
                             }
                         }
-                    }
-                    double timeDelta = 0;
-                    //时间有变化,需要重新计算
-                    if (needRecaculate) {
-                        System.out.println("" + ct.getStartTime() + "--" + ct.getEndTime());
-                        timeDelta = DateTimeUtil.getHoursFromSeconds(DateTimeUtil.getSecondsFromTime(ct.getEndTime()) - DateTimeUtil.getSecondsFromTime(ct.getStartTime()));
-                        //超过下午上班的开始时间,需要减去午休的时间
-                        if (ct.getEndTime().compareTo(baseAfternoonStart) >= 0) {
-                            //重新计算打卡工时时,需要减去中间午休时间
-
-                            timeDelta -= restTime;
+                        double timeDelta = 0;
+                        //时间有变化,需要重新计算
+                        if (needRecaculate) {
+                            System.out.println("" + ct.getStartTime() + "--" + ct.getEndTime());
+                            timeDelta = DateTimeUtil.getHoursFromSeconds(DateTimeUtil.getSecondsFromTime(ct.getEndTime()) - DateTimeUtil.getSecondsFromTime(ct.getStartTime()));
+                            //超过下午上班的开始时间,需要减去午休的时间
+                            if (ct.getEndTime().compareTo(baseAfternoonStart) >= 0) {
+                                //重新计算打卡工时时,需要减去中间午休时间
+                                timeDelta -= restTime;
+                            }
+                        } else {
+                            timeDelta = ct.getCardTime();
                         }
-                    } else {
-                        timeDelta = ct.getCardTime();
-                    }
 
-                    if (showLog) System.out.println("上下班间隔时长为==" + timeDelta);
-                    ct.setName(name);
-                    //解析请假和外出的情况
-                    JSONArray sp_items = jsonObject.getJSONArray("sp_items");
-                    for (int j = 0; j < sp_items.size(); j++) {
-                        JSONObject spItem = sp_items.getJSONObject(j);
-                        switch (spItem.getInteger("type")) {
-                            case 1://请假
-                                Double leaveTime = ct.getAskLeaveTime();
-                                if (leaveTime == null) {
-                                    leaveTime = 0.0;
-                                }
-                                ct.setAskLeaveTime(leaveTime + convertDayTimeToHours(DateTimeUtil.getHoursFromSeconds(spItem.getInteger("duration"))));
-                                break;
-                            case 2://补卡
-                            case 3://出差
-                            case 4://外出
-                            case 100://外勤
-                                Double outdoorTime = ct.getOutdoorTime();
-                                if (outdoorTime == null) {
-                                    outdoorTime = 0.0;
-                                }
-                                double otTime = convertDayTimeToHours(DateTimeUtil.getHoursFromSeconds(spItem.getInteger("duration")));
-                                if (otTime > 8.0) {
-                                    otTime = 8.0;
-                                }
-                                ct.setOutdoorTime(outdoorTime + otTime);
-                                break;
+                        if (showLog) System.out.println("上下班间隔时长为==" + timeDelta);
+                        ct.setName(name);
+                        //解析请假和外出的情况
+                        JSONArray sp_items = jsonObject.getJSONArray("sp_items");
+                        for (int j = 0; j < sp_items.size(); j++) {
+                            JSONObject spItem = sp_items.getJSONObject(j);
+                            switch (spItem.getInteger("type")) {
+                                case 1://请假
+                                    Double leaveTime = ct.getAskLeaveTime();
+                                    if (leaveTime == null) {
+                                        leaveTime = 0.0;
+                                    }
+                                    int wxDuration = spItem.getInteger("duration");
+                                    int seconds = 0;
+                                    if (betweenNonWorkDays.size() > 0) {
+                                        //跨天请假中含有非工作日的情况,要减去非工作日来重新计算实际工作日的每天请假时长。
+                                        seconds = wxDuration * betweenTotalDays/(betweenTotalDays - betweenNonWorkDays.size());
+                                    }
+                                    double curLeaveTime = convertDayTimeToHours(DateTimeUtil.getHoursFromSeconds(seconds));
+                                    ct.setAskLeaveTime(leaveTime + curLeaveTime);
+                                    break;
+                                case 2://补卡
+                                case 3://出差
+                                case 4://外出
+                                case 100://外勤
+                                    Double outdoorTime = ct.getOutdoorTime();
+                                    if (outdoorTime == null) {
+                                        outdoorTime = 0.0;
+                                    }
+                                    double otTime = convertDayTimeToHours(DateTimeUtil.getHoursFromSeconds(spItem.getInteger("duration")));
+                                    if (otTime > 8.0) {
+                                        otTime = 8.0;
+                                    }
+                                    ct.setOutdoorTime(outdoorTime + otTime);
+                                    break;
+                            }
                         }
-                    }
 
-                    //获取请假的最早和最晚时间
-                    for (int t = 0; t < holidayItems.size(); t++) {
-                        JSONObject holiday = holidayItems.getJSONObject(t);
-                        JSONObject spTitle = holiday.getJSONObject("sp_title");
-                        JSONArray data = spTitle.getJSONArray("data");
-                        for (int m = 0; m < data.size(); m++) {
-                            String leaveText = data.getJSONObject(m).getString("text");
-                            if (leaveText.startsWith("请假")) {
-                                //获取对应位置的请假时间段
-                                String string = holiday.getJSONObject("sp_description").getJSONArray("data").getJSONObject(m).getString("text");
-                                String[] s = string.split(" |\\~");
-                                boolean isOldFormat = false;
-                                if (s.length < 5) {
-                                    isOldFormat = true;
-                                }
-                                //获取到请假的开始时间和结束时间
-                                String leaveStart = s[1];
-                                String leaveEnd = isOldFormat ? s[3] : s[4];
-
-                                //检查请假时间段是否在打卡的时间范围内
-                                if ("上午".equals(leaveEnd) || "下午".equals(leaveEnd)) {
-                                    //半天或者全天请假, 上面已经处理过结束时间为请假之前的时间了,此处不需要再处理了
-                                    if (ct.getAskLeaveTime() >= 12) {
-                                        if (showLog)
-                                            System.out.println("====半天或者全天请假 =转化为8小时制下的时间=" + (ct.getAskLeaveTime() / 24 * 8.0));
-                                        //12小时以上的,是请假半天或者全天的。 防止1天有2次上下午分开的请假,导致计算两次的错误
-                                        ct.setAskLeaveTime(ct.getAskLeaveTime() / 24 * 8.0);//转换成一天8小时工作制
+                        //获取请假的最早和最晚时间
+                        for (int t = 0; t < holidayItems.size(); t++) {
+                            JSONObject holiday = holidayItems.getJSONObject(t);
+                            JSONObject spTitle = holiday.getJSONObject("sp_title");
+                            JSONArray data = spTitle.getJSONArray("data");
+                            for (int m = 0; m < data.size(); m++) {
+                                String leaveText = data.getJSONObject(m).getString("text");
+                                if (leaveText.startsWith("请假")) {
+                                    //获取对应位置的请假时间段
+                                    String string = holiday.getJSONObject("sp_description").getJSONArray("data").getJSONObject(m).getString("text");
+                                    String[] s = string.split(" |\\~");
+                                    boolean isOldFormat = false;
+                                    if (s.length < 5) {
+                                        isOldFormat = true;
                                     }
-                                } else if (ct.getStartTime().compareTo(leaveStart) <= 0 && ct.getEndTime().compareTo(leaveEnd) >= 0) {
-                                    String hourLeaveTime = leaveText.replaceAll("请假", "").replaceAll("小时", "");
-                                    if (showLog) System.out.println("请假时长=" + hourLeaveTime);
+                                    //获取到请假的开始时间和结束时间
+                                    String leaveStart = s[1];
+                                    String leaveEnd = isOldFormat ? s[3] : s[4];
+
+                                    //检查请假时间段是否在打卡的时间范围内
+                                    if ("上午".equals(leaveEnd) || "下午".equals(leaveEnd)) {
+                                        //半天或者全天请假, 上面已经处理过结束时间为请假之前的时间了,此处不需要再处理了
+                                        if (ct.getAskLeaveTime() >= 12) {
+                                            if (showLog)
+                                                System.out.println("====半天或者全天请假 =转化为8小时制下的时间=" + (ct.getAskLeaveTime() / 24 * 8.0));
+                                            //12小时以上的,是请假半天或者全天的。 防止1天有2次上下午分开的请假,导致计算两次的错误
+                                            ct.setAskLeaveTime(ct.getAskLeaveTime() / 24 * 8.0);//转换成一天8小时工作制
+                                        }
+                                    } else if (ct.getStartTime().compareTo(leaveStart) <= 0 && ct.getEndTime().compareTo(leaveEnd) >= 0) {
+                                        String hourLeaveTime = leaveText.replaceAll("请假", "").replaceAll("小时", "");
+                                        if (showLog) System.out.println("请假时长=" + hourLeaveTime);
 //                                        ct.setCardTime(ct.getCardTime() - Double.parseDouble(hourLeaveTime));
+                                    }
                                 }
                             }
                         }
-                    }
-                    //校正请假时长
-                    if (ct.getAskLeaveTime() != null && ct.getAskLeaveTime() == 24.0) {
-                        ct.setAskLeaveTime(8.0);//24小时为一天,修正为8小时
-                    }
-                    if (ct.getAskLeaveTime() > 8.0) {
-                        ct.setAskLeaveTime(8.0);//超过8小时都以8小时计算
-                    }
-                    if (showLog) System.out.println("校正后请假时长=" + ct.getAskLeaveTime());
-                    //如果有出差的,但是没有打卡,则用出差的时间作为timeDelta
-                    if (timeDelta < 8.0 && ct.getOutdoorTime() > 0) {
-                        timeDelta += ct.getOutdoorTime();
-                    }
-                    double workHours = timeDelta - ct.getAskLeaveTime();
-                    if (workHours < 0) {
-                        workHours = 0;
-                    }
-                    if (ct.getAskLeaveTime() >= 8.0) {
-                        //全天请假了,就不算打卡工作时长了。
-                        workHours = 0;
-                        //重新校正开始时间和结束时间
-                        ct.setStartTime(baseMorningStart);
-                        ct.setEndTime(baseAfternoonEnd);
-                    }
-                    if (showLog) System.out.println("工作时长==" + workHours);
-                    ct.setWorkHours(DateTimeUtil.getHoursFromDouble(workHours));
+                        //校正请假时长
+                        if (ct.getAskLeaveTime() != null && ct.getAskLeaveTime() == 24.0) {
+                            ct.setAskLeaveTime(8.0);//24小时为一天,修正为8小时
+                        }
+                        if (ct.getAskLeaveTime() > 8.0) {
+                            ct.setAskLeaveTime(8.0);//超过8小时都以8小时计算
+                        }
+                        if (showLog) System.out.println("校正后请假时长=" + ct.getAskLeaveTime());
+                        //如果有出差的,但是没有打卡,则用出差的时间作为timeDelta
+                        if (timeDelta < 8.0 && ct.getOutdoorTime() > 0) {
+                            timeDelta += ct.getOutdoorTime();
+                        }
+                        double workHours = timeDelta - ct.getAskLeaveTime();
+                        if (workHours < 0) {
+                            workHours = 0;
+                        }
+                        if (ct.getAskLeaveTime() >= 8.0) {
+                            //全天请假了,就不算打卡工作时长了。
+                            workHours = 0;
+                            //重新校正开始时间和结束时间
+                            ct.setStartTime(baseMorningStart);
+                            ct.setEndTime(baseAfternoonEnd);
+                        }
+                        if (showLog) System.out.println("工作时长==" + workHours);
+                        ct.setWorkHours(DateTimeUtil.getHoursFromDouble(workHours));
 //                        if (regular_work_sec < standard_work_sec) {
 //                            ct.setWorkHours(DateTimeUtil.getHoursFromDouble(ct.getCardTime() + ct.getOutdoorTime()));
 //                        } else {
 //                            ct.setWorkHours(DateTimeUtil.getHoursFromDouble(ct.getCardTime()));
 //                        }
-                    //仅有一次打卡,并且没有请假,外出的情况,需要补足下班的打卡时间
-                    if (ct.getStartTime().equals(ct.getEndTime()) && !"00:00".equals(ct.getStartTime())) {
-                        if (ct.getEndTime().compareTo(baseAfternoonEnd) < 0) {
-                            ct.setEndTime(baseAfternoonEnd);
-                            //重新计算时长
-                            double workTime = DateTimeUtil.getHoursFromSeconds(DateTimeUtil.getSecondsFromTime(ct.getEndTime()) - DateTimeUtil.getSecondsFromTime(ct.getStartTime()));
-                            if (ct.getStartTime().compareTo(baseMorningEnd) >= 0) {
-                                //重新计算打卡工时时,需要减去中间午休时间
-                                workTime -= restTime;
+                        //仅有一次打卡,并且没有请假,外出的情况,需要补足下班的打卡时间
+                        if (ct.getStartTime().equals(ct.getEndTime()) && !"00:00".equals(ct.getStartTime())) {
+                            if (ct.getEndTime().compareTo(baseAfternoonEnd) < 0) {
+                                ct.setEndTime(baseAfternoonEnd);
+                                //重新计算时长
+                                double workTime = DateTimeUtil.getHoursFromSeconds(DateTimeUtil.getSecondsFromTime(ct.getEndTime()) - DateTimeUtil.getSecondsFromTime(ct.getStartTime()));
+                                if (ct.getStartTime().compareTo(baseMorningEnd) >= 0) {
+                                    //重新计算打卡工时时,需要减去中间午休时间
+                                    workTime -= restTime;
+                                }
+                                ct.setCardTime(workTime);
+                                ct.setWorkHours(DateTimeUtil.getHoursFromDouble(workTime));
                             }
-                            ct.setCardTime(workTime);
-                            ct.setWorkHours(DateTimeUtil.getHoursFromDouble(workTime));
                         }
                     }
+
                     UserCorpwxTime item = userCorpwxTimeMapper.selectOne(new QueryWrapper<UserCorpwxTime>().eq("corpwx_userid", curUserid)
                             .eq("create_date", localDate));
                     if (item != null) {

+ 29 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/util/WorkDayCalculateUtils.java

@@ -119,6 +119,35 @@ public class WorkDayCalculateUtils {
         return list;
     }
 
+    /**
+     * 获取期间的非工作日
+     * @param startDate
+     * @param endDate
+     * @return
+     */
+    public static List<LocalDate> getNonWorkDaysListInRange(String startDate, String endDate) {
+        int daysOffset = 0;
+        LocalDate localStartDate = LocalDate.parse(startDate, dateTimeFormatter);
+        LocalDate localEndDate = LocalDate.parse(endDate, dateTimeFormatter);
+        List<LocalDate> list = new ArrayList<>();
+        while(true) {
+            localStartDate = localStartDate.plusDays(daysOffset);
+            if (!isWorkDay(localStartDate)) {
+                list.add(localStartDate);
+            }
+            //到达结束日期,结束计算
+            if (localStartDate.isEqual(localEndDate)) {
+                break;
+            }
+            //每次加一天
+            if (daysOffset == 0) {
+                daysOffset = 1;
+            }
+        }
+        return list;
+    }
+
+
     /**
      * 计算给定时间范围内的工作日天数
      * @param startDate