Prechádzať zdrojové kódy

Merge branch 'master' of http://47.100.37.243:10191/wutt/manHourHousekeeper

Min 1 rok pred
rodič
commit
1881154c65
17 zmenil súbory, kde vykonal 958 pridanie a 441 odobranie
  1. 9 3
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/ReportController.java
  2. 8 1
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/ReportBatch.java
  3. 7 1
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/TimeType.java
  4. 3 1
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/ReportService.java
  5. 29 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ProjectServiceImpl.java
  6. 309 32
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ReportServiceImpl.java
  7. 44 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/task/TimingTask.java
  8. 2 2
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/ProjectMapper.xml
  9. 2 1
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/ReportBatchMapper.xml
  10. 16 9
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/ReportMapper.xml
  11. 2 1
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/TimeTypeMapper.xml
  12. 7 1
      fhKeeper/formulahousekeeper/timesheet/src/views/settings/timetype.vue
  13. 109 66
      fhKeeper/formulahousekeeper/timesheet/src/views/workReport/daily.vue
  14. 9 0
      fhKeeper/formulahousekeeper/timesheet/src/views/workReport/weeklyCustomization.vue
  15. 382 303
      fhKeeper/formulahousekeeper/timesheet_h5/src/views/edit/weekEdit.vue
  16. 1 3
      fhKeeper/formulahousekeeper/timesheet_h5/src/views/index/index.vue
  17. 19 17
      fhKeeper/formulahousekeeper/timesheet_h5/src/views/view/index.vue

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

@@ -242,6 +242,11 @@ public class ReportController {
         return reportService.getReport(date, request);
     }
 
+    @RequestMapping("/getReportById")
+    public HttpRespMsg getReportById(@RequestParam Integer reportId) {
+        return reportService.getReportById(reportId, request);
+    }
+
     /**
      * AI智能填报
      * @return
@@ -338,7 +343,8 @@ public class ReportController {
                                   String[] picStr, //图片的文件名,不含后缀的,多个用@分隔,如:["3UlRmLbTnqLPM0-xjja2dS2VAg5OFERPUZz0HRqjb8BXLq8ewaFH6NmlFm1pnVza0"@"338EniZDtXtKGSnavdgvebGGyRgoieGv2aobIq6k5jboa_DsZNIvLmzHjW69kDG6x"]
                                   Integer[] extraField1,
                                   Integer[] extraField2,
-                                  Integer[] extraField3
+                                  Integer[] extraField3,
+                                  String summary         //针对工作总结的字段
                                     ) {
         List<Report> reportList = new ArrayList<>();
         String token = request.getHeader("Token");
@@ -1564,8 +1570,8 @@ public class ReportController {
                 return msg;
             }
         }
-
-        HttpRespMsg httpRespMsg = reportService.editReport(reportList, createDate.length > 0 ? createDate[0] : null, targetUserList, hourCost, user.getCompanyId());
+        System.out.println("summary==========="+summary);
+        HttpRespMsg httpRespMsg = reportService.editReport(reportList, createDate.length > 0 ? createDate[0] : null, targetUserList, hourCost, user.getCompanyId(), summary);
         //填报自动通过功能:【上海绎维】、【火石演示】、【博通容合】、【威派格】使用
         if (company.getId() == 862 || company.getId() == 10 || company.getId() == 3344 || company.getId() == 936) {
             //项目审核人是提交人的情况,直接审核

+ 8 - 1
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/ReportBatch.java

@@ -22,7 +22,7 @@ import org.springframework.format.annotation.DateTimeFormat;
  * </p>
  *
  * @author Seyason
- * @since 2023-08-11
+ * @since 2023-11-27
  */
 @Data
 @EqualsAndHashCode(callSuper = false)
