Browse Source

兼容正常工时模式

QuYueTing 3 days ago
parent
commit
7bd872361a

+ 33 - 6
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/UserCorpwxTimeController.java

@@ -1774,7 +1774,12 @@ public class UserCorpwxTimeController {
             // 处理第二个sheet:人员分配
             Sheet staffSheet = workbook.getSheetAt(1);
             System.out.println("正在处理第二个Sheet: " + staffSheet.getSheetName() + " (人员分配)");
-            List<Map<String, Object>> staffAllocationResult = processStaffAllocationSheet(year, staffSheet, companyId, allUserList);
+            HttpRespMsg staffAllocationMsg = processStaffAllocationSheet(year, staffSheet, companyId, allUserList);
+            if (staffAllocationMsg.code.equals("error")) {
+                //解析返回错误了,需要中断直接返回。
+                return staffAllocationMsg;
+            }
+            List<Map<String, Object>> staffAllocationResult = (List<Map<String, Object>>)msg.data;
             //检查系统中是否存在表格中员工没有参与的项目
             List<Project> projectList = projectMapper.selectList(new QueryWrapper<Project>().eq("company_id", companyId));
             List<Participation> participationList = participationMapper.selectList(new QueryWrapper<Participation>().in("project_id", projectList.stream().map(Project::getId).collect(Collectors.toList())));
@@ -2153,12 +2158,13 @@ public class UserCorpwxTimeController {
      * 前面7列是合并的多行数据,形成人员-项目的一对多关系,项目和月份又是一对多的关系
      * 返回员工-项目-可填月份的数据集合
      */
-    private List<Map<String, Object>> processStaffAllocationSheet(Integer startYear,Sheet staffSheet, Integer companyId, List<User> allUserList) {
+    private HttpRespMsg processStaffAllocationSheet(Integer startYear,Sheet staffSheet, Integer companyId, List<User> allUserList) {
+        HttpRespMsg msg = new HttpRespMsg();
         List<Map<String, Object>> result = new ArrayList<>();
         
         if (staffSheet.getLastRowNum() == 0) {
-            System.out.println("人员分配sheet中没有数据");
-            return result;
+            msg.setError("人员分配sheet中没有数据");
+            return msg;
         }
         
         // 解析表头,获取月份信息(从第12列开始)
@@ -2167,6 +2173,17 @@ public class UserCorpwxTimeController {
         LocalDate now = LocalDate.now();
         int startYearColIndex = -1;
         if (headerRow != null) {
+            String[] headerColumnFixed = new String[]{"序号", "姓名", "账号", "全职/兼职", "工种", "个人项目研发最晚结束时间", "入职时间"};
+            for (int colIndex = 0; colIndex < headerColumnFixed.length; colIndex++) {
+                Cell cell = headerRow.getCell(colIndex);
+                if (cell != null) {
+                    String cellValue = cell.getStringCellValue().trim();
+                    if (!cellValue.equals(headerColumnFixed[colIndex])) {
+                        msg.setError("人员分配表头不正确 ,第"+(colIndex+1)+"列应为["+headerColumnFixed[colIndex]+"]");
+                        return msg;
+                    }
+                }
+            }
             for (int colIndex = 11; colIndex < 11 + 24; colIndex++) { // 第12列开始(索引11)
                 Cell cell = headerRow.getCell(colIndex);
                 if (cell != null) {
@@ -2183,7 +2200,10 @@ public class UserCorpwxTimeController {
         }
         
         System.out.println("找到月份列: " + monthColumns);
-        if (monthColumns.size() == 0) return result;
+        if (monthColumns.size() == 0) {
+            msg.setError("找不到月份列");
+            return msg;
+        }
         // 收集所有员工姓名用于批量查询
         List<String> userNameList = new ArrayList<>();
         for (int rowIndex = 1; rowIndex <= staffSheet.getLastRowNum(); rowIndex++) {
@@ -2353,6 +2373,8 @@ public class UserCorpwxTimeController {
             } catch (Exception e) {
                 System.out.println("处理第" + (rowIndex + 1) + "行人员分配数据时出错: " + e.getMessage());
                 e.printStackTrace();
+                msg.setError("处理第" + (rowIndex + 1) + "行人员分配数据时出错: " + e.getMessage());
+                return msg;
             }
         }
         
@@ -2367,13 +2389,18 @@ public class UserCorpwxTimeController {
         // 打印未找到的用户
         if (!missingUser.isEmpty()) {
             System.out.println("未找到的用户:");
+            String strbuilder = "";
             for (User user : missingUser) {
                 System.out.println("姓名: " + user.getName() + ", 工号: " + user.getJobNumber());
+                strbuilder += "姓名: " + user.getName() + ", 工号: " + user.getJobNumber() + "\n";
             }
+            msg.setError("未找到的用户:" + strbuilder);
+            return msg;
         }
         
         System.out.println("处理完成,共生成 " + result.size() + " 条员工-项目-月份分配记录");
-        return result;
+        msg.setData(result);
+        return msg;
     }
     
     /**

+ 6 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/TimeType.java

@@ -3,6 +3,7 @@ package com.management.platform.entity;
 import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.extension.activerecord.Model;
+import com.sun.org.apache.xpath.internal.operations.Bool;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
 import lombok.experimental.Accessors;
@@ -727,6 +728,11 @@ public class TimeType extends Model<TimeType> {
     @TableField("is_project_closure")
     private Integer isProjectClosure;
 
+    /**
+     * 工时录入是否为正常工时
+     */
+    @TableField("time_input_normal")
+    private Boolean timeInputNormal;
 
 
     @TableField(exist = false)

+ 408 - 204
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ReportServiceImpl.java

@@ -10032,53 +10032,56 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
         HttpRespMsg msg = new HttpRespMsg();
         String userId = request.getHeader("TOKEN");
         User user = userMapper.selectById(userId);
-        //根据targetDate获取本周的日期
-        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd");
-        LocalDate date = LocalDate.parse(targetDate, dtf);
-        LocalDate firstDayOfWeek = date.with(DayOfWeek.MONDAY);
-        //需要填报的最后一天
-        LocalDate lastDayOfWeek = date.with(DayOfWeek.SUNDAY);
-//        int days = sunday.lengthOfMonth() - sunday.getDayOfMonth();
-//        if (days <= 3) {
-//            //周日距离月底相差天数在3天以内,比如周日是10.28,则10.29,10.30和10.31也算在本周内
-//            lastDayOfWeek = sunday.plusDays(days);
-//        }
-        //如果上周只有2天以内工作日,需要并到这周来
-//        LocalDate lastSunday = firstDayOfWeek.minusDays(1);
-//        LocalDate lastSaturday = lastSunday.with(DayOfWeek.SATURDAY);
-
-//        if (WorkDayCalculateUtils.isWorkDay(lastSunday) && WorkDayCalculateUtils.isWorkDay(lastSaturday)) {
-//            //合并上周的工作日的情况:上周周末两天是工作日,并且只有2天以内工作日,需要并到这周来
-//            LocalDate lastMonday = lastSunday.with(DayOfWeek.MONDAY);
-//            boolean hasMoreWorkDays = false;
-//            while (lastMonday.isBefore(lastSaturday)) {
-//                if (WorkDayCalculateUtils.isWorkDay(lastMonday)) {
-//                    hasMoreWorkDays = true;
-//                    break;
-//                }
-//                lastMonday = lastMonday.plusDays(1);
-//            }
-//            if (!hasMoreWorkDays) {
-//                firstDayOfWeek = lastSaturday;
-//            }
-//        } else {
-//            //剔除被合并到上周的情况,如果本周一周二周三中有工作日,但是是上个月的月末,会被合并到上周去,本周要去掉
-//            boolean hasFirstDayOfMonth = false;
-//            LocalDate checkDate = firstDayOfWeek;
-//            int beforeDays = 0;
-//            while (!checkDate.isAfter(lastDayOfWeek)) {
-//                if (checkDate.getDayOfMonth() == 1) {
-//                    hasFirstDayOfMonth = true;
-//                    break;
-//                } else {
-//                    beforeDays++;
-//                }
-//                checkDate = checkDate.plusDays(1);
-//            }
-//            if (hasFirstDayOfMonth && beforeDays <= 3) {
-//                firstDayOfWeek = checkDate;
-//            }
-//        }
+        TimeType timeType = timeTypeMapper.selectById(user.getCompanyId());
+        if (timeType.getEnableNewWeeklyfill() == 1) {
+            //根据targetDate获取本周的日期
+            DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+            LocalDate date = LocalDate.parse(targetDate, dtf);
+            LocalDate firstDayOfWeek = date.with(DayOfWeek.MONDAY);
+            LocalDate sunday = date.with(DayOfWeek.SUNDAY);
+            //需要填报的最后一天
+            LocalDate lastDayOfWeek = sunday;
+            int days = sunday.lengthOfMonth() - sunday.getDayOfMonth();
+            if (days <= 3) {
+                //周日距离月底相差天数在3天以内,比如周日是10.28,则10.29,10.30和10.31也算在本周内
+                lastDayOfWeek = sunday.plusDays(days);
+            }
+            //如果上周只有2天以内工作日,需要并到这周来
+            LocalDate lastSunday = firstDayOfWeek.minusDays(1);
+            LocalDate lastSaturday = lastSunday.with(DayOfWeek.SATURDAY);
+
+            if (WorkDayCalculateUtils.isWorkDay(lastSunday) && WorkDayCalculateUtils.isWorkDay(lastSaturday)) {
+                //合并上周的工作日的情况:上周周末两天是工作日,并且只有2天以内工作日,需要并到这周来
+                LocalDate lastMonday = lastSunday.with(DayOfWeek.MONDAY);
+                boolean hasMoreWorkDays = false;
+                while (lastMonday.isBefore(lastSaturday)) {
+                    if (WorkDayCalculateUtils.isWorkDay(lastMonday)) {
+                        hasMoreWorkDays = true;
+                        break;
+                    }
+                    lastMonday = lastMonday.plusDays(1);
+                }
+                if (!hasMoreWorkDays) {
+                    firstDayOfWeek = lastSaturday;
+                }
+            } else {
+                //剔除被合并到上周的情况,如果本周一周二周三中有工作日,但是是上个月的月末,会被合并到上周去,本周要去掉
+                boolean hasFirstDayOfMonth = false;
+                LocalDate checkDate = firstDayOfWeek;
+                int beforeDays = 0;
+                while (!checkDate.isAfter(lastDayOfWeek)) {
+                    if (checkDate.getDayOfMonth() == 1) {
+                        hasFirstDayOfMonth = true;
+                        break;
+                    } else {
+                        beforeDays++;
+                    }
+                    checkDate = checkDate.plusDays(1);
+                }
+                if (hasFirstDayOfMonth && beforeDays <= 3) {
+                    firstDayOfWeek = checkDate;
+                }
+            }
 
 //        if (WorkDayCalculateUtils.isWorkDay(firstDayOfWeek) && firstDayOfWeek.getDayOfMonth() >= 30) {
 //            firstDayOfWeek = firstDayOfWeek.plusDays(1);
@@ -10086,96 +10089,297 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
 //                firstDayOfWeek = firstDayOfWeek.plusDays(1);
 //            }
 //        }
-        //死代码 2025-01-27 周一 合并到1-26号那一周
-//        LocalDate specialDate = LocalDate.of(2025, 1, 27);
-//        if(lastDayOfWeek.plusDays(1).isEqual(specialDate)){
-//            lastDayOfWeek = specialDate;
-//        }
+            //死代码 2025-01-27 周一 合并到1-26号那一周
+            LocalDate specialDate = LocalDate.of(2025, 1, 27);
+            if(lastDayOfWeek.plusDays(1).isEqual(specialDate)){
+                lastDayOfWeek = specialDate;
+            }
 
 
 
-        //再按照当前用户的入职离职日期进行过滤
-        LocalDate entryDate = user.getInductionDate();
-        LocalDate leaveDate = user.getInactiveDate();
-        boolean needFill = true;
-        if (entryDate != null && entryDate.isAfter(firstDayOfWeek)) {
-            if (lastDayOfWeek.isBefore(entryDate)) {
-                //最后一天也在入职日期之前,不需要填报
-                needFill = false;
-            } else {
-                firstDayOfWeek = entryDate;
-            }
-        }
-        if (user.getIsActive()==0 && leaveDate != null && leaveDate.isBefore(lastDayOfWeek)) {
-            lastDayOfWeek = leaveDate;
-        }
-        Map<String, Object> reportMap = new HashMap<>();
-        if (needFill) {
-            String summary = null;
-            String attachment = null;
-            String startDate = firstDayOfWeek.format(dtf);
-            String endDate = lastDayOfWeek.format(dtf);
-            TimeType timeType = timeTypeMapper.selectById(user.getCompanyId());
-            //获取日报详情
-            List<Report> reportList = reportMapper.selectList(new QueryWrapper<Report>().eq("creator_id", userId).between("create_date", startDate, endDate).orderByAsc("create_date"));
-            //已填日报设置审核人姓名
-            if (reportList.size() > 0) {
-                Integer batchId = reportList.get(0).getBatchId();
-                if (batchId != null) {
-                    //获取周总结
-                    ReportBatch batch = reportBatchMapper.selectById(batchId);
-                    //老数据可能出现batchId错误的情况,已经被删掉了,就不处理了。
-                    if (batch != null) {
-                        summary = batch.getSummary();
-                        attachment = batch.getAttachment();
-                    }
-                }
-                List<String> collect = reportList.stream().map(Report::getProjectAuditorId).distinct().collect(Collectors.toList());
-                if (collect.size() > 0) {
-                    List<User> auditorUserList = userMapper.selectList(new QueryWrapper<User>().in("id", collect));
-                    reportList.forEach(r->{
-                        if (r.getProjectAuditorId() != null) {
-                            Optional<User> first = auditorUserList.stream().filter(au -> au.getId().equals(r.getProjectAuditorId())).findFirst();
-                            if (first.isPresent()) {
-                                r.setProjectAuditorName(first.get().getName());
+            //再按照当前用户的入职离职日期进行过滤
+            LocalDate entryDate = user.getInductionDate();
+            LocalDate leaveDate = user.getInactiveDate();
+            boolean needFill = true;
+            if (entryDate != null && entryDate.isAfter(firstDayOfWeek)) {
+                if (lastDayOfWeek.isBefore(entryDate)) {
+                    //最后一天也在入职日期之前,不需要填报
+                    needFill = false;
+                } else {
+                    firstDayOfWeek = entryDate;
+                }
+            }
+            if (user.getIsActive()==0 && leaveDate != null && leaveDate.isBefore(lastDayOfWeek)) {
+                lastDayOfWeek = leaveDate;
+            }
+            Map<String, Object> reportMap = new HashMap<>();
+            if (needFill) {
+                String summary = null;
+                String attachment = null;
+                String startDate = firstDayOfWeek.format(dtf);
+                String endDate = lastDayOfWeek.format(dtf);
+                //获取日报详情
+                List<Report> reportList = reportMapper.selectList(new QueryWrapper<Report>().eq("creator_id", userId).between("create_date", startDate, endDate).orderByAsc("create_date"));
+                //已填日报设置审核人姓名
+                if (reportList.size() > 0) {
+                    Integer batchId = reportList.get(0).getBatchId();
+                    if (batchId != null) {
+                        //获取周总结
+                        ReportBatch batch = reportBatchMapper.selectById(batchId);
+                        //老数据可能出现batchId错误的情况,已经被删掉了,就不处理了。
+                        if (batch != null) {
+                            summary = batch.getSummary();
+                            attachment = batch.getAttachment();
+                        }
+                    }
+                    List<String> collect = reportList.stream().map(Report::getProjectAuditorId).distinct().collect(Collectors.toList());
+                    if (collect.size() > 0) {
+                        List<User> auditorUserList = userMapper.selectList(new QueryWrapper<User>().in("id", collect));
+                        reportList.forEach(r->{
+                            if (r.getProjectAuditorId() != null) {
+                                Optional<User> first = auditorUserList.stream().filter(au -> au.getId().equals(r.getProjectAuditorId())).findFirst();
+                                if (first.isPresent()) {
+                                    r.setProjectAuditorName(first.get().getName());
+                                }
                             }
-                        }
-                    });
+                        });
+                    }
                 }
-            }
 
 
-            List<Integer> collect = reportList.stream().map(Report::getProjectId).collect(Collectors.toList());
-            final List<ReportExtraDegree> degreeList = reportExtraDegreeMapper.selectList(new QueryWrapper<ReportExtraDegree>().eq("company_id", user.getCompanyId()));
+                List<Integer> collect = reportList.stream().map(Report::getProjectId).collect(Collectors.toList());
+                final List<ReportExtraDegree> degreeList = reportExtraDegreeMapper.selectList(new QueryWrapper<ReportExtraDegree>().eq("company_id", user.getCompanyId()));
 
-            //加载这段时间内已填报过的项目
-            List<Project> projectList = new ArrayList<>();
-            if (collect.size() > 0) {
-                projectList = projectMapper.selectList(new QueryWrapper<Project>().in("id", collect));
-                final List<Project> finalProjectList = projectList;
-                //获取项目的任务分组列表
-
-
-                QueryWrapper<TaskGroup> taskGroupQueryWrapper = new QueryWrapper<TaskGroup>().in("project_id", collect);
-                if (timeType.getReportAuditType() == 1) {//分组负责人审核模式,需要按参与的任务分组显示
+                //加载这段时间内已填报过的项目
+                List<Project> projectList = new ArrayList<>();
+                if (collect.size() > 0) {
+                    projectList = projectMapper.selectList(new QueryWrapper<Project>().in("id", collect));
+                    final List<Project> finalProjectList = projectList;
+                    //获取项目的任务分组列表
                     //需要是他参与的任务分组
                     List<GroupParticipator> groupParticipatorList = groupParticipatorMapper.selectList(new QueryWrapper<GroupParticipator>().eq("user_id", userId));
                     List<Integer> joinGroupList = groupParticipatorList.stream().map(GroupParticipator::getGroupId).collect(Collectors.toList());
                     if (joinGroupList.size() > 0) {
-                        taskGroupQueryWrapper.in("id", joinGroupList);
-                    } else {
-                        taskGroupQueryWrapper.eq("id", -1);//没有分组
+                        List<TaskGroup> taskGroups = taskGroupMapper.selectList(new QueryWrapper<TaskGroup>().in("project_id", collect).in("id", joinGroupList));
+                        //获取负责人的用户集合
+                        List<String> inchargerIds = taskGroups.stream().map(TaskGroup::getInchargerId).collect(Collectors.toList());
+                        if (inchargerIds.size() == 0) {
+                            inchargerIds.add("-1");
+                        }
+                        List<User> userList = userMapper.selectList(new QueryWrapper<User>().in("id", inchargerIds));
+                        reportList.forEach(r->{
+                            r.setTaskGroups(taskGroups.stream().filter(tg->tg.getProjectId().equals(r.getProjectId())).collect(Collectors.toList()));
+                            for (TaskGroup gp : r.getTaskGroups()) {
+                                if (!StringUtils.isEmpty(gp.getInchargerId()) ) {
+                                    if (gp.getInchargerId().equals(userId)) {
+                                        //自己担任任务分组的负责人,自己的审核人是项目经理
+                                        gp.setInchargerId(projectMapper.selectById(r.getProjectId()).getInchargerId());
+                                        //如果自己就是项目经理,审核人变成自己的部门负责人
+                                        if (gp.getInchargerId().equals(userId)) {
+                                            Integer dpId = user.getDepartmentId();
+                                            if (dpId != null && dpId > 0) {
+                                                Department department = departmentMapper.selectById(dpId);
+                                                if (department != null) {
+                                                    gp.setInchargerId(department.getManagerId());
+                                                }
+                                            }
+                                        }
+                                        //不存在的话,加上项目经理
+                                        if (!userList.stream().anyMatch(u->u.getId().equals(gp.getInchargerId()))) {
+                                            userList.add(userMapper.selectById(gp.getInchargerId()));
+                                        }
+                                    }
+                                    Optional<User> first = userList.stream().filter(u -> u.getId().equals(gp.getInchargerId())).findFirst();
+                                    if (first.isPresent()) {
+                                        gp.setInchargerName(first.get().getName());
+                                    }
+                                }
+                            }
+                            //设置项目名称
+                            Optional<Project> optional = finalProjectList.stream().filter(p->p.getId().equals(r.getProjectId())).findFirst();
+                            if (optional.isPresent()) {
+                                r.setProjectName(optional.get().getProjectName());
+                            }
+                            //设置自定义维度
+                            if (timeType.getCustomDegreeActive() == 1) {
+                                if (timeType.getCustomDegreeWithPro() == 1) {
+                                    String associateDegrees = optional.get().getAssociateDegrees();
+                                    List<HashMap> degreeMapList = new ArrayList<>();
+                                    if (associateDegrees != null) {
+                                        String[] split = associateDegrees.split("\\,");
+                                        for (int i=0;i<split.length; i++) {
+                                            HashMap map = new HashMap();
+                                            if (!StringUtils.isEmpty(split[i])) {
+                                                Integer id = Integer.parseInt(split[i]);
+                                                map.put("id", id);
+                                                map.put("name", degreeList.stream().filter(d->d.getId().equals(id)).findFirst().get().getName());
+                                                degreeMapList.add(map);
+                                            }
+                                        }
+                                    }
+                                    r.setDegreeList(degreeMapList);
+                                } else {
+                                    //把degreeList改成HashMap结构
+                                    List<HashMap> mapDegreeList = new ArrayList<>();
+                                    for (ReportExtraDegree degree : degreeList) {
+                                        HashMap map = new HashMap();
+                                        map.put("id", degree.getId());
+                                        map.put("name", degree.getName());
+                                        mapDegreeList.add(map);
+                                    }
+                                    r.setDegreeList(mapDegreeList);
+                                }
+                            }
+                        });
                     }
                 }
-                List<TaskGroup> taskGroups = taskGroupMapper.selectList(taskGroupQueryWrapper);
-                //获取负责人的用户集合
-                List<String> inchargerIds = taskGroups.stream().map(TaskGroup::getInchargerId).collect(Collectors.toList());
-                if (inchargerIds.size() == 0) {
-                    inchargerIds.add("-1");
+
+                reportMap.put("projectList", projectList);
+                //计算日期,进行返回
+                List<HashMap> dateList = new ArrayList<>();
+                LocalDate today = LocalDate.now();
+                LocalDate itemDate = firstDayOfWeek;
+                while(true) {
+                    if (WorkDayCalculateUtils.isWorkDay(itemDate)) {
+                        HashMap item = new HashMap();
+                        item.put("date", itemDate.format(dtf));
+                        //计算显示的周几
+                        item.put("weekDayTxt", DateTimeUtil.getWeekDayTxt(itemDate.getDayOfWeek().getValue()));
+                        //不可提前填报
+                        if (timeType.getFillAhead() == 0 && itemDate.isAfter(today)) {
+                            item.put("canFill", 0);
+                        } else {
+                            item.put("canFill", 1);
+                        }
+                        //放入当天对应的日报
+                        final LocalDate finalItemDate = itemDate;
+                        List<Report> dateReportList = reportList.stream().filter(r -> r.getCreateDate().isEqual(finalItemDate)).collect(Collectors.toList());
+                        item.put("reportList", dateReportList);
+                        double sum = dateReportList.stream().mapToDouble(Report::getWorkingTime).sum();
+                        item.put("filledTime", sum);
+                        dateList.add(item);
+                    }
+                    //往后推一天
+                    itemDate = itemDate.plusDays(1);
+                    //超过最后一天了,跳出循环
+                    if (itemDate.isAfter(lastDayOfWeek)) {
+                        break;
+                    }
                 }
-                List<User> userList = userMapper.selectList(new QueryWrapper<User>().in("id", inchargerIds));
-                reportList.forEach(r->{
-                    r.setTaskGroups(taskGroups.stream().filter(tg->tg.getProjectId().equals(r.getProjectId())).collect(Collectors.toList()));
+                //241226 当日期为 25-01-27 周一 时,去掉列表
+                if(firstDayOfWeek.isEqual(specialDate)){
+                    dateList = new ArrayList<>();
+                }
+                reportMap.put("dateList", dateList);
+                //查询考勤请假状态
+                WxCorpInfo wxCorpInfo = wxCorpInfoMapper.selectOne(new QueryWrapper<WxCorpInfo>().eq("company_id", user.getCompanyId()));
+                if (wxCorpInfo != null && dateList.size() > 0) {
+                    List<UserCorpwxTime> userCorpwxTimeList = userCorpwxTimeMapper.selectList(new QueryWrapper<UserCorpwxTime>().eq("corpwx_userid", user.getCorpwxUserid()).in("create_date", dateList.stream().map(r -> (String) r.get("date")).collect(Collectors.toList())));
+                    for (HashMap item : dateList) {
+                        String curDate = (String) item.get("date");
+                        UserCorpwxTime userCorpwxTime = userCorpwxTimeList.stream().filter(r -> r.getCreateDate().isEqual(LocalDate.parse(curDate, DateTimeFormatter.ofPattern("yyyy-MM-dd")))).findFirst().orElse(null);
+                        if (userCorpwxTime != null) {
+                            item.put("time", userCorpwxTime);
+                        }
+                    }
+                }
+                reportMap.put("summary", summary);
+                reportMap.put("weeklyAttachment", attachment);
+            } else {
+                reportMap.put("dateList", new ArrayList());
+            }
+
+            msg.data = reportMap;
+            return msg;
+        } else {
+            //根据targetDate获取本周的日期
+            DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+            LocalDate date = LocalDate.parse(targetDate, dtf);
+            LocalDate firstDayOfWeek = date.with(DayOfWeek.MONDAY);
+            //需要填报的最后一天
+            LocalDate lastDayOfWeek = date.with(DayOfWeek.SUNDAY);
+
+            //再按照当前用户的入职离职日期进行过滤
+            LocalDate entryDate = user.getInductionDate();
+            LocalDate leaveDate = user.getInactiveDate();
+            boolean needFill = true;
+            if (entryDate != null && entryDate.isAfter(firstDayOfWeek)) {
+                if (lastDayOfWeek.isBefore(entryDate)) {
+                    //最后一天也在入职日期之前,不需要填报
+                    needFill = false;
+                } else {
+                    firstDayOfWeek = entryDate;
+                }
+            }
+            if (user.getIsActive()==0 && leaveDate != null && leaveDate.isBefore(lastDayOfWeek)) {
+                lastDayOfWeek = leaveDate;
+            }
+            Map<String, Object> reportMap = new HashMap<>();
+            if (needFill) {
+                String summary = null;
+                String attachment = null;
+                String startDate = firstDayOfWeek.format(dtf);
+                String endDate = lastDayOfWeek.format(dtf);
+                //获取日报详情
+                List<Report> reportList = reportMapper.selectList(new QueryWrapper<Report>().eq("creator_id", userId).between("create_date", startDate, endDate).orderByAsc("create_date"));
+                //已填日报设置审核人姓名
+                if (reportList.size() > 0) {
+                    Integer batchId = reportList.get(0).getBatchId();
+                    if (batchId != null) {
+                        //获取周总结
+                        ReportBatch batch = reportBatchMapper.selectById(batchId);
+                        //老数据可能出现batchId错误的情况,已经被删掉了,就不处理了。
+                        if (batch != null) {
+                            summary = batch.getSummary();
+                            attachment = batch.getAttachment();
+                        }
+                    }
+                    List<String> collect = reportList.stream().map(Report::getProjectAuditorId).distinct().collect(Collectors.toList());
+                    if (collect.size() > 0) {
+                        List<User> auditorUserList = userMapper.selectList(new QueryWrapper<User>().in("id", collect));
+                        reportList.forEach(r->{
+                            if (r.getProjectAuditorId() != null) {
+                                Optional<User> first = auditorUserList.stream().filter(au -> au.getId().equals(r.getProjectAuditorId())).findFirst();
+                                if (first.isPresent()) {
+                                    r.setProjectAuditorName(first.get().getName());
+                                }
+                            }
+                        });
+                    }
+                }
+
+
+                List<Integer> collect = reportList.stream().map(Report::getProjectId).collect(Collectors.toList());
+                final List<ReportExtraDegree> degreeList = reportExtraDegreeMapper.selectList(new QueryWrapper<ReportExtraDegree>().eq("company_id", user.getCompanyId()));
+
+                //加载这段时间内已填报过的项目
+                List<Project> projectList = new ArrayList<>();
+                if (collect.size() > 0) {
+                    projectList = projectMapper.selectList(new QueryWrapper<Project>().in("id", collect));
+                    final List<Project> finalProjectList = projectList;
+                    //获取项目的任务分组列表
+
+
+                    QueryWrapper<TaskGroup> taskGroupQueryWrapper = new QueryWrapper<TaskGroup>().in("project_id", collect);
+                    if (timeType.getReportAuditType() == 1) {//分组负责人审核模式,需要按参与的任务分组显示
+                        //需要是他参与的任务分组
+                        List<GroupParticipator> groupParticipatorList = groupParticipatorMapper.selectList(new QueryWrapper<GroupParticipator>().eq("user_id", userId));
+                        List<Integer> joinGroupList = groupParticipatorList.stream().map(GroupParticipator::getGroupId).collect(Collectors.toList());
+                        if (joinGroupList.size() > 0) {
+                            taskGroupQueryWrapper.in("id", joinGroupList);
+                        } else {
+                            taskGroupQueryWrapper.eq("id", -1);//没有分组
+                        }
+                    }
+                    List<TaskGroup> taskGroups = taskGroupMapper.selectList(taskGroupQueryWrapper);
+                    //获取负责人的用户集合
+                    List<String> inchargerIds = taskGroups.stream().map(TaskGroup::getInchargerId).collect(Collectors.toList());
+                    if (inchargerIds.size() == 0) {
+                        inchargerIds.add("-1");
+                    }
+                    List<User> userList = userMapper.selectList(new QueryWrapper<User>().in("id", inchargerIds));
+                    reportList.forEach(r->{
+                        r.setTaskGroups(taskGroups.stream().filter(tg->tg.getProjectId().equals(r.getProjectId())).collect(Collectors.toList()));
 //                    for (TaskGroup gp : r.getTaskGroups()) {
 //                        if (!StringUtils.isEmpty(gp.getInchargerId()) ) {
 //                            if (gp.getInchargerId().equals(userId)) {
@@ -10202,96 +10406,96 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
 //                            }
 //                        }
 //                    }
-                    //设置项目名称
-                    Optional<Project> optional = finalProjectList.stream().filter(p->p.getId().equals(r.getProjectId())).findFirst();
-                    if (optional.isPresent()) {
-                        r.setProjectName(optional.get().getProjectName());
-                    }
-                    //设置自定义维度
-                    if (timeType.getCustomDegreeActive() == 1) {
-                        if (timeType.getCustomDegreeWithPro() == 1) {
-                            String associateDegrees = optional.get().getAssociateDegrees();
-                            List<HashMap> degreeMapList = new ArrayList<>();
-                            if (associateDegrees != null) {
-                                String[] split = associateDegrees.split("\\,");
-                                for (int i=0;i<split.length; i++) {
-                                    HashMap map = new HashMap();
-                                    if (!StringUtils.isEmpty(split[i])) {
-                                        Integer id = Integer.parseInt(split[i]);
-                                        map.put("id", id);
-                                        map.put("name", degreeList.stream().filter(d->d.getId().equals(id)).findFirst().get().getName());
-                                        degreeMapList.add(map);
+                        //设置项目名称
+                        Optional<Project> optional = finalProjectList.stream().filter(p->p.getId().equals(r.getProjectId())).findFirst();
+                        if (optional.isPresent()) {
+                            r.setProjectName(optional.get().getProjectName());
+                        }
+                        //设置自定义维度
+                        if (timeType.getCustomDegreeActive() == 1) {
+                            if (timeType.getCustomDegreeWithPro() == 1) {
+                                String associateDegrees = optional.get().getAssociateDegrees();
+                                List<HashMap> degreeMapList = new ArrayList<>();
+                                if (associateDegrees != null) {
+                                    String[] split = associateDegrees.split("\\,");
+                                    for (int i=0;i<split.length; i++) {
+                                        HashMap map = new HashMap();
+                                        if (!StringUtils.isEmpty(split[i])) {
+                                            Integer id = Integer.parseInt(split[i]);
+                                            map.put("id", id);
+                                            map.put("name", degreeList.stream().filter(d->d.getId().equals(id)).findFirst().get().getName());
+                                            degreeMapList.add(map);
+                                        }
                                     }
                                 }
+                                r.setDegreeList(degreeMapList);
+                            } else {
+                                //把degreeList改成HashMap结构
+                                List<HashMap> mapDegreeList = new ArrayList<>();
+                                for (ReportExtraDegree degree : degreeList) {
+                                    HashMap map = new HashMap();
+                                    map.put("id", degree.getId());
+                                    map.put("name", degree.getName());
+                                    mapDegreeList.add(map);
+                                }
+                                r.setDegreeList(mapDegreeList);
                             }
-                            r.setDegreeList(degreeMapList);
-                        } else {
-                            //把degreeList改成HashMap结构
-                            List<HashMap> mapDegreeList = new ArrayList<>();
-                            for (ReportExtraDegree degree : degreeList) {
-                                HashMap map = new HashMap();
-                                map.put("id", degree.getId());
-                                map.put("name", degree.getName());
-                                mapDegreeList.add(map);
-                            }
-                            r.setDegreeList(mapDegreeList);
                         }
-                    }
-                });
-            }
-
-            reportMap.put("projectList", projectList);
-            //计算日期,进行返回
-            List<HashMap> dateList = new ArrayList<>();
-            LocalDate today = LocalDate.now();
-            LocalDate itemDate = firstDayOfWeek;
-            while(true) {
-                HashMap item = new HashMap();
-                item.put("date", itemDate.format(dtf));
-                //计算显示的周几
-                item.put("weekDayTxt", DateTimeUtil.getWeekDayTxt(itemDate.getDayOfWeek().getValue()));
-                //不可提前填报
-                if (timeType.getFillAhead() == 0 && itemDate.isAfter(today)) {
-                    item.put("canFill", 0);
-                } else {
-                    item.put("canFill", 1);
+                    });
                 }
-                //放入当天对应的日报
-                final LocalDate finalItemDate = itemDate;
-                List<Report> dateReportList = reportList.stream().filter(r -> r.getCreateDate().isEqual(finalItemDate)).collect(Collectors.toList());
-                item.put("reportList", dateReportList);
-                double sum = dateReportList.stream().mapToDouble(Report::getWorkingTime).sum();
-                item.put("filledTime", sum);
-                dateList.add(item);
-                //往后推一天
-                itemDate = itemDate.plusDays(1);
-                //超过最后一天了,跳出循环
-                if (itemDate.isAfter(lastDayOfWeek)) {
-                    break;
+
+                reportMap.put("projectList", projectList);
+                //计算日期,进行返回
+                List<HashMap> dateList = new ArrayList<>();
+                LocalDate today = LocalDate.now();
+                LocalDate itemDate = firstDayOfWeek;
+                while(true) {
+                    HashMap item = new HashMap();
+                    item.put("date", itemDate.format(dtf));
+                    //计算显示的周几
+                    item.put("weekDayTxt", DateTimeUtil.getWeekDayTxt(itemDate.getDayOfWeek().getValue()));
+                    //不可提前填报
+                    if (timeType.getFillAhead() == 0 && itemDate.isAfter(today)) {
+                        item.put("canFill", 0);
+                    } else {
+                        item.put("canFill", 1);
+                    }
+                    //放入当天对应的日报
+                    final LocalDate finalItemDate = itemDate;
+                    List<Report> dateReportList = reportList.stream().filter(r -> r.getCreateDate().isEqual(finalItemDate)).collect(Collectors.toList());
+                    item.put("reportList", dateReportList);
+                    double sum = dateReportList.stream().mapToDouble(Report::getWorkingTime).sum();
+                    item.put("filledTime", sum);
+                    dateList.add(item);
+                    //往后推一天
+                    itemDate = itemDate.plusDays(1);
+                    //超过最后一天了,跳出循环
+                    if (itemDate.isAfter(lastDayOfWeek)) {
+                        break;
+                    }
                 }
-            }
-            reportMap.put("dateList", dateList);
-            //查询考勤请假状态
-            WxCorpInfo wxCorpInfo = wxCorpInfoMapper.selectOne(new QueryWrapper<WxCorpInfo>().eq("company_id", user.getCompanyId()));
-            if (wxCorpInfo != null && dateList.size() > 0) {
-                List<UserCorpwxTime> userCorpwxTimeList = userCorpwxTimeMapper.selectList(new QueryWrapper<UserCorpwxTime>().eq("corpwx_userid", user.getCorpwxUserid()).in("create_date", dateList.stream().map(r -> (String) r.get("date")).collect(Collectors.toList())));
-                for (HashMap item : dateList) {
-                    String curDate = (String) item.get("date");
-                    UserCorpwxTime userCorpwxTime = userCorpwxTimeList.stream().filter(r -> r.getCreateDate().isEqual(LocalDate.parse(curDate, DateTimeFormatter.ofPattern("yyyy-MM-dd")))).findFirst().orElse(null);
-                    if (userCorpwxTime != null) {
-                        item.put("time", userCorpwxTime);
+                reportMap.put("dateList", dateList);
+                //查询考勤请假状态
+                WxCorpInfo wxCorpInfo = wxCorpInfoMapper.selectOne(new QueryWrapper<WxCorpInfo>().eq("company_id", user.getCompanyId()));
+                if (wxCorpInfo != null && dateList.size() > 0) {
+                    List<UserCorpwxTime> userCorpwxTimeList = userCorpwxTimeMapper.selectList(new QueryWrapper<UserCorpwxTime>().eq("corpwx_userid", user.getCorpwxUserid()).in("create_date", dateList.stream().map(r -> (String) r.get("date")).collect(Collectors.toList())));
+                    for (HashMap item : dateList) {
+                        String curDate = (String) item.get("date");
+                        UserCorpwxTime userCorpwxTime = userCorpwxTimeList.stream().filter(r -> r.getCreateDate().isEqual(LocalDate.parse(curDate, DateTimeFormatter.ofPattern("yyyy-MM-dd")))).findFirst().orElse(null);
+                        if (userCorpwxTime != null) {
+                            item.put("time", userCorpwxTime);
+                        }
                     }
                 }
+                reportMap.put("summary", summary);
+                reportMap.put("weeklyAttachment", attachment);
+            } else {
+                reportMap.put("dateList", new ArrayList());
             }
-            reportMap.put("summary", summary);
-            reportMap.put("weeklyAttachment", attachment);
-        } else {
-            reportMap.put("dateList", new ArrayList());
-        }
 
-
-        msg.data = reportMap;
-        return msg;
+            msg.data = reportMap;
+            return msg;
+        }
     }
 
     @Override
@@ -14551,7 +14755,6 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
             
             // 生成Excel文件导出
             String fileName = "日报列表_" + startDate + "至" + endDate + "_" + System.currentTimeMillis();
-            System.out.println("到处日报文件==>" + fileName);
             return excelExportService.exportGeneralExcelByTitleAndList(wxCorpInfo, dingding, fileName, dataList, path);
             
         } catch (Exception e) {
@@ -14992,6 +15195,7 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
             titles.add("是否为异常申报");
             titles.add("日报汇报日期");
             titles.add("填写人");
+            titles.add("填报时间");
             titles.add("当日考勤记录");
             titles.add("当日加班申请");
 
@@ -15031,7 +15235,7 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
                 } else {
                     item.add((String) map.get("userName"));
                 }
-
+                item.add((String) map.get("createTime"));
                 //考勤
                 item.add(map.get("cardRecord") != null ? (String) map.get("cardRecord") : "");
 

+ 2 - 11
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/WxCorpInfoServiceImpl.java

@@ -1206,10 +1206,6 @@ public class WxCorpInfoServiceImpl extends ServiceImpl<WxCorpInfoMapper, WxCorpI
                             userCorpwxTimeMapper.insert(userCorpwxTime);
                         }
                     }
-                    //处理曦合超导的加班补贴
-                    if (corpInfo.getCompanyId() == Constant.XI_HE_CHAO_DAO_COMPANY_ID || corpInfo.getCompanyId() == Constant.XI_HE_CHAO_DAO_JIA_XING_COMPANY_ID || corpInfo.getCompanyId() == 8128) {
-//                        handleAllowance(userCorpwxTime, baseMorningStart, baseMorningEnd, baseAfternoonStart, baseAfternoonEnd, restTime);
-                    }
                 }
             }
         }
@@ -1865,9 +1861,10 @@ public class WxCorpInfoServiceImpl extends ServiceImpl<WxCorpInfoMapper, WxCorpI
                         double timeDelta = 0;
                         //时间有变化,需要重新计算
                         if (needRecaculate) {
+//                            DateTimeUtil.calculateWorkHours(ct.getStartTime(), ct.getEndTime());
                             timeDelta = DateTimeUtil.getHoursFromSeconds(DateTimeUtil.getSecondsFromTime(ct.getEndTime()) - DateTimeUtil.getSecondsFromTime(ct.getStartTime()));
                             //超过下午上班的开始时间,需要减去午休的时间
-                            if (ct.getEndTime().compareTo(baseAfternoonStart) >= 0) {
+                            if (ct.getStartTime().compareTo(baseMorningEnd) <= 0 && ct.getEndTime().compareTo(baseAfternoonStart) >= 0) {
                                 //重新计算打卡工时时,需要减去中间午休时间
                                 timeDelta -= restTime;
                             }
@@ -2160,17 +2157,11 @@ public class WxCorpInfoServiceImpl extends ServiceImpl<WxCorpInfoMapper, WxCorpI
                                 if (showLog) System.out.println("更新考勤记录"+curUserid+", "+localDate);
                                 userCorpwxTimeMapper.updateById(ct);
                             }
-                            if (corpInfo.getCompanyId() == Constant.XI_HE_CHAO_DAO_COMPANY_ID || corpInfo.getCompanyId() == Constant.XI_HE_CHAO_DAO_JIA_XING_COMPANY_ID || corpInfo.getCompanyId() == 8128) {
-//                                handleAllowance(item, baseMorningStart, baseMorningEnd, baseAfternoonStart, baseAfternoonEnd, restTime);
-                            }
                         }
                     } else {
                         if (hasTimeRecord) {
                             if (showLog) System.out.println("插入考勤记录"+curUserid+", "+localDate);
                             userCorpwxTimeMapper.insert(ct);
-                            if (corpInfo.getCompanyId() == Constant.XI_HE_CHAO_DAO_COMPANY_ID || corpInfo.getCompanyId() == Constant.XI_HE_CHAO_DAO_JIA_XING_COMPANY_ID || corpInfo.getCompanyId() == 8128) {
-//                                handleAllowance(ct, baseMorningStart, baseMorningEnd, baseAfternoonStart, baseAfternoonEnd, restTime);
-                            }
 
                         } else {
                             //调用打卡详情去获取,弥补外出打卡且时间不在自动同步范围内的情况; 仅对工作日有效

File diff suppressed because it is too large
+ 2 - 1
fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/TimeTypeMapper.xml


+ 9 - 3
fhKeeper/formulahousekeeper/octopus/src/views/customer/list.vue

@@ -257,7 +257,13 @@
                     <el-form-item><el-checkbox v-model="dialogData.projectManDay">是否开启项目人天字段</el-checkbox></el-form-item>
                     <el-form-item><el-checkbox v-model="dialogData.projectCustom">是否开启项目自定义表单</el-checkbox></el-form-item>
                     <el-form-item><el-checkbox v-model="dialogData.easyExpense">是否开启简易费用报销</el-checkbox></el-form-item>
-                    <el-form-item><el-checkbox v-model="dialogData.enableNewWeeklyfill">是否启用新的按周填报模式</el-checkbox></el-form-item>
+                    <el-form-item>按周填报模式
+                        <el-select v-model="dialogData.enableNewWeeklyfill" size="small">
+                            <el-option :value="0" label="0-旧版"></el-option>
+                            <el-option :value="1" label="1-新版(物奇)"></el-option>
+                            <el-option :value="2" label="2-新版通用"></el-option>
+                        </el-select>
+                    </el-form-item>
                     <el-form-item><el-checkbox v-model="dialogData.hideSubproject">是否去除子项目</el-checkbox></el-form-item>
                     <el-form-item><el-checkbox v-model="dialogData.userWithMultiDept">是否开启人员设置可填报部门</el-checkbox></el-form-item>
                     <el-form-item><el-checkbox v-model="dialogData.importReportAuditNormal">导入的日报正常审批</el-checkbox></el-form-item>
@@ -515,7 +521,7 @@ import App from '../../App.vue';
                             this.$set(this.dialogData,'projectManDay',res.data.projectManDay ? true : false)
                             this.$set(this.dialogData,'projectCustom',res.data.projectCustom ? true : false)
                             this.$set(this.dialogData,'easyExpense',res.data.easyExpense ? true : false)
-                            this.$set(this.dialogData,'enableNewWeeklyfill',res.data.enableNewWeeklyfill ? true : false)
+                            this.$set(this.dialogData,'enableNewWeeklyfill',res.data.enableNewWeeklyfill)
                             this.$set(this.dialogData,'hideSubproject',res.data.hideSubproject ? true : false)
                             this.$set(this.dialogData,'userWithMultiDept',res.data.userWithMultiDept ? true : false)
                             this.$set(this.dialogData,'taskFileCharge',res.data.taskFileCharge ? true : false) 
@@ -867,7 +873,7 @@ import App from '../../App.vue';
                     projectManDay: this.dialogData.projectManDay ? 1 : 0,
                     projectCustom: this.dialogData.projectCustom ? 1 : 0,
                     easyExpense: this.dialogData.easyExpense ? 1 : 0,
-                    enableNewWeeklyfill: this.dialogData.enableNewWeeklyfill ? 1 : 0,
+                    enableNewWeeklyfill: this.dialogData.enableNewWeeklyfill,
                     hideSubproject:this.dialogData.hideSubproject ? 1: 0, 
                     userWithMultiDept:this.dialogData.userWithMultiDept ? 1: 0, 
                     taskFileCharge:this.dialogData.taskFileCharge ? 1: 0, 

+ 89 - 78
fhKeeper/formulahousekeeper/timesheet/src/views/workReport/daily.vue

@@ -389,8 +389,8 @@
         </el-dialog>
 
         <!-- 填写日报的dialog -->
-        <el-dialog :title="isSubstitude?$t('textLink.helpToFillIn'):editTitle[isBatch]" :visible.sync="dialogVisible" width="60%" :close-on-click-modal="false" @closed="guanbi()" :top="'5.5vh'" custom-class="editReportDialog" ref="editReportDialog">
-            <div style="height: 65vh;overflow: auto;">
+        <el-dialog :title="isSubstitude?$t('textLink.helpToFillIn'):editTitle[isBatch]" :visible.sync="dialogVisible" width="60%" :close-on-click-modal="false" @closed="guanbi()" :top="'5.2vh'" custom-class="editReportDialog" ref="editReportDialog">
+            <div style="height: 70vh;overflow: auto;">
                 <div style="margin:0 120px 10px 120px;position:relative;" v-if="user.company.enableAi && this.workForm.domains.filter(item=>!item.canEdit).length == 0 && !isSubstitude && !isBatch">
                     <div style="display:flex;align-items:flex-start;gap:10px;">
                         <el-input v-model="userInputMsg" type="textarea" :rows="2" placeholder="样例:今天/昨天/本周三... [A项目], 3小时,做了产品的需求分析;[B项目],5小时,进行技术文档编写。(按Ctrl+Enter快速提交) 当前免费体验" clearable 
@@ -399,7 +399,7 @@
                     </div>
                     <div style="margin-top:5px;"><el-tag size="mini" :key="word.value" effect="plain" v-for="word in quickWords" @click="fillWord(word)">{{ word }}</el-tag></div>
                 </div>
-                <el-form ref="workForm" :model="workForm" :rules="workRules" label-width="120px">
+                <el-form ref="workForm" :model="workForm" :rules="workRules" label-width="120px" >
                     <el-form-item :label="$t('screening.selectPeople')" v-if="isSubstitude">
                         <el-input v-if="user.userNameNeedTranslate != 1" @focus="showChooseMembTree" v-model="workForm.userNames"
                         :placeholder="$t('defaultText.pleaseSelectAsubstitute')" style="width:200px;"></el-input>
@@ -513,12 +513,12 @@
                     <!--加班申请时长-->
                     <el-form-item label="已通过加班申请" v-if="workForm.overtime"><span style="color:#FFA500;">{{ workForm.overtime.toFixed(1) }} h</span></el-form-item>
                     <!-- 000000 -->
-                    <div v-for="(domain, index) in workForm.domains" :key="domain.id" :style="index>0?'padding-top:25px;':''" >
+                    <div v-for="(domain, index) in workForm.domains" :key="domain.id" class="time_box" :style="index>0?'border-top: none;':''" >
                         <div v-if="reportTimeType.multiWorktime==0">
-                        <!-- <template v-if="user.companyId == 10">
+                        <template v-if="user.timeType.timeInputNormal">
                             <el-form-item v-if="!(permissions.reportHideWorkingHours && workForm.domains[index].state == 1)" label="正常工时" :prop="'domains.' + index + '.'+timeFields[reportTimeType.type]"
                                 :rules="{ required: true, message: '请选择正常工作时长', trigger: 'blur' }">
-                                <el-select v-model="domain.totalWorkingTime" style="width:200px;"
+                                <el-select v-model="domain.normalWorkingTime" style="width:200px;"
                                 v-if="reportTimeType.type == 1"
                                 :disabled="workForm.domains.length==0?true:(workForm.domains[index].state>=2?false:true)"
                                 placeholder="请选择正常工作时长"
@@ -526,16 +526,15 @@
                                 default-first-option
                                 @change="seleChn(0,domain)">
                                 <el-option v-for="item in timeRange" :key="item" :value="item.toFixed(1)">{{item.toFixed(1)}}</el-option>
-                                </el-select>
-                                <span v-if="reportTimeType.type == 1">小时</span>
+                                </el-select>&nbsp;小时
                                 <div class="overtime" v-if="user.timeType.fillOvertime || (isWeekend && user.timeType.lockWorktime != 1)">
-                                    <el-checkbox :disabled="!domain.canEdit" v-model="domain.isOvertime">额外加班工时</el-checkbox>
-                                    <el-input :disabled="!domain.canEdit || domain.isOvertime==null || domain.isOvertime==0 || !domain.isOvertime" v-model="domain.overtimeHours" @blur="triggerCalculateOT(index)" @input="domain.overtimeHours=domain.overtimeHours.replace(/[^\d.]/g,'')" style="width: 100px;"></el-input><span style="margin-left:5px">{{$t('time.hour')}}</span>
+                                    <el-checkbox :disabled="!domain.canEdit" v-model="domain.isOvertime" @change="seleChn(0,domain)">额外加班工时</el-checkbox>
+                                    <el-input :disabled="!domain.canEdit || domain.isOvertime==null || domain.isOvertime==0 || !domain.isOvertime" v-model="domain.overtimeHours" @blur="(user.timeType.timeInputNormal?seleChn(0, domain):null);triggerCalculateOT(index)" @input="domain.overtimeHours=domain.overtimeHours.replace(/[^\d.]/g,'')" style="width: 100px;"></el-input><span style="margin-left:5px">{{$t('time.hour')}}</span>
                                 </div>
-                                ,&nbsp;&nbsp;总工时:{{ parseFloat(domain.totalWorkingTime||0) + parseFloat(domain.overtimeHours || 0)}} 小时
+                                ,&nbsp;&nbsp;合计:{{ domain.workingTime }} 小时
                             </el-form-item>
                         </template>
-                        <template v-else> -->
+                        <template v-else>
                             <el-form-item v-if="reportTimeType.type != 3 && !(permissions.reportHideWorkingHours && workForm.domains[index].state == 1)" :label="reportTimeType.type ==2?$t('screening.workHours'):$t('screening.workTime')" :prop="'domains.' + index + '.'+timeFields[reportTimeType.type]"
                                 :rules="{ required: true, message: $t('defaultText.pleaseSelectWorkingHours'), trigger: 'blur' }">
                                 <el-select v-model="domain.timeType" style="width:200px;"
@@ -598,8 +597,7 @@
                                     <el-input :disabled="!domain.canEdit || domain.isOvertime==null || domain.isOvertime==0 || !domain.isOvertime" v-model="domain.overtimeHours" @blur="triggerCalculateOT(index)" @input="domain.overtimeHours=domain.overtimeHours.replace(/[^\d.]/g,'')" style="width: 100px;"></el-input><span style="margin-left:5px">{{$t('time.hour')}}</span>
                                 </div>
                             </el-form-item>
-
-                        <!-- </template> -->
+                        </template>
                         
                         <el-form-item :label="$t('tianBaoBuMen')" v-if="user.timeType.userWithMultiDept == 1 && userReportDeptList.length > 0"
                             :prop="'domains.' + index + '.reportTargetDeptId'"
@@ -1091,24 +1089,17 @@
                             </div>
                             <el-link size="small" @click="addNewWorktime(index, domain)" style="margin-left:15px;margin-top:5px;margin-bottom:5px;">{{$t('other.AddWorkTime')}}</el-link>
                         </div>
-
-                        <!--照片的显示 -->
-                        <!-- <p v-if="domain.pics != null && domain.pics.length > 0" style="text-align:center;"> 
-                            <el-image v-for="(pic, index) in domain.pics" :key="index"
-                                style="width: 100px; height: 100px; margin-right:10px;"
-                                :src="pic" 
-                                :preview-src-list="domain.pics">
-                            </el-image>
-                        </p>
-                        <el-divider v-if="workForm.domains.length>1" style="margin-bottom:10px;"></el-divider> -->
-
                     </div>
                     <span id="workFormsItemBottom"></span>
                     <template v-if="yonghuUser.type != 3">
-                        <el-link v-if="showAddMore" type="primary" :underline="false" @click="addDomain(reportTimeType.type)" style="margin-left:40px;">{{$t('other.addMore')}}</el-link>
+                        <div v-if="showAddMore" style="text-align: center;">
+                            <el-button type="primary" plain :underline="false" @click="addDomain(reportTimeType.type)" style="width: 300px;margin-top:10px;">+ 添加更多项目</el-button>
+                        </div>
                     </template>
                     <template v-if="yonghuUser.type == 3">
-                        <el-link v-if="canEdit" type="primary" :underline="false" @click="addDomain(reportTimeType.type)" style="margin-left:40px;">{{$t('other.addMore')}}</el-link>
+                        <div v-if="canEdit" style="text-align: center;">
+                            <el-button type="primary" plain :underline="false" @click="addDomain(reportTimeType.type)" style="width: 300px;margin-top:10px;">+ 添加更多项目</el-button>
+                        </div>
                     </template>
                 </el-form>
             </div>
@@ -4666,6 +4657,12 @@
                     this.seleChn(0)
                 }
             },
+            calculateWorkingTime(domain) {
+                if (domain != null && this.user.timeType.timeInputNormal) {
+                    //需要计算合计工时
+                    domain.workingTime = parseFloat(domain.normalWorkingTime||0) + (domain.isOvertime?parseFloat(domain.overtimeHours||0):0.0);
+                }
+            },
             seleChn(e,domain) {
                 if(e == 1) {
                     for(var i in this.workForm.domains) {
@@ -4676,6 +4673,9 @@
                         }
                     }
                 }
+                if (this.user.timeType.timeInputNormal) {
+                    this.calculateWorkingTime(domain);
+                }
                 var quanbu = 0 
                 var spl = this.workForm.domains
                 var zhi = ''
@@ -4686,65 +4686,67 @@
                 }
                 this.jsTime = quanbu
                 this.totalReportHours = quanbu
-                let worktime = this.jsTime
-                
-                // 自动计算加班时长
-                if(this.isBatch != 0){
-                    worktime = this.jsTime / this.jsDay
-                }
-                if(this.user.timeType.fillOvertime && domain){
-                    let isover = false
-                    let alltime = 0
-                    let allover = 0     //此处alltime同上面的worktime
-                    for(let d in spl){
-                        if(spl[d].isOvertime){
-                            isover = true
-                            allover += spl[d].overtimeHours*1
-                        }
-                        alltime += spl[d].workingTime*1
-                    }
-                    if(domain.overtimeHours){
-                        allover = allover - domain.overtimeHours
-                    }
-                    if(worktime*1 > this.user.timeType.allday){
-                        if(isover){
-                            if(alltime > (allover + this.user.timeType.allday)){
-                                    this.$set(domain,'isOvertime',true)
-                                    this.$set(domain,'overtimeHours',worktime - this.user.timeType.allday - allover)
-                            }else{
-                                this.$set(domain,'isOvertime',false)
-                                this.$set(domain,'overtimeHours',null)
-                                if(alltime < (allover + this.user.timeType.allday)){
-                                    let overtime = allover + this.user.timeType.allday - alltime
-                                    for(let pi in spl){
-                                        if(spl[pi].overtimeHours){
-                                            if((overtime - spl[pi].overtimeHours*1) > 0){
-                                                overtime = overtime - spl[pi].overtimeHours*1
-                                                this.$set(spl[pi],'isOvertime',false)
-                                                this.$set(spl[pi],'overtimeHours',null)
-                                            }else if((overtime - spl[pi].overtimeHours*1) < 0){
-                                                this.$set(spl[pi],'overtimeHours',spl[pi].overtimeHours*1 - overtime)
-                                                break
-                                            }else{
-                                                this.$set(spl[pi],'isOvertime',false)
-                                                this.$set(spl[pi],'overtimeHours',null)
-                                                break
+                if (!this.user.timeType.timeInputNormal) {
+                    let worktime = this.jsTime
+                    // 自动计算加班时长
+                    if(this.isBatch != 0){
+                        worktime = this.jsTime / this.jsDay
+                    }
+                    if(this.user.timeType.fillOvertime && domain){
+                        let isover = false
+                        let alltime = 0
+                        let allover = 0     //此处alltime同上面的worktime
+                        for(let d in spl){
+                            if(spl[d].isOvertime){
+                                isover = true
+                                allover += spl[d].overtimeHours*1
+                            }
+                            alltime += spl[d].workingTime*1
+                        }
+                        if(domain.overtimeHours){
+                            allover = allover - domain.overtimeHours
+                        }
+                        if(worktime*1 > this.user.timeType.allday){
+                            if(isover){
+                                if(alltime > (allover + this.user.timeType.allday)){
+                                        this.$set(domain,'isOvertime',true)
+                                        this.$set(domain,'overtimeHours',worktime - this.user.timeType.allday - allover)
+                                }else{
+                                    this.$set(domain,'isOvertime',false)
+                                    this.$set(domain,'overtimeHours',null)
+                                    if(alltime < (allover + this.user.timeType.allday)){
+                                        let overtime = allover + this.user.timeType.allday - alltime
+                                        for(let pi in spl){
+                                            if(spl[pi].overtimeHours){
+                                                if((overtime - spl[pi].overtimeHours*1) > 0){
+                                                    overtime = overtime - spl[pi].overtimeHours*1
+                                                    this.$set(spl[pi],'isOvertime',false)
+                                                    this.$set(spl[pi],'overtimeHours',null)
+                                                }else if((overtime - spl[pi].overtimeHours*1) < 0){
+                                                    this.$set(spl[pi],'overtimeHours',spl[pi].overtimeHours*1 - overtime)
+                                                    break
+                                                }else{
+                                                    this.$set(spl[pi],'isOvertime',false)
+                                                    this.$set(spl[pi],'overtimeHours',null)
+                                                    break
+                                                }
                                             }
                                         }
                                     }
                                 }
+                            }else{
+                                this.$set(domain,'isOvertime',true)
+                                this.$set(domain,'overtimeHours',worktime - this.user.timeType.allday)
                             }
                         }else{
-                            this.$set(domain,'isOvertime',true)
-                            this.$set(domain,'overtimeHours',worktime - this.user.timeType.allday)
-                        }
-                    }else{
-                        for(let di in spl){
-                            this.$set(spl[di],'isOvertime',false)
-                            this.$set(spl[di],'overtimeHours',null)
+                            for(let di in spl){
+                                this.$set(spl[di],'isOvertime',false)
+                                this.$set(spl[di],'overtimeHours',null)
+                            }
                         }
                     }
                 }
+                
             },
             iptChang() {
                 var sl = this.workForm.domains
@@ -7489,13 +7491,16 @@
                                     serviceList: list.report[i].serviceList,
                                     sapServiceId: list.report[i].sapServiceId,
                                     reportTargetDeptId: list.report[i].deptId,
-                                    auditWorkflow: list.report[i].auditWorkflow
+                                    auditWorkflow: list.report[i].auditWorkflow,
                                 }
                                 if (this.user.timeType.reportAuditType != 1 && this.user.timeType.reportAuditType != 2 && this.user.timeType.reportAuditType != 9) {
                                     //分组负责人审核的情况下,前端不需要显示,无需设置
                                     copyData.projectAuditorId = list.report[i].projectAuditorId;
                                     copyData.projectAuditorName = list.report[i].projectAuditorName;
                                 }
+                                if (this.user.timeType.timeInputNormal) {
+                                    copyData.normalWorkingTime = copyData.workingTime - copyData.overtimeHours;
+                                }
                                 
                                 if (this.allConstructionStages.length > 0) {
                                     copyData.engineeringCategory = this.fillProjectList.filter(p=>p.id == copyData.projectId)[0].plate1;
@@ -7588,6 +7593,9 @@
                             if(res.data.timeType.type == 3) {
                                 copyWorkForm.totalDuration = res.data.timeType.allday
                             }
+                            if (this.user.timeType.timeInputNormal) {
+                                copyWorkForm.domains[0].normalWorkingTime = copyWorkForm.domains[0].workingTime;
+                            }
                             this.workForm = copyWorkForm
                             // businessTrips 有数据的情况下
                             const businessTrips = res.data.businessTrips || []
@@ -11032,4 +11040,7 @@
         opacity: 1;
         box-shadow: 0 6px 20px 0 rgba(102, 126, 234, 0.6);
     }
+    .time_box {
+        padding-top:15px;border:0.5px dashed #ddd;margin-right:20px;
+    }
 </style>

+ 57 - 41
fhKeeper/formulahousekeeper/timesheet_h5/src/views/edit/index.vue

@@ -179,12 +179,9 @@
                             @cancel="item.showPickerTaskGroup = false; $forceUpdate();" />
                     </van-popup> -->
 
-                    <van-popup v-model="item.showPickerTaskGroup" position="bottom" :style="{ height: '80vh' }" @click-overlay="item.showPickerTaskGroup = false;$forceUpdate();">
-                        <div class="groupingSelection">
-                            <div v-for="(taskItem, taskIndex) in item.taskGroups" :key="taskIndex" class="groupingSelectionItem" @click="choseTaskGroup(taskItem, taskIndex)">
-                                {{ taskItem.name }}
-                            </div>
-                        </div>
+                    <van-popup v-model="item.showPickerTaskGroup" position="bottom">
+                        <van-picker show-toolbar :columns="item.taskGroups" value-key="name" @confirm="choseTaskGroup"
+                            @cancel="item.showPickerTaskGroup = false; $forceUpdate();" />
                     </van-popup>
 
                     <!--工作职责-->
@@ -444,10 +441,19 @@
                     </van-popup>
                     <!-- 全天上下午模式 -->
                     <div v-if="reportTimeType.multiWorktime == 0 && (!hideWorkingHours || (hideWorkingHours && item.canEdit)) ">
-                        <van-field v-if="reportTimeType.type < 2" readonly clickable :disabled="!item.canEdit"
+                        <template v-if="user.timeType.timeInputNormal">
+                            <van-field readonly clickable :disabled="!item.canEdit"
+                            :value="reportTimeType.type == 0 ? item.label : (parseFloat(item.normalWorkingTime).toFixed(1) + 'h')"
+                            label="正常工时" placeholder="请选择正常工时(小时)" @click="clickTimePicker(index, item)"
+                            :rules="[{ required: true, message: '请选择正常工时' }]" />
+                        </template>
+                        <template v-else>
+                            <van-field v-if="reportTimeType.type < 2" readonly clickable :disabled="!item.canEdit"
                             :value="reportTimeType.type == 0 ? item.label : (parseFloat(item.workingTime).toFixed(1) + 'h')"
                             label="工作时长" placeholder="请选择工作时长(小时)" @click="clickTimePicker(index, item)"
                             :rules="[{ required: true, message: '请选择工作时长' }]" />
+                        </template>
+                        
                         <van-popup v-model="showPickerTime" position="bottom">
                             <van-picker show-toolbar :columns="timeType" value-key="label" @confirm="choseTimePick"
                                 @cancel="showPickerTime = false" />
@@ -556,10 +562,10 @@
                         v-if="((user.timeType.fillOvertime || (isWeekend && user.timeType.lockWorktime != 1)) || (isCorpWX && canEdit)) && (!hideWorkingHours || (hideWorkingHours && item.canEdit))">
                         <div class="overTimeClas"
                             v-if="user.timeType.fillOvertime || (isWeekend && user.timeType.lockWorktime != 1)">
-                            <van-checkbox :disabled="!item.canEdit" v-model="item.isOvertime"
-                                style="width: 4.3rem;">含加班</van-checkbox>
+                            <van-checkbox :disabled="!item.canEdit" v-model="item.isOvertime" @change="calculateWorkingTime(item)"
+                                style="width: 4.3rem;">{{user.timeType.timeInputNormal?'额外加班':'含加班'}}</van-checkbox>
                             <van-field v-model="item.overtimeHours" type="number"
-                                :disabled="!item.canEdit || item.isOvertime == null || item.isOvertime == 0 || !item.isOvertime"
+                                :disabled="!item.canEdit || item.isOvertime == null || item.isOvertime == 0 || !item.isOvertime" @blur="calculateWorkingTime(item)"
                                 placeholder="请输入加班时长" style="width: 5.2rem" @input="$forceUpdate()"></van-field>
                             <span :class="item.canEdit ? 'overListTime' : 'overListTime hoveOver'">小时</span>
                         </div>
@@ -1683,24 +1689,12 @@ export default {
                 if (this.reportTimeType.multiWorktime == 1) {
                     for (let m in domains[i].worktimeList) {
                         if (domains[i].worktimeList[m].startTime && domains[i].worktimeList[m].endTime) {
-                            // hours += this.getHour(domains[i].worktimeList[m].startTime, domains[i].worktimeList[m].endTime)
                             timeArr.push({ startTime: domains[i].worktimeList[m].startTime, endTime: domains[i].worktimeList[m].endTime })
                         }
                     }
                 } else {
                     if (this.user.timeType.type == 2) {
                         if (domains[i].startTime && domains[i].endTime) {
-                            // let selectionTime = this.getHour(domains[i].startTime, domains[i].endTime)
-                            // let subtractedData = 0
-                            // let arr = JSON.parse(JSON.stringify(this.vacationTime))
-                            // arr.unshift({s: domains[i].startTime, e: domains[i].endTime})
-                            // for(var j in arr) {
-                            //     subtractedData += +this.timeOverlap(j, arr)
-                            // }
-                            // console.log(selectionTime, subtractedData)
-                            // hours += +selectionTime - +subtractedData
-                            // console.log(hours)
-                            // arrNum.push(+selectionTime - +subtractedData)
                             timeArr.push({ startTime: domains[i].startTime, endTime: domains[i].endTime })
                         }
                     } else {
@@ -1709,8 +1703,6 @@ export default {
                 }
             }
 
-            // this.totalReportHours = hours.toFixed(2)
-            console.log('timeArr', timeArr)
             if (this.reportTimeType.multiWorktime == 1 || this.user.timeType.type == 2) {
                 const { timeCanOverlap } = this.reportTimeType // timeCanOverlap 为零时校验不允许重叠
                 if(timeCanOverlap == 0) {
@@ -1762,6 +1754,12 @@ export default {
 
             return options;
         },
+        calculateWorkingTime(domain) {
+            if (this.user.timeType.timeInputNormal) {
+                domain.workingTime = parseFloat(domain.normalWorkingTime||0) + (domain.isOvertime?parseFloat(domain.overtimeHours||0):0);
+                this.setTotalReportHours();
+            }
+        },
         choseTimePick(value, index) {
             if (value == null || value == undefined) {
                 return
@@ -1774,27 +1772,35 @@ export default {
                 this.showPickerTime = false;
             } else if (this.reportTimeType.type == 1) {
                 // console.log('this.reportTimeType.type=='+value,this.form.domains);
-                this.form.domains[this.clickTimeIndex].workingTime = value;
+                if (this.user.timeType.timeInputNormal) {
+                    this.form.domains[this.clickTimeIndex].normalWorkingTime = value;
+                    this.calculateWorkingTime(this.form.domains[this.clickTimeIndex]);
+                } else {
+                    this.form.domains[this.clickTimeIndex].workingTime = value;
+                }
+                
                 this.form.domains[this.clickTimeIndex].label = value.toFixed(1) + '小时';
                 this.showPickerHours = false;
 
-                let allhour = 0
-                for (let i in this.form.domains) {
-                    if (this.isWeekend) {
-                        this.form.domains[i].isOvertime = true
-                        this.form.domains[i].overtimeHours = this.form.domains[i].workingTime
-                    } else {
-                        this.form.domains[i].isOvertime = false
-                        delete this.form.domains[i].overtimeHours
+                
+                if (!this.user.timeType.timeInputNormal) {
+                    let allhour = 0
+                    for (let i in this.form.domains) {
+                        if (this.isWeekend) {
+                            this.form.domains[i].isOvertime = true
+                            this.form.domains[i].overtimeHours = this.form.domains[i].workingTime
+                        } else {
+                            this.form.domains[i].isOvertime = false
+                            delete this.form.domains[i].overtimeHours
+                        }
+                        allhour += this.form.domains[i].workingTime * 1
                     }
-                    allhour += this.form.domains[i].workingTime * 1
-                }
-                if (allhour > this.user.timeType.allday && !this.isWeekend) {
-                    this.form.domains[this.clickTimeIndex].isOvertime = true
-                    this.form.domains[this.clickTimeIndex].overtimeHours = allhour - this.user.timeType.allday
-                }
+                    if (allhour > this.user.timeType.allday && !this.isWeekend) {
+                        this.form.domains[this.clickTimeIndex].isOvertime = true
+                        this.form.domains[this.clickTimeIndex].overtimeHours = allhour - this.user.timeType.allday
+                    }
+                } 
             }
-
             this.setTotalReportHours()
         },
         clickTimePicker(i, item) {
@@ -2256,6 +2262,10 @@ export default {
                                     copyData.projectAuditorId = list[i].projectAuditorId;
                                     copyData.projectAuditorName = list[i].projectAuditorName;
                                 }
+                                if (this.user.timeType.timeInputNormal) {
+                                    copyData.normalWorkingTime = copyData.workingTime - copyData.overtimeHours;
+                                }
+                                
                                 array.push(copyData);
                                 if (list[i].state >= 2) {
                                     this.canEdit = true;
@@ -2365,8 +2375,10 @@ export default {
                                 this.form.domains[0].basecostId = this.report.timeBasecostList[0].id;
                                 this.form.domains[0].basecostName = this.report.timeBasecostList[0].name;
                             }
+                            if (this.user.timeType.timeInputNormal) {
+                                this.form.domains[0].normalWorkingTime = this.form.domains[0].workingTime;
+                            }
                             this.canEdit = true;
-
                             this.setTotalReportHours()
                         }
                     } else {
@@ -2844,6 +2856,10 @@ export default {
                 canEdit: true,
                 constructionStages: [],
             }
+            if (this.user.timeType.timeInputNormal) {
+                //设置正常工时
+                item.normalWorkingTime = item.workingTime;
+            }
             if (this.isWeekend && this.user.timeType.lockWorktime != 1) {
                 this.$set(item, 'isOvertime', true)
                 if (this.reportTimeType.type == 3) {