Переглянути джерело

工时成本统计模块的主项目模式下的导出Excel格式调整,增加主项目的数据

seyason 1 рік тому
батько
коміт
b7b6306e4e

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

@@ -132,8 +132,8 @@ public class DepartmentController {
      * departmentId 要查询的项目
      */
     @RequestMapping("/exportUserStatistic")
-    public HttpRespMsg exportUserStatistic(String startDate, String endDate, String userIds, HttpServletRequest request) {
-        return departmentService.exportUserStatistic(startDate, endDate, userIds, request);
+    public HttpRespMsg exportUserStatistic(boolean mainProjectColumn, String startDate, String endDate, String userIds, HttpServletRequest request) {
+        return departmentService.exportUserStatistic(mainProjectColumn, startDate, endDate, userIds, request);
     }
 
 

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

@@ -262,8 +262,8 @@ public class ProjectController {
      * 导出查询者所在公司每个项目的工时成本
      */
     @RequestMapping("/exportTimeCost")
-    public HttpRespMsg exportTimeCost(String exportContent,String startDate, String endDate, Integer projectId, String userIds, Boolean projectSum,Integer type,Integer deptId,@RequestParam(defaultValue = "1") Integer stateKey, @RequestParam(required = false, defaultValue = "0") Integer withPercent) {
-        return projectService.exportTimeCost(exportContent,startDate, endDate, projectId, userIds, projectSum,type,deptId,stateKey, withPercent, request);
+    public HttpRespMsg exportTimeCost(@RequestParam(required = false, defaultValue = "0") Integer withMainProject, String exportContent,String startDate, String endDate, Integer projectId, String userIds, Boolean projectSum,Integer type,Integer deptId,@RequestParam(defaultValue = "1") Integer stateKey, @RequestParam(required = false, defaultValue = "0") Integer withPercent) {
+        return projectService.exportTimeCost(withMainProject, exportContent,startDate, endDate, projectId, userIds, projectSum,type,deptId,stateKey, withPercent, request);
     }
 
     /**

+ 4 - 3
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/TaskController.java

@@ -1034,10 +1034,11 @@ public class TaskController {
 
     //获取当前用户在任务上参与的服务
     @RequestMapping("/getMyTaskService")
-    public HttpRespMsg getMyTaskService(Integer taskId) throws Exception {
+    public HttpRespMsg getMyTaskService(Integer taskId, String userId) throws Exception {
         HttpRespMsg httpRespMsg=new HttpRespMsg();
-        String userId = request.getHeader("token");
-        System.out.println(userId+"======="+taskId);
+        if (StringUtils.isEmpty(userId)) {
+            userId = request.getHeader("token");
+        }
         List<TaskExecutor> taskExecutors = taskExecutorMapper.selectList(new QueryWrapper<TaskExecutor>().eq("executor_id", userId).eq("task_id", taskId));
         List<Integer> serviceIds = new ArrayList<>();
         for (TaskExecutor executor : taskExecutors) {

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

@@ -34,7 +34,7 @@ public interface DepartmentService extends IService<Department> {
 
     HttpRespMsg getUserStatistics(String startDate, String endDate, Integer departmentId, HttpServletRequest request);
 
-    HttpRespMsg exportUserStatistic(String startDate, String endDate, String userIds, HttpServletRequest request);
+    HttpRespMsg exportUserStatistic(boolean mainProjectColumn, String startDate, String endDate, String userIds, HttpServletRequest request);
 
     HttpRespMsg listAllMemb(HttpServletRequest request,String keyword,String cursor) throws Exception;
 

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

@@ -70,7 +70,7 @@ public interface ProjectService extends IService<Project> {
 
     HttpRespMsg getAllMembCost(String startDate, String endDate, Integer projectId, HttpServletRequest request);
 
-    HttpRespMsg exportTimeCost(String exportContent,String startDate, String endDate, Integer projectId,String userIds, Boolean projectSum,Integer type,Integer deptId,Integer stateKey, Integer withPercent, HttpServletRequest request);
+    HttpRespMsg exportTimeCost(Integer withMainProject, String exportContent,String startDate, String endDate, Integer projectId,String userIds, Boolean projectSum,Integer type,Integer deptId,Integer stateKey, Integer withPercent, HttpServletRequest request);
 
     HttpRespMsg updateProgress(Integer id, Integer progress, HttpServletRequest request);
 

+ 144 - 62
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/DepartmentServiceImpl.java

@@ -664,7 +664,7 @@ public class DepartmentServiceImpl extends ServiceImpl<DepartmentMapper, Departm
     }
 
     @Override
-    public HttpRespMsg exportUserStatistic(String startDate, String endDate, String userIds, HttpServletRequest request) {
+    public HttpRespMsg exportUserStatistic(boolean mainProjectColumn,  String startDate, String endDate, String userIds, HttpServletRequest request) {
         HttpRespMsg httpRespMsg = new HttpRespMsg();
         try {
             User targetUser = userMapper.selectById(request.getHeader("Token"));
@@ -710,47 +710,88 @@ public class DepartmentServiceImpl extends ServiceImpl<DepartmentMapper, Departm
 
             List<Map<String, Object>> list = departmentMapper
                     .getCostByUser(deptIds, startDate, endDate, companyId, allUserIds);
-            Map<String, List<Map<String, Object>>> tempMap = new HashMap<>();
-            List<String> names = new ArrayList<>();
+//            Map<String, List<Map<String, Object>>> tempMap = new HashMap<>();
+            List<Map> userListMap = new ArrayList<>();
             BigDecimal totalCostMoney = new BigDecimal(0);
+            double totalTime = 0;
             for (Map<String, Object> map : list) {
-                if (tempMap.containsKey(map.get("id"))) {
-                    //这个名字已经装进数组中了
-                    List<Map<String, Object>> tempList;
-                    tempList = tempMap.get(map.get("id"));
-                    Map<String, Object> dataMap = new HashMap<>();
-                    dataMap.put("project", map.get("project"));
-                    BigDecimal money = (BigDecimal) map.getOrDefault("money", 0);
-                    Double time = (Double) map.getOrDefault("time", 0);
-                    totalCostMoney = totalCostMoney.add(money);
-                    dataMap.put("money", money);
-                    dataMap.put("time", time);
-                    tempList.add(dataMap);
+                String uid = (String) map.get("id");
+                double time = (double) map.getOrDefault("time", 0);
+                BigDecimal money = (BigDecimal) map.getOrDefault("money", 0);
+                totalCostMoney = totalCostMoney.add(money);
+                totalTime += time;
+                Optional<Map> find = userListMap.stream().filter(um -> um.get("id").equals(uid)).findFirst();
+                if (find.isPresent()) {
+                    Map userMap = find.get();
+                    //累加数据
+                    userMap.put("time", ((Double) userMap.get("time")) + time);
+                    userMap.put("money", ((BigDecimal) userMap.get("money")).add(money));
+                    Object data = userMap.get("data");
+                    List<Map<String, Object>> tempList = (List<Map<String, Object>>) data;
+                    tempList.add(map);
                 } else {
-                    names.add((String)map.get("id"));
+                    Map<String, Object> userMap = new HashMap<>();
+                    userMap.put("id", map.get("id"));
+                    userMap.put("name", map.get("user"));
+                    userMap.put("jobNumber", map.get("jobNumber"));
+                    userMap.put("corpwxUserId", "corpwxUserId");
+                    //添加工时和成本
+                    userMap.put("time", time);
+                    userMap.put("money", money);
+                    userListMap.add(userMap);
                     //这个名字尚未装进数组中
                     List<Map<String, Object>> tempList = new ArrayList<>();
-                    if (map.containsKey("project")) {
-                        Map<String, Object> dataMap = new HashMap<>();
-                        dataMap.put("project", map.get("project"));
-                        BigDecimal money = (BigDecimal) map.getOrDefault("money", 0);
-                        Double time = (Double) map.getOrDefault("time", 0);
-                        totalCostMoney = totalCostMoney.add(money);
-                        dataMap.put("money", money);
-                        dataMap.put("time", time);
-                        tempList.add(dataMap);
+                    tempList.add(map);
+                    userMap.put("data", tempList);
+                }
+            }
+            if (mainProjectColumn) {
+                //带主项目的模式,二次处理数据
+                List<Map<String, Object>> finalList = new ArrayList<>();
+                for (Map<String, Object> map : userListMap) {
+                    List<Map<String, Object>> tempList = (List<Map<String, Object>>)map.get("data");
+                    List<Map<String, Object>> mainPList = new ArrayList<>();
+                    //按照主项目进行分类
+                    for (Map<String, Object> membData : tempList) {
+                        Integer projectMainId = (Integer) membData.get("projectMainId") == null?0:(Integer) membData.get("projectMainId");
+                        String projectMainName = membData.get("mainProjectName") == null?"无主项目":(String) membData.get("mainProjectName");
+                        Optional<Map<String, Object>> find = mainPList.stream().filter(mp -> mp.get("projectMainId").equals(projectMainId)).findFirst();
+                        if (find.isPresent()) {
+                            //累加数据
+                            Map<String, Object> mainProject = find.get();
+                            mainProject.put("money", ((BigDecimal) mainProject.get("money")).add((BigDecimal) membData.getOrDefault("money", 0)));
+                            mainProject.put("time", ((Double) mainProject.get("time")) + ((Double) membData.getOrDefault("time", 0)));
+                            List<Map<String, Object>> projectList = (List<Map<String, Object>>) mainProject.get("project");
+                            projectList.add(membData);
+                        } else {
+                            Map<String, Object> mainProject = new HashMap<>();
+                            mainProject.put("projectMainId", projectMainId);
+                            mainProject.put("mainProjectCode", membData.get("mainProjectCode"));
+                            mainProject.put("mainProjectName", projectMainName);
+                            mainProject.put("money", membData.getOrDefault("money", 0));
+                            mainProject.put("time", membData.getOrDefault("time", 0));
+                            List<Map<String, Object>> projectList = new ArrayList<>();
+                            projectList.add(membData);
+                            mainProject.put("project", projectList);
+                            mainPList.add(mainProject);
+                        }
                     }
-                    tempMap.put((String) map.get("id"), tempList);
+                    //添加主项目列表
+                    map.put("mainPList", mainPList);
                 }
             }
-//            Map<String, Object> finalMap = new HashMap<>();
-//            List<Map<String, Object>> finalList = new ArrayList<>();
             DecimalFormat df = new DecimalFormat("#0.00");
             df.setRoundingMode(RoundingMode.HALF_UP);
             List<List<String>> dataList = new ArrayList<List<String>>();
             List<String> titleList =new ArrayList<>();
             //titleList.add("人员");
             titleList.add(MessageUtils.message("entry.personnel"));
+            if (mainProjectColumn) {
+                //titleList.add("项目");
+                titleList.add("主项目编号");
+                titleList.add("主项目名称");
+            }
+            titleList.add("项目编号");
             //titleList.add("项目");
             titleList.add(MessageUtils.message("entry.project"));
             if(functionTimeList.size()>0){
@@ -764,48 +805,84 @@ public class DepartmentServiceImpl extends ServiceImpl<DepartmentMapper, Departm
             dataList.add(titleList);
             BigDecimal totalMoneyCost = BigDecimal.valueOf(0);
             double totalCostTime = 0;
-            for (String key : names) {
-                List<String> nameList = new ArrayList<String>();
+            for (Map userItem : userListMap) {
+                String uid = (String) userItem.get("id");
+
                 String name;
                 if(wxCorpInfo!=null&&wxCorpInfo.getSaasSyncContact()==1){
-                    String corpwxUserId = userList.stream().filter(ul -> ul.getId().equals(key)).findFirst().get().getCorpwxUserid();
+                    String corpwxUserId = userList.stream().filter(ul -> ul.getId().equals(uid)).findFirst().get().getCorpwxUserid();
                     name ="$userName="+ (corpwxUserId==null?"":corpwxUserId) +"$";
                 }else {
-                     name = userList.stream().filter(ul -> ul.getId().equals(key)).findFirst().get().getName();
-                }
-                nameList.add(name);//姓名
-                nameList.add("");//空着
-                List<Map<String, Object>> tempList = tempMap.get(key);
-                //统计个人的时间和成本
-                double tTime = 0;
-                BigDecimal tCost = new BigDecimal(0);
-                for (Map<String, Object> membData : tempList) {
-                    tTime += (double)membData.get("time");
-                    tCost = tCost.add((BigDecimal)membData.get("money"));
+                     name = userList.stream().filter(ul -> ul.getId().equals(uid)).findFirst().get().getName();
                 }
-                totalMoneyCost = totalMoneyCost.add(tCost);
-                totalCostTime += tTime;
-                if(functionTimeList.size()>0){
-                    nameList.add(df.format(tTime));
-                }
-                if(functionCostList.size()>0){
-                    nameList.add(tCost.setScale(2, BigDecimal.ROUND_UP).toString());
-                }
-                dataList.add(nameList);
-                //装载该人员下的项目的工时数据
-                for (Map<String, Object> membData : tempList) {
-                    tTime += (double)membData.get("time");
-                    tCost.add((BigDecimal)membData.get("money"));
-                    List<String> projectDataList = new ArrayList<>();
-                    projectDataList.add("");
-                    projectDataList.add(membData.get("project")+"");
+                if (mainProjectColumn) {
+                    List<Map<String, Object>> mainPList = (List<Map<String, Object>>)userItem.get("mainPList");
+                    for (Map<String, Object> mainP : mainPList) {
+                        List<String> nameList = new ArrayList<String>();
+                        nameList.add(name);//姓名
+                        nameList.add((String)mainP.get("mainProjectCode"));//主项目编号
+                        nameList.add((String)mainP.get("mainProjectName"));//主项目名称
+                        nameList.add("");
+                        nameList.add("");
+                        if(functionTimeList.size()>0){
+                            nameList.add(df.format((double)mainP.get("time")));
+                        }
+                        if(functionCostList.size()>0){
+                            nameList.add(((BigDecimal)mainP.get("money")).setScale(2, BigDecimal.ROUND_UP).toString());
+                        }
+                        dataList.add(nameList);
+                        //添加主项目下的子项目
+                        List<Map<String, Object>> tempList = (List<Map<String, Object>>)mainP.get("project");
+                        for (Map<String, Object> membData : tempList) {
+                            List<String> projectDataList = new ArrayList<>();
+                            projectDataList.add("");
+                            projectDataList.add("");
+                            projectDataList.add("");
+                            projectDataList.add((String)membData.get("projectCode"));
+                            projectDataList.add((String)membData.get("project"));
+                            if(functionTimeList.size()>0){
+                                projectDataList.add(df.format((double)membData.get("time")));
+                            }
+                            if(functionCostList.size()>0){
+                                projectDataList.add(((BigDecimal)membData.get("money")).setScale(2, BigDecimal.ROUND_UP).toString());
+                            }
+                            dataList.add(projectDataList);
+                        }
+                    }
+                } else {
+                    List<String> nameList = new ArrayList<String>();
+                    nameList.add(name);//姓名
+                    nameList.add("");//项目编号
+                    nameList.add("");//项目名称
+                    List<Map<String, Object>> tempList = (List<Map<String, Object>>)userItem.get("data");
+                    //统计个人的时间和成本
+                    double tTime = 0;
+                    BigDecimal tCost = new BigDecimal(0);
+                    for (Map<String, Object> membData : tempList) {
+                        tTime += (double)membData.get("time");
+                        tCost = tCost.add((BigDecimal)membData.get("money"));
+                    }
                     if(functionTimeList.size()>0){
-                        projectDataList.add(df.format((double)membData.get("time"))+"");
+                        nameList.add(df.format(tTime));
                     }
                     if(functionCostList.size()>0){
-                        projectDataList.add(((BigDecimal)membData.get("money")).setScale(2, BigDecimal.ROUND_UP).toString());
+                        nameList.add(tCost.setScale(2, BigDecimal.ROUND_UP).toString());
+                    }
+                    dataList.add(nameList);
+                    //装载该人员下的项目的工时数据
+                    for (Map<String, Object> membData : tempList) {
+                        List<String> projectDataList = new ArrayList<>();
+                        projectDataList.add("");
+                        projectDataList.add(membData.get("projectCode")+"");
+                        projectDataList.add(membData.get("project")+"");
+                        if(functionTimeList.size()>0){
+                            projectDataList.add(df.format((double)membData.get("time"))+"");
+                        }
+                        if(functionCostList.size()>0){
+                            projectDataList.add(((BigDecimal)membData.get("money")).setScale(2, BigDecimal.ROUND_UP).toString());
+                        }
+                        dataList.add(projectDataList);
                     }
-                    dataList.add(projectDataList);
                 }
             }
             String total = totalMoneyCost.setScale(2, BigDecimal.ROUND_UP).toString();
@@ -814,7 +891,12 @@ public class DepartmentServiceImpl extends ServiceImpl<DepartmentMapper, Departm
             //sumRow.add("合计");
             //sumRow.add("合计");
             sumRow.add(MessageUtils.message("entry.total"));
-            sumRow.add("");
+            if (mainProjectColumn) {
+                sumRow.add("");
+                sumRow.add("");
+            }
+            sumRow.add("");//项目编号
+            sumRow.add("");//项目名称
             if(functionTimeList.size()>0){
                 sumRow.add(""+df.format(totalCostTime));
             }

+ 301 - 94
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ProjectServiceImpl.java

@@ -64,6 +64,7 @@ import java.util.*;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.Executor;
 import java.util.concurrent.Executors;
+import java.util.function.Function;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
@@ -1475,14 +1476,152 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
         return httpRespMsg;
     }
 
+    private HashMap fillMainProjectRowData(Integer projectMainId, Integer companyId, String startDate, String endDate, Integer stateKey, List<String> userIdList, List<Map<String, Object>> list,
+                                           List<UserCustom> userCustoms, List<SysRichFunction> functionTimeList, List<SysRichFunction> functionCostList,
+                                           String exportContent, List<User> userList, List<Integer> deptIds, List<Integer> deptRelatedProjectIds,
+                                           List<Integer> filterDeptIds, Boolean projectSum, WxCorpInfo wxCorpInfo) {
+        List<List<String>> allList = new ArrayList<List<String>>();
+        BigDecimal totalMoneyCost = new BigDecimal(0);
+        double totalCostTime = 0;
+        for (Map<String, Object> map : list) {
+            //只查找和当前主项目相关的项目
+            Integer pmid = (Integer)map.get("projectMainId");
+            if (projectMainId == null) {
+                if (pmid != null) {
+                    continue;
+                }
+            } else {
+                if (pmid == null || !pmid.equals(projectMainId)) {
+                    continue;
+                }
+            }
+            if (!map.containsKey("cost")) {
+                map.put("cost", 0);
+            }
+            if (!map.containsKey("costMoney")) {
+                map.put("costMoney", 0);
+            } else {
+                totalMoneyCost = totalMoneyCost.add((BigDecimal)map.get("costMoney"));
+            }
+            totalCostTime += (Double)map.get("cost");
+            List<String> rowData = new ArrayList<String>();
+            //空出两类主项目编号和名称
+            rowData.add("");
+            rowData.add("");
+            rowData.add((String)map.get("projectCode"));
+            rowData.add((String)map.get("project"));
+            rowData.add((String)map.get("categoryName"));
+            rowData.add("");
+            rowData.add("");
+            //针对项目合计行,自定义的字段要空出来
+            for (UserCustom userCustom : userCustoms) {
+                rowData.add("");
+            }
+            if ("hours".equals(exportContent) && functionTimeList.size()>0){
+                rowData.add(((Double)map.get("cost")).toString());
+            }else if ("cost".equals(exportContent) && functionCostList.size()>0){
+                rowData.add(((BigDecimal)map.get("costMoney")).toString());
+            }else {
+                if(functionTimeList.size()>0){
+                    rowData.add(((Double)map.get("cost")).toString());
+                }
+                if (functionCostList.size()>0){
+                    rowData.add(((BigDecimal)map.get("costMoney")).toString());
+                }
+            }
+            if (projectSum != null && projectSum == true) {
+                allList.add(rowData);
+            }
+            //统计每个项目中的人员时间成本投入
+            int curProjectId = (Integer)map.get("id");
+            //判断是否是当前项目的所属部门的主要或者其他负责人
+            List<Integer> finalDeptIds = null;
+            if (deptRelatedProjectIds.contains(curProjectId)) {
+                //有权限看该项目的全部参与人员,不需要按照部门过滤了
+            } else {
+                finalDeptIds = deptIds;
+            }
+            List<Map<String, Object>> membList = projectMapper.getProjectCost(companyId,startDate, endDate, curProjectId,stateKey, userIdList,finalDeptIds,filterDeptIds, true);
+            map.put("membList", membList);
+            for (Map<String, Object> membMap : membList) {
+                double pTotalTime = 0;
+                BigDecimal pTotalMoney = new BigDecimal(0);
+                List<String> membRowData = new ArrayList<String>();
+                if (projectSum == null || projectSum == false) {
+                    membRowData.add("");
+                    membRowData.add("");
+                    membRowData.add((String)map.get("projectCode"));
+                    membRowData.add((String)map.get("project"));
+                    membRowData.add((String)map.get("categoryName"));
+                } else {
+                    membRowData.add("");
+                    membRowData.add("");
+                    membRowData.add("");
+                    membRowData.add("");
+                    membRowData.add("");
+                }
+                if(wxCorpInfo!=null&&wxCorpInfo.getSaasSyncContact()==1){
+                    membRowData.add((String)("$userName="+membMap.get("corpwxUserId")+"$"));
+                    if(membMap.get("departmentName").equals("未分配")){
+                        membRowData.add("未分配");
+                    }else {
+                        membRowData.add((String)("$departmentName="+membMap.get("corpwxDeptId")+"$"));
+                    }
+                }else {
+                    membRowData.add((String)membMap.get("name"));
+                    membRowData.add((String)membMap.get("departmentName"));
+                }
+                String creatorId = (String)membMap.get("creatorId");
+                User us = userList.stream().filter(u->u.getId().equals(creatorId)).findFirst().get();
+                for (int i = 0; i < userCustoms.size(); i++) {
+                    switch (i){
+                        case 0:
+                            membRowData.add(us.getPlate1()==null?"":us.getPlate1());
+                            break;
+                        case 1:
+                            membRowData.add(us.getPlate2()==null?"":us.getPlate2());
+                            break;
+                        case 2:
+                            membRowData.add(us.getPlate3()==null?"":us.getPlate3());
+                            break;
+                        case 3:
+                            membRowData.add(us.getPlate4()==null?"":us.getPlate4());
+                            break;
+                        case 4:
+                            membRowData.add(us.getPlate5()==null?"":us.getPlate5());
+                            break;
+                    }
+                }
+                if ("hours".equals(exportContent) && functionTimeList.size()>0){
+                    membRowData.add(((Double)membMap.get("cost")).toString());
+                }else if ("cost".equals(exportContent) && functionCostList.size()>0){
+                    membRowData.add(((BigDecimal)membMap.get("costMoney")).toString());
+                }else {
+                    if(functionTimeList.size()>0){
+                        membRowData.add(((Double)membMap.get("cost")).toString());
+                    }
+                    if (functionCostList.size()>0){
+                        membRowData.add(((BigDecimal)membMap.get("costMoney")).toString());
+                    }
+                }
+                allList.add(membRowData);
+            }
+        }
+        HashMap map = new HashMap();
+        map.put("totalMoneyCost", totalMoneyCost);
+        map.put("totalCostTime", totalCostTime);
+        map.put("allList", allList);
+        return map;
+    }
+
     //导出查询者所在公司每个项目的工时成本,包括项目人员明细统计
     @Override
-    public HttpRespMsg exportTimeCost(String exportContent,String startDate, String endDate,Integer projectId, String userIds,
+    public HttpRespMsg exportTimeCost(Integer withMainProject, String exportContent,String startDate, String endDate,Integer projectId, String userIds,
                                         Boolean projectSum,Integer type,Integer deptId, Integer stateKey, Integer withPercent, HttpServletRequest request) {
         HttpRespMsg httpRespMsg = new HttpRespMsg();
         try {
             User targetUser = userMapper.selectById(request.getHeader("Token"));
-            Integer companyId =targetUser.getCompanyId();
+            Integer companyId = targetUser.getCompanyId();
             WxCorpInfo wxCorpInfo = wxCorpInfoMapper.selectOne(new QueryWrapper<WxCorpInfo>().eq("company_id", companyId));
             Map<String, Object> resultMap = new HashMap<>();
             //当前用户管理部门
@@ -1562,8 +1701,24 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
             List<List<String>> allList=null ;
             List<String> sumRow = null;
             List<UserCustom> userCustoms = userCustomMapper.selectList(new QueryWrapper<UserCustom>().eq("company_id", companyId));
-            if(type==0){
+            //按主项目导出时,项目固定在行上
+            if(type==0 || withMainProject == 1){
+                //取主项目
+                List<Integer> mainPidList = list.stream().map(m -> (Integer)m.get("projectMainId")).distinct().collect(Collectors.toList());
+                //查找有没有未分类的
+                boolean hasNoMainProject = list.stream().anyMatch(m -> m.get("projectMainId") == null);
+                List<ProjectMain> mainProjectList = new ArrayList<>();
+                if (mainPidList.size() > 0) {
+                    mainProjectList = projectMainMapper.selectList(new QueryWrapper<ProjectMain>().in("id", mainPidList));
+                }
+
+
                 List<String> headList = new ArrayList<String>();
+                if (withMainProject == 1) {
+                    //增加主项目合计的一行
+                    headList.add("主项目编号");
+                    headList.add("主项目名称");
+                }
                 //headList.add("项目编号");
                 headList.add(MessageUtils.message("entry.projectId"));
                 //headList.add("项目名称");
@@ -1598,119 +1753,165 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
                 allList=new ArrayList<>();
                 allList.add(headList);
                 double totalCostTime = 0;
-                for (Map<String, Object> map : list) {
-                    if (!map.containsKey("cost")) {
-                        map.put("cost", 0);
-                    }
-                    if (!map.containsKey("costMoney")) {
-                        map.put("costMoney", 0);
-                    } else {
-                        totalMoneyCost = totalMoneyCost.add((BigDecimal)map.get("costMoney"));
-                    }
-                    totalCostTime += (Double)map.get("cost");
-                    List<String> rowData = new ArrayList<String>();
-                    rowData.add((String)map.get("projectCode"));
-                    rowData.add((String)map.get("project"));
-                    rowData.add((String)map.get("categoryName"));
-                    rowData.add("");
-                    rowData.add("");
-                    //针对项目合计行,自定义的字段要空出来
-                    for (UserCustom userCustom : userCustoms) {
-                        rowData.add("");
-                    }
-                    if ("hours".equals(exportContent) && functionTimeList.size()>0){
-                        rowData.add(((Double)map.get("cost")).toString());
-                    }else if ("cost".equals(exportContent) && functionCostList.size()>0){
-                        rowData.add(((BigDecimal)map.get("costMoney")).toString());
-                    }else {
+                if (withMainProject == 1) {
+                    //主项目模式下的导出数据
+                    //存在无主项目的数据,放在最后
+                    if (hasNoMainProject) {
+                        ProjectMain noMainProject = new ProjectMain();
+                        noMainProject.setName("无主项目");
+                        mainProjectList.add(noMainProject);
+                    }
+                    for (ProjectMain mainP : mainProjectList) {
+                        HashMap sumData = fillMainProjectRowData(mainP.getId(), companyId, startDate, endDate, stateKey, userIdList, list, userCustoms, functionTimeList, functionCostList, exportContent, userList, deptIds, deptRelatedProjectIds, filterDeptIds, projectSum, wxCorpInfo);
+                        totalMoneyCost = totalMoneyCost.add((BigDecimal)sumData.get("totalMoneyCost"));
+                        totalCostTime += (double)sumData.get("totalCostTime");
+                        //增加主项目合计的一行
+                        List<String> mainProjectRowData = new ArrayList<String>();
+                        mainProjectRowData.add(mainP.getCode());
+                        mainProjectRowData.add(mainP.getName());
+                        mainProjectRowData.add("");//项目编号
+                        mainProjectRowData.add("");//项目名称
+                        mainProjectRowData.add("");//项目分类
+                        mainProjectRowData.add("");//姓名
+                        mainProjectRowData.add("");//部门
+                        //针对项目合计行,自定义的字段要空出来
+                        for (UserCustom userCustom : userCustoms) {
+                            mainProjectRowData.add("");
+                        }
+
                         if(functionTimeList.size()>0){
-                            rowData.add(((Double)map.get("cost")).toString());
+                            mainProjectRowData.add(((Double)sumData.get("totalCostTime")).toString());
                         }
                         if (functionCostList.size()>0){
-                            rowData.add(((BigDecimal)map.get("costMoney")).toString());
+                            mainProjectRowData.add(((BigDecimal)sumData.get("totalMoneyCost")).toString());
                         }
+                        allList.add(mainProjectRowData);
+                        //增加主项目下的项目列表
+                        allList.addAll((List<List<String>>)sumData.get("allList"));
                     }
-                    if (projectSum != null && projectSum == true) {
-                        allList.add(rowData);
-                    }
-                    //统计每个项目中的人员时间成本投入
-                    int curProjectId = (Integer)map.get("id");
-                    //判断是否是当前项目的所属部门的主要或者其他负责人
-                    List<Integer> finalDeptIds = null;
-                    if (deptRelatedProjectIds.contains(curProjectId)) {
-                        //有权限看该项目的全部参与人员,不需要按照部门过滤了
-                    } else {
-                        finalDeptIds = deptIds;
-                    }
-                    List<Map<String, Object>> membList = projectMapper.getProjectCost(companyId,startDate, endDate, curProjectId,stateKey, userIdList,finalDeptIds,filterDeptIds, true);
-                    map.put("membList", membList);
-                    for (Map<String, Object> membMap : membList) {
-                        double pTotalTime = 0;
-                        BigDecimal pTotalMoney = new BigDecimal(0);
-                        List<String> membRowData = new ArrayList<String>();
-                        if (projectSum == null || projectSum == false) {
-                            membRowData.add((String)map.get("projectCode"));
-                            membRowData.add((String)map.get("project"));
-                            membRowData.add((String)map.get("categoryName"));
-
+                } else {
+                    //常规项目的工时导出
+                    for (Map<String, Object> map : list) {
+                        if (!map.containsKey("cost")) {
+                            map.put("cost", 0);
+                        }
+                        if (!map.containsKey("costMoney")) {
+                            map.put("costMoney", 0);
                         } else {
-                            membRowData.add("");
-                            membRowData.add("");
-                            membRowData.add("");
-
+                            totalMoneyCost = totalMoneyCost.add((BigDecimal)map.get("costMoney"));
                         }
-                        if(wxCorpInfo!=null&&wxCorpInfo.getSaasSyncContact()==1){
-                            membRowData.add((String)("$userName="+membMap.get("corpwxUserId")+"$"));
-                            if(membMap.get("departmentName").equals("未分配")){
-                                membRowData.add("未分配");
-                            }else {
-                                membRowData.add((String)("$departmentName="+membMap.get("corpwxDeptId")+"$"));
-                            }
-                        }else {
-                            membRowData.add((String)membMap.get("name"));
-                            membRowData.add((String)membMap.get("departmentName"));
-                        }
-                        String creatorId = (String)membMap.get("creatorId");
-                        User us = userList.stream().filter(u->u.getId().equals(creatorId)).findFirst().get();
-                        for (int i = 0; i < userCustoms.size(); i++) {
-                            switch (i){
-                                case 0:
-                                    membRowData.add(us.getPlate1()==null?"":us.getPlate1());
-                                    break;
-                                case 1:
-                                    membRowData.add(us.getPlate2()==null?"":us.getPlate2());
-                                    break;
-                                case 2:
-                                    membRowData.add(us.getPlate3()==null?"":us.getPlate3());
-                                    break;
-                                case 3:
-                                    membRowData.add(us.getPlate4()==null?"":us.getPlate4());
-                                    break;
-                                case 4:
-                                    membRowData.add(us.getPlate5()==null?"":us.getPlate5());
-                                    break;
-                            }
+                        totalCostTime += (Double)map.get("cost");
+                        List<String> rowData = new ArrayList<String>();
+                        rowData.add((String)map.get("projectCode"));
+                        rowData.add((String)map.get("project"));
+                        rowData.add((String)map.get("categoryName"));
+                        rowData.add("");
+                        rowData.add("");
+                        //针对项目合计行,自定义的字段要空出来
+                        for (UserCustom userCustom : userCustoms) {
+                            rowData.add("");
                         }
                         if ("hours".equals(exportContent) && functionTimeList.size()>0){
-                            membRowData.add(((Double)membMap.get("cost")).toString());
+                            rowData.add(((Double)map.get("cost")).toString());
                         }else if ("cost".equals(exportContent) && functionCostList.size()>0){
-                            membRowData.add(((BigDecimal)membMap.get("costMoney")).toString());
+                            rowData.add(((BigDecimal)map.get("costMoney")).toString());
                         }else {
                             if(functionTimeList.size()>0){
-                                membRowData.add(((Double)membMap.get("cost")).toString());
+                                rowData.add(((Double)map.get("cost")).toString());
                             }
                             if (functionCostList.size()>0){
-                                membRowData.add(((BigDecimal)membMap.get("costMoney")).toString());
+                                rowData.add(((BigDecimal)map.get("costMoney")).toString());
                             }
                         }
+                        if (projectSum != null && projectSum == true) {
+                            allList.add(rowData);
+                        }
+                        //统计每个项目中的人员时间成本投入
+                        int curProjectId = (Integer)map.get("id");
+                        //判断是否是当前项目的所属部门的主要或者其他负责人
+                        List<Integer> finalDeptIds = null;
+                        if (deptRelatedProjectIds.contains(curProjectId)) {
+                            //有权限看该项目的全部参与人员,不需要按照部门过滤了
+                        } else {
+                            finalDeptIds = deptIds;
+                        }
+                        List<Map<String, Object>> membList = projectMapper.getProjectCost(companyId,startDate, endDate, curProjectId,stateKey, userIdList,finalDeptIds,filterDeptIds, true);
+                        map.put("membList", membList);
+                        for (Map<String, Object> membMap : membList) {
+                            double pTotalTime = 0;
+                            BigDecimal pTotalMoney = new BigDecimal(0);
+                            List<String> membRowData = new ArrayList<String>();
+                            if (projectSum == null || projectSum == false) {
+                                membRowData.add((String)map.get("projectCode"));
+                                membRowData.add((String)map.get("project"));
+                                membRowData.add((String)map.get("categoryName"));
 
-                        allList.add(membRowData);
+                            } else {
+                                membRowData.add("");
+                                membRowData.add("");
+                                membRowData.add("");
+
+                            }
+                            if(wxCorpInfo!=null&&wxCorpInfo.getSaasSyncContact()==1){
+                                membRowData.add((String)("$userName="+membMap.get("corpwxUserId")+"$"));
+                                if(membMap.get("departmentName").equals("未分配")){
+                                    membRowData.add("未分配");
+                                }else {
+                                    membRowData.add((String)("$departmentName="+membMap.get("corpwxDeptId")+"$"));
+                                }
+                            }else {
+                                membRowData.add((String)membMap.get("name"));
+                                membRowData.add((String)membMap.get("departmentName"));
+                            }
+                            String creatorId = (String)membMap.get("creatorId");
+                            User us = userList.stream().filter(u->u.getId().equals(creatorId)).findFirst().get();
+                            for (int i = 0; i < userCustoms.size(); i++) {
+                                switch (i){
+                                    case 0:
+                                        membRowData.add(us.getPlate1()==null?"":us.getPlate1());
+                                        break;
+                                    case 1:
+                                        membRowData.add(us.getPlate2()==null?"":us.getPlate2());
+                                        break;
+                                    case 2:
+                                        membRowData.add(us.getPlate3()==null?"":us.getPlate3());
+                                        break;
+                                    case 3:
+                                        membRowData.add(us.getPlate4()==null?"":us.getPlate4());
+                                        break;
+                                    case 4:
+                                        membRowData.add(us.getPlate5()==null?"":us.getPlate5());
+                                        break;
+                                }
+                            }
+                            if ("hours".equals(exportContent) && functionTimeList.size()>0){
+                                membRowData.add(((Double)membMap.get("cost")).toString());
+                            }else if ("cost".equals(exportContent) && functionCostList.size()>0){
+                                membRowData.add(((BigDecimal)membMap.get("costMoney")).toString());
+                            }else {
+                                if(functionTimeList.size()>0){
+                                    membRowData.add(((Double)membMap.get("cost")).toString());
+                                }
+                                if (functionCostList.size()>0){
+                                    membRowData.add(((BigDecimal)membMap.get("costMoney")).toString());
+                                }
+                            }
+
+                            allList.add(membRowData);
+                        }
                     }
                 }
+
+
                 //合计
                 sumRow=new ArrayList<>();
                 //sumRow.add("合计");
                 sumRow.add(MessageUtils.message("entry.total"));
+                if (withMainProject == 1) {
+                    //多两列
+                    sumRow.add("");
+                    sumRow.add("");
+                }
                 sumRow.add("");
                 sumRow.add("");
                 sumRow.add("");
@@ -1891,7 +2092,13 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
             }
             //生成excel文件导出
             //String fileName = "项目成本工时统计_"+System.currentTimeMillis();
-            String fileName = MessageUtils.message("fileName.projectCost")+System.currentTimeMillis();
+            String fileName = null;
+            if (withMainProject == 1) {
+                fileName = "主项目成本工时统计"+System.currentTimeMillis();
+            } else {
+                fileName = MessageUtils.message("fileName.projectCost")+System.currentTimeMillis();
+            }
+
             return excelExportService.exportGeneralExcelByTitleAndList(wxCorpInfo,fileName , allList, path);
         } catch (NullPointerException e) {
             e.printStackTrace();

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

@@ -40,11 +40,12 @@
 
     <!--根据人员获取成本-->
     <select id="getCostByUser" resultType="java.util.Map">
-        SELECT a.id as id, a.name AS user,a.corpwx_userid as corpwxUserId, a.job_number as jobNumber, c.project_name AS project, SUM(b.working_time) AS time, SUM(b.cost) AS
+        SELECT a.id as id, a.name AS user,a.corpwx_userid as corpwxUserId, a.job_number as jobNumber, c.project_name AS project,c.project_code as projectCode, c.project_main_id as projectMainId, project_main.code as mainProjectCode, project_main.name as mainProjectName, ifnull(SUM(b.working_time),0) AS time, ifnull(SUM(b.cost),0) AS
         money
         FROM user AS a
         LEFT JOIN report AS b ON a.id = b.creator_id
         LEFT JOIN project AS c ON b.project_id = c.id
+        left join project_main on project_main.id = c.project_main_id
         WHERE b.state = 1
         <if test="departmentIds != null and departmentIds.size()>0">
             AND b.dept_id IN

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

@@ -145,7 +145,7 @@
     </select>
     <!--获取查询者所在公司每个项目的工时成本-->
     <select id="getTimeCost" resultType="java.util.Map">
-        SELECT a.id, a.project_code as projectCode, a.project_name AS project, SUM(b.working_time) AS cost, SUM(b.cost) AS costMoney,a.category_name as categoryName
+        SELECT a.id, a.project_main_id as projectMainId, a.project_code as projectCode, a.project_name AS project, SUM(b.working_time) AS cost, SUM(b.cost) AS costMoney,a.category_name as categoryName
         FROM project AS a
         LEFT JOIN report AS b ON b.project_id = a.id
         JOIN user AS c ON b.creator_id = c.id
@@ -260,7 +260,7 @@
 
     <!--获取查询者所在公司每个项目的工时成本-->
     <select id="getTimeCostByMainProject" resultType="java.util.Map">
-        SELECT SUM(b.working_time) AS cost, SUM(b.cost) AS costMoney,a.category_name as categoryName,IFNULL(pm.name,'未分类') as mainProjectName
+        SELECT SUM(b.working_time) AS cost, SUM(b.cost) AS costMoney,a.category_name as categoryName,IFNULL(pm.name,'无主项目') as mainProjectName
         FROM project AS a
         LEFT JOIN report AS b ON b.project_id = a.id
         JOIN user AS c ON b.creator_id = c.id

+ 15 - 5
fhKeeper/formulahousekeeper/timesheet/src/views/project/cost.vue

@@ -93,7 +93,7 @@
         <!--导出报表条件选择 -->
         <el-dialog :title="$t('timeReportExport')" v-if="exportDialog" :visible.sync="exportDialog" :close-on-click-modal="false" customClass="customWidth" width="500px">
             <el-form ref="form3" :model="exportParam" >
-                <el-form-item prop="projectId" :label="$t('defaultText.selectProject')" v-if="radio != $t('ren-yuan') && radio != $t('projectclassification') && radio != $t('lable.department')">
+                <el-form-item prop="projectId" :label="$t('defaultText.selectProject')" v-if="radio != $t('ren-yuan') && radio != $t('projectclassification') && radio != $t('lable.department') && radio != $t('zhu-xiang-mu')">
                     <el-select v-model="exportParam.projectId" :placeholder="$t('other.allProject')"  clearable style="width:350px;" filterable="true" popper-class="projectSelectPopperClass">
                         <el-option v-for="item in projectList"  :key="item.id" :label="item.projectName + item.projectCode" :value="item.id">
                             <span style="float: left;color: #8492a6;">{{ item.projectCode }}</span>
@@ -183,13 +183,15 @@
                 <el-form-item v-if="exportParam.type == 1 && permissions.countHours && (radio == $t('other.project'))">
                     <el-checkbox v-model="exportParam.withPercent" >含项目工时占比</el-checkbox>
                 </el-form-item>
-                <el-form-item v-if="(radio == $t('other.project') || radio == $t('projectclassification')) && exportParam.type == '0'">
+                <el-form-item v-if="radio == $t('zhu-xiang-mu') || ((radio == $t('other.project') || radio == $t('projectclassification')) && exportParam.type == '0')">
                     <el-checkbox v-model="exportParam.projectSum" >{{ $t('individualprojectdata') }}</el-checkbox>
                 </el-form-item>
-                
+                <el-form-item v-if="radio == $t('ren-yuan') && user.timeType.mainProjectState == 1">
+                    <el-checkbox v-model="exportParam.mainProjectColumn" >含主项目</el-checkbox>
+                </el-form-item>
             </el-form>
             <div slot="footer" class="dialog-footer">
-                <el-button type="primary" @click="exportProjectData" style="width:100%;" >{{ $t('export.export') }}</el-button>
+                <el-button type="primary" @click="exportProjectData" style="width:100%;" :loading="exporting">{{ $t('export.export') }}</el-button>
             </div>
         </el-dialog>
     </section>
@@ -209,6 +211,7 @@
         },
         data() {
             return {
+                exporting: false,
                 totalTime111: 0,
                 allListData: [],
                 page: 1,
@@ -360,6 +363,9 @@
                  }
                  var url = "/project/exportTimeCost";
                  var fileName = this.$t('projectmanhourcoststatistics')+ '.xlsx';
+                 if (this.radio == this.$t('zhu-xiang-mu')) {
+                    param.withMainProject = 1;
+                 }
                  if(this.radio == this.$t('other.project')){
                     if (this.exportParam.userIds != null && this.exportParam.userIds.length > 0) {
                          var ids = '';
@@ -384,6 +390,7 @@
                         })
                         param.userIds = ids.substring(0,ids.length-1);
                      }
+                     param.mainProjectColumn = this.exportParam.mainProjectColumn;
                  } 
                 if(this.radio == this.$t('projectclassification')){
                     fileName = this.$t('projectclassificationlaborosttatistics')+ '.xlsx';
@@ -416,7 +423,7 @@
                     this.exportParam.projectSum = null
                 }
                 if (this.exportParam.projectSum != null) {
-                    if(this.radio == this.$t('other.project') || this.radio == this.$t('lable.department') || this.radio == this.$t('projectclassification')){
+                    if(this.radio == this.$t('other.project') || this.radio == this.$t('lable.department') || this.radio == this.$t('projectclassification') || this.radio == this.$t('zhu-xiang-mu')){
                         param.projectSum = this.exportParam.projectSum;
                     }
                 }
@@ -450,8 +457,10 @@
                     }
                     fileName = this.radio + '成本统计' + '.xlsx'
                 }
+                this.exporting = true;
                 this.http.post(url, param,
                     res => {
+                        this.exporting = false;
                         if (res.code == "ok") {
                             this.exportDialog = false;
                             var aTag = document.createElement('a');
@@ -470,6 +479,7 @@
                             message: error,
                             type: "error"
                         });
+                        this.exporting = false;
                     });
             },
             // 人员筛选

+ 6 - 1
fhKeeper/formulahousekeeper/timesheet/src/views/workReport/daily.vue

@@ -2334,7 +2334,12 @@
                 //取服务
                 if (domainItem.taskId) {
                     var that = this;
-                    this.http.post('/task/getMyTaskService',{taskId:domainItem.taskId},res => {
+                    var param = {taskId:domainItem.taskId};
+                    if (this.isSubstitude) {
+                        if (this.workForm.userId != null && this.workForm.userId.length>0)
+                        param.userId = this.workForm.userId[0];
+                    }
+                    this.http.post('/task/getMyTaskService',param, res => {
                             if (res.code == "ok") {
                                 // domainItem.workContentList = res.data;
                                 that.$set(domainItem, 'sapServiceId', null);