QuYueTing 2 недель назад
Родитель
Сommit
c8234bcfe2
38 измененных файлов с 202112 добавлено и 77323 удалено
  1. 1 2
      fhKeeper/formulahousekeeper/inva_4_tivo/css/index.css
  2. 1 0
      fhKeeper/formulahousekeeper/inva_4_tivo/index.html
  3. 0 1
      fhKeeper/formulahousekeeper/management-platform-mld/src/main/java/com/management/platform/controller/ReportController.java
  4. 0 101
      fhKeeper/formulahousekeeper/management-platform-yzr/src/main/java/com/management/platform/controller/WxCorpInfoController.java
  5. 18 1
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/EmployeeController.java
  6. 2 2
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/ProjectAuditorController.java
  7. 90 58
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/ReportController.java
  8. 4 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/AuditWorkflowTimeSetting.java
  9. 3 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/Department.java
  10. 6 1
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/ProjectCustom.java
  11. 7 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/Report.java
  12. 2 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/vo/DepartmentVO.java
  13. 4 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/PermissionServiceImpl.java
  14. 152 5
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ReportServiceImpl.java
  15. 6 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/UserServiceImpl.java
  16. 0 1
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/util/HttpRespMsg.java
  17. 0 70
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/util/HttpRespMsg.java~
  18. 1 1
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/ProjectMapper.xml
  19. 200937 76320
      fhKeeper/formulahousekeeper/management-platform/workTime.log
  20. 3 0
      fhKeeper/formulahousekeeper/management-workshop/src/main/resources/application.yml
  21. 4 2
      fhKeeper/formulahousekeeper/octopus/src/views/customer/list.vue
  22. 355 711
      fhKeeper/formulahousekeeper/ops-platform/octopus.log
  23. 8 1
      fhKeeper/formulahousekeeper/ops-platform/src/main/java/com/management/platform/controller/TimeTypeController.java
  24. 6 0
      fhKeeper/formulahousekeeper/ops-platform/src/main/java/com/management/platform/entity/Company.java
  25. 5 0
      fhKeeper/formulahousekeeper/ops-platform/src/main/java/com/management/platform/entity/TimeType.java
  26. 6 0
      fhKeeper/formulahousekeeper/ops-platform/src/main/java/com/management/platform/service/impl/CompanyServiceImpl.java
  27. 2 1
      fhKeeper/formulahousekeeper/ops-platform/src/main/resources/mapper/CompanyMapper.xml
  28. 1 0
      fhKeeper/formulahousekeeper/timesheet/src/permissions.js
  29. 15 0
      fhKeeper/formulahousekeeper/timesheet/src/routes.js
  30. 90 14
      fhKeeper/formulahousekeeper/timesheet/src/views/corpreport/list.vue
  31. 1 1
      fhKeeper/formulahousekeeper/timesheet/src/views/financeAudit/financeAudit.vue
  32. 19 1
      fhKeeper/formulahousekeeper/timesheet/src/views/project/costReportExport.vue
  33. 189 9
      fhKeeper/formulahousekeeper/timesheet/src/views/project/list.vue
  34. 116 10
      fhKeeper/formulahousekeeper/timesheet/src/views/workReport/daily.vue
  35. 22 2
      fhKeeper/formulahousekeeper/timesheet/src/views/workReport/dailyReportReview.vue
  36. 15 7
      fhKeeper/formulahousekeeper/timesheet_h5/src/views/edit/index.vue
  37. 20 1
      fhKeeper/formulahousekeeper/webttkuaiban/src/main/resources/static/css/index.css
  38. 1 0
      fhKeeper/formulahousekeeper/webttkuaiban/src/main/resources/static/index.html

+ 1 - 2
fhKeeper/formulahousekeeper/inva_4_tivo/css/index.css

@@ -167,8 +167,7 @@
     list-style: disc;
 }
 .bannarTextList li:nth-child(2) {
-    margin-top: 2.8125rem;
-    margin-bottom: 4.4375rem;
+    margin-top: 4.8125rem;
 }
 
 /* 产品介绍 */

+ 1 - 0
fhKeeper/formulahousekeeper/inva_4_tivo/index.html

@@ -72,6 +72,7 @@
             </div>
             <div class="bannarTextList">
                 <ul>
+                    <li>独创AI解析填报,比传统软件提效50% <a href="/video/AIReport.mp4" style="color:#3396FB;" target="_blank">查看对比视频</a></li>
                     <li>提供最全面的项目工时统计解决方案</li>
                     <li>满足小团队项目管理需求 / 大公司IPO财务分摊需求</li>
                 </ul>

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

@@ -832,7 +832,6 @@ public class ReportController {
                     //前3天
                     targetDate=curMonth.minusDays(3);
                 }
-
                 DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
                 //检查填报日期,是否早于限制的日期
                 boolean isForbidden = false;

+ 0 - 101
fhKeeper/formulahousekeeper/management-platform-yzr/src/main/java/com/management/platform/controller/WxCorpInfoController.java

@@ -1,101 +0,0 @@
-package com.management.platform.controller;
-
-
-import com.alibaba.fastjson.JSONArray;
-import com.alibaba.fastjson.JSONObject;
-import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
-import com.management.platform.entity.User;
-import com.management.platform.entity.WxCorpInfo;
-import com.management.platform.mapper.UserMapper;
-import com.management.platform.service.WxCorpInfoService;
-import com.management.platform.task.TimingTask;
-import com.management.platform.util.HttpRespMsg;
-import com.management.platform.util.ListUtil;
-import org.springframework.http.HttpRequest;
-import org.springframework.util.StringUtils;
-import org.springframework.web.bind.annotation.RequestMapping;
-
-import org.springframework.web.bind.annotation.RestController;
-
-import javax.annotation.Resource;
-import javax.servlet.http.HttpServletRequest;
-import java.util.Arrays;
-import java.util.List;
-import java.util.stream.Collectors;
-
-/**
- * <p>
- *  前端控制器
- * </p>
- *
- * @author Seyason
- * @since 2021-07-14
- */
-@RestController
-@RequestMapping("/wx-corp-info")
-public class WxCorpInfoController {
-
-    @Resource
-    WxCorpInfoService wxCorpInfoService;
-    @Resource
-    UserMapper userMapper;
-    @Resource
-    private TimingTask timingTask;
-
-    @RequestMapping("/testDownload")
-    public HttpRespMsg testDownload() {
-        HttpRespMsg msg = new HttpRespMsg();
-        msg.data = wxCorpInfoService.testDownloadFile();
-        return msg;
-    }
-
-    @RequestMapping("/saveContactSecret")
-    public HttpRespMsg saveContactSecret(WxCorpInfo info) {
-        HttpRespMsg msg = new HttpRespMsg();
-        msg.data = wxCorpInfoService.updateById(info);
-        return msg;
-    }
-
-    @RequestMapping("/get")
-    public HttpRespMsg get(Integer companyId) {
-        HttpRespMsg msg = new HttpRespMsg();
-        msg.data = wxCorpInfoService.getOne(new QueryWrapper<WxCorpInfo>().eq("company_id", companyId));
-        return msg;
-    }
-
-    @RequestMapping("/testSendTemplateMsg")
-    public HttpRespMsg testSendTemplateMsg(String userId) {
-        int companyId=7;
-        WxCorpInfo corpInfo = wxCorpInfoService.getOne(new QueryWrapper<WxCorpInfo>().eq("company_id", companyId));
-        String corpwxuserIds = "woy9TkCAAAPD6149u46N_Yi5ARSA4VFw";
-        System.out.println("发送给:"+corpwxuserIds);
-        //推送到企业微信
-//        String corpUid = user.getCorpwxUserid();
-        JSONObject json=new JSONObject();
-        JSONArray dataJson=new JSONArray();
-        JSONObject item=new JSONObject();
-        item.put("key","审核人");
-        item.put("value","$userName=woy9TkCAAAPD6149u46N_Yi5ARSA4VFw$");
-        dataJson.add(item);
-        json.put("template_id","tty9TkCAAANpvEtLrkPUGeOEd1-U7W2w");
-        JSONObject item2=new JSONObject();
-        item2.put("key","日期");
-        item2.put("value","2021-07-14");
-        dataJson.add(item2);
-        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);
-        wxCorpInfoService.sendWXCorpTemplateMsg(corpInfo,corpwxuserIds,json);
-        return new HttpRespMsg();
-    }
-
-    @RequestMapping("/wxLeaveTest")
-    public void wxLeaveTest() throws Exception {
-        timingTask.synWxLeave();
-    }
-
-    @RequestMapping("/batchTransferLicense")
-    public HttpRespMsg batchTransferLicense(HttpServletRequest request,String handoverId,String takeoverId) throws Exception {
-        return wxCorpInfoService.batchTransferLicense(request,handoverId,takeoverId);
-    }
-}
-

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

@@ -5,9 +5,13 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.management.platform.entity.Employee;
 import com.management.platform.entity.EmployeeGroup;
 import com.management.platform.entity.Report;
+import com.management.platform.entity.User;
 import com.management.platform.mapper.ReportMapper;
+import com.management.platform.mapper.UserMapper;
 import com.management.platform.service.EmployeeGroupService;
 import com.management.platform.service.EmployeeService;
+import com.management.platform.service.SysFunctionService;
+import com.management.platform.service.SysRoleFunctionService;
 import com.management.platform.util.HttpRespMsg;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