@@ -91,6 +91,13 @@ public class ReportBatch extends Model<ReportBatch> {
     @TableField(exist = false)
     private String reportIds;
 
+    /**
+     * 周总结
+     */
+    @TableField("summary")
+    private String summary;
+
+
     @Override
     protected Serializable pkVal() {
         return this.id;

+ 7 - 1
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/TimeType.java

@@ -17,7 +17,7 @@ import lombok.experimental.Accessors;
  * </p>
  *
  * @author Seyason
- * @since 2023-11-17
+ * @since 2023-11-27
  */
 @Data
 @EqualsAndHashCode(callSuper = false)
@@ -522,6 +522,12 @@ public class TimeType extends Model<TimeType> {
     @TableField("sync_sap")
     private Integer syncSap;
 
+    /**
+     * 项目超期不可填报
+     */
+    @TableField("not_allowed_expired_project")
+    private Integer notAllowedExpiredProject;
+
 
     @Override
     protected Serializable pkVal() {

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

@@ -33,7 +33,7 @@ public interface ReportService extends IService<Report> {
 
     HttpRespMsg getCardTime(String date, HttpServletRequest request);
 
-    HttpRespMsg editReport(List<Report> reportList, String date, List<User> userList, BigDecimal hourCost, Integer companyId);
+    HttpRespMsg editReport(List<Report> reportList, String date, List<User> userList, BigDecimal hourCost, Integer companyId, String summary);
 
     HttpRespMsg deleteReport(String userId, String date);
 
@@ -133,4 +133,6 @@ public interface ReportService extends IService<Report> {
     HttpRespMsg getWeeklyFillReportData(String targetDate, HttpServletRequest request);
 
     HttpRespMsg pushProjectReportToSap(String startDate, String endDate,String userId);
+
+    HttpRespMsg getReportById(Integer reportId, HttpServletRequest request);
 }

+ 29 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ProjectServiceImpl.java

@@ -265,6 +265,35 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
                     httpRespMsg.data = projectMapper.selectList(new QueryWrapper<Project>().eq("company_id", user.getCompanyId()).orderByDesc("is_public").orderByAsc("id"));
                 }
             }
+
+            //按计划完成日期进行过滤
+            if (timeTypeMapper.selectById(user.getCompanyId()).getNotAllowedExpiredProject() == 1) {
+                Object data = httpRespMsg.data;
+                List projectList = (List) data;
+                SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
+                DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+
+                for (int i=0;i<projectList.size(); i++) {
+                    Object item = projectList.get(i);
+                    if (item instanceof Project) {
+                        Project project = (Project) item;
+                        if (project.getPlanEndDate() != null && project.getPlanEndDate().isBefore(LocalDate.now())) {
+                            projectList.remove(i);
+                            i--;
+                        }
+                    } else if (item instanceof HashMap) {
+                        HashMap project = (HashMap) item;
+                        if (project.get("planEndDate") != null) {
+                            String yyyymmdd = simpleDateFormat.format((java.sql.Date)project.get("planEndDate"));
+                            if (LocalDate.parse(yyyymmdd, dateTimeFormatter).isBefore(LocalDate.now())) {
+                                projectList.remove(i);
+                                i--;
+                            }
+                        }
+                    }
+                }
+                httpRespMsg.data = projectList;
+            }
         } catch (NullPointerException e) {
             //httpRespMsg.setError("验证失败");
             httpRespMsg.setError(MessageUtils.message("access.verificationError"));

+ 309 - 32
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ReportServiceImpl.java

@@ -216,6 +216,7 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
             //首先根据日期获取当天所有提交过日志的人
             String userId = request.getHeader("Token");
             User user = userMapper.selectById(userId);
+            TimeType timeType = timeTypeMapper.selectById(user.getCompanyId());
             List<Map<String, Object>> nameList = new ArrayList<>();
             List<SysRichFunction> functionList = sysFunctionMapper.getRoleFunctions(user.getRoleId(), "查看全公司工时");
             if (functionList.size() == 0) {
@@ -329,7 +330,7 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
                     //担任项目经理或者日报审核人,查找相关的人员的日报
                     List<Map<String, Object>> puserNames = reportMapper.getReportNameByDate(date, user.getCompanyId(), leaderId);
                     List<Map<String, Object>> inchargeReportList= reportMapper.getInchargeReportByDate(date, leaderId, null);
-                    TimeType timeType = timeTypeMapper.selectById(user.getCompanyId());
+
                     if ((timeType.getReportAuditType() == 5 || timeType.getReportAuditType() == 6)&& timeType.getReportCc() == 1) {
                         //存在抄送人的设置,需要把抄送人的项目相关日报也加上
                         List<Map<String, Object>> viewUserNames = reportMapper.getCcReportNameByDate(date, user.getCompanyId(),leaderId);
@@ -542,6 +543,35 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
                     }
                 }
             }
+            if (timeType.getEnableNewWeeklyfill() == 1) {
+                //新版按周填报有周总结
+                List<Integer> batchIds = new ArrayList<>();
+                for (Map map : nameList) {
+                    List<Map<String, Object>> reportList = (List<Map<String, Object>>)map.get("data");
+                    for (Map<String, Object> report : reportList) {
+                        Integer batchId = (Integer)report.get("batchId");
+                        if (!batchIds.contains(batchId)) {
+                            batchIds.add(batchId);
+                        }
+                    }
+                }
+                if (batchIds.size() > 0) {
+                    List<ReportBatch> batchList = reportBatchMapper.selectList(new QueryWrapper<ReportBatch>().in("id", batchIds));
+                    DateTimeFormatter sdf = DateTimeFormatter.ofPattern("MM/dd");
+                    for (Map map : nameList) {
+                        List<Map<String, Object>> reportList = (List<Map<String, Object>>)map.get("data");
+                        if (reportList.size() > 0) {
+                            Integer batchId = (Integer)((Map)reportList.get(0)).get("batchId");
+                            Optional<ReportBatch> first = batchList.stream().filter(b -> b.getId().equals(batchId)).findFirst();
+                            if (first.isPresent()) {
+                                ReportBatch batchItem = first.get();
+                                map.put("summaryTitle", sdf.format(batchItem.getStartDate())+"至"+sdf.format(batchItem.getEndDate())+"周总结:");
+                                map.put("summary", batchItem.getSummary());
+                            }
+                        }
+                    }
+                }
+            }
             httpRespMsg.data = nameList;
         } catch (NullPointerException e) {
             e.printStackTrace();
@@ -798,6 +828,227 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
         return httpRespMsg;
     }
 
+    @Override
+    public HttpRespMsg getReportById(Integer reportId, HttpServletRequest request) {
+        HttpRespMsg httpRespMsg = new HttpRespMsg();
+        try {
+            String userId = request.getHeader("Token");
+            Integer companyId = userMapper.selectById(userId).getCompanyId();
+            Company company = companyMapper.selectById(companyId);
+            Map<String, Object> resultMap = new HashMap<>();
+            //查日报
+            Report report = reportMapper.selectById(reportId);
+            LocalDate date = report.getCreateDate();
+            Integer projectId = report.getProjectId();
+            List<SubProject> subProjectList = subProjectMapper.selectList(new QueryWrapper<SubProject>().eq("project_id",projectId));
+            List<ProjectAuditor> auditorList = projectAuditorMapper.selectList(new QueryWrapper<ProjectAuditor>().eq("project_id", projectId));
+
+            List<Profession> professions = professionMapper.selectList(new QueryWrapper<Profession>().eq("company_id", companyId));
+
+            List<ReportExtraDegree> degreeList = reportExtraDegreeMapper.selectList(new QueryWrapper<ReportExtraDegree>().eq("company_id", companyId));
+            List<TaskGroup> taskGroups = taskGroupMapper.selectList(new QueryWrapper<TaskGroup>().eq("project_id", projectId));
+            List<Stages> stagesList =stagesMapper.selectList(new QueryWrapper<Stages>().eq("project_id", projectId));
+
+            //获取当前项目的子项目列表,任务分组,任务列表,项目相关维度列表
+            Report r = report;
+            r.setSubProjectList(subProjectList.stream().filter(s->s.getProjectId().equals(r.getProjectId())).collect(Collectors.toList()));
+            r.setTaskList(taskMapper.recentSimpleList(r.getProjectId(), userId));
+            //获取当前项目的工程专业进度
+            List<ReportProfessionProgress> progressList = reportProfessionProgressService.list(new QueryWrapper<ReportProfessionProgress>().eq("report_id", r.getId()));
+            //去掉当前项目上已经不存在的专业
+            List<ProjectProfession> projectProfessions = projectProfessionMapper.selectList(new QueryWrapper<ProjectProfession>().eq("project_id", r.getProjectId()));
+            progressList = progressList.stream().filter(p->projectProfessions.stream().anyMatch(pp->pp.getProfessionId().equals(p.getProfessionId()))).collect(Collectors.toList());
+            progressList.stream().forEach(p->{
+                p.setProfessionName(professions.stream().filter(m->m.getId().equals(p.getProfessionId())).findFirst().get().getName());
+            });
+            r.setProfessionProgressList(progressList);
+            //获取任务阶段列表
+            if (company.getPackageProject() == 1 && r.getGroupId() != null && r.getGroupId() != 0) {
+                r.setStages(stagesList.stream().filter(s->s.getGroupId() !=null && s.getGroupId().equals(r.getGroupId())).collect(Collectors.toList()));
+            }
+            //处理图片
+            if (!StringUtils.isEmpty(r.getPicStr()) && !r.getPicStr().equals("@")) {
+                JSONArray array = JSONArray.parseArray(r.getPicStr().replaceAll("@", ","));
+                List<String> list = new ArrayList<>();
+                for (int i=0;i<array.size(); i++) {
+                    String picName = array.getString(i);
+                    if (!picName.contains(".")) {
+                        picName += ".jpg";
+                    }
+                    list.add("/upload/"+picName);
+                }
+                r.setPics(list);
+            }
+            if (r.getMultiWorktime() == 1) {
+                //设置多个工时情况下的报告列表
+                String timeStr = r.getContent();
+                if (timeStr != null) {
+                    JSONArray parse = JSONArray.parseArray(timeStr);
+                    List<WorktimeItem> list = new ArrayList<>();
+                    for (int i=0;i<parse.size(); i++) {
+                        JSONObject obj = parse.getJSONObject(i);
+                        list.add(JSONObject.toJavaObject(obj, WorktimeItem.class));
+                    }
+                    r.setWorktimeList(list);
+                }
+            }
+
+            //处理维度列表数据
+            if (timeTypeMapper.selectById(companyId).getCustomDegreeActive() == 1) {
+                Project project = projectMapper.selectById(projectId);
+                String associateDegrees = project.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);
+            }
+            //检查是否是按照任务分组负责人审核
+            int reportAuditType = timeTypeMapper.selectById(companyId).getReportAuditType();
+            //分组
+            if (company.getPackageProject() == 1) {
+                //如果是按照任务分组负责人审核,取参与的分组
+                if (reportAuditType == 1 || reportAuditType == 2){
+                    List<GroupParticipator> groupParticipatorList = groupParticipatorMapper.selectList(new QueryWrapper<GroupParticipator>().eq("user_id", r.getCreatorId()));
+                    if (groupParticipatorList.size() > 0) {
+                        List<Integer> groupIds = groupParticipatorList.stream().map(GroupParticipator::getGroupId).collect(Collectors.toList());
+                        List<TaskGroup> findGroups = taskGroups.stream().filter(tg->groupIds.contains(tg.getId()) || userId.equals(tg.getInchargerId())).collect(Collectors.toList());
+                        r.setTaskGroups(findGroups);
+                        if (r.getGroupId() != null && r.getGroupId() != 0) {
+                            Optional<TaskGroup> optinal = taskGroups.stream().filter(tg->tg.getId().equals(r.getGroupId())).findFirst();
+                            if (optinal.isPresent()) {
+                                r.setGroupName(optinal.get().getName());
+                            }
+                        }
+                    }
+                } else {
+                    //取该项目下的全部分组数据
+                    r.setTaskGroups(taskGroups.stream().filter(tg->tg.getProjectId().equals(r.getProjectId())).collect(Collectors.toList()));
+                    if (r.getGroupId() != null && r.getGroupId() != 0) {
+                        Optional<TaskGroup> optinal = taskGroups.stream().filter(tg->tg.getId().equals(r.getGroupId())).findFirst();
+                        if (optinal.isPresent()) {
+                            r.setGroupName(optinal.get().getName());
+                        }
+                    }
+                }
+            }
+            //项目的审核人
+            if (reportAuditType == 0) {
+                r.setAuditUserList(auditorList.stream().filter(au->au.getProjectId().equals(r.getProjectId())).collect(Collectors.toList()));
+                if (r.getProjectAuditorId() != null) {
+                    Optional<ProjectAuditor> auItem = auditorList.stream().filter(au->au.getAuditorId().equals(r.getProjectAuditorId())).findFirst();
+                    if (auItem.isPresent()) {
+                        r.setProjectAuditorName(auItem.get().getAuditorName());
+                    }
+                }
+            } else if (reportAuditType == 1 || reportAuditType == 2) {
+                if (r.getGroupId() != null && r.getGroupId() != 0) {
+                    //直接获取分组的负责人作为审核人
+                    Optional<TaskGroup> tgoup = taskGroups.stream().filter(tg->tg.getId().equals(r.getGroupId())).findFirst();
+                    if (tgoup.isPresent()) {
+                        TaskGroup curGroup = tgoup.get();
+                        if (curGroup.getInchargerId() != null) {
+                            User user = userMapper.selectById(curGroup.getInchargerId());
+                            HashMap map = new HashMap();
+                            map.put("auditorId", user.getId());
+                            map.put("auditorName", user.getName());
+                            List list = new ArrayList();
+                            list.add(map);
+                            r.setAuditUserList(list);
+                            if (r.getProjectAuditorId() != null) {
+                                r.setProjectAuditorName(user.selectById(r.getProjectAuditorId()).getName());
+                            }
+                        }
+                    }
+                }
+            } else if (reportAuditType == 3) {
+                //获取日报对应已经设置好的审核人和抄送人
+                ReportAuditorSetting reportAuditorSetting = reportAuditorSettingMapper.selectById(r.getId());
+                r.setAuditorSetting(reportAuditorSetting);
+                //手机端数据
+                if (reportAuditorSetting.getAuditorFirst() != null) {
+                    User auditorItem = userMapper.selectOne(new QueryWrapper<User>().select("id, name").eq("id", reportAuditorSetting.getAuditorFirst()));
+                    r.setAuditorFirst(auditorItem);
+                }
+                if (reportAuditorSetting.getAuditorSec() != null) {
+                    User auditorItem = userMapper.selectOne(new QueryWrapper<User>().select("id, name").eq("id", reportAuditorSetting.getAuditorSec()));
+                    r.setAuditorSec(auditorItem);
+                }
+                if (reportAuditorSetting.getAuditorThird() != null) {
+                    User auditorItem = userMapper.selectOne(new QueryWrapper<User>().select("id, name").eq("id", reportAuditorSetting.getAuditorThird()));
+                    r.setAuditorThird(auditorItem);
+                }
+                if (reportAuditorSetting.getCcUserid() != null) {
+                    User auditorItem = userMapper.selectOne(new QueryWrapper<User>().select("id, name").eq("id", reportAuditorSetting.getCcUserid()));
+                    r.setCcUserid(auditorItem);
+                }
+            }
+            //昱众要返回工作内容下拉选项
+            if (companyId == 3385) {
+                HttpRespMsg funWorkContextList = projectService.getFunWorkContextList(r.getExtraField2());
+                List<ProFunWorkContext> workContentList = ((List<ProFunWorkContext>)funWorkContextList.data);
+                r.setWorkContentList(workContentList);
+            }
+            resultMap.put("report", report);
+            TimeType timeType = timeTypeMapper.selectById(companyId);
+            if (timeType.getShowDdCardtime() == 1) {
+                List<UserDingdingTime> dingdingTimes = userDingdingTimeMapper.selectList(new QueryWrapper<UserDingdingTime>()
+                        .eq("user_id", userId).eq("work_date", date));
+                if (dingdingTimes.size() > 0) {
+                    UserDingdingTime time = dingdingTimes.get(0);
+                    resultMap.put("time", time);
+                }
+            }else if(timeType.getSyncFanwei()==1){
+                List<UserFvTime> userFvTimeList = userFvTimeMapper.selectList(new QueryWrapper<UserFvTime>()
+                        .eq("user_id", userId).eq("work_date", date));
+                if (userFvTimeList.size() > 0) {
+                    UserFvTime time = userFvTimeList.get(0);
+                    resultMap.put("time", time);
+                }
+            } else if (timeType.getShowCorpwxCardtime() == 1) {
+                User user = userMapper.selectById(userId);
+                List<UserCorpwxTime> corpwxTimes = userCorpwxTimeMapper.selectList(new QueryWrapper<UserCorpwxTime>()
+                        .eq("corpwx_userid", user.getCorpwxUserid()).eq("create_date", date));
+                if (corpwxTimes.size() > 0) {
+                    UserCorpwxTime time = corpwxTimes.get(0);
+                    resultMap.put("time", time);
+                }
+            }
+
+            //顺便返回公司的工作时间设置
+            resultMap.put("timeType",timeType);
+            //返回公司的项目工时预警的成本项列表
+            List<ProjectBasecostSetting> timeBasecostList = new ArrayList<>();
+            if (company.getPackageProject() == 1) {
+                timeBasecostList = projectBasecostSettingMapper.selectList(new QueryWrapper<ProjectBasecostSetting>().eq("company_id", companyId).eq("alarm_type", 1));
+            }
+            //当天是否是工作日
+            boolean isWorkDay = companyId == 817 ? WorkDayCalculateUtils.isWorkDayExceptSaturday(date) : WorkDayCalculateUtils.isWorkDay(date);
+            resultMap.put("isWorkDay", isWorkDay);
+            resultMap.put("timeBasecostList",timeBasecostList);
+            httpRespMsg.data = resultMap;
+        } catch (NullPointerException e) {
+            e.printStackTrace();
+            //httpRespMsg.setError("验证失败");
+            httpRespMsg.setError(MessageUtils.message("Company.validationError"));
+            return httpRespMsg;
+        } catch (DateTimeParseException e) {
+            //httpRespMsg.setError("日期格式有误");
+            httpRespMsg.setError(MessageUtils.message("date.formatError"));
+            return httpRespMsg;
+        }
+        return httpRespMsg;
+    }
+
     @Override
     public HttpRespMsg getCardTime(String date, HttpServletRequest request) {
         String userId = request.getHeader("TOKEN");
@@ -832,7 +1083,7 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
 
     //新增或编辑报告
     @Override
-    public HttpRespMsg editReport(List<Report> reportList, String date, List<User> userList, BigDecimal hourCost, Integer companyId) {
+    public HttpRespMsg editReport(List<Report> reportList, String date, List<User> userList, BigDecimal hourCost, Integer companyId, String summary) {
         HttpRespMsg httpRespMsg = new HttpRespMsg();
         TimeType timeType = timeTypeMapper.selectById(companyId);
         //删除不在本次更新名单中的老记录
@@ -893,7 +1144,8 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
             //成都明夷电子,需要生成批量记录
             Company company = companyMapper.selectById(companyId);
             System.out.println(company.getCompanyName()+", date==="+date);
-            if (company.getCompanyName().equals("成都明夷电子科技有限公司")) {
+
+            if (company.getCompanyName().equals("成都明夷电子科技有限公司") || timeType.getEnableNewWeeklyfill() == 1) {//物奇需要填写周总结
                 if (date.contains("@")) {
                     //批量填报
                     String[] split = date.split("\\@");
@@ -919,42 +1171,46 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
                     //每日或按周填报,为每天生成一条记录; 每日或者按周填报时,填报人就是操作人自己,不存在代填的情况
                     List<LocalDate> dateList = reportList.stream().map(Report::getCreateDate).distinct().collect(Collectors.toList());
                     String creatorId = reportList.get(0).getCreatorId();
-                    for (LocalDate curDate : dateList) {
+                    if (timeType.getEnableNewWeeklyfill() == 1) {
+                        //按周填报,需要保存周总结
+                        LocalDate minDate = dateList.stream().min(LocalDate::compareTo).get();
+                        LocalDate maxDate = dateList.stream().max(LocalDate::compareTo).get();
                         //删除已有的记录
-                        reportBatchMapper.delete(new QueryWrapper<ReportBatch>().eq("start_date", curDate).eq("end_date", curDate).eq("creator_id", creatorId));
+                        reportBatchMapper.delete(new QueryWrapper<ReportBatch>().eq("start_date", minDate).eq("end_date", maxDate).eq("creator_id", creatorId));
                         ReportBatch batch = new ReportBatch();
                         batch.setCreatorId(creatorId);
                         batch.setState(0);
                         batch.setCompanyId(companyId);
-                        batch.setStartDate(curDate);
-                        batch.setEndDate(curDate);
-                        batch.setTotalWorkTime(reportList.stream().filter(item->item.getCreateDate().equals(curDate) && item.getCreatorId().equals(creatorId)).mapToDouble(Report::getWorkingTime).sum());
+                        batch.setStartDate(minDate);
+                        batch.setEndDate(maxDate);
+                        //周总结
+                        batch.setSummary(summary);
+                        batch.setTotalWorkTime(reportList.stream().filter(item->item.getCreatorId().equals(creatorId)).mapToDouble(Report::getWorkingTime).sum());
                         reportBatchMapper.insert(batch);
-
                         //更新batchId
-                        List<Integer> curDateReportIds = reportList.stream().filter(item -> item.getCreateDate().equals(curDate) && item.getCreatorId().equals(creatorId)).map(Report::getId).collect(Collectors.toList());
+                        List<Integer> curDateReportIds = reportList.stream().map(Report::getId).collect(Collectors.toList());
                         reportMapper.update(new Report().setBatchId(batch.getId()), new QueryWrapper<Report>().in("id", curDateReportIds));
+                    } else {
+                        for (LocalDate curDate : dateList) {
+                            //删除已有的记录
+                            reportBatchMapper.delete(new QueryWrapper<ReportBatch>().eq("start_date", curDate).eq("end_date", curDate).eq("creator_id", creatorId));
+                            ReportBatch batch = new ReportBatch();
+                            batch.setCreatorId(creatorId);
+                            batch.setState(0);
+                            batch.setCompanyId(companyId);
+                            batch.setStartDate(curDate);
+                            batch.setEndDate(curDate);
+                            //周总结
+                            batch.setSummary(summary);
+                            batch.setTotalWorkTime(reportList.stream().filter(item->item.getCreateDate().equals(curDate) && item.getCreatorId().equals(creatorId)).mapToDouble(Report::getWorkingTime).sum());
+                            reportBatchMapper.insert(batch);
+
+                            //更新batchId
+                            List<Integer> curDateReportIds = reportList.stream().filter(item -> item.getCreateDate().equals(curDate) && item.getCreatorId().equals(creatorId)).map(Report::getId).collect(Collectors.toList());
+                            reportMapper.update(new Report().setBatchId(batch.getId()), new QueryWrapper<Report>().in("id", curDateReportIds));
+                        }
                     }
-//                    for (Report r : reportList) {
-//                        LocalDate curDate = r.getCreateDate();
-//                        //删除已有的记录; //TODO: 一天多个项目会导致删除其他项目的记录, 需要修复
-//                        reportBatchMapper.delete(new QueryWrapper<ReportBatch>().eq("start_date", curDate).eq("end_date", curDate).eq("creator_id", r.getCreatorId()));
-//
-//                        ReportBatch batch = new ReportBatch();
-//                        batch.setCreatorId(reportList.get(0).getCreatorId());
-//                        batch.setState(0);
-//                        batch.setCompanyId(companyId);
-//                        batch.setStartDate(curDate);
-//                        batch.setEndDate(curDate);
-//                        batch.setTotalWorkTime(reportList.stream().filter(item->item.getCreateDate().equals(curDate) && item.getCreatorId().equals(r.getCreatorId())).mapToDouble(Report::getWorkingTime).sum());
-//                        reportBatchMapper.insert(batch);
-//                        //更新batchId
-//                        Report uItem = new Report();
-//                        uItem.setId(r.getId());
-//                        uItem.setBatchId(batch.getId());
-//                        updateBIdList.add(uItem);
-//                    }
-//                    reportService.updateBatchById(updateBIdList);
+
                 }
             }
         } else {
@@ -6717,6 +6973,7 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
                 .eq("creator_id", userId).between("create_date", startDate, endDate).groupBy("create_date"));
         //获取日报详情
         List<Report> reportList = reportMapper.selectList(new QueryWrapper<Report>().eq("creator_id", userId).between("create_date", startDate, endDate).orderByAsc("create_date"));
+
         List<Integer> collect = reportList.stream().map(Report::getProjectId).collect(Collectors.toList());
         //加载这段时间内已填报过的项目
         List<Project> projectList = new ArrayList<>();
@@ -6729,6 +6986,13 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
                 projectList = projectMapper.selectList(new QueryWrapper<Project>().in("id", oldReport.stream().map(Report::getProjectId).collect(Collectors.toList())));
             }
         }
+//
+//        List<TaskGroup> allGroupList = taskGroupMapper.selectList(new QueryWrapper<TaskGroup>().in("project_id", projectList.stream().map(Project::getId).collect(Collectors.toList())));
+//        //获取当前日报项目下的所有任务分组
+//        for (Report report : reportList) {
+//            Integer targetPid = report.getProjectId();
+//            report.setTaskGroups(allGroupList.stream().filter(tg->tg.getProjectId().equals(targetPid)).collect(Collectors.toList()));
+//        }
 
         List cardTimeList = new ArrayList();
         if (timeType.getShowDdCardtime() == 1) {
@@ -6945,8 +7209,9 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
         if (user.getIsActive()==0 && leaveDate != null && leaveDate.isBefore(lastDayOfWeek)) {
             lastDayOfWeek = leaveDate;
         }
-        Map<String, List> reportMap = new HashMap<>();
+        Map<String, Object> reportMap = new HashMap<>();
         if (needFill) {
+            String summary = null;
             String startDate = firstDayOfWeek.format(dtf);
             String endDate = lastDayOfWeek.format(dtf);
             TimeType timeType = timeTypeMapper.selectById(user.getCompanyId());
@@ -6954,6 +7219,11 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
             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) {
+                    //获取周总结
+                    summary = reportBatchMapper.selectById(batchId).getSummary();
+                }
                 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));
@@ -6981,7 +7251,11 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
                 if (joinGroupList.size() > 0) {
                     List<TaskGroup> taskGroups = taskGroupMapper.selectList(new QueryWrapper<TaskGroup>().in("project_id", collect).in("id", joinGroupList));
                     //获取负责人的用户集合
-                    List<User> userList = userMapper.selectList(new QueryWrapper<User>().in("id", taskGroups.stream().map(TaskGroup::getInchargerId).collect(Collectors.toList())));
+                    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()) {
@@ -7047,9 +7321,12 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
                 }
             }
             reportMap.put("dateList", dateList);
+            reportMap.put("summary", summary);
         } else {
             reportMap.put("dateList", new ArrayList());
         }
+
+
         msg.data = reportMap;
         return msg;
     }

+ 44 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/task/TimingTask.java

@@ -1273,6 +1273,50 @@ public class TimingTask {
             }
         }
     }
+
+
+    @Scheduled(cron = "0 0 10 28-31 * ?")
+    private void sendMonthlyMissReportLog() {
+        if (isDev || isPrivateDeploy) {
+            return;
+        }
+        //每月最后一天
+        LocalDate now = LocalDate.now();
+        LocalDate lastDay = now.with(TemporalAdjusters.lastDayOfMonth());
+        if (!now.isEqual(lastDay)) {
+            return;
+        }
+        //目前针对物奇进行推送
+        Integer companyId = 1071;
+        //获取
+        LocalDate startDate = now.with(TemporalAdjusters.firstDayOfMonth());
+        LocalDate endDate = lastDay;
+        List<Map<String, Object>> userList = reportService.getNotFullReportUserList(companyId, startDate, endDate);
+//        System.out.println("漏填报人员列表:"+userList);
+        List<WxCorpInfo> cpList = wxCorpInfoMapper.selectList(new QueryWrapper<WxCorpInfo>().eq("company_id", companyId));
+        userList.forEach(u->{
+            if (u.get("corpwxUserid") != null){
+                //推送到企业微信
+                String corpUid = (String) u.get("corpwxUserid");
+                JSONObject json=new JSONObject();
+                JSONArray dataJson = new JSONArray();
+                JSONObject jsonObj = new JSONObject();
+                jsonObj.put("key", "提示");
+                jsonObj.put("value", "您本月有"+(Integer)u.get("days")+"天未填写工时报告,请尽快填写");
+                dataJson.add(jsonObj);
+                json.put("template_id","tty9TkCAAAYoevY-40ciWD5lDncDfR5w");
+                json.put("url", "https://open.weixin.qq.com/connect/oauth2/authorize?appid=ww4e237fd6abb635af&redirect_uri=http://worktime.ttkuaiban.com/api/corpWXAuth&response_type=code&scope=snsapi_base&state=0#wechat_redirect");
+                json.put("content_item",dataJson);
+                if (cpList.size() > 0) {
+//                      System.out.println("发送企业微信漏填提醒:" + LocalDateTime.now().toString() + ", corpUid=" + corpUid + ", json=" + json.toJSONString());
+                    wxCorpInfoService.sendWXCorpTemplateMsg(cpList.get(0), corpUid, json);
+                }
+            }
+        });
+    }
+
+
+
     //每分钟校验是否有需要提醒的填报
     @Scheduled(fixedRate = 60 * 1000)
     private void process() {

+ 2 - 2
fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/ProjectMapper.xml

@@ -121,7 +121,7 @@
     </select>
     <!--获取查询者所在公司每个项目的工时成本-->
     <select id="getParticipatedProject" resultType="java.util.Map">
-        SELECT id, project_code AS projectCode, project_name AS projectName, status, task_gp_incharge as taskGpIncharge, project_desc as projectDesc,is_public as isPublic
+        SELECT id, project_code AS projectCode, project_name AS projectName, status, task_gp_incharge as taskGpIncharge, project_desc as projectDesc,is_public as isPublic, plan_end_date as planEndDate
         FROM project
         WHERE id IN (
             SELECT project_id
@@ -133,7 +133,7 @@
         ORDER BY is_public DESC, id DESC
     </select>
     <select id="getOnlyJoinProjects" resultType="java.util.Map">
-        SELECT id, project_code AS projectCode, project_name AS projectName, status, task_gp_incharge as taskGpIncharge, project_desc as projectDesc, is_public as isPublic
+        SELECT id, project_code AS projectCode, project_name AS projectName, status, task_gp_incharge as taskGpIncharge, project_desc as projectDesc, is_public as isPublic, plan_end_date as planEndDate
         FROM project
         WHERE status = 1 and (id IN (
             SELECT project_id

+ 2 - 1
fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/ReportBatchMapper.xml

@@ -12,11 +12,12 @@
         <result column="state" property="state" />
         <result column="create_time" property="createTime" />
         <result column="company_id" property="companyId" />
+        <result column="summary" property="summary" />
     </resultMap>
 
     <!-- 通用查询结果列 -->
     <sql id="Base_Column_List">
-        id, creator_id, start_date, end_date, total_work_time, state, create_time, company_id
+        id, creator_id, start_date, end_date, total_work_time, state, create_time, company_id, summary
     </sql>
 
 </mapper>

+ 16 - 9
fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/ReportMapper.xml

@@ -68,7 +68,7 @@
         ,c.plate1 as plate1,c.plate2 as plate2,c.plate3 as plate3,c.plate4 as plate4,c.plate5 as plate5
         , reject_reason as rejectReason, reject_username as rejectUsername, reject_userid as rejectUserid, degree_id as degree_id,report_extra_degree.name as degreeName,task_group.name as groupName,a.group_id as groupId,a.custom_data as customData
         ,u.name as projectAuditorName,u.corpwx_userid as projectAuditorCorpwxUserId, a.project_auditor_id as projectAuditorId, department.department_name as departmentName,dp2.department_name as buDepartmentName,department.department_id as departmentId, a.overtime_hours as overtimeHours, a.custom_text as customText,a.project_audit_time  as projectAuditTime,project_main.name as projectMainName,
-        a.extra_field1 as extraField1,a.extra_field2 as extraField2,a.extra_field3 as extraField3
+        a.extra_field1 as extraField1,a.extra_field2 as extraField2,a.extra_field3 as extraField3, a.batch_id as batchId
         FROM report AS a
         JOIN project AS b ON a.project_id=b.id
         LEFT JOIN user AS c ON a.creator_id=c.id
@@ -200,7 +200,7 @@
         ,c.plate1 as plate1,c.plate2 as plate2,c.plate3 as plate3,c.plate4 as plate4,c.plate5 as plate5
         ,u.name as projectAuditorName,u.corpwx_userid as projectAuditorCorpwxUserId, a.project_auditor_id as projectAuditorId, department.department_name as
         departmentName,dp2.department_name as buDepartmentName,department.department_id as departmentId, a.overtime_hours as overtimeHours, a.custom_text as customText, a.project_audit_time as
-        projectAuditTime,project_main.name as projectMainName,a.extra_field1 as extraField1,a.extra_field2 as extraField2,a.extra_field3 as extraField3
+        projectAuditTime,project_main.name as projectMainName,a.extra_field1 as extraField1,a.extra_field2 as extraField2,a.extra_field3 as extraField3, a.batch_id as batchId
         FROM report AS a
         JOIN project AS b ON a.project_id=b.id
         LEFT JOIN user AS c ON a.creator_id=c.id
@@ -325,7 +325,7 @@
         ,c.plate1 as plate1,c.plate2 as plate2,c.plate3 as plate3,c.plate4 as plate4,c.plate5 as plate5
         , reject_reason as rejectReason, reject_username as rejectUsername, reject_userid as rejectUserid, degree_id as degree_id,report_extra_degree.name as degreeName,task_group.name as groupName,a.group_id as groupId, a.custom_data as customData
         ,u.name as projectAuditorName,u.corpwx_userid as projectAuditorCorpwxUserId, a.project_auditor_id as projectAuditorId, department.department_name as departmentName,dp2.department_name as buDepartmentName,department.department_id as departmentId, a.overtime_hours as overtimeHours, a.custom_text as customText, a.project_audit_time as projectAuditTime,project_main.name as projectMainName
-        ,a.extra_field1 as extraField1,a.extra_field2 as extraField2,a.extra_field3 as extraField3
+        ,a.extra_field1 as extraField1,a.extra_field2 as extraField2,a.extra_field3 as extraField3, a.batch_id as batchId
         FROM report AS a
         JOIN project AS b ON a.project_id=b.id
         LEFT JOIN user AS c ON a.creator_id=c.id
@@ -385,7 +385,7 @@
         , reject_reason as rejectReason, reject_username as rejectUsername, reject_userid as rejectUserid, degree_id as degree_id,report_extra_degree.name as degreeName,
         department.department_name as auditDeptName, a.is_dept_audit as isDeptAudit, a.project_audit_state as projectAuditState,task_group.name as groupName,a.group_id as groupId, a.custom_data as customData
         ,u.name as projectAuditorName, a.project_auditor_id as projectAuditorId,dp2.department_name as buDepartmentName,a.overtime_hours as overtimeHours, a.custom_text as customText,a.evaluate as evaluate,a.report_auto_approve as reportAutoApprove,
-        a.extra_field1 as extraField1,a.extra_field2 as extraField2,a.extra_field3 as extraField3
+        a.extra_field1 as extraField1,a.extra_field2 as extraField2,a.extra_field3 as extraField3, a.batch_id as batchId
         FROM report AS a
         JOIN project AS b ON a.project_id=b.id
         left join sub_project as d on d.id = a.sub_project_id
@@ -412,7 +412,7 @@
         , reject_reason as rejectReason, reject_username as rejectUsername, reject_userid as rejectUserid, degree_id as degree_id,report_extra_degree.name as degreeName,
         department.department_name as auditDeptName, a.is_dept_audit as isDeptAudit, a.project_audit_state as projectAuditState,task_group.name as groupName,a.group_id as groupId, a.custom_data as customData
         ,u.name as projectAuditorName, a.project_auditor_id as projectAuditorId, a.overtime_hours as overtimeHours, a.custom_text as customText,a.evaluate as evaluate,a.report_auto_approve as reportAutoApprove,
-        a.extra_field1 as extraField1,a.extra_field2 as extraField2,a.extra_field3 as extraField3
+        a.extra_field1 as extraField1,a.extra_field2 as extraField2,a.extra_field3 as extraField3, a.batch_id as batchId
         FROM report AS a
             JOIN project AS b ON a.project_id=b.id
             left join sub_project as d on d.id = a.sub_project_id
@@ -436,7 +436,7 @@
         , reject_reason as rejectReason, reject_username as rejectUsername, reject_userid as rejectUserid, degree_id as degree_id,report_extra_degree.name as degreeName,
         department.department_name as auditDeptName, a.is_dept_audit as isDeptAudit, a.project_audit_state as projectAuditState,task_group.name as groupName,a.group_id as groupId, a.custom_data as customData
         ,u.name as projectAuditorName, a.project_auditor_id as projectAuditorId, a.overtime_hours as overtimeHours, a.custom_text as customText, dept_manager.name as deptAuditorName,a.evaluate as evaluate,
-        a.extra_field1 as extraField1,a.extra_field2 as extraField2,a.extra_field3 as extraField3
+        a.extra_field1 as extraField1,a.extra_field2 as extraField2,a.extra_field3 as extraField3, a.batch_id as batchId
         FROM report AS a
         JOIN project AS b ON a.project_id=b.id
         left join sub_project as d on d.id = a.sub_project_id
@@ -467,7 +467,7 @@
         , reject_reason as rejectReason, reject_username as rejectUsername, reject_userid as rejectUserid, degree_id as degree_id,report_extra_degree.name as degreeName,
         department.department_name as auditDeptName, a.is_dept_audit as isDeptAudit, a.project_audit_state as projectAuditState,task_group.name as groupName,a.group_id as groupId, a.custom_data as customData
         ,u.name as projectAuditorName, a.project_auditor_id as projectAuditorId, a.overtime_hours as overtimeHours, a.custom_text as customText, dept_manager.name as deptAuditorName,a.evaluate as evaluate,
-        a.extra_field1 as extraField1,a.extra_field2 as extraField2,a.extra_field3 as extraField3
+        a.extra_field1 as extraField1,a.extra_field2 as extraField2,a.extra_field3 as extraField3, a.batch_id as batchId
         FROM report AS a
         JOIN project AS b ON a.project_id=b.id
         left join project_ccuser on project_ccuser.project_id = a.project_id
@@ -499,7 +499,7 @@
         , reject_reason as rejectReason, reject_username as rejectUsername, reject_userid as rejectUserid, degree_id as degree_id,report_extra_degree.name as degreeName,
         department.department_name as auditDeptName, a.is_dept_audit as isDeptAudit, a.project_audit_state as projectAuditState,task_group.name as groupName,a.group_id as groupId, a.custom_data as customData
         ,u.name as projectAuditorName, a.project_auditor_id as projectAuditorId, a.overtime_hours as overtimeHours, a.custom_text as customText, dept_manager.name as deptAuditorName
-        ,a.group_audit_state as groupAuditState,a.batch_id as batchId,a.extra_field1 as extraField1,a.extra_field2 as extraField2,a.extra_field3 as extraField3
+        ,a.group_audit_state as groupAuditState,a.batch_id as batchId,a.extra_field1 as extraField1,a.extra_field2 as extraField2,a.extra_field3 as extraField3, a.batch_id as batchId
         FROM report AS a
         left join user on user.id = a.creator_id
         JOIN project AS b ON a.project_id=b.id
@@ -579,7 +579,7 @@
         , reject_reason as rejectReason, reject_username as rejectUsername, reject_userid as rejectUserid, degree_id as degree_id,report_extra_degree.name as degreeName,
         department.department_name as auditDeptName, a.is_dept_audit as isDeptAudit, a.project_audit_state as projectAuditState,task_group.name as groupName,a.group_id as groupId, a.custom_data as customData
         ,u.name as projectAuditorName, a.project_auditor_id as projectAuditorId,dp2.department_name as buDepartmentName, a.overtime_hours as overtimeHours, a.custom_text as customText, dept_manager.name as deptAuditorName,a.evaluate as evaluate,a.report_auto_approve as reportAutoApprove,
-        a.extra_field1 as extraField1,a.extra_field2 as extraField2,a.extra_field3 as extraField3
+        a.extra_field1 as extraField1,a.extra_field2 as extraField2,a.extra_field3 as extraField3, a.batch_id as batchId
         FROM report AS a
         JOIN project AS b ON a.project_id=b.id
         left join sub_project as d on d.id = a.sub_project_id
@@ -978,6 +978,13 @@
         </foreach>
         AND p.company_id=936 AND p.category IN(168,169,171,172)
         AND r.create_date BETWEEN #{startDate} AND #{endDate}
+        AND r.creator_id NOT IN(8276751764399792128,8236086890927300608,8326361182460387328,
+        8342351512166014976,8236086972770754560,8236087310001184768,
+        8236087296243867648,8236087257492692992,8236088012337389568,
+        8245855829805441024,8318841602900172800,8236087360399941632,
+        8236087733260984320,8236090183732764672,8291179326062796800,
+        8236090183611129856,8236087738910711808
+        )
     </select>
 
     <select id="getReallWorkingTimeByProjectId" resultType="java.lang.Double">

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 2 - 1
fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/TimeTypeMapper.xml


+ 7 - 1
fhKeeper/formulahousekeeper/timesheet/src/views/settings/timetype.vue

@@ -313,7 +313,11 @@
                                 <i class="el-icon-question" style="color:#606266"></i>
                             </el-tooltip>
             </el-tag>
-
+        </div>
+        <div class="yanjiu">
+            <p style="margin-left:10px;color:#666;">项目超期后不可填报</p>
+            <el-switch style="margin-left: 40px" v-model="timeType.notAllowedExpiredProject" active-color="#20a0ff" > </el-switch>
+            <span style="margin-left:10px;color:#999;">开启后超过计划结束日期的项目将不可填报</span>
         </div>
         <!-- <p style="margin-left:10px;color:#666;" v-if="user.timeType.pushReportData == 1">推送工时设置</p>
         <el-row :gutter="20" style="padding-top:10px;width:100%;margin:0 auto;padding-left:10px;padding-right:10px;" v-if="user.timeType.pushReportData == 1">
@@ -1286,6 +1290,7 @@
                         param.mainProjectState = param.mainProjectState ? 1 : 0
                         param.stopReport = param.stopReport? 1: 0;
                         param.notAllowedOnNonWorkday = param.notAllowedOnNonWorkday? 1: 0;
+                        param.notAllowedExpiredProject = param.notAllowedExpiredProject? 1: 0;
                         if(param.lockWorktime){
                             param.fillOvertime = 0
                             param.payOvertime = 0
@@ -1375,6 +1380,7 @@
                             this.timeType.reportAutoApproveDays = this.timeType.reportAutoApproveDays ? this.timeType.reportAutoApproveDays : 1
                             this.timeType.stopReport = this.timeType.stopReport? true: false;
                             this.timeType.notAllowedOnNonWorkday = this.timeType.notAllowedOnNonWorkday? true: false;
+                            this.timeType.notAllowedExpiredProject = this.timeType.notAllowedExpiredProject? true: false;
                             // this.timeType.alertNonWorkday = this.timeType.alertNonWorkday ? true : false
 
                             if(this.timeType.alertNonWorkday) {

+ 109 - 66
fhKeeper/formulahousekeeper/timesheet/src/views/workReport/daily.vue

@@ -175,9 +175,15 @@
                                         </span>
                                     </span>
                                     <div class="checkbtn" style="padding-right:20px;">
-                                        <el-button v-if="item1.state >= 2 && user.id == item1.id" type="primary" size="small" @click="isSubstitude=false; fillInReport(index1,0)">{{$t('btn.editWorkReport')}}</el-button>
+                                        <!--编辑和删除日报-->
+                                        
+                                        <el-button v-if="item1.state >= 2 && user.id == item1.id && user.timeType.enableNewWeeklyfill == 1" type="primary" size="small" @click="isSubstitude=false;fillInReportCustom()">{{$t('btn.editWorkReport')}}</el-button>
+                                        <el-button v-if="item1.state >= 2 && user.id == item1.id && user.timeType.enableNewWeeklyfill != 1" type="primary" size="small" @click="isSubstitude=false; fillInReport(index1,0)">{{$t('btn.editWorkReport')}}</el-button>
                                         <el-button v-if="permissions.reportsDeleteAll && item1.state != 1" size="small" @click="guanli(item1)" style="float: right;">{{$t('btn.delete')}}</el-button>
                                     </div>
+                                    <div v-if="user.timeType.enableNewWeeklyfill == 1 && item1.summary != null" style="margin-left:20px;">
+                                        <p v-html="'<b>'+item1.summaryTitle+'</b><br>'+item1.summary.replace(/[\r\n]/g,'<br>')"> </p>
+                                    </div>
                                     <div class="one_daily_body">
                                         <el-timeline>
                                             <el-timeline-item v-for="(item2,index2) in item1.data" :key="index2">
@@ -942,25 +948,6 @@
                 </el-table>
             </el-form>
 
-            <!-- 按周填报项目筛选 -->
-            <!-- <div v-if="selConShow" class="selConStyle">
-                <div class="selConStyle_title">{{$t('defaultText.pleaseSelectTheItemYouWantToFillIn')}}</div>
-                <el-select v-model="selCon" multiple :placeholder="$t('defaultText.pleaseChoose')" filterable>
-                    <el-option
-                    v-for="item in fillProjectList"
-                    :disabled="item.status!=1 && item.status!=4"
-                    :key="item.id"
-                    :label="item.projectName + '\u3000' + item.projectCode"
-                    :value="item.id">
-                    <span style="float: left; color: #8492a6; font-size: 13px">{{ item.projectCode }}</span>
-                    <span style="float: right">{{ item.projectName }}</span>
-                    </el-option>
-                </el-select>
-            </div> -->
-            <!-- <span slot="footer" class="dialog-footer" v-if="selConShow">
-                <el-button @click="selListqx()">{{$t('btn.cancel')}}</el-button>
-                <el-button type="primary" @click="selListFun()">{{$t('btn.nextStep')}}</el-button>
-            </span> -->
             <span slot="footer" class="dialog-footer" >
                 <!-- <el-button @click="zhoAddlast()" style="float:left;" class="el-icon-back">{{$t('defaultText.selectProject')}}</el-button> -->
                 <el-button @click="closeAddWeeklyReport()" :loading="submitingReport">{{$t('btn.cancel')}}</el-button>
@@ -1061,7 +1048,6 @@
                     <el-select v-model="zhoBao.degreeId" :placeholder="$t('defaultText.pleaseChoose')" clearable="true" style="width: 355px" filterable>
                         <el-option v-for="item in zhoBao.wuduList" :key="item.id" :label="item.name" :value="item.id"></el-option>
                     </el-select>
-                    
                 </div>
                 <!-- 自定义数值 -->
                 <div class="zhoFel" v-if="user.timeType.customDataActive">
@@ -1092,7 +1078,7 @@
                 </div>
                 <div class="zhoFel">
                     <p>{{$t('other.workMatters')}}</p>
-                    <el-input type="textarea" v-model="zhoBao.con" :placeholder="$t('other.tianworkMatters')" style="width: 355px" clearable></el-input>
+                    <el-input type="textarea" v-model="zhoBao.content" :placeholder="$t('other.tianworkMatters')" style="width: 355px" clearable></el-input>
                 </div>
             </div>
             <span slot="footer" class="dialog-footer">
@@ -2532,7 +2518,6 @@
                         //最近项目如果在fillProjectList中不存在,需要移除
                         topObj.peojectList = topObj.peojectList.filter(top=>this.fillProjectList.find(fp=>fp.id==top.id) != null);
                         this.integrationProjectList = [topObj, botomObj]
-                        console.log(this.integrationProjectList, '整合')
                     }else {
                         this.$message({
                             message: res.msg,
@@ -5524,6 +5509,39 @@
                 this.dialogVisible = true;
                 
             },
+
+            //按周填报的弹窗口中编辑单项目相关数据
+            setWeekFormReportItem(reportId, i, names, row,sss) {
+                console.log(sss)
+                this.http.post('/report/getReportById', {
+                    reportId: reportId
+                },
+                res => {
+                    if (res.code == "ok") {
+                        var data = res.data.report;
+                        sss.subProjectId = data.subProjectId
+                        sss.subProjectList = data.subProjectList;
+                        sss.stage = data.stage
+                        sss.subProjectList = data.subProjectList
+                        sss.stages = data.stages
+                        sss.taskGroups = data.taskGroups;
+                        sss.auditUserList = data.auditUserList;
+                        sss.degreeId = data.degreeId;
+                        sss.customData = data.customData;
+                        sss.wuduList = data.degreeList;
+                        this.zhoBaoIdx = i
+                        this.zhoBaoName = names
+                        this.zhoBao = sss
+                        this.zhis = row
+                        if (sss.groupId) {
+                            //最后一个参数表示是否保留stage的值,不要重置为空
+                            this.getGroupStages(this.zhoBao, 0, true)
+                        }
+                        this.$forceUpdate();
+                    }
+                });
+            },
+
             // 按周填报里内容的填写
             tianxies(item, i, names, row) {
                 if (item.state == 0) {
@@ -5564,8 +5582,7 @@
                     if(this.projectList[l].projectName == names) idd = this.projectList[l].id
                 }
                 obj.projectId = idd
-                this.selectProject(obj, 0)
-                // console.log(this.workForm.domains[0], '打印出来的')
+                
                 this.tianxieDialogVisible = true
                 this.scopess = item
                 var sss = {}
@@ -5577,9 +5594,10 @@
                     sss.state = 3;
                 }
                 sss.projectId = idd;
-                sss.con = item.con
                 sss.progress = item.progress
                 sss.time = item.time
+                sss.content = item.content;
+                console.log('333', sss.content)
                 if (sss.time == '' && this.reportTimeType.type == 2) {
                     //取已填时间范围中最大的一个作为开始时间
                     var startTime = '09:00';
@@ -5609,44 +5627,68 @@
                     //默认选中第一个
                     sss.basecostId = this.timeBasecostList[0].id;
                 }
-                var that = this
-                setTimeout(() =>{
-                    var isFirstEdit = false;
-                    if(Object.keys(item).length < 5) {
-                        //首次点开当前的这个cell,初始化数据
-                        isFirstEdit = true;
-                        sss.subProjectId = that.workForm.domains[0].subProjectId
-                        sss.stage = that.workForm.domains[0].stage
-                        sss.subProjectList = that.workForm.domains[0].subProjectList
-                        sss.stages = that.workForm.domains[0].stages
-                        sss.taskGroups = that.workForm.domains[0].taskGroups;
-                        sss.auditUserList = obj.auditUserList;
-                    } else {
-                        sss.subProjectId = item.subProjectId
-                        sss.stage = item.stage
-                        sss.subProjectList = item.subProjectList
-                        sss.stages = item.stages
-                        sss.taskGroups = item.taskGroups;
-                        sss.auditUserList = obj.auditUserList;
-                        sss.degreeId = item.degreeId;
-                        sss.customData = item.customData;
-                    }
+                var hasEdited = this.zhoData[i][names].hasEdited;
+                if (hasEdited) {
+                    //编辑过了
+                    sss.subProjectId = item.subProjectId
+                    sss.stage = item.stage
+                    sss.subProjectList = item.subProjectList
+                    sss.stages = item.stages
+                    sss.taskGroups = item.taskGroups;
+                    console.log(sss.taskGroups, '33333');
+                    sss.auditUserList = obj.auditUserList;
+                    sss.degreeId = item.degreeId;
+                    sss.customData = item.customData;
                     if (sss.auditUserList != null && sss.auditUserList.length==1) {
                         //只有一个审核人,自动设置上去
                         sss.projectAuditorId = sss.auditUserList[0].auditorId;
                     }
-                    sss.wuduList = row[0].wuduList
-                    // console.log(sss, '数据')
-                    that.zhoBaoIdx = i
-                    that.zhoBaoName = names
-                    that.zhoBao = sss
-                    that.zhis = row
+                    sss.wuduList = item.wuduList;
+                    this.zhoBaoIdx = i
+                    this.zhoBaoName = names
+                    this.zhoBao = sss
+                    this.zhis = row
                     if (sss.groupId) {
                         //最后一个参数表示是否保留stage的值,不要重置为空
-                        this.getGroupStages(that.zhoBao, 0, !isFirstEdit)
+                        this.getGroupStages(this.zhoBao, 0, true)
                     }
-                    that.$forceUpdate();
-                },600);
+                    this.$forceUpdate();
+                } else {
+                    //第一次打开,获取数据
+                    if (sss.id == -1) {
+                        //新填报的
+                        this.selectProject(obj, 0);
+                        var that = this
+                        setTimeout(() =>{
+                            sss.subProjectId = that.workForm.domains[0].subProjectId
+                            sss.subProjectList = item.subProjectList;
+                            sss.stage = that.workForm.domains[0].stage
+                            sss.subProjectList = that.workForm.domains[0].subProjectList
+                            sss.stages = that.workForm.domains[0].stages
+                            sss.taskGroups = that.workForm.domains[0].taskGroups;
+                            sss.auditUserList = obj.auditUserList;
+                            sss.degreeId = item.degreeId;
+                            sss.customData = item.customData;
+                            if (sss.auditUserList != null && sss.auditUserList.length==1) {
+                                //只有一个审核人,自动设置上去
+                                sss.projectAuditorId = sss.auditUserList[0].auditorId;
+                            }
+                            sss.wuduList = row[0].wuduList
+                            that.zhoBaoIdx = i
+                            that.zhoBaoName = names
+                            that.zhoBao = sss
+                            that.zhis = row
+                            if (sss.groupId) {
+                                //最后一个参数表示是否保留stage的值,不要重置为空
+                                this.getGroupStages(that.zhoBao, 0, false)
+                            }
+                            that.$forceUpdate();
+                        },600);
+                    } else {
+                        //编辑填报过的;数据库已经存在的
+                        this.setWeekFormReportItem(sss.id, i, names, row, sss);
+                    }
+                }
             },
             // 按周填报里内容的填写点击确定
             setWeekProItemData() {
@@ -5699,7 +5741,7 @@
                 if(this.user.timeType.customTextStatus == 1 && !this.zhoBao.customText){
                     errtips += this.user.timeType.customTextName + '、'
                 }
-                if(this.user.timeType.workContentState == 1 && !this.zhoBao.con){
+                if(this.user.timeType.workContentState == 1 && !this.zhoBao.content){
                     errtips +=  this.user.companyId==781?this.$t('other.specificcontentandresults')+'、': this.$t('other.workMatters') +'、'
                 }
                 if(errtips){
@@ -5713,6 +5755,7 @@
 
                 this.tianxieDialogVisible = false
                 var zhong = this.zhoData
+                this.zhoBao.hasEdited = true;
                 zhong[this.zhoBaoIdx][this.zhoBaoName] = this.zhoBao
                 this.zhoData = zhong
                 if(this.reportTimeType.type == 1) this.zhoXuan(this.zhoBao, this.zhoBaoIdx)
@@ -5793,7 +5836,7 @@
                             var xinzhi = this.selProjectList[j].projectName 
                             obj[xinzhi] = {}
                             obj[xinzhi].time = ''
-                            obj[xinzhi].con = ''
+                            obj[xinzhi].content = ''
                             obj[xinzhi].progress = 0
                             obj[xinzhi].workingTime = 0
                         }
@@ -6024,7 +6067,7 @@
                             var pName = newProject.projectName;
                             dayItem[pName] = {};
                             dayItem[pName].time = ''
-                            dayItem[pName].con = ''
+                            dayItem[pName].content = ''
                             dayItem[pName].progress = 0
                             dayItem[pName].workingTime = 0
                         }
@@ -6116,7 +6159,7 @@
                                 var pName = this.selProjectList[j].projectName 
                                 obj[pName] = {}
                                 obj[pName].time = ''
-                                obj[pName].con = ''
+                                obj[pName].content = ''
                                 obj[pName].progress = 0
                                 obj[pName].workingTime = 0
                             }
@@ -6293,10 +6336,10 @@
                                     var objjs = {}
                                     objjs.startTime = zhoD[j].time[0]
                                     objjs.endTime = zhoD[j].time[1]
-                                    if (zhoD[j].con == null || zhoD[j].con == '') {
-                                        zhoD[j].con == '-'
+                                    if (zhoD[j].content == null || zhoD[j].content == '') {
+                                        zhoD[j].content == '-'
                                     }
-                                    objjs.content = zhoD[j].con
+                                    objjs.content = zhoD[j].content
                                     lix.push(objjs)
                                     var zhiZhi = JSON.stringify(lix)
                                     zhiZhi = zhiZhi.replace(/,/g,"@");
@@ -6378,7 +6421,7 @@
                                         formData.append("endTime", zhoD[j].time[1]);
                                         formData.append("startTime", zhoD[j].time[0]);
                                         formData.append("multiWorktime", this.reportTimeType.multiWorktime);
-                                        zhoD[j].con == '' || zhoD[j].con == null ? formData.append("content", '-') : formData.append("content", zhoD[j].con)
+                                        zhoD[j].content == '' || zhoD[j].content == null ? formData.append("content", '-') : formData.append("content", zhoD[j].content)
                                         formData.append("isOvertime", 0)
                                         formData.append("professionProgress", "[]")
                                         if (zhoD[j].groupId) {
@@ -6459,7 +6502,7 @@
                                             formData.append("workingTime", zhoD[j].workingTime);
                                         }
                                         formData.append("multiWorktime", this.reportTimeType.multiWorktime);
-                                        zhoD[j].con == '' || zhoD[j].con == null ? formData.append("content", '-') : formData.append("content", zhoD[j].con)
+                                        zhoD[j].content == '' || zhoD[j].content == null ? formData.append("content", '-') : formData.append("content", zhoD[j].content)
                                         formData.append("isOvertime", 0)
                                         formData.append("professionProgress", "[]")
                                         if (zhoD[j].groupId) {

+ 9 - 0
fhKeeper/formulahousekeeper/timesheet/src/views/workReport/weeklyCustomization.vue

@@ -77,6 +77,12 @@
                     </el-table-column>
                 </el-table>
             </div>
+            <div>
+                <el-input type="textarea" :autosize="{ minRows: 4, maxRows: 6}" maxlength="1000" show-word-limit
+                    placeholder="请输入周总结"
+                    v-model="summaryContent">
+                    </el-input>
+            </div>
             <div class="weeklyCustomization_btn">
                 <el-button @click="handleClose()">取 消</el-button>
                 <el-button @click="submitWeekData(1)">暂 存</el-button>
@@ -101,6 +107,7 @@ export default {
     },
     data() {
         return {
+            summaryContent: null,
             weekTableData: [],
             projectList: [],
             nowTime: this.dayjs().format('YYYY-MM-DD'),
@@ -134,6 +141,7 @@ export default {
 
             let formData = new FormData();
             formData.append("draft", draft);
+            formData.append('summary', this.summaryContent);
             let fixation = {
                 id: -1,
                 projectId: '',
@@ -256,6 +264,7 @@ export default {
             }
             let { data } = await this.getData('/report/getWeeklyFillReportData', { targetDate: this.nowTime })
             console.log(JSON.parse(JSON.stringify(data)), '<===== 处理之前的')
+            this.summaryContent = data.summary;
             data.dateList.forEach(dateItem => {
                 const reportList = dateItem.reportList;
                 reportList.forEach(report => {

+ 382 - 303
fhKeeper/formulahousekeeper/timesheet_h5/src/views/edit/weekEdit.vue

@@ -27,8 +27,14 @@
                     @click="switchWeek(item,index)"
                     :disabled="canSelect(item)" v-if="user.timeType.enableNewWeeklyfill == 1">{{ weekText(dateRange[index]) }}</van-button>
                 </van-grid-item>
-                <van-grid-item v-if="weekIndex != 7">
-                    <van-button type="default" size="mini" class="selectgxbtn" @click="addWeekIndex()" icon="plus" v-if="user.timeType.enableNewWeeklyfill != 1"></van-button>
+                <!-- 周总结 -->
+                <van-grid-item v-if="user.timeType.enableNewWeeklyfill == 1" :class="999 == inbtn ? 'inbtn' : ''">
+                    <van-button class="selectgxbtn"
+                    type="default"
+                    size="mini" @click="switchWeekly(999)">周总结</van-button>
+                </van-grid-item>
+                <van-grid-item v-if="weekIndex != 7 && user.timeType.enableNewWeeklyfill != 1">
+                    <van-button type="default" size="mini" class="selectgxbtn" @click="addWeekIndex()" icon="plus"></van-button>
                 </van-grid-item>
                 <div class="kaoqin2" v-if="kaoqinText"><span>当日考勤:</span><span>{{kaoqinText}}</span></div>
                 <div class="kaoqin" v-if="workTimeText"><span>已填报工时:</span><span>{{workTimeText}}小时</span></div>
@@ -37,306 +43,327 @@
                 </div>
             </van-grid>
             <van-cell title="总时长(h)" v-if="reportTimeType.type == 3">
-                        <template>
-                            <van-stepper style="float:left;" :disabled="user.timeType.lockWorktime == 1" v-model="reportTimeType.allday" @change="changeAllTime" min="0.5" max="12" step="0.5" button-size="24px" :decimal-length="1" />
-                        </template>
-                    </van-cell>
-
+                <template>
+                    <van-stepper style="float:left;" :disabled="user.timeType.lockWorktime == 1" v-model="reportTimeType.allday" @change="changeAllTime" min="0.5" max="12" step="0.5" button-size="24px" :decimal-length="1" />
+                </template>
+            </van-cell>
 
-            <div class="form_domains" v-for="(item,index) in currentForm.domains" :key="item.id">
-                <div style="float:right;margin-top:10px;margin-right:10px;">
-                
-                <van-tag v-if="index>0" color="#fff" 
-                @click="delPro(index)" style="border: 1px solid #ff0000;padding:5px;margin-left:10px;"
-                 icon="plus" type="default" ><span style="color:#666;padding: 0 5px;">删除</span></van-tag>
-                </div>
+            
+            <!-- 每一周的数据循环 -->
+            <div v-if="inbtn != 999">
+                <div class="form_domains" v-for="(item,index) in currentForm.domains" :key="item.id">
+                    <div style="float:right;margin-top:10px;margin-right:10px;">
+                    
+                    <van-tag v-if="index>0" color="#fff" 
+                    @click="delPro(index)" style="border: 1px solid #ff0000;padding:5px;margin-left:10px;"
+                    icon="plus" type="default" ><span style="color:#666;padding: 0 5px;">删除</span></van-tag>
+                    </div>
 
-                <van-cell-group :title="(user.companyId==781?'任务':'项目') + (index+1)">
-                    <!-- <div>请选择投入项目</div> -->
-                    <!--按周填报的项目改成非必填-->
-                    <van-field  readonly  name="projectId" clickable :value="item.projectName" :label="user.companyId==781?'工作任务':'投入项目'" :placeholder="user.companyId==781?'请选择工作任务':'请选择项目'" @click="clickPicker(index, item)"
-                    />
-                    <van-field  readonly  name="subProjectId" v-if="item.subProjectList != null && item.subProjectList.length > 0 && user.timeType.mainProjectState != 1" clickable 
-                        :value="item.subProjectName" label="子项目" placeholder="请选择子项目" 
-                    @click="clickPickSubProject(index, item)" />
-
-                    <van-popup v-model="item.showPickerSubProject" position="bottom">
-                        <van-picker show-toolbar :columns="item.subProjectList" value-key="name" @confirm="choseSubProject" 
-                            @cancel="item.showPickerSubProject = false;$forceUpdate();" />
-                    </van-popup>
-                    <!--任务分组 -->
-                    <van-field  readonly  name="groupId" v-if="user.company.packageProject==1&&item.taskGroups != null && item.taskGroups.length > 0" clickable 
-                        :value="item.groupName" :label="user.timeType.enableNewWeeklyfill == 1 ? '分组' : '任务分组'" :placeholder="user.timeType.enableNewWeeklyfill == 1 ? '请选择分组' : '请选择任务分组'" 
-                    @click="clickPickTaskGroup(index, item)" />
-                    <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>
-                    <!--任务阶段 -->
-                    <van-field  readonly  name="stage" v-if="user.company.packageProject==1&&item.stages != null && item.stages.length > 0" clickable 
-                        :value="item.stage" label="投入阶段" placeholder="请选择投入阶段" 
-                    @click="clickPickStage(index, item)" />
-                    <van-popup v-model="item.showPickerStage" position="bottom">
-                        <van-picker show-toolbar :columns="item.stages" value-key="stagesName" @confirm="choseStage" 
-                            @cancel="item.showPickerStage = false;$forceUpdate();" />
-                    </van-popup>
-                    <!-- 预算来源 -->
-                    <van-field  readonly  name="basecostId" v-if="user.company.packageProject==1&&reportBasecostList &&reportBasecostList.length>0" 
-                        :value="item.basecostName" label="预算来源" placeholder="请选择预算来源" 
-                    @click="clickPickCostId(index, item)" />
-                    <van-popup v-model="item.showPickerCostId" position="bottom">
-                        <van-picker show-toolbar :columns="reportBasecostList" value-key="name" @confirm="choseCostId" 
-                            @cancel="item.showPickerCostId = false;$forceUpdate();" />
-                    </van-popup>
-                    <!-- 审核人 -->
-                <template v-if="user.timeType.reportAuditType != 3">
-                    <van-field  readonly  name="projectAuditorId" v-if="item.auditUserList != null && item.auditUserList.length > 0" clickable
-                        :value="item.projectAuditorName" :label="user.companyId==781?'审核人':'项目审核人'" placeholder="请选择审核人" 
-                    @click="clickPickAuditor(index, item)">
-                        <template #input>
-                            <span v-if="user.userNameNeedTranslate == '1'"><ww-open-data type='userName' :openid='item.projectAuditorName'></ww-open-data></span>
-                            <span v-else>{{item.projectAuditorName}}</span>
-                        </template>
-                    </van-field>
-                    <van-popup v-model="item.showPickerAuditor" position="bottom">
-                        <van-picker show-toolbar :columns="item.auditUserList" value-key="auditorName" @confirm="choseAuditor" 
-                        @cancel="item.showPickerAuditor = false;$forceUpdate();">
-                            <template #option="item">
-                                <span v-if="user.userNameNeedTranslate == '1'"><ww-open-data type='userName' :openid='item.auditorName'></ww-open-data></span>
-                                <span v-else>{{item.auditorName}}</span>
+                    <van-cell-group :title="(user.companyId==781?'任务':'项目') + (index+1)">
+                        <!-- <div>请选择投入项目</div> -->
+                        <!--按周填报的项目改成非必填-->
+                        <van-field  readonly  name="projectId" clickable :value="item.projectName" :label="user.companyId==781?'工作任务':'投入项目'" :placeholder="user.companyId==781?'请选择工作任务':'请选择项目'" @click="clickPicker(index, item)"
+                        />
+                        <van-field  readonly  name="subProjectId" v-if="item.subProjectList != null && item.subProjectList.length > 0 && user.timeType.mainProjectState != 1" clickable 
+                            :value="item.subProjectName" label="子项目" placeholder="请选择子项目" 
+                        @click="clickPickSubProject(index, item)" />
+
+                        <van-popup v-model="item.showPickerSubProject" position="bottom">
+                            <van-picker show-toolbar :columns="item.subProjectList" value-key="name" @confirm="choseSubProject" 
+                                @cancel="item.showPickerSubProject = false;$forceUpdate();" />
+                        </van-popup>
+                        <!--任务分组 -->
+                        <van-field  readonly  name="groupId" v-if="user.company.packageProject==1&&item.taskGroups != null && item.taskGroups.length > 0" clickable 
+                            :value="item.groupName" :label="user.timeType.enableNewWeeklyfill == 1 ? '分组' : '任务分组'" :placeholder="user.timeType.enableNewWeeklyfill == 1 ? '请选择分组' : '请选择任务分组'" 
+                        @click="clickPickTaskGroup(index, item)" />
+                        <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>
+                        <!--任务阶段 -->
+                        <van-field  readonly  name="stage" v-if="user.company.packageProject==1&&item.stages != null && item.stages.length > 0 && user.timeType.enableNewWeeklyfill != 1" clickable 
+                            :value="item.stage" label="投入阶段" placeholder="请选择投入阶段" 
+                        @click="clickPickStage(index, item)" />
+                        <van-popup v-model="item.showPickerStage" position="bottom">
+                            <van-picker show-toolbar :columns="item.stages" value-key="stagesName" @confirm="choseStage" 
+                                @cancel="item.showPickerStage = false;$forceUpdate();" />
+                        </van-popup>
+                        <!-- 预算来源 -->
+                        <van-field  readonly  name="basecostId" v-if="user.company.packageProject==1&&reportBasecostList &&reportBasecostList.length>0" 
+                            :value="item.basecostName" label="预算来源" placeholder="请选择预算来源" 
+                        @click="clickPickCostId(index, item)" />
+                        <van-popup v-model="item.showPickerCostId" position="bottom">
+                            <van-picker show-toolbar :columns="reportBasecostList" value-key="name" @confirm="choseCostId" 
+                                @cancel="item.showPickerCostId = false;$forceUpdate();" />
+                        </van-popup>
+                        <!-- 审核人 -->
+                    <template v-if="user.timeType.reportAuditType != 3">
+                        <van-field  readonly  name="projectAuditorId" v-if="item.auditUserList != null && item.auditUserList.length > 0" clickable
+                            :value="item.projectAuditorName" :label="user.companyId==781?'审核人':'项目审核人'" placeholder="请选择审核人" 
+                        @click="clickPickAuditor(index, item)">
+                            <template #input>
+                                <span v-if="user.userNameNeedTranslate == '1'"><ww-open-data type='userName' :openid='item.projectAuditorName'></ww-open-data></span>
+                                <span v-else>{{item.projectAuditorName}}</span>
                             </template>
-                        </van-picker>
-                    </van-popup>
-                </template>
+                        </van-field>
+                        <van-popup v-model="item.showPickerAuditor" position="bottom">
+                            <van-picker show-toolbar :columns="item.auditUserList" value-key="auditorName" @confirm="choseAuditor" 
+                            @cancel="item.showPickerAuditor = false;$forceUpdate();">
+                                <template #option="item">
+                                    <span v-if="user.userNameNeedTranslate == '1'"><ww-open-data type='userName' :openid='item.auditorName'></ww-open-data></span>
+                                    <span v-else>{{item.auditorName}}</span>
+                                </template>
+                            </van-picker>
+                        </van-popup>
+                    </template>
 
 
-                    <!-- 自选审批人 -->
-                <template v-if="user.timeType.reportAuditType == 3">
-                    <van-field readonly clickable label="第一审核人" @click="auditorClick(index,'auditorFirst')">
-                        <template #input>
-                            <span v-if="!item.auditorFirst"></span>
-                            <span v-else-if="user.userNameNeedTranslate == '1'"><ww-open-data type='userName' :openid='item.auditorFirst.name'></ww-open-data></span>
-                            <span v-else>{{item.auditorFirst.name}}</span>
-                        </template>
-                    </van-field>
-                    <van-field readonly clickable label="第二审核人" @click="auditorClick(index,'auditorSec')" v-if="user.timeType.auditLevel > 1">
-                        <template #input>
-                            <span v-if="!item.auditorSec"></span>
-                            <span v-else-if="user.userNameNeedTranslate == '1'"><ww-open-data type='userName' :openid='item.auditorSec.name'></ww-open-data></span>
-                            <span v-else>{{item.auditorSec.name}}</span>
-                        </template>
-                    </van-field>
-                    <van-field readonly clickable label="第三审核人" @click="auditorClick(index,'auditorThird')" v-if="user.timeType.auditLevel > 2">
-                        <template #input>
-                            <span v-if="!item.auditorThird"></span>
-                            <span v-else-if="user.userNameNeedTranslate == '1'"><ww-open-data type='userName' :openid='item.auditorThird.name'></ww-open-data></span>
-                            <span v-else>{{item.auditorThird.name}}</span>
-                        </template>
-                    </van-field>
-                    <van-field readonly clickable label="抄送人" @click="auditorClick(index,'ccUserid')">
-                        <template #input>
-                            <span v-if="!item.ccUserid"></span>
-                            <span v-else-if="user.userNameNeedTranslate == '1'"><ww-open-data type='userName' :openid='item.ccUserid.name'></ww-open-data></span>
-                            <span v-else>{{item.ccUserid.name}}</span>
-                        </template>
-                    </van-field>
-                    <van-popup v-model="auditorShow" position="bottom">
-                        <van-search v-model="auditor.searchText" placeholder="输入员工姓名搜索" @search="onSearch" v-if="user.userNameNeedTranslate != '1'"></van-search>
-                        <div style="minHeight:300px;">
-                            <van-radio-group v-model="auditor.item">
-                                <van-radio v-for="uitem in auditor.searchList" :key="uitem.id" :name="uitem" style="padding:10px">
-                                    <span>{{uitem.name}}</span>
-                                </van-radio>
-                            </van-radio-group>
-                            <van-button style="width:100%;position: -webkit-sticky;position: sticky;bottom: 0;" @click="searchAuditor()">确定</van-button>
-                        </div>
-                    </van-popup>
-                </template>
+                        <!-- 自选审批人 -->
+                    <template v-if="user.timeType.reportAuditType == 3">
+                        <van-field readonly clickable label="第一审核人" @click="auditorClick(index,'auditorFirst')">
+                            <template #input>
+                                <span v-if="!item.auditorFirst"></span>
+                                <span v-else-if="user.userNameNeedTranslate == '1'"><ww-open-data type='userName' :openid='item.auditorFirst.name'></ww-open-data></span>
+                                <span v-else>{{item.auditorFirst.name}}</span>
+                            </template>
+                        </van-field>
+                        <van-field readonly clickable label="第二审核人" @click="auditorClick(index,'auditorSec')" v-if="user.timeType.auditLevel > 1">
+                            <template #input>
+                                <span v-if="!item.auditorSec"></span>
+                                <span v-else-if="user.userNameNeedTranslate == '1'"><ww-open-data type='userName' :openid='item.auditorSec.name'></ww-open-data></span>
+                                <span v-else>{{item.auditorSec.name}}</span>
+                            </template>
+                        </van-field>
+                        <van-field readonly clickable label="第三审核人" @click="auditorClick(index,'auditorThird')" v-if="user.timeType.auditLevel > 2">
+                            <template #input>
+                                <span v-if="!item.auditorThird"></span>
+                                <span v-else-if="user.userNameNeedTranslate == '1'"><ww-open-data type='userName' :openid='item.auditorThird.name'></ww-open-data></span>
+                                <span v-else>{{item.auditorThird.name}}</span>
+                            </template>
+                        </van-field>
+                        <van-field readonly clickable label="抄送人" @click="auditorClick(index,'ccUserid')">
+                            <template #input>
+                                <span v-if="!item.ccUserid"></span>
+                                <span v-else-if="user.userNameNeedTranslate == '1'"><ww-open-data type='userName' :openid='item.ccUserid.name'></ww-open-data></span>
+                                <span v-else>{{item.ccUserid.name}}</span>
+                            </template>
+                        </van-field>
+                        <van-popup v-model="auditorShow" position="bottom">
+                            <van-search v-model="auditor.searchText" placeholder="输入员工姓名搜索" @search="onSearch" v-if="user.userNameNeedTranslate != '1'"></van-search>
+                            <div style="minHeight:300px;">
+                                <van-radio-group v-model="auditor.item">
+                                    <van-radio v-for="uitem in auditor.searchList" :key="uitem.id" :name="uitem" style="padding:10px">
+                                        <span>{{uitem.name}}</span>
+                                    </van-radio>
+                                </van-radio-group>
+                                <van-button style="width:100%;position: -webkit-sticky;position: sticky;bottom: 0;" @click="searchAuditor()">确定</van-button>
+                            </div>
+                        </van-popup>
+                    </template>
 
 
-                    <!-- 相关维度 -->
-                    <van-field :value="item.weiduName" v-if="item.projectId && user.timeType.customDegreeActive == 1"  readonly  name="id" clickable :label="user.timeType.customDegreeName" placeholder="请选择" @click="clickPickers(index)"/>
-                    <van-popup v-model="item.showPickDegree" position="bottom">
-                        <van-picker show-toolbar :columns="item.wuduList" value-key="name" @confirm="choseProjects" @cancel="item.showPickDegree = false;$forceUpdate()" />
-                    </van-popup>
-
-                    <!-- 自定义数值 -->
-                    <van-field v-if="user.timeType.customDataActive==1" type="number" v-model="item.customData" :label="user.timeType.customDataName" 
-                         placeholder="请输入数字" ></van-field> 
-                    <!-- 自定义文本 -->
-                    <van-field v-if="user.timeType.customTextActive==1" v-model="item.customText" :label="user.timeType.customTextName" 
-                         placeholder="请输入" maxlength="25"></van-field> 
-
-                    <van-cell title="专业进度" v-if="user.company.packageEngineering == 1">
-                    </van-cell>
-                    <van-field 
-                        type="number"  :name="'progress_'+pItem.professionId" input-align="right" 
-                        v-for="pItem in item.professionProgress" :key="pItem.professionId"
-                        :label="'--    '+pItem.professionName"  
-                    >
-                    <template slot="input">
-                        <van-stepper v-model="pItem.progress" integer min="0" max="100" />%
-                    </template>
-                    </van-field>
-                    
-                    <!-- 常规选择时间的方式 -->
-                    <!-- 全天上下午模式 -->
-                    <div v-if="reportTimeType.multiWorktime==0">
-                    <van-field v-if="reportTimeType.type < 2" readonly clickable  :value="reportTimeType.type==0?item.label:(parseFloat(item.workingTime).toFixed(1)+'h')" label="工作时长" placeholder="请选择工作时长(小时)" @click="clickTimePicker(index)"
-                    :rules="[{ required: true, message: '请选择工作时长' }]"/>
-                    <van-popup v-model="showPickerTime" position="bottom">
-                        <van-picker show-toolbar :columns="timeType"  value-key="label" @confirm="choseTimePick" @cancel="showPickerTime = false" />
-                    </van-popup>
-                    
-                    <!-- 选择数字时间长度模式 -->
-                    <van-popup v-model="showPickerHours" position="bottom">
-                        <van-picker show-toolbar :columns="timeRange" 
-                        :default-index="15"
-                        @confirm="choseTimePick" @cancel="showPickerHours = false" />
-                    </van-popup>
-
-                    <!-- 时间段选择模式 -->
-                    <van-field readonly v-if="reportTimeType.type == 2" clickable name="datetimePicker" :value="item.startTime" label="开始时间" placeholder="点击选择时间" 
-                        @click="showStartTime = true"
-                        :rules="[{ required: true, message: '请选择开始时间' }]"
-                          />
-                    <van-popup v-model="showStartTime" position="bottom">
-                        <van-datetime-picker
-                        v-model="startTime"
-                        type="time"
-                        @confirm="confirmTime(item,0);"
-                        @cancel="showStartTime = false"
-                        :min-hour="0"
-                        :max-hour="23"
-                        />
-                        <!-- :filter="filter" 原本这个属性在里面 -->
-                    </van-popup>
-                    <van-field v-if="reportTimeType.type == 2" readonly clickable name="datetimePicker" :value="item.endTime" label="结束时间" placeholder="点击选择时间" 
-                        @click="showEndTime = true"
-                        :rules="[{ required: true, message: '请选择结束时间' }]" />
-                    <van-popup v-model="showEndTime" position="bottom" >
-                        <van-datetime-picker
-                        v-model="endTime"
-                        type="time"
-                        :min-hour="0"
-                        :max-hour="23"
-                        @confirm="confirmTime(item,1)"
-                        @cancel="showEndTime = false" 
-                        />
-                        <!-- :filter="filter" 原本这个属性在里面 -->
-                    </van-popup>
-                    <van-cell v-if="reportTimeType.type == 3" >
-                        <template >
-                            <div>
-                        <span>用时占比</span>
-                        <van-slider :min="5" :step="5" style="width:120px;display:inline-block;margin-left:50px;" v-model="item.progress" :value="100" @change="item.workingTime = (reportTimeType.allday*item.progress/100).toFixed(1)" >
-                        <template #button>
-                            <div class="custom-button">{{ item.progress }}%</div>
+                        <!-- 相关维度 -->
+                        <van-field :value="item.weiduName" v-if="item.projectId && user.timeType.customDegreeActive == 1"  readonly  name="id" clickable :label="user.timeType.customDegreeName" placeholder="请选择" @click="clickPickers(index)"/>
+                        <van-popup v-model="item.showPickDegree" position="bottom">
+                            <van-picker show-toolbar :columns="item.wuduList" value-key="name" @confirm="choseProjects" @cancel="item.showPickDegree = false;$forceUpdate()" />
+                        </van-popup>
+
+                        <!-- 自定义数值 -->
+                        <van-field v-if="user.timeType.customDataActive==1" type="number" v-model="item.customData" :label="user.timeType.customDataName" 
+                            placeholder="请输入数字" ></van-field> 
+                        <!-- 自定义文本 -->
+                        <van-field v-if="user.timeType.customTextActive==1" v-model="item.customText" :label="user.timeType.customTextName" 
+                            placeholder="请输入" maxlength="25"></van-field> 
+
+                        <van-cell title="专业进度" v-if="user.company.packageEngineering == 1">
+                        </van-cell>
+                        <van-field 
+                            type="number"  :name="'progress_'+pItem.professionId" input-align="right" 
+                            v-for="pItem in item.professionProgress" :key="pItem.professionId"
+                            :label="'--    '+pItem.professionName"  
+                        >
+                        <template slot="input">
+                            <van-stepper v-model="pItem.progress" integer min="0" max="100" />%
                         </template>
-                        </van-slider>
-                        <span style="margin-left:10px;float:right;">{{item.workingTime}}小时</span>
+                        </van-field>
+                        
+                        <!-- 常规选择时间的方式 -->
+                        <!-- 全天上下午模式 -->
+                        <div v-if="reportTimeType.multiWorktime==0">
+                        <van-field v-if="reportTimeType.type < 2" readonly clickable  :value="reportTimeType.type==0?item.label:(parseFloat(item.workingTime).toFixed(1)+'h')" label="工作时长" placeholder="请选择工作时长(小时)" @click="clickTimePicker(index)"
+                        :rules="[{ required: true, message: '请选择工作时长' }]"/>
+                        <van-popup v-model="showPickerTime" position="bottom">
+                            <van-picker show-toolbar :columns="timeType"  value-key="label" @confirm="choseTimePick" @cancel="showPickerTime = false" />
+                        </van-popup>
+                        
+                        <!-- 选择数字时间长度模式 -->
+                        <van-popup v-model="showPickerHours" position="bottom">
+                            <van-picker show-toolbar :columns="timeRange" 
+                            :default-index="15"
+                            @confirm="choseTimePick" @cancel="showPickerHours = false" />
+                        </van-popup>
+
+                        <!-- 时间段选择模式 -->
+                        <van-field readonly v-if="reportTimeType.type == 2" clickable name="datetimePicker" :value="item.startTime" label="开始时间" placeholder="点击选择时间" 
+                            @click="showStartTime = true"
+                            :rules="[{ required: true, message: '请选择开始时间' }]"
+                            />
+                        <van-popup v-model="showStartTime" position="bottom">
+                            <van-datetime-picker
+                            v-model="startTime"
+                            type="time"
+                            @confirm="confirmTime(item,0);"
+                            @cancel="showStartTime = false"
+                            :min-hour="0"
+                            :max-hour="23"
+                            />
+                            <!-- :filter="filter" 原本这个属性在里面 -->
+                        </van-popup>
+                        <van-field v-if="reportTimeType.type == 2" readonly clickable name="datetimePicker" :value="item.endTime" label="结束时间" placeholder="点击选择时间" 
+                            @click="showEndTime = true"
+                            :rules="[{ required: true, message: '请选择结束时间' }]" />
+                        <van-popup v-model="showEndTime" position="bottom" >
+                            <van-datetime-picker
+                            v-model="endTime"
+                            type="time"
+                            :min-hour="0"
+                            :max-hour="23"
+                            @confirm="confirmTime(item,1)"
+                            @cancel="showEndTime = false" 
+                            />
+                            <!-- :filter="filter" 原本这个属性在里面 -->
+                        </van-popup>
+                        <van-cell v-if="reportTimeType.type == 3" >
+                            <template >
+                                <div>
+                            <span>用时占比</span>
+                            <van-slider :min="5" :step="5" style="width:120px;display:inline-block;margin-left:50px;" v-model="item.progress" :value="100" @change="item.workingTime = (reportTimeType.allday*item.progress/100).toFixed(1)" >
+                            <template #button>
+                                <div class="custom-button">{{ item.progress }}%</div>
+                            </template>
+                            </van-slider>
+                            <span style="margin-left:10px;float:right;">{{item.workingTime}}小时</span>
+                                </div>
+                            </template>
+                        </van-cell>
+                        <van-field class="form_input"
+                        v-model="item.content" name="content" type="textarea" :label="user.companyId==781?'具体内容与结果':'工作事项'" placeholder="请输入" 
+                        rows="3" autosize :rules="user.timeType.workContentState == 1 ? [{ required: true, message: user.companyId==781?'具体内容与结果':'工作事项' }] : null" />
+                        </div>
+                        
+                        <!-- 多个时间和工作事项的选择方式 -->
+                        <div v-if="reportTimeType.multiWorktime==1">
+                            <div v-for="(timeItem, tindex) in item.worktimeList" :key="tindex" style="position:relative;border:#ccc 0.5px solid;margin:7px;">
+                                <van-tag v-if="tindex>0" style="position:absolute; right:-7px;top:-7px;z-index:10;" 
+                                    @click="removeTimeItem(item,tindex)">X</van-tag>
+                                
+                                <!-- 时间段选择模式 -->
+                                <van-field readonly v-if="reportTimeType.type == 2" :clickable="true" name="datetimePicker" 
+                                :value="timeItem.startTime" label="开始时间" placeholder="点击选择时间" 
+                                :rules="[{ required: true, message: '必填项' }]"
+                                    @click="showStartDialog(timeItem)"  />
+                                
+                                <van-field v-if="reportTimeType.type == 2" readonly :clickable="true" name="datetimePicker" 
+                                :value="timeItem.endTime" label="结束时间" placeholder="点击选择时间" 
+                                :rules="[{ required: true, message: '必填项' }]"
+                                    @click="showEndDialog(timeItem)"  />
+                                
+                                <van-field class="form_input" style="color:#333;-webkit-text-fill-color:#646566;"
+                                
+                                    v-model="timeItem.content" name="content" type="textarea" label="工作事项" placeholder="请输入工作事项" 
+                                    :rules="user.timeType.workContentState == 1 ? [{ required: true, message: '请填写工作事项' }] : null"
+                                    rows="1" autosize  />
                             </div>
-                        </template>
-                    </van-cell>
-                    <van-field class="form_input"
-                    v-model="item.content" name="content" type="textarea" :label="user.companyId==781?'具体内容与结果':'工作事项'" placeholder="请输入" 
-                    rows="3" autosize :rules="user.timeType.workContentState == 1 ? [{ required: true, message: user.companyId==781?'具体内容与结果':'工作事项' }] : null" />
-                    </div>
-                    
-                    <!-- 多个时间和工作事项的选择方式 -->
-                    <div v-if="reportTimeType.multiWorktime==1">
-                        <div v-for="(timeItem, tindex) in item.worktimeList" :key="tindex" style="position:relative;border:#ccc 0.5px solid;margin:7px;">
-                            <van-tag v-if="tindex>0" style="position:absolute; right:-7px;top:-7px;z-index:10;" 
-                                @click="removeTimeItem(item,tindex)">X</van-tag>
-                            
-                            <!-- 时间段选择模式 -->
-                            <van-field readonly v-if="reportTimeType.type == 2" :clickable="true" name="datetimePicker" 
-                            :value="timeItem.startTime" label="开始时间" placeholder="点击选择时间" 
-                            :rules="[{ required: true, message: '必填项' }]"
-                                @click="showStartDialog(timeItem)"  />
-                            
-                            <van-field v-if="reportTimeType.type == 2" readonly :clickable="true" name="datetimePicker" 
-                            :value="timeItem.endTime" label="结束时间" placeholder="点击选择时间" 
-                            :rules="[{ required: true, message: '必填项' }]"
-                                @click="showEndDialog(timeItem)"  />
-                            
-                            <van-field class="form_input" style="color:#333;-webkit-text-fill-color:#646566;"
-                            
-                                v-model="timeItem.content" name="content" type="textarea" label="工作事项" placeholder="请输入工作事项" 
-                                :rules="user.timeType.workContentState == 1 ? [{ required: true, message: '请填写工作事项' }] : null"
-                                rows="1" autosize  />
+                            <!--时间选择器 , 做统一处理,不能放到循环里,不然会有多个公用showStartTime,最后一个会现在最上层UI,导致BUG -->
+                            <van-popup v-model="showWorkStartTime" position="bottom">
+                                    <van-datetime-picker
+                                    v-model="startTime"
+                                    type="time"
+                                    @confirm="confirmWorkTime(0);"
+                                    @cancel="showWorkStartTime = false"
+                                    :min-hour="0"
+                                    :max-hour="23"
+                                    />
+                                    <!-- :filter="filter" 原本这个属性在里面 -->
+                                </van-popup>
+                            <van-popup v-model="showWorkEndTime" position="bottom" >
+                                    <van-datetime-picker
+                                    v-model="endTime"
+                                    type="time"
+                                    :min-hour="0"
+                                    :max-hour="23"
+                                    @confirm="confirmWorkTime(1)"
+                                    @cancel="showWorkEndTime = false" 
+                                    />
+                                    <!-- :filter="filter" 原本这个属性在里面 -->
+                                </van-popup>
                         </div>
-                        <!--时间选择器 , 做统一处理,不能放到循环里,不然会有多个公用showStartTime,最后一个会现在最上层UI,导致BUG -->
-                        <van-popup v-model="showWorkStartTime" position="bottom">
-                                <van-datetime-picker
-                                v-model="startTime"
-                                type="time"
-                                @confirm="confirmWorkTime(0);"
-                                @cancel="showWorkStartTime = false"
-                                :min-hour="0"
-                                :max-hour="23"
-                                />
-                                <!-- :filter="filter" 原本这个属性在里面 -->
-                            </van-popup>
-                        <van-popup v-model="showWorkEndTime" position="bottom" >
-                                <van-datetime-picker
-                                v-model="endTime"
-                                type="time"
-                                :min-hour="0"
-                                :max-hour="23"
-                                @confirm="confirmWorkTime(1)"
-                                @cancel="showWorkEndTime = false" 
-                                />
-                                <!-- :filter="filter" 原本这个属性在里面 -->
-                            </van-popup>
-                    </div>
-                    
-                    <div style="width:100%;" v-if="reportTimeType.multiWorktime==1">
-                    <van-tag  style="text-align:center;padding:5px;margin-left:15px;border: 1px solid #20a0ff;"
-                         @click="addNewWorktime(index, item)" 
-                        icon="plus" color="#ffffff" ><span style="color:#999;text-align:center;padding: 0 5px;"> 添加工时  </span></van-tag>
-                    </div>
-                    
-                    <div class="overtime" v-if="((user.timeType.fillOvertime || (isWeekend && user.timeType.lockWorktime != 1)) || (isCorpWX&&canEdit)) && user.timeType.enableNewWeeklyfill != 1">
-                        <div class="overTimeClas">
-                            <van-checkbox  v-model="item.isOvertime" style="width: 4.3rem;">加班</van-checkbox>
-                            <van-field v-model="item.overtimeHours" type="number" :disabled="item.isOvertime==null||item.isOvertime==0"
-                            placeholder="请输入加班时长" style="width: 5rem"></van-field>
-                            <span :class="'overListTime'">小时</span>    
+                        
+                        <div style="width:100%;" v-if="reportTimeType.multiWorktime==1">
+                        <van-tag  style="text-align:center;padding:5px;margin-left:15px;border: 1px solid #20a0ff;"
+                            @click="addNewWorktime(index, item)" 
+                            icon="plus" color="#ffffff" ><span style="color:#999;text-align:center;padding: 0 5px;"> 添加工时  </span></van-tag>
                         </div>
-                        <van-tag style="position:absolute;right:10px;" v-if="isCorpWX" type="primary" size="large" @click="takePhoto(index)">拍照上传</van-tag>
-                    </div>
-                    <div style="padding:5px;text-align:center;" v-if="!isIOSystem">
-                        <span v-for="(p, index) in item.pics"  :key="p" style="margin-right:15px;">
-                        <div class="imgList">    
-                            <van-icon v-if=" user.companyId==7" size="20" name="clear"  @click="deleteImg(item, index)" class="imgList_i"/>
-                            <img  :src="p" style="width:100px; height:100px;" @click="showLargeImg(item.pics, index)"/>
+                        
+                        <div class="overtime" v-if="((user.timeType.fillOvertime || (isWeekend && user.timeType.lockWorktime != 1)) || (isCorpWX&&canEdit)) && user.timeType.enableNewWeeklyfill != 1">
+                            <div class="overTimeClas">
+                                <van-checkbox  v-model="item.isOvertime" style="width: 4.3rem;">加班</van-checkbox>
+                                <van-field v-model="item.overtimeHours" type="number" :disabled="item.isOvertime==null||item.isOvertime==0"
+                                placeholder="请输入加班时长" style="width: 5rem"></van-field>
+                                <span :class="'overListTime'">小时</span>    
+                            </div>
+                            <van-tag style="position:absolute;right:10px;" v-if="isCorpWX" type="primary" size="large" @click="takePhoto(index)">拍照上传</van-tag>
                         </div>
-                        </span>
-                    </div>
-                    <div style="padding:5px;text-align:center;" v-if="isIOSystem">
-                        <span v-for="(p, index) in item.iospics"  :key="p" style="margin-right:15px;">
-                        <div class="imgList">
-                            <van-icon  v-if=" user.companyId==7" size="20" name="clear"  @click="deleteImg(item, index)" class="imgList_i"/>
-                            <img :src="p" style="width:100px; height:100px;" @click="showLargeImg(item.iospics, index)"/>
+                        <div style="padding:5px;text-align:center;" v-if="!isIOSystem">
+                            <span v-for="(p, index) in item.pics"  :key="p" style="margin-right:15px;">
+                            <div class="imgList">    
+                                <van-icon v-if=" user.companyId==7" size="20" name="clear"  @click="deleteImg(item, index)" class="imgList_i"/>
+                                <img  :src="p" style="width:100px; height:100px;" @click="showLargeImg(item.pics, index)"/>
+                            </div>
+                            </span>
                         </div>
-                        </span>
-                    </div>
-                    <van-popup v-model="imgShow" position="bottom" closeable >
-                        <van-swipe class="my-swipe"  indicator-color="white">
-                        <van-swipe-item v-for="(picItem, index) in tmpPics" :key="index">
-                            <img :src="picItem" style="width:100%;" />
-                        </van-swipe-item>
-                        </van-swipe>
-                    </van-popup>
-                </van-cell-group>
-                
+                        <div style="padding:5px;text-align:center;" v-if="isIOSystem">
+                            <span v-for="(p, index) in item.iospics"  :key="p" style="margin-right:15px;">
+                            <div class="imgList">
+                                <van-icon  v-if=" user.companyId==7" size="20" name="clear"  @click="deleteImg(item, index)" class="imgList_i"/>
+                                <img :src="p" style="width:100px; height:100px;" @click="showLargeImg(item.iospics, index)"/>
+                            </div>
+                            </span>
+                        </div>
+                        <van-popup v-model="imgShow" position="bottom" closeable >
+                            <van-swipe class="my-swipe"  indicator-color="white">
+                            <van-swipe-item v-for="(picItem, index) in tmpPics" :key="index">
+                                <img :src="picItem" style="width:100%;" />
+                            </van-swipe-item>
+                            </van-swipe>
+                        </van-popup>
+                    </van-cell-group>
+                    
+                </div>
+
+                <!-- 新增项目或者任务 -->
+                <div style="text-align:center;" >
+                <van-tag size="large" style="text-align:center;margin:10px;padding:12px;margin-bottom:120px;border: 1px solid #20a0ff;"
+                    @click="addNewPro" 
+                    icon="plus" color="#ffffff" ><span style="color:#999;text-align:center;padding: 0 50px;"> + 新增{{user.companyId==781?'任务':'项目'}}  </span></van-tag>
+                </div> 
             </div>
-            <div style="text-align:center;" >
-            <van-tag size="large" style="text-align:center;margin:10px;padding:12px;margin-bottom:120px;border: 1px solid #20a0ff;"
-                 @click="addNewPro" 
-                icon="plus" color="#ffffff" ><span style="color:#999;text-align:center;padding: 0 50px;"> + 新增{{user.companyId==781?'任务':'项目'}}  </span></van-tag>
-            </div>  
+            
+
+            <!-- 周总结 -->
+            <div v-if="user.timeType.enableNewWeeklyfill == 1 && inbtn == 999">
+                <div class="van-cell-group__title">周总结</div>
+                <van-field
+                    v-model.trim="summary"
+                    rows="9"
+                    autosize
+                    type="textarea"
+                    maxlength="1000"
+                    show-word-limit
+                    placeholder="请输入周总结"
+                />
+            </div>
+             
             <div class="form_btn" style="position:fixed; bottom:0px;width:100%;">
                 <div style="padding-bottom:10px;">
                     <van-button square block type="info" @click="submitReport" native-type="submit" style="width:100%;float:left;">
@@ -486,7 +513,8 @@
                     list: [],
                     searchList: [],
                 },
-                integrationProjectList: []
+                integrationProjectList: [],
+                summary: '', // 周总结
             };
         },
         methods: {
@@ -583,6 +611,11 @@
             },
             // 切换星期
             switchWeek(item,index){
+                console.log(this.inbtn)
+                if(this.inbtn == 999) {
+                    this.inbtn = index
+                    return
+                }
                 this.form[this.inbtn] = this.currentForm
                 this.inbtn = index
                 this.currentForm = this.form[this.inbtn]
@@ -590,10 +623,14 @@
                     this.currentForm.domains[0].basecostId = this.reportBasecostList[0].id;
                     this.currentForm.domains[0].basecostName = this.reportBasecostList[0].name;
                 }
-                // console.log(this.form);
                 this.getKaoqin()
                 this.getWorkTime()
             },
+            // 切换按周
+            switchWeekly(index) {
+                this.inbtn = index
+                console.log(this.form)
+            },
             addWeekIndex(){
                 console.log(this.weekIndex, this.dateRange);
                 if(this.dateRange.length < 7){
@@ -740,7 +777,8 @@
                 let startDateM = startDate.getMonth() + 1
                 let startDateD = startDate.getDate()
 
-                let endDate = this.dateRange[this.weekIndex - 1]
+                // let endDate = this.dateRange[this.weekIndex - 1]
+                let endDate = this.dateRange.at(-1)
                 let endDateM = endDate.getMonth() + 1
                 let endDateD = endDate.getDate()
 
@@ -752,7 +790,8 @@
                 }
 
                 this.form = []
-                for(let i=0;i<this.weekIndex;i++){
+                // for(let i=0;i<this.weekIndex;i++){
+                for(let i=0;i<this.dateRange.length;i++){
                     let formItem = {
                             createDate: this.format(this.dateRange[i],"yyyy-MM-dd"),
                             domains: [{
@@ -1408,10 +1447,6 @@
                 this.$forceUpdate();
             },
             clickPickTaskGroup(i, item) {
-                // if (!this.canEdit) return;
-                if(this.user.timeType.enableNewWeeklyfill == 1) {
-                    return
-                }
                 this.clickIndex = i;
                 item.showPickerTaskGroup = true;
                 this.$forceUpdate();
@@ -1648,6 +1683,10 @@
             },
             // 清空当前填写信息
             submitClear(){
+                if(this.inbtn == 999) {
+                    this.summary = ''
+                    return
+                }
                 this.currentForm.domains = [{
                                 id: null,
                                 projectId: "",
@@ -1664,9 +1703,10 @@
 
             // 提交日报
             submitReport() {
-                this.form[this.inbtn] = this.currentForm
-                const { allday, workContentState } = this.user.timeType // 系统设置的每日工作时间
-
+                if(this.inbtn != 999) {
+                    this.form[this.inbtn] = this.currentForm
+                }
+                const { allday, workContentState, enableNewWeeklyfill, reportAuditType } = this.user.timeType // 系统设置的每日工作时间
                 // 针对物奇做的判断
                 if(this.user.timeType.enableNewWeeklyfill == 1){
                     const { next, error, group } = this.judgeStrange(this.form)
@@ -1689,7 +1729,16 @@
                         return
                     }
                 }
-                
+
+                // 判断 report_audit_type  = 1 和 2 的情况下任务分组填没填
+                if(reportAuditType == 1 || reportAuditType == 2) {
+                    const { error, next } = this.judgeWorkGroud(this.form)
+                    if(!next) {
+                        this.$toast(`【${error.join('、')}】请填写任务分组`)
+                        return
+                    }
+                }
+
                 //检查子项目
                 if (this.user.timeType.subProMustFill == 1) {
                     for(let i in this.form){
@@ -1747,10 +1796,11 @@
                 }
 
                 let formData = new URLSearchParams()
+                // 周总结
+                if(enableNewWeeklyfill == 1) {
+                    formData.append("summary", this.summary);
+                }
                 for(let formIndex=0;formIndex<this.form.length;formIndex++){
-                    
-
-
                     this.dateAr = []
                     let alp = []
                     if(this.user.timeType.multiWorktime == 1) {
@@ -2051,6 +2101,7 @@
                             this.$toast.success(this.isDraft==0?'提交成功':'暂存成功');
                             setTimeout(()=> {
                                 that.$router.push("/index");
+                                that.summary = ''
                             }, 1000);
                         }
                     } else {
@@ -2215,6 +2266,34 @@
                     }
                 }
             },
+            // 判断任务分组是否填写
+            judgeWorkGroud(from) {
+                const newFrom = JSON.parse(JSON.stringify(from))
+                const arrList = []
+                for(var i in newFrom) {
+                    const { domains, createDate } = newFrom[i]
+                    for(var j in domains) {
+                        if(domains[j].projectId && !domains[j].groupId) {
+                            arrList.push({
+                                dateTime: createDate,
+                                projectName: domains[j].projectName,
+                                weeks: this.getNewWeek(createDate)
+                            })
+                        }
+                    }
+                }
+                if(arrList.length > 0) {
+                    return {
+                        next: false,
+                        error: arrList.map(item => `【${item.dateTime} ${item.weeks} 中的 (${item.projectName})项目】`),
+                    }
+                } else {
+                    return {
+                        next: true,
+                        error: [],
+                    }
+                }
+            },
             // 判断是否小于系统设置的每日工作时间
             judgmentData(data) {
                 const { allday } = this.user.timeType // 系统设置的每日工作时间

+ 1 - 3
fhKeeper/formulahousekeeper/timesheet_h5/src/views/index/index.vue

@@ -185,10 +185,8 @@
                 for (var i in list) {
                     if(list[i].name == '工时报告') {
                         this.routers.push({name: '查看日报',url: '/calendar',icon: 'description'})
-                        if(this.user.companyId != '1071') { // 针对物奇公司去掉填写日报
+                        if(this.user.timeType.enableNewWeeklyfill != 1) { // 针对新版按周填报去掉填写日报
                             this.routers.push({name: '填写日报',url: '/edit',icon: 'edit'})
-                            //物奇临时去掉按周填报
-                            // this.routers.push({name: '按周填报',url: '/weekEdit',icon: 'records'})
                         }
                         this.routers.push({name: '按周填报',url: '/weekEdit',icon: 'records'})
                     }

+ 19 - 17
fhKeeper/formulahousekeeper/timesheet_h5/src/views/view/index.vue

@@ -32,6 +32,10 @@
                             <span>{{ parseFloat(item.reportTime).toFixed(1) }}h</span>
                         </span>
                     </div>
+                    <div v-if="user.timeType.enableNewWeeklyfill == 1 && item.summary != null" style="margin-left:20px;"
+                         v-html="'<b>'+item.summaryTitle+'</b><br>'+item.summary.replace(/\r\n/g, '<br>')">
+                        
+                    </div>
                     <div v-for="(item1, index1) in item.data" class="one_report_data" :key="index1">
                         <div class="project_title" style="font-weight:bold;">项目:{{ item1.project }} <span
                                 :style="'color:' + statusColor[item1.state]">[
@@ -242,9 +246,13 @@ export default {
         },
         // 点击编辑
         editor(item) {
-            console.log(item, '编辑')
+            var path = '/edit';
+            if(this.user.timeType.enableNewWeeklyfill == 1) {
+                //物奇要填到按周填报
+                path = '/weekEdit';
+            }
             this.$router.push({
-                path: '/edit',
+                path: path,
                 query: {
                     date: this.nowTime
                 }
@@ -252,23 +260,17 @@ export default {
         },
         // 去填写日报
         toWriteReport() {
-            if(this.user.companyId == '1071') {
+            var path = '/edit';
+            if(this.user.timeType.enableNewWeeklyfill == 1) {
                 //物奇要填到按周填报
-                this.$router.push({
-                    path: '/weekEdit',
-                    query: {
-                        date: this.nowTime
-                    }
-                });
-            } else {
-                this.$router.push({
-                    path: '/edit',
-                    query: {
-                        date: this.nowTime
-                    }
-                });
+                path = '/weekEdit';
             }
-            
+            this.$router.push({
+                path: path,
+                query: {
+                    date: this.nowTime
+                }
+            });
         }
     },
     mounted() {