@@ -43,6 +47,12 @@ public class EmployeeController {
     
     @Value(value = "${upload.path}")
     private String path;
+    @Autowired
+    private SysRoleFunctionService sysRoleFunctionService;
+    @Autowired
+    private SysFunctionService sysFunctionService;
+    @Autowired
+    private UserMapper userMapper;
 
     @RequestMapping("/list")
     public HttpRespMsg list(Integer companyId, Integer groupId, String name) {
@@ -72,7 +82,14 @@ public class EmployeeController {
         HttpRespMsg msg = new HttpRespMsg();
         String token = request.getHeader("TOKEN");
         QueryWrapper<Employee> queryWrapper = new QueryWrapper<Employee>().eq("company_id", companyId);
-        List<EmployeeGroup> groupList = employeeGroupService.list(new QueryWrapper<EmployeeGroup>().eq("company_id", companyId).eq("manager_id", token));
+        //检查权限,是否有:可选全部分组人员权限
+        User user = userMapper.selectById(token);
+        boolean canViewAll = sysFunctionService.hasPriviledge(user.getRoleId(), "可选全部分组人员");
+        QueryWrapper<EmployeeGroup> groupQueryWrapper = new QueryWrapper<EmployeeGroup>().eq("company_id", companyId);
+        if (!canViewAll) {//不可看全部,需要按照分组负责人匹配
+            groupQueryWrapper.eq("manager_id", token);
+        }
+        List<EmployeeGroup> groupList = employeeGroupService.list(groupQueryWrapper);
         List<Employee> list = employeeService.list(queryWrapper);
         for (EmployeeGroup group : groupList) {
             group.setEmployeeList(list.stream().filter(e->e.getGroupId().equals(group.getId())).collect(Collectors.toList()));

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

@@ -52,7 +52,7 @@ public class ProjectAuditorController {
     private TimeTypeMapper timeTypeMapper;
 
     @RequestMapping("/getWorkFlowList")
-    private HttpRespMsg getWorkFlowList(Integer projectId, String userId) {
+    public HttpRespMsg getWorkFlowList(Integer projectId, String userId) {
         String token = userId==null?request.getHeader("TOKEN"):userId;
         HttpRespMsg msg = new HttpRespMsg();
         User user = userMapper.selectById(token);
@@ -64,7 +64,7 @@ public class ProjectAuditorController {
     }
 
     @RequestMapping("/getList")
-    private HttpRespMsg getList(Integer projectId, String userId, @RequestParam(required = false, defaultValue = "false") Boolean forReport) {
+    public HttpRespMsg getList(Integer projectId, String userId, @RequestParam(required = false, defaultValue = "false") Boolean forReport) {
         String token = userId==null?request.getHeader("TOKEN"):userId;
         HttpRespMsg msg = new HttpRespMsg();
         User user = userMapper.selectById(token);

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

@@ -16,6 +16,7 @@ import com.management.platform.entity.vo.SysRichFunction;
 import com.management.platform.entity.vo.WorktimeItem;
 import com.management.platform.mapper.*;
 import com.management.platform.service.*;
+import com.management.platform.service.impl.ProjectConstructionStageServiceImpl;
 import com.management.platform.service.impl.WxCorpInfoServiceImpl;
 import com.management.platform.util.*;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -51,8 +52,15 @@ import java.util.stream.Collectors;
 @RestController
 @RequestMapping("/report")
 public class ReportController {
+    @Resource
+    private ReportProjectConstructionService  reportProjectConstructionService;
+
     @Resource
     private UserRecentReportService userRecentReportService;
+    @Resource
+    private ConstructionStageService constructionStageService;
+    @Resource
+    private ProjectConstructionStageService projectConstructionStageService;
     @Autowired
     private ReportService reportService;
     @Resource
@@ -131,6 +139,8 @@ public class ReportController {
     private UserDingdingTimeMapper userDingdingTimeMapper;
     @Resource
     private MaskWordService maskWordService;
+    @Autowired
+    private ReportProjectConstructionMapper reportProjectConstructionMapper;
 
     //获取任务相关的日报列表
     @RequestMapping("/getTaskReportList")
@@ -494,7 +504,8 @@ public class ReportController {
                                   String weeklyAttachment,
                                   String[] extraField4,
                                   String[] extraField5,
-                                  Boolean abnormalTime
+                                  Boolean abnormalTime,
+                                  String[] constructionStagesStr //柘中定制的施工进度
                                     ) {
         List<Report> reportList = new ArrayList<>();
         String token = request.getHeader("Token");
@@ -522,28 +533,20 @@ public class ReportController {
         }
         if (subProjectId == null) {
             subProjectId = new Integer[projectId.length];
-            for(int i=0;i<subProjectId.length; i++) {
-                subProjectId[i] = 0;
-            }
+            Arrays.fill(subProjectId, 0);
         }
         //初始化,防止老版本无此字段奔溃报错
         if (multiWorktime == null) {
             multiWorktime = new Integer[projectId.length];
-            for(int i=0;i<multiWorktime.length; i++) {
-                multiWorktime[i] = 0;
-            }
+            Arrays.fill(multiWorktime, 0);
         }
         if (degreeId == null) {
             degreeId = new Integer[projectId.length];
-            for(int i=0;i<degreeId.length; i++) {
-                degreeId[i] = -1;
-            }
+            Arrays.fill(degreeId, -1);
         }
         if (groupId == null) {
             groupId = new Integer[projectId.length];
-            for(int i=0;i<groupId.length; i++) {
-                groupId[i] = 0;
-            }
+            Arrays.fill(groupId, 0);
         }
         if (groupId.length != id.length) {
             HttpRespMsg msg = new HttpRespMsg();
@@ -581,15 +584,10 @@ public class ReportController {
 
         if (customData == null) {
             customData = new Double[projectId.length];
-            for(int i=0;i<customData.length; i++) {
-                customData[i] = 0.0;
-            }
+            Arrays.fill(customData, 0.0);
         }
         if (projectAuditorId == null || projectAuditorId.length == 0) {
             projectAuditorId = new String[projectId.length];
-            for(int i=0;i<projectAuditorId.length; i++) {
-                projectAuditorId[i] = null;
-            }
         }
         else if (projectAuditorId.length < projectId.length) {
             if (comTimeType.getReportAuditType() <= 1) {
@@ -612,27 +610,18 @@ public class ReportController {
 
         if (overtimeHours == null) {
             overtimeHours = new Double[projectAuditorId.length];
-            for(int i=0;i<projectAuditorId.length; i++) {
-                overtimeHours[i] = null;
-            }
         }
         if (taskFinish == null) {
             taskFinish = new Integer[projectId.length];
-            for(int i=0;i<taskFinish.length; i++) {
-                taskFinish[i] = 0;
-            }
+            Arrays.fill(taskFinish, 0);
         }
         if (customText == null) {
             customText = new String[projectId.length];
-            for(int i=0;i<customText.length; i++) {
-                customText[i] = "-";
-            }
+            Arrays.fill(customText, "-");
         }
         if (basecostId == null) {
             basecostId = new Integer[projectId.length];
-            for(int i=0;i<basecostId.length; i++) {
-                basecostId[i] = 0;
-            }
+            Arrays.fill(basecostId, 0);
         }
         if (extraField1 == null) {
             extraField1 = new Integer[projectId.length];
@@ -644,53 +633,46 @@ public class ReportController {
                 }
             }
         }
+        for (int i=0;i<extraField1.length; i++) {
+            if (extraField1[i] != null && extraField1[i] == -1) {
+                extraField1[i] = null;//针对前端传的占位值,进行转化
+            }
+        }
 
         if (extraField2 == null) {
             extraField2 = new Integer[projectId.length];
-            for(int i=0;i<extraField2.length; i++) {
-                extraField2[i] = null;
-            }
         }
         if (extraField3 == null) {
             extraField3 = new Integer[projectId.length];
-            for(int i=0;i<extraField3.length; i++) {
-                extraField3[i] = null;
-            }
         }
         if (extraField4 == null || extraField4.length == 0) {
             extraField4 = new String[projectId.length];
-            for(int i=0;i<extraField4.length; i++) {
-                extraField4[i] = "";
-            }
+            Arrays.fill(extraField4, "");
         }
         if (extraField5 == null || extraField5.length == 0) {
             extraField5 = new String[projectId.length];
-            for(int i=0;i<extraField5.length; i++) {
-                extraField5[i] = "";
-            }
+            Arrays.fill(extraField5, "");
         }
         if (professionProgress == null) {
             professionProgress = new String[projectId.length];
-            for(int i=0;i<professionProgress.length; i++) {
-                professionProgress[i] = null;
-            }
         }
         if (sapServiceId == null) {
             sapServiceId = new Integer[projectId.length];
-            for (int i=0;i<sapServiceId.length; i++) {
-                sapServiceId[i] = null;
-            }
         }
         if (multiDegrId == null) {
             multiDegrId = new String[projectId.length];
-            for (int i=0;i<multiDegrId.length; i++) {
-                multiDegrId[i] = null;
-            }
         }
         if (reportTargetDeptId == null) {
             reportTargetDeptId = new Integer[projectId.length];
-            for (int i=0;i<reportTargetDeptId.length; i++) {
-                reportTargetDeptId[i] = -1;
+        }
+        if (constructionStagesStr == null) {
+            constructionStagesStr = new String[projectId.length];
+        } else {
+            //替换符号
+            for (int i=0; i < constructionStagesStr.length; i++) {
+                if (!StringUtils.isEmpty(constructionStagesStr[i])) {
+                    constructionStagesStr[i] = constructionStagesStr[i].replaceAll("@", ",");
+                }
             }
         }
         if (company.getPackageProject() == 1) {
@@ -843,12 +825,57 @@ public class ReportController {
                     }
                 }
             }
-
         }
         //检查项目是否可填报; 修改为不校验项目,前端加载的项目已经过滤掉了完成和撤销的
         List<Integer> integers = Arrays.asList(projectId);
         List<Project> projectList = projectMapper.selectList(new QueryWrapper<Project>().in("id", integers));
 
+        //柘中,校验完成数量累计不可超过项目中每个施工节点的设计量
+        if (company.getId() == 10 || company.getId() == 4811) {
+            for (int i=0;i<integers.size(); i++) {
+                if (!StringUtils.isEmpty(constructionStagesStr[i])) {
+                    final int i1 = i;
+                    Project project = projectList.stream().filter(p -> p.getId().equals(integers.get(i1))).findFirst().orElse(null);
+                    List<ConstructionStage> stageList = JSONArray.parseArray(constructionStagesStr[i], ConstructionStage.class);
+                    for (ConstructionStage currentStage : stageList) {
+                        if (currentStage == null) continue;
+                        //获取到施工分项的id
+                        ProjectConstructionStage projectConstructionStage = projectConstructionStageService.getOne(new QueryWrapper<ProjectConstructionStage>().eq("project_id", project.getId()).eq("stage_id", currentStage.getId()));
+                        if (projectConstructionStage != null && projectConstructionStage.getDesignNumber() != null && projectConstructionStage.getDesignNumber() > 0) {
+                            Double currentMax = projectConstructionStage.getDesignNumber();
+                            System.out.println("currentStage.getId(), "+currentStage.getId());
+                            ReportProjectConstruction rpc = reportProjectConstructionMapper.selectOne(new QueryWrapper<ReportProjectConstruction>().select("sum(finish_number) as finish_number").eq("project_id", project.getId())
+                                    .eq("construction_stage_id", currentStage.getId()));
+                            System.out.println("rpc==="+(rpc == null) + ", "+(rpc != null ? rpc.getFinishNumber()+"哥":"0"));
+                            Double finishNum = (rpc == null || rpc.getFinishNumber() == null) ? 0: rpc.getFinishNumber();
+                            double left = currentMax - finishNum;
+                            if (left < 0) {
+                                HttpRespMsg msg = new HttpRespMsg();
+                                msg.setError("项目"+project.getProjectName()+"当前施工分项完成数量为"+finishNum+", 施工节点设计量不足,请联系管理员修改。");
+                                return msg;
+                            }
+                            //叠加上当前日报上合计填报的完成数量
+                            int currentNum = 0;
+                            for (int j=0;j<projectId.length; j++) {
+                                if (projectId[j].equals(project.getId())) {
+                                    //取该项目上填报的该施工节点的数量
+                                    List<ConstructionStage> nextStageList = JSONArray.parseArray(constructionStagesStr[j], ConstructionStage.class);
+                                    ConstructionStage nextStage = nextStageList.stream().filter(next->next.getId().equals(currentStage.getId())).findFirst().orElse(null);
+                                    if (nextStage != null && nextStage.getFinishNumber() != null ) {
+                                        currentNum += nextStage.getFinishNumber();
+                                    }
+                                }
+                            }
+                            if (currentNum > 0 && currentNum > left) {
+                                HttpRespMsg msg = new HttpRespMsg();
+                                msg.setError("项目"+project.getProjectName()+"中的【"+currentStage.getName()+"】最大为"+currentMax+",仅剩余:"+left+", 当前填报:"+currentNum);
+                                return msg;
+                            }
+                        }
+                    }
+                }
+            }
+        }
 
         List<ReportAuditorSetting> auditorSettingList = null;
         if (comTimeType.getReportAuditType() == 3) {
@@ -1239,6 +1266,7 @@ public class ReportController {
                             report.setMultiDegrId(multiDegrId[i]);
                             report.setExtraField4(extraField4[i]);
                             report.setExtraField5(extraField5[i]);
+                            report.setConstructionStagesStr(constructionStagesStr[i]);
                             //如果是员工自由选择审批流程的方式,需要处理一下
                             if (comTimeType.getReportAuditType() == 3) {
                                 report.setAuditorSetting(auditorSettingList.get(i));
@@ -1298,6 +1326,7 @@ public class ReportController {
                                 report.setMultiDegrId(multiDegrId[i]);
                                 report.setExtraField4(extraField4[i]);
                                 report.setExtraField5(extraField5[i]);
+                                report.setConstructionStagesStr(constructionStagesStr[i]);
                                 //如果是员工自由选择审批流程的方式,需要处理一下
                                 if (comTimeType.getReportAuditType() == 3) {
                                     report.setAuditorSetting(auditorSettingList.get(i));
@@ -1357,6 +1386,7 @@ public class ReportController {
                         report.setMultiDegrId(multiDegrId[i]);
                         report.setExtraField4(extraField4[i]);
                         report.setExtraField5(extraField5[i]);
+                        report.setConstructionStagesStr(constructionStagesStr[i]);
                         //如果是员工自由选择审批流程的方式,需要处理一下
                         if (comTimeType.getReportAuditType() == 3) {
                             report.setAuditorSetting(auditorSettingList.get(i));
@@ -1422,6 +1452,7 @@ public class ReportController {
                             report.setMultiDegrId(multiDegrId[i]);
                             report.setExtraField4(extraField4[i]);
                             report.setExtraField5(extraField5[i]);
+                            report.setConstructionStagesStr(constructionStagesStr[i]);
                             //如果是员工自由选择审批流程的方式,需要处理一下
                             if (comTimeType.getReportAuditType() == 3) {
                                 report.setAuditorSetting(auditorSettingList.get(i));
@@ -2364,9 +2395,9 @@ public class ReportController {
                 Integer oneId = id[i];
                 if (oneId == -1) {
                     Report report = reportList.get(i);
-                    if (report.getCreatorId().equals(report.getProjectAuditorId())) {
-                        //直接审核
-                        if (report.getState() == 0) {
+                    if (report.getState() == 0) {//部门也直接审核通过
+                        if (report.getCreatorId().equals(report.getProjectAuditorId()) || (comTimeType.getAutoProjectApprove() && report.getIsDeptAudit() == 1 && report.getAuditDeptManagerid().equals(report.getCreatorId()))) {
+                            //直接审核
                             reportIds.add(report.getId().toString());
                         }
                     }
@@ -2646,6 +2677,7 @@ public class ReportController {
                 Department curDept = allDeptList.stream()
                         .filter(ad->ad.getDepartmentId().equals(firstNode.getAuditDeptId())).findFirst().get();
                 String curDeptManagerId = curDept.getManagerId();
+
                 //启用了本部门负责人的日报由上级部门主要负责人审核
                 if (comTimeType.getReportAuditFlowEnableSuperDeptAduit() == 1 && curDeptManagerId.equals(report.getCreatorId())) {
                     //当前提交的人是这个部门的主要负责人,那么要取该部门的上一级部门的主要负责人来审核

+ 4 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/AuditWorkflowTimeSetting.java

@@ -1,5 +1,7 @@
 package com.management.platform.entity;
 
+import com.alibaba.fastjson.annotation.JSONField;
+import com.alibaba.fastjson.annotation.JSONType;
 import com.baomidou.mybatisplus.annotation.IdType;
 import com.baomidou.mybatisplus.extension.activerecord.Model;
 import com.baomidou.mybatisplus.annotation.TableId;
@@ -7,6 +9,7 @@ import com.baomidou.mybatisplus.annotation.TableField;
 import java.io.Serializable;
 import java.util.List;
 
+import com.fasterxml.jackson.annotation.JsonInclude;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
 import lombok.experimental.Accessors;
@@ -22,6 +25,7 @@ import lombok.experimental.Accessors;
 @Data
 @EqualsAndHashCode(callSuper = false)
 @Accessors(chain = true)
+@JsonInclude(JsonInclude.Include.NON_NULL)
 public class AuditWorkflowTimeSetting extends Model<AuditWorkflowTimeSetting> {
 
     private static final long serialVersionUID=1L;

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

@@ -5,6 +5,8 @@ import com.baomidou.mybatisplus.extension.activerecord.Model;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableField;
 import java.io.Serializable;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
 import lombok.experimental.Accessors;
@@ -20,6 +22,7 @@ import lombok.experimental.Accessors;
 @Data
 @EqualsAndHashCode(callSuper = false)
 @Accessors(chain = true)
+@JsonInclude(JsonInclude.Include.NON_NULL)
 public class Department extends Model<Department> {
 
     private static final long serialVersionUID=1L;

+ 6 - 1
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/ProjectCustom.java

@@ -37,11 +37,16 @@ public class ProjectCustom extends Model<ProjectCustom> {
     private String customName;
 
     /**
-     * 0-文本 1-图片 2-日期
+     * 0-文本 1-图片 2-日期 3-下拉选项
      */
     @TableField("custom_type")
     private Integer customType;
 
+    /**
+     * 下拉选项列表,逗号隔开
+     */
+    @TableField("custom_options")
+    private String customOptions;
 
     @Override
     protected Serializable pkVal() {

+ 7 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/Report.java

@@ -457,9 +457,16 @@ public class Report extends Model<Report> {
     @TableField(exist = false)
     private List<AuditWorkflowTimeSetting> auditWorkflow;
 
+    @TableField(exist = false)
+    private List<ProjectConstructionStage> projectConsStageList;
+
+    @TableField(exist = false)
+    private String constructionStagesStr;
+
     @Override
     protected Serializable pkVal() {
         return this.id;
     }
 
+
 }

+ 2 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/vo/DepartmentVO.java

@@ -1,5 +1,6 @@
 package com.management.platform.entity.vo;
 
+import com.fasterxml.jackson.annotation.JsonInclude;
 import com.management.platform.entity.Department;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
@@ -11,6 +12,7 @@ import java.util.List;
 @Data
 @EqualsAndHashCode(callSuper = false)
 @Accessors(chain = true)
+@JsonInclude(JsonInclude.Include.NON_NULL)
 public class DepartmentVO {
     private Integer id;
     private String label;

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

@@ -284,6 +284,10 @@ public class PermissionServiceImpl extends ServiceImpl<PermissionMapper, Permiss
         }
         functionQueryWrapper.orderByAsc("seq");
         List<SysFunction> functionList = sysFunctionMapper.selectList(functionQueryWrapper);
+        //针对柘中定制的,其他公司需要去掉:可选全部分组人员
+        if (companyId != 4811) {
+            functionList.removeIf(f -> f.getName().equals("可选全部分组人员"));
+        }
         //勾选上角色选中的功能
         List<SysRoleFunction> roleFunctionList = sysRoleFunctionMapper.selectList(new QueryWrapper<SysRoleFunction>().eq("role_id", role));
         //获取当前公司开启了得报表

+ 152 - 5
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ReportServiceImpl.java

@@ -109,7 +109,11 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
     private ReportDeleteService reportDeleteService;
     @Resource
     private UserFvTimeMapper userFvTimeMapper;
+    @Resource
+    private ReportProjectConstructionMapper reportProjectConstructionMapper;
 
+    @Resource
+    private ConstructionStageMapper constructionStageMapper;
     @Resource
     private AuditWorkflowTimeSettingService auditWorkflowTimeSettingService;
     @Resource
@@ -261,6 +265,10 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
     private FinanceMapper financeMapper;
     @Resource
     private FinancialAuditMapper financialAuditMapper;
+    @Resource
+    private ProjectConstructionStageMapper projectConstructionStageMapper;
+    @Resource
+    private ReportProjectConstructionService reportProjectConstructionService;
 
 
     //获取报告列表
@@ -504,10 +512,13 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
             }
 
             //针对柘中,增加重新设置customText
-            if (companyId == 4811) {
+            if (companyId == 4811 || companyId == 10) {
+                List<ConstructionStage> stageList = constructionStageMapper.selectList(new QueryWrapper<ConstructionStage>());
                 for (Map map : nameList) {
                     List<Map<String, Object>> reportList = (List<Map<String, Object>>) map.get("data");
                     changeCustomText(reportList);
+                    //设置对应的施工节点完成数量
+                    setConstructionStageList(reportList, stageList);
                 }
             }
             if (timeType.getEnableNewWeeklyfill() == 1) {
@@ -618,6 +629,25 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
         return httpRespMsg;
     }
 
+    //柘中,设置施工节点和完成数量
+    private void setConstructionStageList(List<Map<String, Object>> reportList, List<ConstructionStage> stageList) {
+        for (Map<String, Object> map : reportList) {
+            List<ReportProjectConstruction> rpcList = reportProjectConstructionMapper.selectList(new QueryWrapper<ReportProjectConstruction>().eq("report_id", (Integer)map.get("id")).ne("finish_number", 0));
+            StringBuilder sb = new StringBuilder();
+            for (ReportProjectConstruction rpc : rpcList) {
+                ConstructionStage curStage = stageList.stream().filter(stage->stage.getId().equals(rpc.getConstructionStageId())).findFirst().orElse(null);
+                if (curStage != null) {
+                    sb.append(curStage.getName() + "("+rpc.getFinishNumber()+"), ");
+                }
+            }
+            String finalStr = sb.toString();
+            if (finalStr.contains(", ")) {
+                finalStr = finalStr.substring(0, finalStr.length() -2);
+            }
+            map.put("constructionStageStr", finalStr);
+        }
+    }
+
     private List<Department> getSubDepts(Department dp, List<Department> list) {
         List<Department> collect = list.stream().filter(l -> dp.getDepartmentId().equals(l.getSuperiorId())).collect(Collectors.toList());;
         List<Department> allList = new ArrayList<>();
@@ -656,6 +686,7 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
             List<TaskGroup> taskGroups = integerList.size() > 0?taskGroupMapper.selectList(new QueryWrapper<TaskGroup>().in("project_id", integerList)):new ArrayList<>();
             List<Stages> stagesList = integerList.size() > 0?stagesMapper.selectList(new QueryWrapper<Stages>().in("project_id", integerList)) : new ArrayList<>();
             TimeType timeType = timeTypeMapper.selectById(companyId);
+//            List<ConstructionStage> constructionStages = (companyId == 4811 || companyId == 10)?constructionStageMapper.selectList(new QueryWrapper<ConstructionStage>().eq("company_id", companyId)):new ArrayList<>();
             //获取当前项目的子项目列表,任务分组,任务列表,项目相关维度列表
             reports.forEach(r->{
                 //设置项目名称
@@ -902,6 +933,7 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
                         }
                     }
                 }
+
                 //解析自定义多选数组
                 if (!StringUtils.isEmpty(r.getMultiDegrId())) {
                     String multi = r.getMultiDegrId().replace("@", ",");
@@ -913,6 +945,24 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
                     }
                     r.setMultiDegrIdList(list);
                 }
+
+                if (companyId == 10 || companyId == 4811) {
+                    List<ReportProjectConstruction> rpcList = reportProjectConstructionMapper.selectList(new QueryWrapper<ReportProjectConstruction>().eq("report_id", r.getId()));
+                    System.out.println(r.getProjectName()+ ", rpcList.size()=="+rpcList.size()+", r.getProjectId()="+r.getProjectId());
+                    for (ReportProjectConstruction rpc : rpcList) {
+                        System.out.println(rpc.getConstructionStageId()+", "+rpc.getFinishNumber());
+                    }
+                    List<ProjectConstructionStage> projectConstructionStageList = projectConstructionStageMapper.selectList(new QueryWrapper<ProjectConstructionStage>().eq("project_id", r.getProjectId()));
+                    for (ProjectConstructionStage stage : projectConstructionStageList) {
+                        if (rpcList.size() > 0) {
+                            rpcList.stream().filter(rpc->rpc.getConstructionStageId().equals(stage.getStageId())).findFirst().ifPresent(rpc-> {
+                                stage.setFinishNumber(rpc.getFinishNumber());
+                            });
+                        }
+                    }
+                    r.setProjectConsStageList(projectConstructionStageList);
+                }
+
             });
             resultMap.put("report", reports);
             if(CollectionUtils.isEmpty(reports)){
@@ -1440,6 +1490,10 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
         //批量新增或更新
         if (reportList.size() > 0) {
             reportService.saveOrUpdateBatch(reportList);
+            System.out.println("打印日报主键:");
+            for (Report r : reportList) {
+                System.out.println("reportId==========="+r.getId());
+            }
             //成都明夷电子,需要生成批量记录
             Company company = companyMapper.selectById(companyId);
             if (company.getCompanyName().equals("成都明夷电子科技股份有限公司") || timeType.getEnableNewWeeklyfill() == 1 || timeType.getWeeklyChargeFilter() == 1) {//物奇需要填写周总结
@@ -1655,6 +1709,59 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
                 reportAuditorSettingService.saveOrUpdateBatch(collect);
             }
         }
+        //存储日报中的施工节点完成数量,并更新柘中的项目的完成度
+        if (companyId == 10 || companyId == 4811) {
+            List<ReportProjectConstruction> rpcList = new ArrayList<>();
+            //先删除,当天该员工的rpc记录
+            String creatorId = reportList.get(0).getCreatorId();
+            LocalDate workDate = reportList.get(0).getCreateDate();
+            reportProjectConstructionService.remove(new QueryWrapper<ReportProjectConstruction>().eq("user_id", creatorId).eq("work_date", workDate));
+            for (Report report : reportList) {
+                if (!StringUtils.isEmpty(report.getConstructionStagesStr())) {
+                    List<ConstructionStage> stageList = JSONArray.parseArray(report.getConstructionStagesStr(), ConstructionStage.class);
+                    for (ConstructionStage stage : stageList) {
+                        ReportProjectConstruction rpc = new ReportProjectConstruction();
+                        rpc.setReportId(report.getId());
+                        rpc.setFinishNumber(stage.getFinishNumber());
+                        rpc.setProjectId(report.getProjectId());
+                        rpc.setConstructionStageId(stage.getId());
+                        rpc.setUserId(creatorId);
+                        rpc.setWorkDate(workDate);
+                        rpcList.add(rpc);
+                    }
+                }
+            }
+            if (rpcList.size() > 0) {
+                reportProjectConstructionService.saveBatch(rpcList);
+            }
+            List<Integer> pids = reportList.stream().map(Report::getProjectId).distinct().collect(Collectors.toList());
+            //获取已经填报的数据
+            List<ReportProjectConstruction> list = reportProjectConstructionService.list(new QueryWrapper<ReportProjectConstruction>().select("project_id, construction_stage_id, sum(finish_number) as finish_number")
+                    .isNotNull("construction_stage_id").groupBy("project_id, construction_stage_id"));
+            for (Integer projectId : pids) {
+                //计算完成度
+                List<ProjectConstructionStage> stages = projectConstructionStageMapper.selectList(new QueryWrapper<ProjectConstructionStage>().eq("project_id", projectId));
+                if (stages.size() == 0) {
+                    break;
+                }
+                List<ReportProjectConstruction> currentRpcList = list.stream().filter(p->p.getProjectId().equals(projectId)).collect(Collectors.toList());
+                if (currentRpcList.size() > 0) {
+                    double totalRate = 0;
+                    for (ReportProjectConstruction rpc : currentRpcList) {
+                        Integer stageId = rpc.getConstructionStageId();
+                        Double finishNumber = rpc.getFinishNumber();
+                        ProjectConstructionStage curItem = stages.stream().filter(s->s.getStageId().equals(stageId)).findFirst().orElse(null);
+                        if (curItem != null && curItem.getDesignNumber() != 0 && curItem.getPercent() != 0) {
+                            totalRate += finishNumber / curItem.getDesignNumber() * curItem.getPercent();
+                        }
+                    }
+                    Project project = new Project();
+                    project.setId(projectId);
+                    project.setProgress((int)Math.round(totalRate));
+                    projectMapper.updateById(project);
+                }
+            }
+        }
 
         return httpRespMsg;
     }
@@ -1902,6 +2009,40 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
                 delList.add(delLog);
             }
             reportDeleteService.saveOrUpdateBatch(delList);
+            //更新项目施工进度
+            if (company.getId() == 10 || company.getId() == 4811) {
+                List<ReportProjectConstruction> rpcList = new ArrayList<>();
+                //先删除,当天该员工的rpc记录
+                String creatorId = reportList.get(0).getCreatorId();
+                LocalDate workDate = reportList.get(0).getCreateDate();
+                List<Integer> pids = reportList.stream().map(Report::getProjectId).distinct().collect(Collectors.toList());
+                //获取已经填报的数据
+                List<ReportProjectConstruction> list = reportProjectConstructionService.list(new QueryWrapper<ReportProjectConstruction>().select("project_id, construction_stage_id, sum(finish_number) as finish_number")
+                        .isNotNull("construction_stage_id").groupBy("project_id, construction_stage_id"));
+                for (Integer projectId : pids) {
+                    //计算完成度
+                    List<ProjectConstructionStage> stages = projectConstructionStageMapper.selectList(new QueryWrapper<ProjectConstructionStage>().eq("project_id", projectId));
+                    if (stages.size() == 0) {
+                        break;
+                    }
+                    List<ReportProjectConstruction> currentRpcList = list.stream().filter(p->p.getProjectId().equals(projectId)).collect(Collectors.toList());
+                    if (currentRpcList.size() > 0) {
+                        double totalRate = 0;
+                        for (ReportProjectConstruction rpc : currentRpcList) {
+                            Integer stageId = rpc.getConstructionStageId();
+                            Double finishNumber = rpc.getFinishNumber();
+                            ProjectConstructionStage curItem = stages.stream().filter(s->s.getStageId().equals(stageId)).findFirst().orElse(null);
+                            if (curItem != null && curItem.getDesignNumber() != 0 && curItem.getPercent() != 0) {
+                                totalRate += finishNumber / curItem.getDesignNumber() * curItem.getPercent();
+                            }
+                        }
+                        Project project = new Project();
+                        project.setId(projectId);
+                        project.setProgress((int)Math.round(totalRate));
+                        projectMapper.updateById(project);
+                    }
+                }
+            }
         }
         return httpRespMsg;
     }
@@ -2300,10 +2441,7 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
                     }
                 }
             }
-            //针对柘中,增加重新设置customText
-            if (companyId == 4811) {
-                changeCustomText(auditReportList);
-            }
+
             //抽取姓名,进行分组
             List<Map<String, Object>> nameList = new ArrayList<Map<String, Object>>();
             Map<String, Object> lastName = null;
@@ -2417,6 +2555,15 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
                     }
                 }
             }
+            //针对柘中的施工节点进度显示
+            if (companyId == 10 || companyId == 4811) {
+                changeCustomText(auditReportList);
+                List<ConstructionStage> stageList = constructionStageMapper.selectList(new QueryWrapper<ConstructionStage>());
+                for (Map map : nameList) {
+                    List<Map<String, Object>> reportList = (List<Map<String, Object>>)map.get("data");
+                    setConstructionStageList(reportList, stageList);
+                }
+            }
             DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd");
             String minDate = null;
             String maxDate = null;

+ 6 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/UserServiceImpl.java

@@ -660,6 +660,12 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
             proModule.setPath("/employeeManagement");
             proModule.setId(0);
             moduleList.add(proModule);
+
+            proModule = new SysModule();
+            proModule.setName("分项工程管理");
+            proModule.setPath("/construction");
+            proModule.setId(-1);
+            moduleList.add(proModule);
         }
         //组装层级关系,默认只有两级
         List<SysModule> menuList = new ArrayList<>();

+ 0 - 1
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/util/HttpRespMsg.java

@@ -4,7 +4,6 @@ import com.alibaba.fastjson.JSONObject;
 import com.fasterxml.jackson.annotation.JsonInclude;
 
 import java.io.Serializable;
-
 public class HttpRespMsg implements Serializable {
 
     //status code, ok or error.

+ 0 - 70
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/util/HttpRespMsg.java~

@@ -1,70 +0,0 @@
-package com.management.platform.util;
-
-import com.alibaba.fastjson.JSONObject;
-import com.fasterxml.jackson.annotation.JsonInclude;
-
-import java.io.Serializable;
-
-public class HttpRespMsg implements Serializable {
-
-    //status code, ok or error.
-    public String code;
-
-    //为code生成getter和setter方法
-    public String getCode() {
-        return code;
-    }
-    public void setCode(String code) {
-        this.code = code;
-    }
-
-    //为data生成getter和setter方法
-    public Object getData() {
-        return data;
-    }
-    public void setData(Object data) {
-        this.data = data;
-    }
-
-    //为msg生成getter和setter方法
-    public String getMsg() {
-        return msg;
-    }
-    public void setMsg(String msg) {
-        this.msg = msg;
-    }
-
-
-
-
-    @JsonInclude(JsonInclude.Include.NON_NULL)
-    public String msg;
-
-    //data content, in jsonformat, or zipped string when format is gzip
-    @JsonInclude(JsonInclude.Include.NON_NULL)
-    public Object data;
-
-    public HttpRespMsg() {
-        code = "ok";
-    }
-
-    public HttpRespMsg setError(String errorMsg) {
-        code = "error";
-        msg = errorMsg;
-        return msg;
-    }
-
-    public HttpRespMsg fail(String errorMsg) {
-        setError(errorMsg);
-        return this;
-    }
-
-    public String toJSONStr() {
-        JSONObject json = new JSONObject();
-        json.put("code", code);
-        json.put("data", data);
-        json.put("msg", msg);
-
-        return json.toJSONString();
-    }
-}

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

@@ -141,7 +141,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, plan_end_date as planEndDate
+        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, plate1, plate2
         FROM project
         WHERE status = 1 and (id IN (
             SELECT project_id

Разница между файлами не показана из-за своего большого размера
+ 200937 - 76320
fhKeeper/formulahousekeeper/management-platform/workTime.log


+ 3 - 0
fhKeeper/formulahousekeeper/management-workshop/src/main/resources/application.yml

@@ -18,6 +18,9 @@ spring:
     url: jdbc:mysql://1.94.62.58:17089/man_workshop_lew?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&rewriteBatchedStatements=true&useSSL=false
     username: root
     password: P011430@Huoshi*
+#    url: jdbc:mysql://47.100.37.243:7644/man_workshop_lew?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&rewriteBatchedStatements=true
+#    username: root
+#    password: Ziyu20141026!@@
     hikari:
       maximum-pool-size: 60
       minimum-idle: 10

+ 4 - 2
fhKeeper/formulahousekeeper/octopus/src/views/customer/list.vue

@@ -264,7 +264,7 @@
                     <el-form-item><el-checkbox v-model="dialogData.onlyShowPercent">工时报告页面,工时仅显示比例</el-checkbox></el-form-item>
                     <el-form-item><el-checkbox v-model="dialogData.taskFileCharge">任务文件支持审核</el-checkbox></el-form-item>
                     <el-form-item><el-checkbox v-model="dialogData.projectProgressCheck">项目进度依据任务工时</el-checkbox></el-form-item>
-                    
+                    <el-form-item><el-checkbox v-model="dialogData.enableAi">开启AI解析</el-checkbox></el-form-item>
                 </el-form>
             </div>
             <!-- 是否开启审批流设置,是否启用主项目模式,是否秘薪模式,是否显示日报审批流程,是否CRO企业,是否仅使用导入日报审核(不要项目审核) reportAuditType-->
@@ -520,6 +520,7 @@ import App from '../../App.vue';
                             this.$set(this.dialogData,'taskFileCharge',res.data.taskFileCharge ? true : false) 
                             this.$set(this.dialogData,'projectProgressCheck',res.data.projectProgressCheck ? true : false)
                             this.$set(this.dialogData,'importReportAuditNormal',res.data.importReportAuditNormal ? true : false)
+                            this.$set(this.dialogData,'enableAi',res.data.enableAi ? true : false)
                         }else{
                             this.$message({
                                 message: res.msg,
@@ -869,7 +870,8 @@ import App from '../../App.vue';
                     userWithMultiDept:this.dialogData.userWithMultiDept ? 1: 0, 
                     taskFileCharge:this.dialogData.taskFileCharge ? 1: 0, 
                     projectProgressCheck:this.dialogData.projectProgressCheck ? 1: 0,
-                    importReportAuditNormal: this.dialogData.importReportAuditNormal ? 1: 0
+                    importReportAuditNormal: this.dialogData.importReportAuditNormal ? 1: 0,
+                    enableAi: this.dialogData.enableAi
                 },res => {
                     if(res.code == 'ok'){
                         this.editDialogG = false

Разница между файлами не показана из-за своего большого размера
+ 355 - 711
fhKeeper/formulahousekeeper/ops-platform/octopus.log


+ 8 - 1
fhKeeper/formulahousekeeper/ops-platform/src/main/java/com/management/platform/controller/TimeTypeController.java

@@ -1,8 +1,11 @@
 package com.management.platform.controller;
 
 
+import com.management.platform.entity.TimeType;
+import com.management.platform.mapper.CompanyMapper;
 import com.management.platform.mapper.TimeTypeMapper;
 import com.management.platform.util.HttpRespMsg;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.RequestMapping;
 
 import org.springframework.web.bind.annotation.RestController;
@@ -22,6 +25,8 @@ import javax.annotation.Resource;
 public class TimeTypeController {
     @Resource
     TimeTypeMapper timeTypeMapper;
+    @Autowired
+    private CompanyMapper companyMapper;
 
     /**
      * 获取企业列表,显示到期时间
@@ -30,7 +35,9 @@ public class TimeTypeController {
     @RequestMapping("get")
     public HttpRespMsg get(Integer companyId) {
         HttpRespMsg msg = new HttpRespMsg();
-        msg.data = timeTypeMapper.selectById(companyId);
+        TimeType timeType = timeTypeMapper.selectById(companyId);
+        timeType.setEnableAi(companyMapper.selectById(companyId).getEnableAi());
+        msg.data = timeType;
         return msg;
     }
 }

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

@@ -170,6 +170,12 @@ public class Company extends Model<Company> {
     @TableField("non_project_simple")
     private Integer nonProjectSimple;
 
+    /**
+     * 是否开启AI解析功能
+     */
+    @TableField("enable_ai")
+    private Boolean enableAi;
+
 
     @TableField(exist = false)
     private String wxCorpid;

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

@@ -636,6 +636,11 @@ public class TimeType extends Model<TimeType> {
     @TableField("project_progress_check")
     private Integer projectProgressCheck;
 
+    /**
+     * 是否开启AI解析功能
+     */
+    @TableField(exist = false)
+    private Boolean enableAi;
 
     @Override
     protected Serializable pkVal() {

+ 6 - 0
fhKeeper/formulahousekeeper/ops-platform/src/main/java/com/management/platform/service/impl/CompanyServiceImpl.java

@@ -320,9 +320,15 @@ public class CompanyServiceImpl extends ServiceImpl<CompanyMapper, Company> impl
 
     @Override
     public HttpRespMsg setTimeTypeSetting(TimeType timeType) {
+        Boolean enableAi = timeType.getEnableAi();
         TimeType old = timeTypeMapper.selectById(timeType.getCompanyId());
         timeTypeMapper.updateById(timeType);
         Company company = companyMapper.selectById(timeType.getCompanyId());
+        if (enableAi != null) {
+            company.setEnableAi(enableAi);
+            companyMapper.updateById(company);
+        }
+
         String name = company.getCompanyName();
         String str = "设置["+name+"],";
         if (timeType.getSyncCorpwxTime() != null && old.getSyncCorpwxTime().intValue() != timeType.getSyncCorpwxTime().intValue()) {

+ 2 - 1
fhKeeper/formulahousekeeper/ops-platform/src/main/resources/mapper/CompanyMapper.xml

@@ -26,11 +26,12 @@
         <result column="create_date" property="createDate" />
         <result column="reg_from" property="regFrom" />
         <result column="non_project_simple" property="nonProjectSimple" />
+        <result column="enable_ai" property="enableAi" />
     </resultMap>
 
     <!-- 通用查询结果列 -->
     <sql id="Base_Column_List">
-        id, company_name, staff_count_max, expiration_date, set_meal, package_worktime, package_project, package_contract, package_oa, package_etimecard, package_expense, package_customer, package_engineering, package_simple, package_finance, package_provider, package_project_approval, package_device, is_international, create_date, reg_from, non_project_simple
+        id, company_name, staff_count_max, expiration_date, set_meal, package_worktime, package_project, package_contract, package_oa, package_etimecard, package_expense, package_customer, package_engineering, package_simple, package_finance, package_provider, package_project_approval, package_device, is_international, create_date, reg_from, non_project_simple, enable_ai
     </sql>
 
 </mapper>

+ 1 - 0
fhKeeper/formulahousekeeper/timesheet/src/permissions.js

@@ -335,6 +335,7 @@ const StringUtil = {
         arr[i] == '项目薪资成本表' ? obj.reportProjectSalaryCost = true : ''
         arr[i] == '部门成本表' ? obj.reportDepartmentCost = true : ''
         arr[i] == '员工出勤表' ? obj.employeeAttendance = true : ''
+        arr[i] == '施工进度表' ? obj.engineeringProgress = true : ''
         
     }
     return obj

+ 15 - 0
fhKeeper/formulahousekeeper/timesheet/src/routes.js

@@ -106,6 +106,8 @@ import deviceManagement from './views/deviceManagement/deviceManagement'
 
 // 人员管理
 import employeeManagement from './views/employeeManagement.vue'
+//施工分项工程管理
+import constructionManagement from './views/construction/stage_list.vue'
 
 Vue.use(Router)
 
@@ -536,6 +538,19 @@ export const allRouters = [//组织架构
         // 其他信息
         meta: { text: '人员管理' } 
     },
+    //施工分项目管理
+    {
+        path: '/',
+        component: Home,
+        name: '分项工程管理',
+        iconCls: 'iconfont firerock-icondaibanshixiang',
+        leaf: true,
+        children: [
+            { path: '/construction', component: constructionManagement, name: '分项工程管理' },
+        ],
+        // 其他信息
+        meta: { text: '分项工程管理' } 
+    },
     {
         path: '/404',
         component: NotFound,

Разница между файлами не показана из-за своего большого размера
+ 90 - 14
fhKeeper/formulahousekeeper/timesheet/src/views/corpreport/list.vue


+ 1 - 1
fhKeeper/formulahousekeeper/timesheet/src/views/financeAudit/financeAudit.vue

@@ -110,7 +110,7 @@ export default {
                 this.postData('/financial-audit/undo', { id: item.id }).then(res => {
                     this.$message({
                         type: 'success',
-                        message: this.$t('chexiaoChengGong')
+                        message: '撤销成功'
                     });
                     this.getFinanceAuditTableData();
                 });

+ 19 - 1
fhKeeper/formulahousekeeper/timesheet/src/views/project/costReportExport.vue

@@ -73,7 +73,7 @@
           <el-form-item prop="projectId"
             :label="user.timeType.fixMonthcost == 0 ? $t('time.dateRange') : $t('Selectmonth')">
             <el-date-picker v-show="user.timeType.fixMonthcost == 0" v-model="exportParam.dateRange" :editable="false"
-              format="yyyy-MM-dd" value-format="yyyy-MM-dd" :clearable="false" :range-separator="$t('other.to')"
+              format="yyyy-MM-dd" value-format="yyyy-MM-dd" :clearable="true" :range-separator="$t('other.to')"
               type="daterange" :start-placeholder="$t('time.startDate')"
               :end-placeholder="$t('time.endDate')"></el-date-picker>
 
@@ -496,6 +496,8 @@ export default {
     },
   },
   mounted() {
+    console.log('666666666');
+    console.log('chartDate', this.chartDate);
     this.exportParam.dateRange = this.chartDate
     this.exportParam.date = this.dayjs().format('YYYY-MM')
     this.exportParam.exportContent = 'hoursAndCost'
@@ -504,6 +506,22 @@ export default {
     this.getDepartmentList()
     this.getMyProjectList()
   },
+  watch: {
+    // 监听弹窗打开状态,每次打开时更新chartDate
+    value(newVal) {
+      if (newVal) {
+        // 弹窗打开时,更新日期范围
+        this.exportParam.dateRange = this.chartDate
+      }
+    },
+    // 监听chartDate的变化
+    chartDate(newVal) {
+      if (this.value) {
+        // 如果弹窗是打开状态,同步更新
+        this.exportParam.dateRange = newVal
+      }
+    }
+  }
 }
 </script>
 <style lang="scss" scoped>

+ 189 - 9
fhKeeper/formulahousekeeper/timesheet/src/views/project/list.vue

@@ -613,6 +613,14 @@
                             <div v-if="item.customType == 2">
                                 <el-date-picker v-model="item.value" type="date" :placeholder="$t('pleaseselectadate')"  value-format="yyyy-MM-dd"></el-date-picker>
                             </div>
+                            <div v-if="item.customType == 3">
+                                <el-select v-model="item.value" clearable :placeholder="$t('defaultText.pleaseChoose')" style="width: 100%;" multiple @change="customSelectChange">
+                                    <el-option v-for="option in item.customOptions.split(',')" :key="option" :label="option" :value="option"></el-option>
+                                </el-select>
+                            </div>
+                            <div v-if="item.customType == 4">
+                                <el-input v-model.number="item.value" type="number" clearable :placeholder="$t('pleaseentercontent')" @input="validateInteger(item, index)"></el-input>
+                            </div>
                         </el-form-item>
                     </div>
 
@@ -625,7 +633,7 @@
                     </div> -->
                     <!-- 项目基线 -->
                     <div style="margin: 10px 0 30px 0;min-height:200px;" v-if="user.company.packageProject == 1 && !canOnlyModParticipator && (user.company.nonProjectSimple == 0 || (user.company.nonProjectSimple == 1 && addForm.isPublic == 0))">
-                        <el-tabs v-model="activeName" @tab-click="handleClick">
+                        <el-tabs v-model="activeName" @tab-click="handleClick" tab-position="top">
                         <el-tab-pane :label="$t('costbaseline')" name="baseCostPanel"  >
                             <div style="padding-top:10px;">
                                 <!--新版 -->
@@ -693,11 +701,37 @@
                             </el-table>
                         </div>
                         </el-tab-pane>
-                        <!-- <el-tab-pane label="相关领导" name="leaders" >
-                        <div style="padding-top:10px;">
-                            <el-input @focus="showChooseLeaderTree" v-model="addForm.notifyUserNames" placeholder="请选择需要接收审核通知的相关领导"></el-input>
+                        <el-tab-pane label="施工节点" name="projectConstructionStages" v-if="user.companyId == 10 || user.companyId == 4811">
+                        <template slot="label" v-if="activeName == 'projectConstructionStages'">
+                            <span>施工节点</span>
+                            <el-link  size="small"  type="primary" @click="exportConstrutionData" style="margin-left:80px;" >导出</el-link>
+                            <el-upload ref="consUpload" action="#" :limit="1" :http-request="importConstrutionData" :show-file-list="false" style="display:inline-block;margin-left:20px;">
+                                <el-link type="primary" :underline="true" >导入</el-link>
+                            </el-upload>
+                        </template>
+                        <div style="padding-top:10px;" class="gongcheng">
+                            <!-- <el-button style="float:right;margin-top:10px;" type="primary" @click="saveProjectConstruction" size="small">保存</el-button>
+                            <el-button style="float:right;margin-top:10px;margin-right:10px;" @click="getConstructionStages(addForm.id, addForm.plate1)" size="small">刷新节点</el-button> -->
+                            <el-table :data="constructionStages" size="small" :key="Math.random()" :height="'400px'">
+                                <el-table-column prop="constructionType"  label="一级工程类型">
+                                </el-table-column>
+                                <el-table-column prop="mainName"  label="施工分项">
+                                </el-table-column>
+                                <el-table-column prop="name"  label="施工节点">
+                                </el-table-column>
+                                <el-table-column prop="percent"  label="占比">
+                                    <template slot-scope="scope">
+                                        <el-input type="number" style="width:100px;" v-model="scope.row.percent" min="0" oninput="value=value.replace(/[^\d.]/g,'')"></el-input>&nbsp;%
+                                    </template>
+                                </el-table-column>
+                                <el-table-column prop="designNumber"  label="设计量" width="200">
+                                    <template slot-scope="scope">
+                                        <el-input :id="'designNumberInput'+scope.row.id"  style="width:110px;" v-model="scope.row.designNumber" @keyup.native="restrictNumber('designNumberInput'+scope.row.id)"></el-input>&nbsp;{{ scope.row.unit }}
+                                    </template>
+                                </el-table-column>
+                            </el-table>
                         </div>
-                        </el-tab-pane> -->
+                        </el-tab-pane>
                         </el-tabs>
                     </div>
                 
@@ -1776,7 +1810,7 @@ a {
                     children: 'children',
                     label: 'label'
                 },
-                
+                constructionStages: [],
                 wxFilterText: '',
                 mainProjectId:'',
                 filterName:null,
@@ -2621,7 +2655,7 @@ a {
                     if(res.code == 'ok') {
                         var yaunz = []
                         for(var i in res.data) {
-                            if(res.data[i].customType == '1') {
+                            if(res.data[i].customType == '1' || res.data[i].customType == '3') {
                                 this.$set(res.data[i], 'value', [])
                                 this.$set(res.data[i], 'valuelist', [])
                             } else {
@@ -3369,6 +3403,74 @@ a {
                         });
                     });
             },
+            exportConstrutionData() {
+                let param = {
+                    projectId: this.addForm.id,
+                    constructionType: this.dataList[0].value.join(',')
+                }
+                let projectName = this.addForm.name;
+                //导出施工分项配置
+                this.http.post('/project-construction-stage/export',param,
+                res => {
+                    if (res.code == "ok") {
+                        var filePath = res.data;
+                        const a = document.createElement('a'); // 创建a标签
+                        a.setAttribute('download', projectName + '-施工分项配置.xlsx');// download属性
+                        a.setAttribute('href', filePath);// href链接
+                        a.click(); //自执行点击事件
+                        a.remove();
+                    } 
+                },
+                error => {
+                    this.$message({
+                        message: error,
+                        type: "error"
+                    });
+                    }
+                );
+            },
+            importConstrutionData(item) {
+                //首先判断文件类型
+                let str = item.file.name.split(".");
+                let format = str[str.length - 1];
+                if (format != "xls" && format != "xlsx") {
+                    this.$message({
+                        message: this.$t('other.PleaseselecttheXLSorXLSXfile'),
+                        type: "error"
+                    });
+                } else {
+                    this.listLoading = true;
+                    let formData = new FormData();
+                    formData.append("file", item.file);
+                    formData.append("projectId", this.addForm.id);
+                    this.http.uploadFile('/project-construction-stage/import', formData,
+                    res => {
+                        this.$refs.consUpload.clearFiles();
+                        this.listLoading = false;
+                        if (res.code == "ok") {
+                            this.$message({
+                                message: this.$t('other.importSuccess'),
+                                type: "success"
+                            });
+                            // 重新加载施工节点数据
+                            this.getConstructionStages(this.addForm.id, this.dataList[0].value.join(','));
+                        } else {
+                            this.$message({
+                                message: res.msg,
+                                type: "error"
+                            });
+                        }
+                    },
+                    error => {
+                        this.$refs.consUpload.clearFiles();
+                        this.listLoading = false;
+                        this.$message({
+                            message: error,
+                            type: "error"
+                        });
+                    });
+                }
+            },
             exportProjectData() {
                 let param = {
                     status: this.status,
@@ -3930,6 +4032,19 @@ a {
                     inpu.value = parseFloat(inpu.value);
                 }
             },
+            validateDesignQuantity() {
+                // 确保设计量是整数
+                if (this.addForm.plate2) {
+                    this.addForm.plate2 = Math.floor(Number(this.addForm.plate2));
+                }
+            },
+            validateInteger(item, index) {
+                // 确保自定义字段类型4只接受整数
+                if (item.value) {
+                    item.value = Math.floor(Number(item.value));
+                }
+                this.ipts(item.value, index);
+            },
             showChooseLeaderTree() {
                 this.chosenMembCount = this.chosenLeaders.length;
                 this.chooseLeaderVisible = true;
@@ -5015,7 +5130,14 @@ a {
                 for(var s in arrLists) {
                     for(var p in data.plateMap) {
                         if(arrLists[s].customName == p && arrLists[s].customType != '1') {
-                            arrLists[s].value = data.plateMap[p]
+                            if (arrLists[s].customType == '3') {
+                                //多选
+                                if (data.plateMap[p] != null && data.plateMap[p] != '') {
+                                    arrLists[s].value = data.plateMap[p].split(',')
+                                }
+                            } else {
+                                arrLists[s].value = data.plateMap[p]
+                            }
                         } 
                         if(arrLists[s].customName == p && arrLists[s].customType == '1' && data.plateMap[p] != null && data.plateMap[p] != ''){
                             var sel = data.plateMap[p].split(',')
@@ -5233,6 +5355,9 @@ a {
                     if (this.user.company.packageEngineering == 1) {
                         this.getProjectProfessions(item.id);
                     }
+                    if (this.user.companyId == 10 || this.user.companyId == 4811) {
+                        this.getConstructionStages(item.id, item.plate1);
+                    }
                     //获取审核人
                     this.getProjectAutorList(item.id);
                     if (this.user.timeType.reportCc == 1) {
@@ -5596,8 +5721,12 @@ a {
                                 });
                                 this.addFormVisible = false;
                                 this.getList();
+                                var pid = res.data;
                                 if (this.user.company.packageEngineering == 1) {
-                                    this.saveProjectProfessions(res.data);
+                                    this.saveProjectProfessions(pid);
+                                }
+                                if (this.user.companyId == 10 || this.user.companyId == 4811) {
+                                    this.saveConstructionStages(pid);
                                 }
                             } else {
                                 this.$message({
@@ -6012,6 +6141,57 @@ a {
                 });
                 
             },
+            customSelectChange() {
+                //为柘中定制一个监听加载施工分项
+                if (this.user.companyId == 10 || this.user.companyId == 4811) {
+                    this.getConstructionStages(this.addForm.id, this.dataList[0].value.join(','));
+                }
+            },
+            getConstructionStages(projectId, constructionType) {
+                this.http.post('/project-construction-stage/get',{ 
+                    projectId, constructionType
+                },
+                res => {
+                    if (res.code == "ok") {
+                        this.constructionStages = res.data;
+                    } else {
+                        this.$message({
+                            message: res.msg,
+                            type: "error"
+                        });
+                    }
+                },
+                error => {
+                    this.$message({
+                        message: error,
+                        type: "error"
+                    });
+                    }
+                );
+            },
+            saveConstructionStages(projectId) {
+                var json = JSON.stringify(this.constructionStages);
+                this.http.post('/project-construction-stage/save',{ 
+                    projectId, json
+                },
+                res => {
+                    if (res.code == "ok") {
+                        // this.constructionStages = res.data;
+                    } else {
+                        this.$message({
+                            message: res.msg,
+                            type: "error"
+                        });
+                    }
+                },
+                error => {
+                    this.$message({
+                        message: error,
+                        type: "error"
+                    });
+                    }
+                );
+            },
             //保存职能分工
             submitFunctional(){
                 this.http.post('/project/editFunctionalDivision',{ 

+ 116 - 10
fhKeeper/formulahousekeeper/timesheet/src/views/workReport/daily.vue

@@ -135,7 +135,7 @@
                                 </span>
                                 <span style="float:right;">
                                     <el-link type="primary" v-if="user.timeType.enableNewWeeklyfill != 1 && user.timeType.weeklyChargeFilter != 1" style="margin-right:10px;" :underline="false" @click="isSubstitude=false;fillInReport(-1,0)">{{$t('textLink.fillInTheWork')}}</el-link>
-                                    <el-link v-if="reportTimeType.type != 0 && user.companyId != yuzhongCompId && user.companyId != 469 && user.timeType.enableNewWeeklyfill != 1 && user.companyId != 3092 && user.timeType.enableNewWeeklyfill != 2" type="primary" style="margin-right:10px;" :underline="false" @click="isSubstitude=false;fillInReportss()">{{$t('textLink.fillInAWeek')}}</el-link>
+                                    <el-link v-if="reportTimeType.type != 0 && user.companyId != yuzhongCompId && user.companyId != 469 && user.companyId != 4811 && user.timeType.enableNewWeeklyfill != 1 && user.companyId != 3092 && user.timeType.enableNewWeeklyfill != 2" type="primary" style="margin-right:10px;" :underline="false" @click="isSubstitude=false;fillInReportss()">{{$t('textLink.fillInAWeek')}}</el-link>
                                     <el-link v-if="user.timeType.enableNewWeeklyfill == 1" type="primary" style="margin-right:10px;" :underline="false" @click="isSubstitude=false;fillInReportCustom()">{{ $t('textLink.fillInAWeek') }}</el-link>
                                     <!-- <el-link type="primary" style="margin-right:10px;" :underline="false" @click="isSubstitude=false;fillInReportCustom()">按周填报123</el-link> -->
                                     <el-link type="primary" style="margin-right:10px;" :underline="false" @click="isSubstitude=false;weekIndex++,fillWeekDialogVisiCustomTwo=true" v-if="user.timeType.enableNewWeeklyfill==2">按周填报</el-link>
@@ -278,6 +278,11 @@
                                                         <span>{{ $t('jiao-se') }} :{{item2.extraField1? roleList.filter(r=>r.value == item2.extraField1)[0].label:''}}</span>
                                                     <span style="margin-left:10px;">{{ $t('gongZuoZhiZe') }} :{{ item2.extraField2? item2.extraField2Name:''}}</span>
                                                     <span style="margin-left:10px;">{{ $t('gongZuoNeiRong') }} :{{ item2.extraField3? item2.extraField3Name:''}}</span></p>
+
+                                                    <p v-if="(user.companyId == 4811 || user.companyId == 10) && item2.constructionStageStr">
+                                                        <span>施工分项工程 :{{item2.constructionStageStr}}</span>
+                                                    </p>
+
                                                     <!--任务分组和阶段 -->
                                                     <p v-if="item2.groupId != 0">
                                                         {{$t('other.taskGroup')}}:{{item2.groupName}}
@@ -394,7 +399,7 @@
                                 style="flex:1;" @keydown.native="handleAIInputKeydown"></el-input>
                         <el-button size="mini" type="primary" icon="el-icon-magic-stick" class="ai-parse-btn" @click="handleAIParse" :loading="aiParsing">AI解析</el-button>
                     </div>
-                    <div style="margin-top:5px;"><el-tag size="mini" effect="plain" v-for="word in quickWords" @click="fillWord(word)">{{ word }}</el-tag></div>
+                    <div style="margin-top:5px;"><el-tag size="mini" :key="word.value" effect="plain" v-for="word in quickWords" @click="fillWord(word)">{{ word }}</el-tag></div>
                 </div>
                 <el-form ref="workForm" :model="workForm" :rules="workRules" label-width="120px">
                     <el-form-item :label="$t('screening.selectPeople')" v-if="isSubstitude">
@@ -469,7 +474,7 @@
                         <span v-if="user.companyId==5978" style="margin-left:5px;" class="themeFontColor"><i class="el-icon-warning"></i>{{$t('other.kaoqingTimeTip')}}</span>
 
                         <!--针对羲和超导的异常填报功能-->
-                        <template v-if="(user.companyId <= 10 || user.companyId == 8555) && (!workForm.time || !workForm.time.workHours)">
+                        <template v-if="user.companyId == 8555 && (!workForm.time || !workForm.time.workHours)">
                             <span style="margin-left:70px;color:#666;">异常填报</span>
                             <el-switch v-model="workForm.abnormalTime" :disabled="!canEdit"></el-switch>
                         </template>
@@ -558,7 +563,7 @@
                             :rules="{ required: true, message: $t('defaultText.pleaseSelectSnItem'), trigger: ['change','blur'] }">
                             <el-select v-model="domain.projectId" :placeholder="$t('defaultText.pleaseSelectSnItem')" style="width:200px;" clearable="true"  filterable="true" value-key="id"
                             @change="selectProject(domain, index)"
-                            :disabled="workForm.domains.length==0?true:(workForm.domains[index].state>=2?false:true)" popper-class="projectSelectPopperClass">
+                            :disabled="(isSubstitude && (workForm.userNames == null || workForm.userNames.length == 0)) || (workForm.domains.length==0?true:(workForm.domains[index].state>=2?false:true))" popper-class="projectSelectPopperClass">
                                 <el-option-group v-for="group in integrationProjectList" :key="group.label" :label="group.label">
                                     <el-option v-for="item in group.peojectList" :key="item.id" :label="item.projectName  + '\u3000' + item.projectCode" :value="item.id" :disabled="item.status!=1 && item.status!=4">
                                         <span style="float: left; color: #8492a6; font-size: 13px;">{{ item.projectCode }}</span>
@@ -602,10 +607,42 @@
                             </el-link>
                             <!-- <el-link type="primary" v-if="canEdit"
                                 :underline="false" style="margin-left:10px;" @click="copyProject(index)">复制</el-link> -->
+                            <!--针对柘中,显示项目对应的工程分类-->
+                            <template v-if="(user.companyId == 10 || user.companyId == 4811) && workForm.domains[index].projectId">
+                                <span style="margin-left:10px;">工程分类:{{ workForm.domains[index].engineeringCategory }}</span>
+                            </template>
                         </el-form-item>
                         <el-form-item :label="$t('other.projectDescription')" v-if="user.company.packageProject==0&&domain.projectId&&fillProjectList.filter(p=>p.id == domain.projectId).length>0&&fillProjectList.filter(p=>p.id == domain.projectId)[0].projectDesc">
                             <span>{{fillProjectList.filter(p=>p.id == domain.projectId)[0].projectDesc}}</span>
                         </el-form-item>
+                        <el-form-item label="施工分项工程" v-if="(user.companyId == 10 || user.companyId == 4811) && workForm.domains[index].engineeringCategory != null && workForm.domains[index].engineeringCategory != ''" :rules="{ required: true, message: '请填写', trigger: ['change','blur'] }">
+                            <!-- <el-select v-model="domain.extraField1" :disabled="!domain.canEdit" @change="$forceUpdate()" style="width:200px;" filterable>
+                                <el-option v-for="item in domain.constructionStages" :label="item.name" :value="item.id" :key="item.id"></el-option>
+                            </el-select> -->
+                            <el-row v-for="item in domain.constructionStages" :key="item.id" style="width:80%">
+                                <el-col :span="10" >{{ item.name }} </el-col> 
+                                <el-col :span="14" >今日完成数量: 
+                                <el-input-number 
+                                v-model="item.finishNumber" 
+                                :disabled="!domain.canEdit" 
+                                :precision="2" 
+                                :step="1" 
+                                :min="0" 
+                                style="width:200px;">
+                            </el-input-number> {{ item.unit }} </el-col>
+                            </el-row>
+                        </el-form-item>
+                        <!-- <el-form-item label="完成数量" v-if="(user.companyId == 10 || user.companyId == 4811) && domain.extraField1" :rules="{ required: true, message: '请填写', trigger: ['change','blur'] }">
+                            <el-input-number 
+                                v-model="domain.extraField2" 
+                                :disabled="!domain.canEdit" 
+                                :precision="0" 
+                                :step="1" 
+                                :min="0" 
+                                style="width:200px;">
+                            </el-input-number>
+                            <span style="margin-left:10px;">{{(domain.constructionStages && domain.constructionStages.length>0 && domain.constructionStages.find(item => item.id === domain.extraField1) != null)?domain.constructionStages.find(item => item.id === domain.extraField1).unit || '' :'' }}</span>
+                        </el-form-item> -->
                         <!--如果设置了工时成本预警的预算成本项-->
                         <el-form-item :label="$t('lable.budgetSource')" v-if="user.company.packageProject==1&&timeBasecostList &&timeBasecostList.length>0">
                             <el-select v-model="domain.basecostId" :disabled="!domain.canEdit" @change="$forceUpdate()" style="width:200px;">
@@ -820,13 +857,13 @@
                         </el-form-item>
                         <!--工作事项--> <!-- 加力股份不需要工作内容填报 -->
                         <el-form-item :label="$t('other.workMatters') " :prop="'domains.' + index + '.content'" v-if="user.companyId != 7544 && !user.timeType.hideContent"
-                        :rules="user.timeType.workContentState == 1 ? { required: true, message: $t('other.tianworkMatters'), trigger: 'blur' } : null">
+                        :rules="user.timeType.workContentState == 1 && (user.companyId != 10 || domain.constructionStages == null || domain.constructionStages.length == 0) ? { required: true, message: $t('other.tianworkMatters'), trigger: 'blur' } : null">
                             <el-input v-model="domain.content" type="textarea" :rows="4" :placeholder="$t('defaultText.pleaseFillOut')" clearable style="width:75%;margin-right:7%"
                             :disabled="workForm.domains.length==0?true:(workForm.domains[index].state>=2?false:true)"></el-input>
                         </el-form-item>
 
                         <!-- 拍照上传 -->
-                        <el-form-item :label="$t('tuPianShangChuan')" v-if="user.timeType.choseFromAlbum == 1 || ((user.companyId <= 10 || user.companyId == 8555) && workForm.abnormalTime)" :prop="'domains.' + index + '.imgListUrl'" 
+                        <el-form-item :label="$t('tuPianShangChuan')" v-if="user.timeType.choseFromAlbum == 1 || (user.companyId == 8555 && workForm.abnormalTime)" :prop="'domains.' + index + '.imgListUrl'" 
                         :rules="isCustomization(user, reportPictureRequired) ? { required: true, message: $t('pleaseselectpictures'), trigger: 'blur' } : null">
                             <div class="photos">
                                 <div>
@@ -1079,6 +1116,7 @@
                      <el-button @click="handleGetPrevWeek()" size="small">&lt;&lt;</el-button>
                      <el-button @click="getCurrentWeek()" size="small">{{$t('time.thisWeek')}}</el-button>
                      <el-button @click="handleGetNextvWeek()" size="small">&gt;&gt;</el-button>
+                     <el-button v-if="user.timeType.syncCorpwxTime" @click="refreshWeeklyCardTime()" :disabled="zhoData.length == 0" size="small" style="margin-left:20px;" :loading="refreshingTime">刷新考勤</el-button>
                      <el-select v-if="!isSubstitude" v-model="selCon" size="small" multiple :placeholder="$t('defaultText.pleaseChoose')" @change="onSelProjectChange()" filterable style="margin-right:50px;float:right;width:50%;" collapse-tags>
                         <el-option
                         v-for="item in fillProjectList"
@@ -2645,6 +2683,7 @@
         },
         data() {
             return {
+                allConstructionStages:[],
                 quickWords: [],//用于AI解析快速输入的历史日报填报关键字
                 remindering: false,
                 onlyHaveAttendance: false,
@@ -3087,6 +3126,9 @@
             if (this.user.companyId == this.yuzhongCompId) {
                 this.getJobResponList();
             }
+            if (this.user.companyId == 10 || this.user.companyId == 4811) {
+                this.getConstructionStageList();
+            }
         },
         methods: {
             ...mapMutations(['upDataLoading']),
@@ -3095,6 +3137,19 @@
                 if (!content) return '';
                 return content.replace(/\r\n/g, '<br>').replace(/\n/g, '<br>').replace(/\r/g, '<br>');
             },
+            getConstructionStageList() {
+                this.http.post('/construction-stage/list', {}, res => {
+                    if (res.code == "ok") {
+                        this.allConstructionStages = res.data;
+                    } else {
+                        this.$message({
+                            message: res.msg,
+                            type: "error"
+                        });
+                    }
+                },error => { });
+            },
+            
             // 刷新考勤
             refreshAttendanceCli() {
                 const firstDay = this.dayjs(this.date, 'YYYY-MM').startOf('month');
@@ -3263,6 +3318,36 @@
                 );
             },
             //按选择的日期范围刷新考勤
+            refreshWeeklyCardTime() {
+                if (this.zhoData.length == 0) return;
+                this.refreshingTime = true;
+                var param = {
+                    companyId: this.user.companyId,
+                    startDate: this.zhoData[0].zhoDataTime,
+                    endDate: this.zhoData[this.zhoData.length-1].zhoDataTime,
+                }
+                // if (this.user.roleName.indexOf('管理员') == -1) {
+                param.userId = this.user.id;
+                // }
+                this.http.post('/wxcorp/getUserCheckInDayData',param,res => {
+                    this.refreshingTime = false;
+                    if(res.code == 'ok'){
+                        this.initWeekFormData();
+                    }else {
+                        this.$message({
+                            message: res.msg,
+                            type: 'error'
+                        })
+                    }
+                },err => {
+                    this.syncTimeLoading = false;
+                    this.$message({
+                        message: err,
+                        type: 'error'
+                    })
+                })
+            },
+            //按选择的日期范围刷新考勤
             refreshWXCardTimeByRange() {
                 this.refreshingTime = true;
                 var param = {
@@ -5519,9 +5604,14 @@
                 if(this.yonghuUser.customDegreeActive == 1) {
                     this.selectDegreeId(domain, index)
                 }
-                
                 domain.projectName = this.isSubstitude?this.subFillProjectList.filter(p=>p.id == domain.projectId)[0].projectName:this.fillProjectList.filter(p=>p.id == domain.projectId)[0].projectName;
                 domain.isPublic = this.isSubstitude?this.subFillProjectList.filter(p=>p.id == domain.projectId)[0].isPublic:this.fillProjectList.filter(p=>p.id == domain.projectId)[0].isPublic;
+                domain.engineeringCategory = this.isSubstitude?this.subFillProjectList.filter(p=>p.id == domain.projectId)[0].plate1:this.fillProjectList.filter(p=>p.id == domain.projectId)[0].plate1;
+                
+                if (this.allConstructionStages.length > 0) {
+                    //筛选出当前项目对应的工程分类的下属二级施工分项
+                    domain.constructionStages = JSON.parse(JSON.stringify(this.allConstructionStages.filter(item=>domain.engineeringCategory.indexOf(item.constructionType) != -1 )));
+                }
                 this.http.post('/sub-project/list',{
                     projectId: domain.projectId,
                     isReport: true
@@ -7227,7 +7317,7 @@
                             var abnormalTime = false;
                             for(var i in list.report) {
                                 var flg = null
-                                if (this.user.companyId <= 10 || this.user.companyId == 8555) {
+                                if (this.user.companyId == 8555) {
                                     if (list.report[i].extraField1) {
                                         abnormalTime = true;
                                     }
@@ -7296,6 +7386,16 @@
                                     copyData.projectAuditorId = list.report[i].projectAuditorId;
                                     copyData.projectAuditorName = list.report[i].projectAuditorName;
                                 }
+                                
+                                if (this.allConstructionStages.length > 0) {
+                                    copyData.engineeringCategory = this.fillProjectList.filter(p=>p.id == copyData.projectId)[0].plate1;
+                                    copyData.constructionStages = JSON.parse(JSON.stringify(this.allConstructionStages.filter(s=>copyData.engineeringCategory.indexOf(s.constructionType) > -1)));
+                                    //给完成数量赋值
+                                    var rpcList = list.report[i].projectConsStageList;
+                                    copyData.constructionStages.forEach(stage=>stage.finishNumber =
+                                         rpcList.find(rpc=>rpc.stageId == stage.id)?rpcList.find(rpc=>rpc.stageId == stage.id).finishNumber:0);
+
+                                }
                                 arr.push(copyData);
                                 if (list.report[i].state >= 2) {
                                     this.canEdit = true;
@@ -9352,7 +9452,7 @@
                         //批量填报不校验考勤时长,交给后台校验
                         
                         if (!this.isBatch) {
-                            if ((this.user.companyId <= 10 || this.user.companyId == 8555) && this.workForm.abnormalTime) {
+                            if (this.user.companyId == 8555 && this.workForm.abnormalTime) {
                                 //异常上报情况,需要上传图片
                                 var findImg = false;
                                 for (var t=0;t<this.workForm.domains.length; t++) {
@@ -9696,6 +9796,12 @@
                                 formData.append('extraField2', this.workForm.domains[i].extraField2);
                                 formData.append('extraField3', this.workForm.domains[i].extraField3);
                             }
+                            if (this.user.companyId == 10 || this.user.companyId == 4811) {
+                                // formData.append('extraField1', this.workForm.domains[i].extraField1 || -1);//避免null造成数字类型转化错误
+                                // formData.append('extraField2', this.workForm.domains[i].extraField2 || 0);
+                                let constructionStagesStr = JSON.stringify(this.workForm.domains[i].constructionStages).replace(/,/g,"@");
+                                formData.append('constructionStagesStr', constructionStagesStr);
+                            }
                             //依斯贝的服务Id
                             if (this.user.companyId == this.yisibeiCompId) {
                                 formData.append('sapServiceId', this.workForm.domains[i].sapServiceId);
@@ -9751,7 +9857,7 @@
                                 }
                             }
                             //羲合超导的异常工时上报
-                            if (this.user.companyId <= 10 || this.user.companyId == 8555) {
+                            if (this.user.companyId == 8555) {
                                 if (this.workForm.abnormalTime) {
                                     formData.append('abnormalTime', this.workForm.abnormalTime);
                                 }

+ 22 - 2
fhKeeper/formulahousekeeper/timesheet/src/views/workReport/dailyReportReview.vue

@@ -153,6 +153,9 @@
                                                           <span>{{ $t('jiao-se') }}:{{item.extraField1? roleList.filter(r=>r.value == item.extraField1)[0].label:''}}</span>
                                                       <span style="margin-left:10px;">{{ $t('gongZuoZhiZe') }}:{{ item.extraField2? item.extraField2Name:''}}</span>
                                                       <span style="margin-left:10px;">{{ $t('gongZuoNeiRong') }}:{{ item.extraField3? item.extraField3Name:''}}</span></p>
+                                  <p v-if="(user.companyId == 4811 || user.companyId == 10) && item.constructionStageStr">
+                                        <span>施工分项工程 :{{item.constructionStageStr}}</span>
+                                  </p>
                                   <p v-if="item.taskId != null">{{$t('other.task')}}:{{item.taskName}}
                                       <span style="margin-left:10px;" v-if="user.companyId==3092">-- {{ $t('fuWu') }}:{{ item.sapServiceName }}</span></p>
                                   <p v-if="item.groupId">
@@ -554,6 +557,7 @@
       },
       data() {
           return {
+              allConstructionStages:[],
               exportLoading: false,
               yuzhongCompId: 3385,
               roleList:[{value: 1,label: 'CRC&LM'},{value: 2,label: 'PM'}],
@@ -1312,7 +1316,19 @@
               this.$nextTick(() => {
                   this.showTable = true
               })
-          }
+          },
+          getConstructionStageList() {
+                this.http.post('/construction-stage/list', {}, res => {
+                    if (res.code == "ok") {
+                        this.allConstructionStages = res.data;
+                    } else {
+                        this.$message({
+                            message: res.msg,
+                            type: "error"
+                        });
+                    }
+                },error => { });
+            },
       },
       created() {
           let height = window.innerHeight;
@@ -1322,13 +1338,17 @@
               that.tableHeight = window.innerHeight - 125;
           };
       },
+      
       mounted() {
           this.reviewTableHeight = this.$refs.reviewTable.offsetHeight
           this.reviewTableHeightKey++
           this.getList();
           this.getDepartment();
           this.getProjectList();
-          this.getUsers()
+          this.getUsers();
+          if (this.user.companyId == 10 || this.user.companyId == 4811) {
+            this.getConstructionStageList();
+          }
       }
   };
 </script>

+ 15 - 7
fhKeeper/formulahousekeeper/timesheet_h5/src/views/edit/index.vue

@@ -179,7 +179,7 @@
                             @cancel="item.showPickerConstruction = false; $forceUpdate();" /> -->
                         
                         <van-cell-group>
-                            <van-field label-width="70%" v-for="stage in item.constructionStages" type="digit" :label="stage.name+' - 今日完成'" v-model="stage.finishNumber" placeholder="完成数量" ></van-field>
+                            <van-field label-width="70%" v-for="stage in item.constructionStages" :key="item.id" inputmode="decimal" :label="stage.name+' - 今日完成'" v-model="stage.finishNumber" placeholder="完成数量" :formatter="formatDecimal"></van-field>
                         </van-cell-group>
                         <van-button style="width:100%" type="primary" @click="choseConstruction">确定</van-button>
                     </van-popup>
@@ -460,7 +460,7 @@
                         </van-cell>
                         <van-field class="form_input" :disabled="!item.canEdit" v-model="item.content" name="content" v-if="!user.timeType.hideContent"
                             type="textarea" label="工作内容" placeholder="请输入"
-                            :rules="user.timeType.workContentState == 1 && (user.companyId != 10 || item.constructionStages.length == 0)? [{ required: true, message: '请填写工作内容' }] : null"
+                            :rules="user.timeType.workContentState == 1 && (user.companyId != 10 || item.constructionStages == null || item.constructionStages.length == 0)? [{ required: true, message: '请填写工作内容' }] : null"
                             rows="3" autosize />
                     </div>
 
@@ -884,6 +884,14 @@ export default {
     },
 
     methods: {
+        formatDecimal(val) {
+            // 只留数字和一个小数点
+            val = val.replace(/[^\d.]/g, '')
+            val = val.replace(/\.{2,}/g, '.')
+            // 保留两位小数
+            val = val.replace(/(\.\d{0,2}).*/, '$1')
+            return val
+        },
         scanCodeToFillIn(index) {
             this.clickIndex = index
             this.showQrcode = true
@@ -1999,7 +2007,8 @@ export default {
                         this.$toast.clear();
                         this.report = res.data;
                         this.businessTripsArray = res.data.businessTrips || []
-                        var t = res.data.timeType;
+                        let t = res.data.timeType;
+                        
                         this.reportSettingsRow = res.data.timeType
                         var timeType = [];
                         //转化时间格式
@@ -2101,9 +2110,9 @@ export default {
                                             rpcList.find(rpc=>rpc.stageId == stage.id)?rpcList.find(rpc=>rpc.stageId == stage.id).finishNumber:0);
                                         var constages = list[i].constructionStages;
                                         var str = '';
-                                        for (var t=0;t<constages.length; t++) {
-                                            if (constages[t].finishNumber > 0) {
-                                                str += constages[t].name + '('+constages[t].finishNumber+ '), ';
+                                        for (var p=0;p<constages.length; p++) {
+                                            if (constages[p].finishNumber > 0) {
+                                                str += constages[p].name + '('+constages[p].finishNumber+ '), ';
                                             }
                                         }
                                         if (str.length > 0) {
@@ -2125,7 +2134,6 @@ export default {
                                     }).filter(name => name);
                                     customTextShow = names.join(',');
                                 }
-                                
                                 let copyData = {
                                     id: list[i].id,
                                     projectId: list[i].projectId,

+ 20 - 1
fhKeeper/formulahousekeeper/webttkuaiban/src/main/resources/static/css/index.css

@@ -168,6 +168,9 @@
 }
 .bannarTextList li:nth-child(2) {
     margin-top: 2.8125rem;
+}
+.bannarTextList li:nth-child(3) {
+    margin-top: 2.8125rem;
     margin-bottom: 4.4375rem;
 }
 
@@ -1084,7 +1087,23 @@ body {
     color: #fff;
     width: 100%;
 }
-
+.outlineBtn {
+    font-size: 24px;
+    border: 0.125rem solid #3396FB;
+    color: #3396FB;
+    padding: 6px;
+    text-align: center;
+    border-radius: 5px;
+    margin: 20px 0 0 0;
+    letter-spacing: .3125rem;
+}
+.outlineBtn:hover {
+    cursor: pointer;
+}
+.outlineBtn img {
+    width:24px;
+    vertical-align: middle;
+}
 /* 新写的动画样式 */
 .manConOne{
     animation:manConDD1 2s;

+ 1 - 0
fhKeeper/formulahousekeeper/webttkuaiban/src/main/resources/static/index.html

@@ -85,6 +85,7 @@ Statcounter" href="https://statcounter.com/" target="_blank"><img
             </div>
             <div class="bannarTextList">
                 <ul>
+                    <li>独创<b style="color: #0556f7;">AI解析</b>填报,比传统方式提效50% <a href="/video/AIReport.mp4" style="color:#3396FB;" class="outlineBtn" target="_blank">查看对比<img src="./image/play.png" /> </a></li>
                     <li>提供最全面的项目工时统计解决方案</li>
                     <li>满足对内团队项目管理需求 / 对外IPO审计财务分摊需求</li>
                 </ul>