فهرست منبع

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

QuYueTing 1 ماه پیش
والد
کامیت
652496b08c
57فایلهای تغییر یافته به همراه2945 افزوده شده و 604 حذف شده
  1. 3 3
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/controller/WeiXinCorpController.java
  2. 4 1
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/SalesOrderServiceImpl.java
  3. 1 1
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/TaskServiceImpl.java
  4. 3 3
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/UserServiceImpl.java
  5. 23 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/ProjectController.java
  6. 2 1
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/StagesController.java
  7. 180 56
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/TaskController.java
  8. 18 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/UserController.java
  9. 37 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/ErpOrderInfo.java
  10. 4 1
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/Task.java
  11. 6 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/UserFvTime.java
  12. 10 1
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/vo/GanttDataItem.java
  13. 2 2
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/vo/UserVO.java
  14. 5 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/mapper/BusinessTripMapper.java
  15. 15 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/mapper/ErpOrderInfoMapper.java
  16. 4 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/mapper/LeaveSheetMapper.java
  17. 29 1
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/mapper/ProjectMapper.java
  18. 4 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/mapper/UserFvTimeMapper.java
  19. 6 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/ProjectService.java
  20. 2 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/TaskService.java
  21. 4 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/UserService.java
  22. 313 13
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ProjectServiceImpl.java
  23. 96 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/TaskServiceImpl.java
  24. 44 5
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/UserServiceImpl.java
  25. 5 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/WxCorpInfoServiceImpl.java
  26. 327 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/task/DataCollectTask.java
  27. 15 0
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/BusinessTripMapper.xml
  28. 18 0
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/ErpOrderInfoMapper.xml
  29. 14 0
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/LeaveSheetMapper.xml
  30. 246 3
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/ProjectMapper.xml
  31. 1 1
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/TaskExecutorMapper.xml
  32. 10 0
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/UserFvTimeMapper.xml
  33. 11 1
      fhKeeper/formulahousekeeper/octopus/src/routes.js
  34. 138 0
      fhKeeper/formulahousekeeper/octopus/src/views/expiredCompanyCleanup/expiredCompanyCleanup.vue
  35. 116 31
      fhKeeper/formulahousekeeper/ops-platform/src/main/java/com/management/platform/controller/CompanyController.java
  36. 23 23
      fhKeeper/formulahousekeeper/ops-platform/src/main/java/com/management/platform/entity/Project.java
  37. 25 0
      fhKeeper/formulahousekeeper/ops-platform/src/main/java/com/management/platform/mapper/ProjectBasecostMapper.java
  38. 17 0
      fhKeeper/formulahousekeeper/ops-platform/src/main/java/com/management/platform/mapper/ProjectBasecostSettingMapper.java
  39. 17 0
      fhKeeper/formulahousekeeper/ops-platform/src/main/java/com/management/platform/mapper/ProjectDocfolderMapper.java
  40. 17 0
      fhKeeper/formulahousekeeper/ops-platform/src/main/java/com/management/platform/mapper/ProjectDocumentMapper.java
  41. 17 0
      fhKeeper/formulahousekeeper/ops-platform/src/main/java/com/management/platform/mapper/ProjectNotifyUserMapper.java
  42. 16 0
      fhKeeper/formulahousekeeper/ops-platform/src/main/java/com/management/platform/mapper/ProjectPercentageMapper.java
  43. 17 0
      fhKeeper/formulahousekeeper/ops-platform/src/main/java/com/management/platform/mapper/ProjectProfessionMapper.java
  44. 16 0
      fhKeeper/formulahousekeeper/ops-platform/src/main/java/com/management/platform/mapper/ProjectTimerMapper.java
  45. 17 0
      fhKeeper/formulahousekeeper/ops-platform/src/main/java/com/management/platform/mapper/ProjectUserSalaryMapper.java
  46. 17 0
      fhKeeper/formulahousekeeper/ops-platform/src/main/java/com/management/platform/mapper/ReportAuditLogMapper.java
  47. 17 0
      fhKeeper/formulahousekeeper/ops-platform/src/main/java/com/management/platform/mapper/ReportExtraDegreeMapper.java
  48. 17 0
      fhKeeper/formulahousekeeper/ops-platform/src/main/java/com/management/platform/mapper/ReportImportLogMapper.java
  49. 17 0
      fhKeeper/formulahousekeeper/ops-platform/src/main/java/com/management/platform/mapper/ReportProfessionProgressMapper.java
  50. 17 0
      fhKeeper/formulahousekeeper/ops-platform/src/main/java/com/management/platform/mapper/SubProjectMapper.java
  51. 473 247
      fhKeeper/formulahousekeeper/timesheet/src/components/taskComponent.vue
  52. 4 0
      fhKeeper/formulahousekeeper/timesheet/src/permissions.js
  53. 3 0
      fhKeeper/formulahousekeeper/timesheet/src/views/Home.vue
  54. 89 9
      fhKeeper/formulahousekeeper/timesheet/src/views/corpreport/list.vue
  55. 360 194
      fhKeeper/formulahousekeeper/timesheet/src/views/project/gantt.vue
  56. 27 6
      fhKeeper/formulahousekeeper/timesheet/src/views/project/list.vue
  57. 6 1
      fhKeeper/formulahousekeeper/timesheet/src/views/project/project_gantt.vue

+ 3 - 3
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/controller/WeiXinCorpController.java

@@ -1625,11 +1625,11 @@ public class WeiXinCorpController {
         stages.add(stage2);
         Stage stage3 = new Stage().setName("无效").setPlan("0%").setSeq(6).setIsFinish(1).setCompanyId(company.getId()).setColor("#F4F5F7");
         stages.add(stage3);
-        Stage stage4 = new Stage().setName("验证客户").setPlan("10%").setSeq(1).setIsFinish(1).setCompanyId(company.getId()).setColor("#075985");
+        Stage stage4 = new Stage().setName("验证客户").setPlan("10%").setSeq(1).setIsFinish(0).setCompanyId(company.getId()).setColor("#075985");
         stages.add(stage4);
-        Stage stage5 = new Stage().setName("需求分析").setPlan("30%").setSeq(2).setIsFinish(1).setCompanyId(company.getId()).setColor("#075985");
+        Stage stage5 = new Stage().setName("需求分析").setPlan("30%").setSeq(2).setIsFinish(0).setCompanyId(company.getId()).setColor("#075985");
         stages.add(stage5);
-        Stage stage6 = new Stage().setName("方案/报价").setPlan("80%").setSeq(3).setIsFinish(1).setCompanyId(company.getId()).setColor("#075985");
+        Stage stage6 = new Stage().setName("方案/报价").setPlan("80%").setSeq(3).setIsFinish(0).setCompanyId(company.getId()).setColor("#075985");
         stages.add(stage6);
         return stages;
     }

+ 4 - 1
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/SalesOrderServiceImpl.java

@@ -1031,7 +1031,10 @@ public class SalesOrderServiceImpl extends ServiceImpl<SalesOrderMapper, SalesOr
         SysForm sysForm = sysFormMapper.selectOne(new LambdaQueryWrapper<SysForm>().eq(SysForm::getCompanyId, user.getCompanyId()).eq(SysForm::getCode, "Order").eq(SysForm::getIsCurrent, 1));
         WxCorpInfo wxCorpInfo = wxCorpInfoService.getOne(new LambdaQueryWrapper<WxCorpInfo>().eq(WxCorpInfo::getCompanyId, user.getCompanyId()));
         String config = sysForm.getConfig();
-        JSONObject configOb = JSON.parseObject(config);
+        System.out.println("==>:"+config);
+        // 定位并替换
+        String fixedConfig = config.replace("\"pattern\":\"/^\\d+$/\"", "\"pattern\":\"/^\\\\d+$/\"");
+        JSONObject configOb = JSON.parseObject(fixedConfig); // 现在不会报错
         JSONArray configObJSONArray = configOb.getJSONArray("list");
         List<List<String>> dataList=new ArrayList<>();
         List<String> titleList=new ArrayList<>();

+ 1 - 1
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/TaskServiceImpl.java

@@ -1737,7 +1737,7 @@ public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task> implements Ta
                         value = String.valueOf(aClass.getMethod("getTaskName").invoke(tasKVo)).equals("null") ? "" : String.valueOf(aClass.getMethod("getTaskName").invoke(tasKVo));
                     } else if (model.equals("priority")) {
 //                    0-低 1-中 2-高
-                        Integer priority = tasKVo.getPriority();
+                        int priority = tasKVo.getPriority()==null?3:tasKVo.getPriority();
                         switch (priority) {
                             case 0:
                                 value = "低";

+ 3 - 3
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/UserServiceImpl.java

@@ -1367,11 +1367,11 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
         stages.add(stage2);
         Stage stage3 = new Stage().setName("无效").setPlan("0%").setSeq(6).setIsFinish(1).setCompanyId(company.getId()).setColor("#F4F5F7");
         stages.add(stage3);
-        Stage stage4 = new Stage().setName("验证客户").setPlan("10%").setSeq(1).setIsFinish(1).setCompanyId(company.getId()).setColor("#075985");
+        Stage stage4 = new Stage().setName("验证客户").setPlan("10%").setSeq(1).setIsFinish(0).setCompanyId(company.getId()).setColor("#075985");
         stages.add(stage4);
-        Stage stage5 = new Stage().setName("需求分析").setPlan("30%").setSeq(2).setIsFinish(1).setCompanyId(company.getId()).setColor("#075985");
+        Stage stage5 = new Stage().setName("需求分析").setPlan("30%").setSeq(2).setIsFinish(0).setCompanyId(company.getId()).setColor("#075985");
         stages.add(stage5);
-        Stage stage6 = new Stage().setName("方案/报价").setPlan("80%").setSeq(3).setIsFinish(1).setCompanyId(company.getId()).setColor("#075985");
+        Stage stage6 = new Stage().setName("方案/报价").setPlan("80%").setSeq(3).setIsFinish(0).setCompanyId(company.getId()).setColor("#075985");
         stages.add(stage6);
         return stages;
     }

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

@@ -1612,5 +1612,28 @@ public class ProjectController {
     public HttpRespMsg transferProjectReviwer(String userId, String targetAuditorId){
         return projectService.transferProjectReviwer(userId,targetAuditorId);
     }
+
+    /**
+     * 添加任务计划的时候 项目是小组长参与的项目
+     */
+    @RequestMapping("/getProjectByLeader")
+    public HttpRespMsg getProjectByLeader(Integer projectId, HttpServletRequest request){
+        return projectService.getProjectByLeader(projectId,request);
+    }
+
+
+
+
+    //FTE报表
+    @RequestMapping("/getProjectTaskPlanFTEData")
+    public HttpRespMsg getProjectTaskPlanFTEData(@RequestParam Integer pageIndex, @RequestParam Integer pageSize,String monthStart,String monthEnd,String area,String userId,String sortProp, Integer sortOrder,Integer departmentId,HttpServletRequest request){
+        return projectService.getProjectTaskPlanFTEData(pageIndex,pageSize,monthStart,monthEnd,area,userId,sortProp,sortOrder,departmentId,request);
+    }
+
+    //导出FTE报表
+    @RequestMapping("/exportTaskPlanFTEData")
+    public HttpRespMsg exportTaskPlanFTEData(String monthStart,String monthEnd,String area,String userId,Integer departmentId ,HttpServletRequest request){
+        return projectService.exportTaskPlanFTEData(monthStart,monthEnd,area,userId,departmentId,request);
+    }
 }
 

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

@@ -191,6 +191,7 @@ public class StagesController {
         //按任务分组查看
         queryWrapper.eq("group_id", item.getGroupId());
         queryWrapper.isNull("parent_tid");
+        queryWrapper.eq("is_task_plan",0);
         //排序根据前端传过来的字段
         if (isDesc) {
             queryWrapper.orderByDesc(order);
@@ -210,7 +211,7 @@ public class StagesController {
         List<Task> subTasks = new ArrayList<>();
         if (tasks.size() > 0) {
             List<Integer> collect = tasks.stream().map(Task::getId).collect(Collectors.toList());
-            List<Task> subLists = taskService.simpleList(new QueryWrapper<Task>().in("parent_tid", collect),null,null);
+            List<Task> subLists = taskService.simpleList(new QueryWrapper<Task>().in("parent_tid", collect).eq("is_task_plan",0),null,null);
             if (functionList.size() == 0 && !userId.equals(project.getInchargerId())) {
                 subLists = subLists.stream().filter(t->t.getExecutorId() == null || t.getExecutorId().contains(userId) || userId.equals(t.getCreaterId())).collect(Collectors.toList());
             }

+ 180 - 56
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/TaskController.java

@@ -5,13 +5,16 @@ import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.management.platform.constant.Constant;
 import com.management.platform.entity.*;
 import com.management.platform.entity.bo.QueryTaskChargePage;
 import com.management.platform.entity.vo.SysRichFunction;
 import com.management.platform.mapper.*;
 import com.management.platform.service.*;
+import com.management.platform.service.impl.WxCorpInfoServiceImpl;
 import com.management.platform.util.HttpRespMsg;
 import com.management.platform.util.MessageUtils;
+import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.collections.CollectionUtils;
 import org.apache.poi.hssf.usermodel.*;
 import org.assertj.core.util.Lists;
@@ -46,6 +49,7 @@ import java.util.stream.Collectors;
  */
 @RestController
 @RequestMapping("/task")
+@Slf4j
 public class TaskController {
     @Resource
     private HttpServletRequest request;
@@ -187,13 +191,34 @@ public class TaskController {
         User user = userMapper.selectById(userId);
         HttpRespMsg msg = new HttpRespMsg();
         WxCorpInfo wxCorpInfo = wxCorpInfoService.getOne(new QueryWrapper<WxCorpInfo>().eq("company_id", user.getCompanyId()));
+        int isInsert=0;
+        int isUpdate=0;
         //新建的任务,需要设置创建人,创建时间
         if (task.getId() == null) {
+            isInsert=1;
             task.setCreateDate(LocalDate.now());
             task.setCreaterId(userId);
             task.setCreaterName(user.getName());
             task.setCreatorColor(user.getColor());
             task.setCompanyId(user.getCompanyId());
+
+            if (user.getCompanyId()==Constant.MLD_COMPANY_ID&&task.getIsTaskPlan()==0&&task.getCheckFirstId()==null){
+                if (task.getProjectId()!=null){
+                    Project project = projectMapper.selectById(task.getProjectId());
+                    task.setCheckFirstId(project.getInchargerId());
+                }
+            }
+
+            if (user.getCompanyId()==Constant.MLD_COMPANY_ID&&task.getIsTaskPlan()==1){
+                task.setTaskPlan(1);
+                task.setTaskStatus(3);
+                //状态是请假 直接变成任务
+                if (task.getTaskPlanType()==3){
+                    task.setIsTaskPlan(0);
+                    task.setTaskStatus(0);
+                    task.setTaskPlan(1);
+                }
+            }
 //            TimeType timeType = timeTypeMapper.selectById(user.getCompanyId());
 //            Integer taskFileCharge = timeType.getTaskFileCharge();
 //            if(1 == taskFileCharge){
@@ -304,7 +329,9 @@ public class TaskController {
                         Participation participation=new Participation();
                         participation.setUserId(executor.getExecutorId());
                         participation.setProjectId(task.getProjectId());
-                        participationMapper.insert(participation);
+                        if (participation.getProjectId()!=null) {
+                            participationMapper.insert(participation);
+                        }
                     }
                 }
             }
@@ -342,7 +369,7 @@ public class TaskController {
             if (task.getExecutorId() != null) {
                 msgRecepientList = task.getExecutorList().stream().filter(exe->!StringUtils.isEmpty(exe.getExecutorId())).map(TaskExecutor::getExecutorId).collect(Collectors.toList());
             }
-            if (task.getTaskType() == 1) {
+            if (task.getTaskType()!=null&&task.getTaskType() == 1) {
                 needRecalculateProgress = true;
             }
         } else {
@@ -444,8 +471,86 @@ public class TaskController {
             if ((oldTask.getTaskType() == 1 && task.getTaskType() != 1) || (oldTask.getTaskType() != 1 && task.getTaskType() == 1)) {
                 needRecalculateProgress = true;
             }
+            // 未驳回之前 第一审核人 修改工作计划
+            if (user.getCompanyId()==Constant.MLD_COMPANY_ID
+                    &&task.getIsTaskPlan()==1
+                    && org.apache.commons.lang3.StringUtils.isNotEmpty(task.getCheckFirstId())
+                    &&task.getCheckFirstId().equals(userId)
+                    &&task.getTaskStatus()==3){
+                isUpdate=1;
+                task.setTaskStatus(4);//待第二审核人审核
+            } else if (user.getCompanyId() == Constant.MLD_COMPANY_ID
+                    && task.getIsTaskPlan() == 1
+                    && org.apache.commons.lang3.StringUtils.isNotEmpty(task.getCheckSecondId())
+                    && task.getCheckSecondId().equals(userId)
+                    &&task.getTaskStatus()==4) {
+                isUpdate=2;
+                task.setTaskStatus(0);//变化为进行中
+                task.setIsTaskPlan(0);//不再是计划
+            }
+            // 驳回后,小组长对计划进行修改
+            if (user.getCompanyId()==Constant.MLD_COMPANY_ID
+                    &&task.getIsTaskPlan()==1
+                    &&(task.getTaskStatus()==5||task.getTaskStatus()==6)
+                    &&(!userId.equals(task.getCheckFirstId())&&!userId.equals(task.getCheckSecondId()))
+                    ){
+                isUpdate=3;
+                task.setTaskStatus(3);//待第一审核人审核
+            }
+        }
+        boolean saved = taskService.saveOrUpdate(task);
+        //新增成功,给第一审核人发送信息提醒
+        if (saved&&isInsert==1){
+            if (user.getCompanyId()==Constant.MLD_COMPANY_ID&&task.getIsTaskPlan()==1&& org.apache.commons.lang3.StringUtils.isNotEmpty(task.getCheckFirstId())){
+                //给第一审核人发送信息提醒
+                msgRecepientList=new ArrayList<>();
+                log.info("添加工作计划,给第一审核人发送信息提醒");
+                User owner = userMapper.selectById(task.getCheckFirstId());
+                Information information = new Information();
+                information.setMsg("您有工作计划待审核");
+                information.setType(11);
+                information.setUserId(owner.getId());
+                information.setTime(LocalDateTime.now());
+                informationService.save(information);
+            }
+        } else if (saved && isUpdate > 0) {
+            msgRecepientList=new ArrayList<>();
+            //第一审核人修改后, 变成待第二审核人审核
+            if (isUpdate==1){
+                User owner = userMapper.selectById(task.getCheckSecondId());
+                Information information = new Information();
+                information.setMsg("您有工作计划待审核");
+                information.setType(11);
+                information.setUserId(owner.getId());
+                information.setTime(LocalDateTime.now());
+                informationService.save(information);
+
+            }else if(isUpdate==2){
+                List<TaskExecutor> taskExecutorList = taskExecutorMapper.selectList(new QueryWrapper<TaskExecutor>().eq("task_id", task.getId()));
+                if(CollectionUtils.isNotEmpty(taskExecutorList)){
+                    for (TaskExecutor taskExecutor : taskExecutorList) {
+                        //给任务的执行人发送信息提醒
+                        User owner = userMapper.selectById(taskExecutor.getExecutorId());
+                        Information information = new Information();
+                        information.setMsg("您有新的任务");
+                        information.setType(1);
+                        information.setUserId(owner.getId());
+                        information.setTime(LocalDateTime.now());
+                        informationService.save(information);
+                    }
+                }
+            } else if (isUpdate==3) {
+                //给第一审核人发送信息提醒
+                log.info("驳回后小组长修改,给第一审核人发送信息提醒");
+                User owner = userMapper.selectById(task.getCheckFirstId());
+                Information information = new Information();
+                information.setType(11);
+                information.setMsg("您有工作计划待审核");
+                information.setUserId(owner.getId());
+                information.setTime(LocalDateTime.now());
+                informationService.save(information);
+            }
         }
-        taskService.saveOrUpdate(task);
         if (task.getExecutorId() == null) {
             //清空执行人
             if (!isNew) {
@@ -482,30 +587,32 @@ public class TaskController {
                 informationService.save(new Information().setType(1).setContent(String.valueOf(task.getProjectId())).setUserId(msgRecepient));
             });
             List<User> recpUserList = userMapper.selectList(new QueryWrapper<User>().in("id", msgRecepientList));
-            if (recpUserList.size() > 0) {
-                if (recpUserList.get(0).getDingdingUserid() != null) {
-                    //钉钉用户
-                    CompanyDingding dingding = companyDingdingService.getOne(new QueryWrapper<CompanyDingding>().eq("company_id", user.getCompanyId()));
-                    LocalDate endDate = task.getEndDate();
-                    String endStr = "";
-                    if (endDate != null) {
-                        endStr = DateTimeFormatter.ofPattern("yyyy-MM-dd").format(endDate);
+            if(user.getCompanyId()!=Constant.MLD_COMPANY_ID||task.getIsTaskPlan()!=1) {
+                if (recpUserList.size() > 0) {
+                    if (recpUserList.get(0).getDingdingUserid() != null) {
+                        //钉钉用户
+                        CompanyDingding dingding = companyDingdingService.getOne(new QueryWrapper<CompanyDingding>().eq("company_id", user.getCompanyId()));
+                        LocalDate endDate = task.getEndDate();
+                        String endStr = "";
+                        if (endDate != null) {
+                            endStr = DateTimeFormatter.ofPattern("yyyy-MM-dd").format(endDate);
+                        }
+                        companyDingdingService.sendNewTaskMsg(dingding, recpUserList.stream().map(User::getDingdingUserid).collect(Collectors.joining(",")),
+                                task.getName(), endStr);
+                    } else if (recpUserList.get(0).getCorpwxUserid() != null) {
+                        String corpUid = recpUserList.stream().map(User::getCorpwxUserid).distinct().collect(Collectors.joining("|"));
+                        JSONObject json = new JSONObject();
+                        JSONArray dataJson = new JSONArray();
+                        JSONObject jsonObj = new JSONObject();
+                        jsonObj.put("key", "任务内容");
+                        jsonObj.put("value", task.getName());
+                        dataJson.add(jsonObj);
+                        json.put("template_id", "tty9TkCAAAovv416zsWtn0e06CJ635HA");
+                        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=task#wechat_redirect");
+                        json.put("content_item", dataJson);
+                        //todo:发送消息提醒任务
+                        wxCorpInfoService.sendWXCorpTemplateMsg(wxCorpInfo, corpUid, json);
                     }
-                    companyDingdingService.sendNewTaskMsg(dingding, recpUserList.stream().map(User::getDingdingUserid).collect(Collectors.joining(",")),
-                            task.getName(), endStr);
-                } else if (recpUserList.get(0).getCorpwxUserid() != null) {
-                    String corpUid = recpUserList.stream().map(User::getCorpwxUserid).distinct().collect(Collectors.joining("|"));
-                    JSONObject json=new JSONObject();
-                    JSONArray dataJson=new JSONArray();
-                    JSONObject jsonObj=new JSONObject();
-                    jsonObj.put("key", "任务内容");
-                    jsonObj.put("value",task.getName());
-                    dataJson.add(jsonObj);
-                    json.put("template_id","tty9TkCAAAovv416zsWtn0e06CJ635HA");
-                    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=task#wechat_redirect");
-                    json.put("content_item",dataJson);
-                    //todo:发送消息提醒任务
-                    wxCorpInfoService.sendWXCorpTemplateMsg(wxCorpInfo, corpUid, json);
                 }
             }
         }
@@ -759,6 +866,7 @@ public class TaskController {
             //已超期的任务,未完成的任务
             queryWrapper.lt("end_date", LocalDate.now()).eq("task_status", 0);
         }
+        queryWrapper.eq("is_task_plan",0);
         List<Task> list = taskService.simpleList(queryWrapper,start,size);
         int total = taskMapper.selectCount(queryWrapper);
         //没有权限只能看到自己创建的,负责的和待分配的任务
@@ -920,6 +1028,7 @@ public class TaskController {
                     if(first.isPresent()){
                         e.setServiceName(first.get().getServiceName());
                         e.setServiceCode(first.get().getServiceCode());
+                        e.setId(first.get().getId());
                     }
                 }
             });
@@ -930,6 +1039,7 @@ public class TaskController {
                     if(first.isPresent()){
                         e.setServiceName(first.get().getServiceName());
                         e.setServiceCode(first.get().getServiceCode());
+                        e.setId(first.get().getId());
                     }
                 }
             });
@@ -947,45 +1057,47 @@ public class TaskController {
             userList = userMapper.selectList(new QueryWrapper<User>().select("id, name, phone, job_number, department_id, is_active").eq("company_id", user.getCompanyId()).eq("is_active", 1));
         }
         t.setUserList(userList);
-        //查询项目负责人id以及所属任务分组负责人id
-        Project project = projectService.getOne(new QueryWrapper<Project>().eq("id", t.getProjectId()));
-        TaskGroup group = taskGroupService.getOne(new QueryWrapper<TaskGroup>().eq("id", t.getGroupId()));
-        t.setProjectInchargerId(project.getInchargerId()==null?"":project.getInchargerId());
-        t.setGroupInchargerId(group.getInchargerId()==null?"":group.getInchargerId());
-        //判断当前用户是否有权限创建任务: 有权限的包括管理全部项目,项目创建人,项目PM, 分组负责人,分组参与人
-        List<SysRichFunction> manageAllProjects = sysFunctionMapper.getRoleFunctions(user.getRoleId(), "管理全部项目");
-        boolean canAddTask = false;
-        Integer companyId = user.getCompanyId();
-        TaskAddCtrl taskAddCtrl = taskAddCtrlMapper.selectById(companyId);
-        if (taskAddCtrl == null) {
-            //没有的话,默认生成一个
-            taskAddCtrl = new TaskAddCtrl();
-            taskAddCtrl.setCompanyId(companyId);
-            taskAddCtrl.setCtrlType(1);//0-普通项目参与人不可添加任务,1-项目参与人可添加,2-仅分组参与人可添加
-            taskAddCtrlMapper.insert(taskAddCtrl);
-        }
-        if (manageAllProjects.size() > 0 || userId.equals(project.getCreatorId()) || userId.equals(project.getInchargerId())) {
-            canAddTask = true;
-        }
-        if (!canAddTask) {
-            //进一步判断是否是分组的负责人,参与人
-            if (userId.equals(group.getInchargerId())) {
+        if (t.getTaskPlanType()==null||t.getTaskPlanType()!=3) {
+            //查询项目负责人id以及所属任务分组负责人id
+            Project project = projectService.getOne(new QueryWrapper<Project>().eq("id", t.getProjectId()));
+            TaskGroup group = taskGroupService.getOne(new QueryWrapper<TaskGroup>().eq("id", t.getGroupId()));
+            t.setProjectInchargerId(project.getInchargerId() == null ? "" : project.getInchargerId());
+            t.setGroupInchargerId(group.getInchargerId() == null ? "" : group.getInchargerId());
+            //判断当前用户是否有权限创建任务: 有权限的包括管理全部项目,项目创建人,项目PM, 分组负责人,分组参与人
+            List<SysRichFunction> manageAllProjects = sysFunctionMapper.getRoleFunctions(user.getRoleId(), "管理全部项目");
+            boolean canAddTask = false;
+            Integer companyId = user.getCompanyId();
+            TaskAddCtrl taskAddCtrl = taskAddCtrlMapper.selectById(companyId);
+            if (taskAddCtrl == null) {
+                //没有的话,默认生成一个
+                taskAddCtrl = new TaskAddCtrl();
+                taskAddCtrl.setCompanyId(companyId);
+                taskAddCtrl.setCtrlType(1);//0-普通项目参与人不可添加任务,1-项目参与人可添加,2-仅分组参与人可添加
+                taskAddCtrlMapper.insert(taskAddCtrl);
+            }
+            if (manageAllProjects.size() > 0 || userId.equals(project.getCreatorId()) || userId.equals(project.getInchargerId())) {
                 canAddTask = true;
             }
             if (!canAddTask) {
-                Integer ctrlType = taskAddCtrl.getCtrlType();
-                if (ctrlType == 1) {
+                //进一步判断是否是分组的负责人,参与人
+                if (userId.equals(group.getInchargerId())) {
                     canAddTask = true;
-                } else if (ctrlType == 2) {
-                    //分组参与人可以创建任务
-                    int count = groupParticipatorMapper.selectCount(new QueryWrapper<GroupParticipator>().eq("user_id", userId).eq("group_id", group.getId()));
-                    if (count > 0) {
+                }
+                if (!canAddTask) {
+                    Integer ctrlType = taskAddCtrl.getCtrlType();
+                    if (ctrlType == 1) {
                         canAddTask = true;
+                    } else if (ctrlType == 2) {
+                        //分组参与人可以创建任务
+                        int count = groupParticipatorMapper.selectCount(new QueryWrapper<GroupParticipator>().eq("user_id", userId).eq("group_id", group.getId()));
+                        if (count > 0) {
+                            canAddTask = true;
+                        }
                     }
                 }
             }
+            t.setCanAddTask(canAddTask);
         }
-        t.setCanAddTask(canAddTask);
         msg.data = t;
         return msg;
     }
@@ -1410,6 +1522,10 @@ public class TaskController {
         if(pageIndex!=null&&pageSize!=null){
             pageStart = (pageIndex - 1) * pageSize;
         }
+        if (companyId==Constant.MLD_COMPANY_ID){
+            //美莱德 任务计划状态是1
+            queryWrapper.ne("is_task_plan",1);
+        }
         List<Task> list = taskMapper.getTaskWithProjectName(queryWrapper,pageStart, pageSize,companyId,branchDepartment);
         List<Integer> collect = list.stream().map(l -> l.getId()).distinct().collect(Collectors.toList());
         collect.add(-1);
@@ -1759,5 +1875,13 @@ public class TaskController {
     }
 
 
+    //工作计划的通过或者驳回
+    //通过 type=true ,驳回 type=false
+    @RequestMapping("/taskPlanPassOrReject")
+    public HttpRespMsg taskPlanPassOrReject(Integer taskId, boolean type){
+        return taskService.taskPlanPassOrReject(taskId,type,request);
+    }
+
+
 }
 

+ 18 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/UserController.java

@@ -174,12 +174,30 @@ public class UserController {
     public HttpRespMsg getFirstCheckUserList() {
         return userService.getFirstCheckUserList(request);
     }
+    @RequestMapping("/getChargeUserByProjectId")
+    public HttpRespMsg getChargeUserByProjectId(Integer projectId){
+        return userService.getChargeUserByProjectId(projectId,request);
+    }
 
+    /**
+     * mld工作计划二级审核人
+     * @return
+     */
     @RequestMapping("/getSecondCheckUser")
     public HttpRespMsg getSecondCheckUser() {
         return userService.getSecondCheckUserList(request);
     }
 
+    /**
+     *获取项目参与者信息
+     * @param projectId
+     * @return
+     */
+    @RequestMapping("/getUserByProject")
+    public HttpRespMsg getUserByProject(Integer projectId) {
+        return userService.getUserByProject(projectId,request);
+    }
+
     @RequestMapping("/getSimpleActiveUserListPage")
     public HttpRespMsg getSimpleActiveUserListPage(@RequestParam Integer pageIndex, @RequestParam Integer pageSize,Integer departmentId,String keyword,String cursor,@RequestParam(required = false) String userIds) throws Exception {
         return userService.getSimpleActiveUserListPage(pageIndex,pageSize,departmentId,request,keyword,cursor,userIds);

+ 37 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/ErpOrderInfo.java

@@ -0,0 +1,37 @@
+package com.management.platform.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.extension.activerecord.Model;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+public class ErpOrderInfo extends Model<ErpOrderInfo> {
+    private static final long serialVersionUID=1L;
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Integer id;
+
+    @TableField("order_id")
+    private String orderId;
+
+    @TableField("project_id")
+    private String projectId;
+
+    @TableField("project_name")
+    private String projectName;
+
+    @TableField("line")
+    private Integer line;
+
+    @TableField("status")
+    private Integer status;
+
+    @TableField("moDId")
+    private String MoDId;
+}

+ 4 - 1
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/Task.java

@@ -85,7 +85,7 @@ public class Task extends Model<Task> {
     private Integer taskLevel;
 
     /**
-     * 任务状态,0-进行中 1-已完成 2-已撤销 3-待第一审核人审核 4-待第二审核人审核 5-驳回
+     * 任务状态,0-进行中 1-已完成 2-已撤销 3-待第一审核人审核 4-待第二审核人审核 5-第一审核人驳回  6-第二审核人驳回
      */
     @TableField("task_status")
     private Integer taskStatus;
@@ -225,6 +225,9 @@ public class Task extends Model<Task> {
     @TableField("is_task_plan")
     private Integer isTaskPlan;
 
+    @TableField("task_plan")
+    private Integer taskPlan;
+
     /**
      * 任务计划第一审核人id
      */

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

@@ -54,6 +54,12 @@ public class UserFvTime extends Model<UserFvTime> {
 //    @TableField("overtime_hours")
 //    private Float overTimeHours;
 
+    @TableField("overtime_seconds")
+    private Long overTimeSeconds;
+
+    @TableField("procinst_id")
+    private String procinstId;
+
     /**
      * 是否被标记排除异常范围
      */

+ 10 - 1
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/vo/GanttDataItem.java

@@ -1,9 +1,10 @@
 package com.management.platform.entity.vo;
 
+
 import lombok.Data;
 
 import java.util.List;
-import java.util.logging.Level;
+
 
 @Data
 public class GanttDataItem {
@@ -24,4 +25,12 @@ public class GanttDataItem {
     public Integer level;
     public List<GanttDataItem> children;
     public Integer objType;//对象类型:0是人员,1是部门,2是项目
+    private Integer taskPlanType;
+    private Integer isTaskPlan;
+    private String checkFirstId;
+    private String checkSecondId;
+    private Integer taskStatus;
+    private Integer taskId;
+    private Integer leaderOrManager;
+    private Integer taskPlan;
 }

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

@@ -16,8 +16,8 @@ public class UserVO extends User {
     private Long remainingTime;
     //是否是项目经理
     private boolean isLeader;
-    //是否是项目小组长
-    private boolean isProjectLeader;
+    // 组员0, 小组长1,审核人2
+    private int projectLeaderType;
     private Company company;
 
     //模块菜单的访问权限

+ 5 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/mapper/BusinessTripMapper.java

@@ -2,6 +2,7 @@ package com.management.platform.mapper;
 
 import com.management.platform.entity.BusinessTrip;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Param;
 
 import java.util.List;
 import java.util.Map;
@@ -19,4 +20,8 @@ public interface BusinessTripMapper extends BaseMapper<BusinessTrip> {
     public List<BusinessTrip> summaryData(String keyword, String startDate, String endDate, Integer companyId);
 
     List<Map<String,Object>> selectBusiness(String startDate, String endDate,String deptId);
+
+    void batchInsert(@Param("resList") List<BusinessTrip> resList);
+
+    List<String> getExistIds(@Param("procinstIds") List<String> procinstIds);
 }

+ 15 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/mapper/ErpOrderInfoMapper.java

@@ -0,0 +1,15 @@
+package com.management.platform.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.management.platform.entity.ErpOrderInfo;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+@Mapper
+public interface ErpOrderInfoMapper extends BaseMapper<ErpOrderInfo> {
+    void batchInsert(@Param("resList") List<ErpOrderInfo> resList);
+
+    List<String> getExistIds(@Param("moIds") List<String> moIds);
+}

+ 4 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/mapper/LeaveSheetMapper.java

@@ -27,4 +27,8 @@ public interface LeaveSheetMapper extends BaseMapper<LeaveSheet> {
     List<Map<String,Object>> selectLeaveAll(Integer companyId, String startDate, String endDate,List<Integer> branchDepartment,List<Integer> deptIds);
 
     List<UserRestTimeVO> getCompanyUserRestTimeHours(@Param("companyId") Integer companyId,@Param("userId")String userId);
+
+    void batchInsert(@Param("resList") List<LeaveSheet> resList);
+
+    List<String> getExistIds(@Param("procinstIds") List<String> procinstIds);
 }

+ 29 - 1
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/mapper/ProjectMapper.java

@@ -72,7 +72,28 @@ public interface ProjectMapper extends BaseMapper<Project> {
                                     @Param("endDate") String endDate, @Param("companyId") Integer companyId);
 
     List<Map> getTaskPlanByProject(@Param("projectIds") List<Integer> projectIds, @Param("startDate") String startDate,
-                                @Param("endDate") String endDate, @Param("companyId") Integer companyId);
+                                @Param("endDate") String endDate, @Param("companyId") Integer companyId,@Param("groupName")String groupName,@Param("taskType")Integer taskType);
+    List<Map> getTaskPlanWithLeave(@Param("userIds") List<String> userIds, @Param("startDate") String startDate,
+                                   @Param("endDate") String endDate, @Param("companyId") Integer companyId,@Param("creatorId") String creatorId,@Param("targetUserId") String targetUserId);
+
+    List<Map> getTaskPlanByGeneralMemb(@Param("userIds") List<String> userIds, @Param("startDate") String startDate,
+                                @Param("endDate") String endDate, @Param("companyId") Integer companyId,@Param("creatorId") String creatorId,@Param("targetUserId") String targetUserId);
+
+    List<Map> getTaskPlanByProManager(@Param("userIds") List<String> userIds, @Param("startDate") String startDate,
+                                      @Param("endDate") String endDate, @Param("companyId") Integer companyId,@Param("managerId") String managerId,@Param("targetUserId") String targetUserId);
+    List<Map> getTaskPlanByAreaManager(@Param("userIds") List<String> userIds, @Param("startDate") String startDate,
+                                      @Param("endDate") String endDate, @Param("companyId") Integer companyId,@Param("managerId") String managerId,@Param("targetUserId") String targetUserId);
+
+    List<Map> getTaskPlanByProjectGeneralMemb(@Param("projectIds") List<Integer> projectIds, @Param("startDate") String startDate,
+                                   @Param("endDate") String endDate, @Param("companyId") Integer companyId,@Param("creatorId") String creatorId,
+                                              @Param("groupName")String groupName,@Param("taskType")Integer taskType,@Param("targetProjectId")Integer targetProjectId);
+
+    List<Map> getTaskPlanByProjectManager(@Param("projectIds") List<Integer> projectIds, @Param("startDate") String startDate,
+                                              @Param("endDate") String endDate, @Param("companyId") Integer companyId,@Param("managerId") String managerId,
+                                          @Param("groupName")String groupName,@Param("taskType")Integer taskType,@Param("targetProjectId")Integer targetProjectId);
+    List<Map> getTaskPlanByProjectAreaManager(@Param("projectIds") List<Integer> projectIds, @Param("startDate") String startDate,
+                                          @Param("endDate") String endDate, @Param("companyId") Integer companyId,@Param("managerId") String managerId,
+                                              @Param("groupName")String groupName,@Param("taskType")Integer taskType,@Param("targetProjectId")Integer targetProjectId);
 
     List<ProjectWithStage> selectWithStage(Integer companyId, Integer startIndex, Integer endIndex, Integer projectId,String inchargerId,String startDate,String endDate);
 
@@ -238,4 +259,11 @@ public interface ProjectMapper extends BaseMapper<Project> {
     List<Map<String, Object>> getParticipatedProjectWithMainProjectId(@Param("userId") String userId, @Param("companyId") Integer companyId,@Param("projectMainId") Integer projectMainId);
 
     int getProjectInAndOutTotal(Integer companyId, Integer projectId, List<Integer> inchagerIds,Integer projectMainId);
+
+    List<Map<String, Object>> getFTETaskPlanData(Integer companyId, String startDate, String endDate, Integer start, Integer size, String area,String userId,String sortProp, Integer sortOrder, List<Integer> branchDepartment, List<Integer> deptIds,Integer departmentId);
+
+    public List<Integer> getRelatedProjectIds(@Param("userId")String userId,@Param("companyId") Integer companyId);
+
+
+
 }

+ 4 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/mapper/UserFvTimeMapper.java

@@ -17,4 +17,8 @@ import java.util.List;
 public interface UserFvTimeMapper extends BaseMapper<UserFvTime> {
 
     void batchInsert(@Param("toAddList") List<UserFvTime> toAddList);
+
+    void batchInsertCollect(@Param("resList") List<UserFvTime> resList);
+
+    List<String> getExistIds(@Param("procinstIds") List<String> procinstIds);
 }

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

@@ -324,4 +324,10 @@ public interface ProjectService extends IService<Project> {
     HttpRespMsg exportProjectTaskPlanAndRealCost(Integer projectId, HttpServletRequest request, Integer taskType);
 
     HttpRespMsg transferProjectReviwer(String userId, String targetAuditorId);
+
+    HttpRespMsg getProjectByLeader(Integer projectId, HttpServletRequest request);
+
+    HttpRespMsg getProjectTaskPlanFTEData(Integer pageIndex, Integer pageSize, String monthStart, String monthEnd, String area, String userId, String sortProp, Integer sortOrder, Integer departmentId, HttpServletRequest request);
+
+    HttpRespMsg exportTaskPlanFTEData(String monthStart, String monthEnd, String area, String userId, Integer departmentId, HttpServletRequest request);
 }

+ 2 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/TaskService.java

@@ -64,4 +64,6 @@ public interface TaskService extends IService<Task> {
     HttpRespMsg getOtherTaskChargePage(QueryTaskChargePage queryBO, HttpServletRequest request);
 
     HttpRespMsg sendMsgToChargers(String ids, HttpServletRequest request);
+
+    HttpRespMsg taskPlanPassOrReject(Integer taskId,boolean type, HttpServletRequest request);
 }

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

@@ -118,4 +118,8 @@ public interface UserService extends IService<User> {
     HttpRespMsg getFirstCheckUserList(HttpServletRequest request);
 
     HttpRespMsg getSecondCheckUserList(HttpServletRequest request);
+
+    HttpRespMsg getUserByProject(Integer projectId, HttpServletRequest request);
+
+    HttpRespMsg getChargeUserByProjectId(Integer projectId, HttpServletRequest request);
 }

+ 313 - 13
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ProjectServiceImpl.java

@@ -1236,6 +1236,29 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
         return msg;
     }
 
+    @Override
+    public HttpRespMsg getProjectByLeader(Integer projectId, HttpServletRequest request) {
+        HttpRespMsg httpRespMsg = new HttpRespMsg();
+        User user = userMapper.selectById(request.getHeader("Token"));
+        Integer companyId = user.getCompanyId();
+        List<ProjectLeader> leaderList = projectLeaderService.list(new QueryWrapper<ProjectLeader>()
+                .eq("company_id", companyId).eq("leader_id", user.getId()));
+        List<Integer> projectIds=new ArrayList<>();
+        projectIds= leaderList.stream().map(ProjectLeader::getProjectId).distinct().collect(Collectors.toList());
+        projectIds.add(-1);
+
+        if (projectId!=null) {
+            boolean b = projectIds.stream().anyMatch(p -> p.equals(projectId));
+            if (!b) {
+                projectIds.add(projectId);
+            }
+        }
+        List<Project> projectList = projectMapper.selectList(new QueryWrapper<Project>()
+                .in("id", projectIds).eq("status",1));
+        httpRespMsg.setData(projectList);
+        return httpRespMsg;
+    }
+
     public HttpRespMsg getProjectEstimatedWork(Integer pageIndex, Integer pageSize, Integer projectId, HttpServletRequest request) {
         HttpRespMsg httpRespMsg = new HttpRespMsg();
         //通过公司id获取该公司所有的项目列表
@@ -4741,7 +4764,9 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
         //根据人员权限来获取,
         String token = request.getHeader("TOKEN");
         User user = userMapper.selectById(token);
+
         List<String> userIds = new ArrayList<>();
+        List<String> userIdsExtra = new ArrayList<>();
         List<SysRichFunction> functionList = sysFunctionMapper.getRoleFunctions(user.getRoleId(), "查看全部项目");
         List<Department> departmentList = departmentMapper.selectList(new QueryWrapper<Department>().eq("company_id", user.getCompanyId()));
         List<User> AllUser = userMapper.selectList(new QueryWrapper<User>().eq("company_id", user.getCompanyId()));
@@ -4782,6 +4807,7 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
         } else {
             if (functionList.size() == 0) {
                 //普通员工只看自己相关的
+                userIds.add("-1");
                 List<Participation> participationList
                         = participationMapper.selectList(new QueryWrapper<Participation>().in("user_id", userIds));
                 projectIds = participationList.stream().map(Participation::getProjectId).collect(Collectors.toList());
@@ -4796,6 +4822,59 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
                 String btLastItemId = null;
                 //按人员获取
                 ganttData = projectMapper.getTaskPlanByMemb(userIds, startDate ,endDate, user.getCompanyId());
+                if (user.getCompanyId()==Constant.MLD_COMPANY_ID){
+                    List<ProjectLeader> leaderList = projectLeaderService.list(new QueryWrapper<ProjectLeader>().eq("leader_id", user.getId()).eq("company_id", user.getCompanyId()));
+                    //是小组长
+                    if (!leaderList.isEmpty()){
+                        List<Integer> projectIdList = leaderList.stream().map(ProjectLeader::getProjectId).collect(Collectors.toList());
+                        projectIdList.add(-1);
+                        List<Participation> participations = participationMapper.selectList(new QueryWrapper<Participation>().in("project_id", projectIdList));
+                        List<String> userProjectIds = participations.stream().distinct().map(Participation::getUserId).collect(Collectors.toList());
+                        userProjectIds.removeAll(userIds);
+                        userProjectIds.add("-1");
+                        userIdsExtra.addAll(userProjectIds);
+                        List<Map> taskPlanByGeneralMemb = projectMapper.getTaskPlanByGeneralMemb(userProjectIds, startDate, endDate, user.getCompanyId(), user.getId(),targetUserId);
+                        for (Map map : taskPlanByGeneralMemb) {
+                            map.put("leaderOrManager",1);
+                        }
+                        List<Map> taskPlanWithLeave = projectMapper.getTaskPlanWithLeave(null, startDate, endDate, user.getCompanyId(), user.getId(), targetUserId);
+                        for (Map map : taskPlanWithLeave) {
+                            map.put("leaderOrManager",1);
+                        }
+                        ganttData.addAll(taskPlanByGeneralMemb);
+                        ganttData.addAll(taskPlanWithLeave);
+                    }
+                    //找到自己担任项目经理的项目,: is_task_plan==1 ,checkFirstId=自己的id 并且 task_status=3
+                    List<Project> projectList = projectMapper.selectList(new QueryWrapper<Project>().eq("incharger_id", user.getId()));
+                    if (!projectList.isEmpty()){
+                        List<Integer> projectIdList = projectList.stream().map(Project::getId).collect(Collectors.toList());
+                        projectIdList.add(-1);
+                        List<TaskExecutor> executorList = taskExecutorService.list(new QueryWrapper<TaskExecutor>().in("project_id", projectIdList).isNotNull("executor_id"));
+                        List<String> collectUserIdList = executorList.stream().distinct().map(TaskExecutor::getExecutorId).collect(Collectors.toList());
+                        collectUserIdList.add("-1");
+                        userIdsExtra.addAll(collectUserIdList);
+                        List<Map> getTaskPlanByProManager = projectMapper.getTaskPlanByProManager(collectUserIdList, startDate, endDate, user.getCompanyId(),user.getId(),targetUserId);
+                        for (Map map : getTaskPlanByProManager) {
+                            map.put("leaderOrManager",2);
+                        }
+                        ganttData.addAll(getTaskPlanByProManager);
+                    }
+
+                    if (user.getRoleName().equals("区域经理&PM")){
+                        List<Task> taskList = taskService.list(new QueryWrapper<Task>().eq("check_second_id", user.getId()));
+                        List<Integer> taskIdList = taskList.stream().map(Task::getId).collect(Collectors.toList());
+                        taskIdList.add(-1);
+                        List<TaskExecutor> executorList = taskExecutorService.list(new QueryWrapper<TaskExecutor>().in("task_id", taskIdList).isNotNull("executor_id"));
+                        List<String> collectUserIdList = executorList.stream().distinct().map(TaskExecutor::getExecutorId).collect(Collectors.toList());
+                        collectUserIdList.add("-1");
+                        userIdsExtra.addAll(collectUserIdList);
+                        List<Map> getTaskPlanByProManager = projectMapper.getTaskPlanByAreaManager(collectUserIdList, startDate, endDate, user.getCompanyId(),user.getId(),targetUserId);
+                        for (Map map : getTaskPlanByProManager) {
+                            map.put("leaderOrManager",2);
+                        }
+                        ganttData.addAll(getTaskPlanByProManager);
+                    }
+                }
                 QueryWrapper<LeaveSheet> lsQueryWrapper=new QueryWrapper();
                 lsQueryWrapper.in("owner_id", userIds);
                 if (startDate != null && endDate != null) {
@@ -4839,6 +4918,7 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
                         extraUidList.add(uid);
                     }
                 }
+                extraUidList.addAll(userIdsExtra);
                 if (extraUidList.size() > 0) {
                     List<User> userList = userMapper.selectList(new QueryWrapper<User>().in("id", extraUidList).eq("is_active", 1));
                     for (User u : userList) {
@@ -4867,7 +4947,6 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
                         if(first.isPresent()){
                             departmentId=first.get().getDepartmentId();
                         }
-                        System.out.println("====================="+departmentId+"======================");
                         GanttDataItem parent = new GanttDataItem();
                         parent.id = leaveSheetList.get(i).getOwnerId();
                         parent.userId = leaveSheetList.get(i).getOwnerId();
@@ -4954,6 +5033,7 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
                     itemList.add(curItem);
                     btLastItemId = businessTripList.get(i).getOwnerId();
                 }
+
             }
             else {
                 //按照项目获取
@@ -4983,7 +5063,40 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
                         }
                     }
                 }
-                ganttData = projectMapper.getTaskPlanByProject(projectIds, startDate ,endDate, user.getCompanyId());
+                ganttData = projectMapper.getTaskPlanByProject(projectIds, startDate ,endDate, user.getCompanyId(),groupName,taskType);
+                System.out.println("ganttData1:"+ganttData.size());
+                if (user.getCompanyId()==Constant.MLD_COMPANY_ID){
+                    List<ProjectLeader> leaderList = projectLeaderService.list(new QueryWrapper<ProjectLeader>().eq("leader_id", user.getId()).eq("company_id", user.getCompanyId()));
+                    //是小组长
+                    if (!leaderList.isEmpty()){
+                        List<Integer> projectIdList = leaderList.stream().map(ProjectLeader::getProjectId).collect(Collectors.toList());
+                        projectIdList.add(-1);
+                        List<Map> taskPlanByGeneralMemb = projectMapper.getTaskPlanByProjectGeneralMemb(projectIdList,startDate ,endDate, user.getCompanyId(),user.getId(),groupName,taskType,targetProjectId);
+                        System.out.println("ganttData2:"+taskPlanByGeneralMemb.size());
+                        ganttData.addAll(taskPlanByGeneralMemb);
+                    }
+                    //找到自己担任项目经理的项目,: is_task_plan==1 ,checkFirstId=自己的id 并且 task_status=3
+                    List<Project> projectList = projectMapper.selectList(new QueryWrapper<Project>().eq("incharger_id", user.getId()));
+                    if (!projectList.isEmpty()){
+                        List<Integer> projectIdList = projectList.stream().map(Project::getId).collect(Collectors.toList());
+                        projectIdList.add(-1);
+                        List<Map> taskPlanByProjectManager = projectMapper.getTaskPlanByProjectManager(projectIdList,startDate ,endDate, user.getCompanyId(),user.getId(),groupName,taskType,targetProjectId);
+                        System.out.println("ganttData2:"+taskPlanByProjectManager.size());
+                        ganttData.addAll(taskPlanByProjectManager);
+                    }
+
+                    if (user.getRoleName().equals("区域经理&PM")){
+                        List<Task> taskList = taskService.list(new QueryWrapper<Task>().eq("check_second_id", user.getId()));
+                        List<Integer> taskIdList = taskList.stream().map(Task::getId).collect(Collectors.toList());
+                        taskIdList.add(-1);
+                        List<TaskExecutor> executorList = taskExecutorService.list(new QueryWrapper<TaskExecutor>().in("task_id", taskIdList).isNotNull("executor_id"));
+                        List<Integer> projectIdList = executorList.stream().distinct().map(TaskExecutor::getProjectId).collect(Collectors.toList());
+                        projectIdList.add(-1);
+                        List<Map> taskPlanByProjectAreaManager = projectMapper.getTaskPlanByProjectAreaManager(projectIdList, startDate, endDate, user.getCompanyId(),user.getId(),groupName,taskType,targetProjectId);
+                        System.out.println("ganttData2:"+taskPlanByProjectAreaManager.size());
+                        ganttData.addAll(taskPlanByProjectAreaManager);
+                    }
+                }
                 QueryWrapper<BusinessTrip> btQueryWrapper =new QueryWrapper<>();
                 QueryWrapper<BustripProject> bpQueryWrapper =new QueryWrapper<>();
                 btQueryWrapper.in("owner_id", userIds);
@@ -5039,7 +5152,7 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
                 }
             }
 
-            ganttData.forEach(System.out::println);
+//            ganttData.forEach(System.out::println);
             String lastItemId = null;
             GanttDataItem lastParentItem = null;
             SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
@@ -5056,7 +5169,6 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
                 String start_date = sdf.format((Date) map.get("start_date"));
                 String end_date = sdf.format((Date) map.get("end_date"));
                 String projectId = ""+ (Integer) map.get("id");
-                System.out.println(map);
                 //String exeId = "任务_"+map.get("task_id") +"_"+ (type==0?(Integer) map.get("exe_id"):userId);
                 String exeId = MessageUtils.message("excel.task") + "_"+map.get("task_id") +"_"+ (type==0?(Integer) map.get("exe_id"):userId);
                 String taskId = ""+ (Integer) map.get("task_id");
@@ -5082,16 +5194,29 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
 
                     curItem.id = exeId;
                     curItem.userId = (String) map.get("user_id");
-                    curItem.text = (String) map.get("project_name")+"/"+(String)map.get("task_name");
+                    if (map.get("taskPlanType")!=null&&(Integer)map.get("taskPlanType")==3){
+                        curItem.text ="请假";
+                    }else {
+                        curItem.text = (String) map.get("project_name")+"/"+(String)map.get("task_name");
+                        curItem.setCheckFirstId(map.get("checkFirstId")==null?null:(String) map.get("checkFirstId"));
+                        curItem.setCheckSecondId(map.get("checkSecondId")==null?null:(String) map.get("checkSecondId"));
+                    }
                     curItem.start_date = start_date;
 
+                    curItem.setTaskPlanType(map.get("taskPlanType")==null?null:(Integer)map.get("taskPlanType"));
+                    curItem.setIsTaskPlan(map.get("isTaskPlan")==null?null:(Integer)map.get("isTaskPlan"));
+                    curItem.setTaskStatus(map.get("taskStatus")==null?null:(Integer)map.get("taskStatus"));
+                    curItem.setTaskId(map.get("taskId")==null?null:(Integer)map.get("taskId"));
+                    curItem.setLeaderOrManager(map.get("leaderOrManager")==null?null:(Integer)map.get("leaderOrManager"));
+                    curItem.setTaskPlan(map.get("taskPlan")==null?null:(Integer)map.get("taskPlan"));
                     curItem.end_date = end_date;
                     curItem.time = (Integer)map.get("duration");
                     curItem.parent = lastItemId;
                     curItem.setObjType(2);
                     itemList.add(curItem);
                     lastItemId = userId;
-                } else {
+                }
+                else {
                     if (!projectId.equals(lastItemId)) {
                         //抽取父级对象,项目名称
                         GanttDataItem parent = new GanttDataItem();
@@ -5110,6 +5235,14 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
                     curItem.id = projectId+"_"+exeId;
                     curItem.userId = (String) map.get("user_id");
                     curItem.text = (String) map.get("name")+"/"+(String)map.get("task_name");
+                    curItem.setTaskPlanType(map.get("taskPlanType")==null?null:(Integer)map.get("taskPlanType"));
+                    curItem.setIsTaskPlan(map.get("isTaskPlan")==null?null:(Integer)map.get("isTaskPlan"));
+                    curItem.setCheckFirstId(map.get("checkFirstId")==null?null:(String) map.get("checkFirstId"));
+                    curItem.setCheckSecondId(map.get("checkSecondId")==null?null:(String) map.get("checkSecondId"));
+                    curItem.setTaskStatus(map.get("taskStatus")==null?null:(Integer)map.get("taskStatus"));
+                    curItem.setTaskId(map.get("taskId")==null?null:(Integer)map.get("taskId"));
+                    curItem.setLeaderOrManager(map.get("leaderOrManager")==null?null:(Integer)map.get("leaderOrManager"));
+                    curItem.setTaskPlan(map.get("taskPlan")==null?null:(Integer)map.get("taskPlan"));
                     curItem.start_date = start_date;
                     curItem.end_date = end_date;
                     curItem.time = (Integer)map.get("duration");
@@ -5130,7 +5263,6 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
         }
 
         msg.data = itemList;
-
         return msg;
     }
 
@@ -8623,16 +8755,24 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
             List<Project> projectList = projectMapper.selectList(
                     new QueryWrapper<Project>().eq("incharger_id", user.getId()).eq("status", 1));
             List<String> userIds = new ArrayList<>();
-            userIds.add("0");
-            if (projectList.size() > 0) {
-                List<Integer> proIds = projectList.stream().map(Project::getId).collect(Collectors.toList());
-                List<Participation> pList = participationMapper.selectList(new QueryWrapper<Participation>().in("project_id", proIds));
-                userIds = pList.stream().map(Participation::getUserId).collect(Collectors.toList());
+
+            List<Integer> proIds = projectList.stream().map(Project::getId).collect(Collectors.toList());
+            if (Constant.MLD_COMPANY_ID==user.getCompanyId()){
+                List<Integer> projectSelect =projectMapper.getRelatedProjectIds(user.getId(), user.getCompanyId());
+                proIds.addAll(projectSelect);
             }
+
+            proIds.add(-1);
+            List<Participation> pList = participationMapper.selectList(new QueryWrapper<Participation>().in("project_id", proIds));
+            userIds = pList.stream().map(Participation::getUserId).collect(Collectors.toList());
+
             QueryWrapper<User> queryWrapper = new QueryWrapper<User>();
             if (deptIds.size() > 0) {
+                deptIds.add(-1);
+                userIds.add("-1");
                 queryWrapper.in("department_id", deptIds).or().in("id", userIds);
             } else {
+                userIds.add("-1");
                 queryWrapper.in("id", userIds);
             }
 
@@ -12789,7 +12929,7 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
                         }
                     }
                 }
-                ganttData = projectMapper.getTaskPlanByProject(projectIds, startDate ,endDate, user.getCompanyId());
+                ganttData = projectMapper.getTaskPlanByProject(projectIds, startDate ,endDate, user.getCompanyId(),null,null);
                 QueryWrapper<BusinessTrip> btQueryWrapper =new QueryWrapper<>();
                 QueryWrapper<BustripProject> bpQueryWrapper =new QueryWrapper<>();
                 btQueryWrapper.in("owner_id", userIds);
@@ -13483,6 +13623,166 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
         return httpRespMsg;
     }
 
+    @Override
+    public HttpRespMsg getProjectTaskPlanFTEData(Integer pageIndex, Integer pageSize, String monthStart, String monthEnd, String area, String userId, String sortProp, Integer sortOrder, Integer departmentId, HttpServletRequest request) {
+        HttpRespMsg httpRespMsg =new HttpRespMsg();
+        User targetUser = userMapper.selectById(request.getHeader("token"));
+        List<SysRichFunction> functionAllList = sysFunctionMapper.getRoleFunctions(targetUser.getRoleId(), "全部部门FTE计划报表");
+        List<SysRichFunction> functionDeptList = sysFunctionMapper.getRoleFunctions(targetUser.getRoleId(), "负责部门FTE计划报表");
+        List<Integer> deptIds=null;
+        List<Department> allDepartmentList=departmentMapper.selectList(new QueryWrapper<Department>().eq("company_id",targetUser.getCompanyId()));
+        List<Department> userDepartmentList = departmentMapper.selectList(new QueryWrapper<Department>().eq("manager_id", targetUser.getId()).eq("company_id",targetUser.getCompanyId()));
+        List<DepartmentOtherManager> departmentOtherManagerList = departmentOtherManagerMapper.selectList(new QueryWrapper<DepartmentOtherManager>().eq("other_manager_id", targetUser.getId()));
+        //判断查看权限
+        if(functionAllList.size()==0){
+            deptIds=new ArrayList<>();
+            deptIds.add(-1);
+            if(functionDeptList.size()>0){
+                List<Integer> collect = userDepartmentList.stream().map(dm -> dm.getDepartmentId()).distinct().collect(Collectors.toList());
+                List<Integer> otherCollect = departmentOtherManagerList.stream().map(dom -> dom.getDepartmentId()).distinct().collect(Collectors.toList());
+                collect.addAll(otherCollect);
+                //将该用户管理的所有部门以及部门的子部门id添加到deptIds集合中
+                for (Integer integer : collect) {
+                    List<Integer> branchDepartment = getBranchDepartment(integer, allDepartmentList);
+                    deptIds.addAll(branchDepartment);
+                }
+            }
+        }
+        if(departmentId!=null){
+            deptIds=new ArrayList<>();
+            List<Integer> branchDepartment = getBranchDepartment(departmentId, allDepartmentList);
+            deptIds.addAll(branchDepartment);
+        }
+        long total  = 0;
+        List<Map<String,Object>> resultList = null;
+        String startDate = null;
+        String endDate = null;
+        LocalDate timeStart = LocalDate.parse(monthStart, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
+        LocalDate timeEnd = LocalDate.parse(monthEnd, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
+        startDate = timeStart.with(TemporalAdjusters.firstDayOfMonth()).toString();
+        endDate = timeEnd.with(TemporalAdjusters.lastDayOfMonth()).toString();
+        int days = WorkDayCalculateUtils.getWorkDaysListInRange(startDate, endDate, 0).size();
+        TimeType allDay = timeTypeMapper.selectOne(new QueryWrapper<TimeType>().eq("company_id", targetUser.getCompanyId()));
+        Float monthTime = days * allDay.getAllday();
+        if(pageIndex!=null&&pageSize!=null){
+            Integer size=pageSize;
+            Integer start=(pageIndex-1)*size;
+            resultList=projectMapper.getFTETaskPlanData(targetUser.getCompanyId(),startDate,endDate,start,size,area,userId,sortProp,sortOrder,null,deptIds,departmentId);
+            total=projectMapper.getFTETaskPlanData(targetUser.getCompanyId(),startDate,endDate,null,null,area,userId,sortProp,sortOrder,null,deptIds,departmentId).size();
+        }else{
+            resultList=projectMapper.getFTETaskPlanData(targetUser.getCompanyId(),startDate,endDate,null,null,area,userId,sortProp,sortOrder,null,deptIds,departmentId);
+        }
+
+
+        //计算日期区间一共几个月
+        Period period = Period.between(timeStart, timeEnd);
+        for (Map<String, Object> map : resultList) {
+            Float planHours = Float.parseFloat( map.get("planHours").toString());
+            map.put("FTE",Float.parseFloat(planHours == null?"0":planHours.toString())/monthTime);
+
+        }
+        WxCorpInfo wxCorpInfo = wxCorpInfoMapper.selectOne(new QueryWrapper<WxCorpInfo>().eq("company_id", targetUser.getCompanyId()));
+        if (wxCorpInfo != null && wxCorpInfo.getSaasSyncContact().equals(1)){
+            for (Map<String, Object> map : resultList) {
+                map.put("userName",map.get("wxUserId"));
+                map.put("corpwx_userid","$userName=" + map.get("wxUserId") + "$");
+            }
+        }
+        HashMap<String, Object> map = new HashMap<>();
+        map.put("resultList",resultList);
+        map.put("total",total);
+        map.put("monthTime",monthTime);
+        httpRespMsg.data = map;
+        return httpRespMsg;
+    }
+
+    @Override
+    public HttpRespMsg exportTaskPlanFTEData(String monthStart, String monthEnd, String area,String userId, Integer departmentId, HttpServletRequest request) {
+        HttpRespMsg httpRespMsg = new HttpRespMsg();
+        User user = userMapper.selectById(request.getHeader("token"));
+        WxCorpInfo wxCorpInfo = wxCorpInfoMapper.selectOne(new QueryWrapper<WxCorpInfo>().eq("company_id", user.getCompanyId()));
+        CompanyDingding dingding = companyDingdingMapper.selectOne(new QueryWrapper<CompanyDingding>().eq("company_id", user.getCompanyId()));
+        List<UserCustom> userCustoms = userCustomMapper.selectList(new QueryWrapper<UserCustom>().eq("company_id", user.getCompanyId()).orderByAsc("id"));
+        List<SysRichFunction> functionAllList = sysFunctionMapper.getRoleFunctions(user.getRoleId(), "全部部门FTE计划报表");
+        List<SysRichFunction> functionDeptList = sysFunctionMapper.getRoleFunctions(user.getRoleId(), "负责部门FTE计划报表");
+        List<Integer> deptIds=null;
+        List<Department> allDepartmentList=departmentMapper.selectList(new QueryWrapper<Department>().eq("company_id",user.getCompanyId()));
+        List<Department> userDepartmentList = departmentMapper.selectList(new QueryWrapper<Department>().eq("manager_id", user.getId()).eq("company_id",user.getCompanyId()));
+        List<DepartmentOtherManager> departmentOtherManagerList = departmentOtherManagerMapper.selectList(new QueryWrapper<DepartmentOtherManager>().eq("other_manager_id", user.getId()));
+        //判断查看权限
+        if(functionAllList.size()==0){
+            deptIds=new ArrayList<>();
+            deptIds.add(-1);
+            if(functionDeptList.size()>0){
+                List<Integer> collect = userDepartmentList.stream().map(dm -> dm.getDepartmentId()).distinct().collect(Collectors.toList());
+                List<Integer> otherCollect = departmentOtherManagerList.stream().map(dom -> dom.getDepartmentId()).distinct().collect(Collectors.toList());
+                collect.addAll(otherCollect);
+                //将该用户管理的所有部门以及部门的子部门id添加到deptIds集合中
+                for (Integer integer : collect) {
+                    List<Integer> branchDepartment = getBranchDepartment(integer, allDepartmentList);
+                    deptIds.addAll(branchDepartment);
+                }
+            }
+        }
+        if(departmentId!=null){
+            deptIds=new ArrayList<>();
+            List<Integer> branchDepartment = getBranchDepartment(departmentId, allDepartmentList);
+            deptIds.addAll(branchDepartment);
+        }
+        String startDate = null;
+        String endDate = null;
+        LocalDate timeStart = LocalDate.parse(monthStart, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
+        LocalDate timeEnd = LocalDate.parse(monthEnd, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
+        startDate = timeStart.with(TemporalAdjusters.firstDayOfMonth()).toString();
+        endDate = timeEnd.with(TemporalAdjusters.lastDayOfMonth()).toString();
+        int days = WorkDayCalculateUtils.getWorkDaysListInRange(startDate, endDate, 0).size();
+        TimeType allDay = timeTypeMapper.selectOne(new QueryWrapper<TimeType>().eq("company_id", user.getCompanyId()));
+        Float monthTime = days * allDay.getAllday();
+        List<Map<String, Object>> list = projectMapper.getFTETaskPlanData(user.getCompanyId(), startDate, endDate, null, null, area, userId, null, null, null, deptIds, departmentId);
+        List<List<String>> dataList=new ArrayList<>();
+        List<String> titleList=new ArrayList<>();
+        List<String> subtitle=new ArrayList<>();
+
+        titleList.add("序号");
+        titleList.add("岗位");
+        titleList.add("项目编号");
+        titleList.add("项目名称");
+        titleList.add("姓名");
+        titleList.add("计划工时(H)");
+        titleList.add("FTE(计划工时/当月计划工时基数)");
+        dataList.add(titleList);
+
+        for (int i = 0; i < list.size(); i++) {
+            List<String> item=new ArrayList<>();
+            item.add((i+1)+"");
+            item.add(list.get(i).get("area")==null?"":list.get(i).get("area").toString());
+            item.add(list.get(i).get("projectCode")==null?"":list.get(i).get("projectCode").toString());
+            item.add(list.get(i).get("projectName")==null?"":list.get(i).get("projectName").toString());
+            item.add(list.get(i).get("userName")==null?"":list.get(i).get("userName").toString());
+            item.add(list.get(i).get("planHours")==null?"": String.valueOf(new BigDecimal(list.get(i).get("planHours").toString()).setScale(2,BigDecimal.ROUND_HALF_UP)));
+            item.add(
+                    list.get(i).get("planHours") == null ? "" :
+                            new BigDecimal(list.get(i).get("planHours").toString())
+                                    .divide(
+                                            BigDecimal.valueOf(monthTime),
+                                            2,                  // 保留2位小数
+                                            RoundingMode.HALF_UP // 四舍五入
+                                    )
+                                    .toString()
+            );
+            dataList.add(item);
+        }
+
+        String fileName = "FTE计划报表"+System.currentTimeMillis();
+        try {
+            return excelExportService.exportGeneralExcelByTitleAndList(wxCorpInfo,dingding,fileName, dataList, path);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        httpRespMsg.data =  pathPrefix + fileName+".xlsx";
+        return httpRespMsg;
+    }
+
     //导出FTE报表数据
     @Override
     public HttpRespMsg exportFTEData(String monthStart,String monthEnd, String area,Integer departmentId,HttpServletRequest request) {

+ 96 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/TaskServiceImpl.java

@@ -16,7 +16,9 @@ import com.management.platform.service.*;
 import com.management.platform.util.ExcelUtil;
 import com.management.platform.util.HttpRespMsg;
 import com.management.platform.util.MessageUtils;
+import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.lang3.StringUtils;
 import org.apache.poi.hssf.usermodel.*;
 import org.apache.poi.ss.usermodel.CellType;
 import org.apache.poi.xssf.usermodel.XSSFCell;
@@ -35,6 +37,7 @@ import java.io.*;
 import java.math.BigDecimal;
 import java.text.SimpleDateFormat;
 import java.time.LocalDate;
+import java.time.LocalDateTime;
 import java.time.format.DateTimeFormatter;
 import java.util.*;
 import java.util.stream.Collectors;
@@ -49,6 +52,7 @@ import java.util.stream.Collectors;
  */
 @Service
 @Transactional
+@Slf4j
 public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task> implements TaskService {
 
     @Value(value = "${upload.path}")
@@ -97,6 +101,8 @@ public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task> implements Ta
 
     @Resource
     private TaskCommentMapper taskCommentMapper;
+    @Autowired
+    private InformationMapper informationMapper;
 
     @Override
     public HttpRespMsg getExecutorPanel(Integer projectId) {
@@ -1050,6 +1056,96 @@ public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task> implements Ta
         return msg;
     }
 
+    @Override
+    public HttpRespMsg taskPlanPassOrReject(Integer taskId,boolean type, HttpServletRequest request) {
+        HttpRespMsg msg = new HttpRespMsg();
+        String userId = request.getHeader("Token");
+        User user = userMapper.selectById(userId);
+
+        Task task = taskMapper.selectById(taskId);
+        if (!userId.equals(task.getCheckFirstId())&&!userId.equals(task.getCheckSecondId())){
+            msg.setError("当前人员不是审核人,不能审核");
+            return msg;
+        }
+        //通过
+        if (type){
+            //第一审核人通过
+            if (task.getIsTaskPlan()==1&&task.getTaskStatus()==3
+                    && StringUtils.isNotEmpty(task.getCheckFirstId())
+                    &&userId.equals(task.getCheckFirstId())){
+                task.setTaskStatus(4);
+                taskMapper.updateById(task);
+                //给第二审核人发送信息提醒
+                User owner = userMapper.selectById(task.getCheckSecondId());
+                Information information = new Information();
+                information.setMsg("您有工作计划待审核");
+                information.setUserId(owner.getId());
+                information.setType(11);
+                information.setTime(LocalDateTime.now());
+                informationMapper.insert(information);
+            }
+            //第二审核人通过
+            else if (task.getIsTaskPlan() == 1 && task.getTaskStatus() == 4
+                    && StringUtils.isNotEmpty(task.getCheckSecondId())
+                    && userId.equals(task.getCheckSecondId())) {
+
+                task.setTaskStatus(0);
+                task.setIsTaskPlan(0);
+                taskMapper.updateById(task);
+
+                List<TaskExecutor> taskExecutorList = taskExecutorMapper.selectList(new QueryWrapper<TaskExecutor>().eq("task_id", taskId));
+                if(CollectionUtils.isNotEmpty(taskExecutorList)){
+                    for (TaskExecutor taskExecutor : taskExecutorList) {
+                        //给任务的执行人发送信息提醒
+                        User owner = userMapper.selectById(taskExecutor.getExecutorId());
+                        Information information = new Information();
+                        information.setMsg("您有新的任务");
+                        information.setType(1);
+                        information.setUserId(owner.getId());
+                        information.setTime(LocalDateTime.now());
+                        informationMapper.insert(information);
+                    }
+                }
+            }
+        }
+        //驳回
+        else {
+            //第一审核人驳回
+            if (task.getIsTaskPlan()==1&&task.getTaskStatus()==3
+                    && StringUtils.isNotEmpty(task.getCheckFirstId())
+                    &&userId.equals(task.getCheckFirstId())){
+                task.setTaskStatus(5);
+                taskMapper.updateById(task);
+                //给小组长发送信息提醒
+                User owner = userMapper.selectById(task.getCreaterId());
+                Information information = new Information();
+                information.setMsg("您有工作计划被驳回");
+                information.setType(11);
+                information.setUserId(owner.getId());
+                information.setTime(LocalDateTime.now());
+                informationMapper.insert(information);
+            }
+            //第二审核人驳回
+            else if (task.getIsTaskPlan() == 1 && task.getTaskStatus() == 4
+                    && StringUtils.isNotEmpty(task.getCheckSecondId())
+                    && userId.equals(task.getCheckSecondId())) {
+
+                task.setTaskStatus(6);
+                taskMapper.updateById(task);
+
+                //给小组长发送信息提醒
+                User owner = userMapper.selectById(task.getCreaterId());
+                Information information = new Information();
+                information.setMsg("您有工作计划被驳回");
+                information.setType(11);
+                information.setUserId(owner.getId());
+                information.setTime(LocalDateTime.now());
+                informationMapper.insert(information);
+            }
+        }
+        return msg;
+    }
+
     private List<Integer> getBranchDepartment(Integer departmentId, List<Department> departmentList) {
         List<Integer> list = new ArrayList<>();
         list.add(departmentId);

+ 44 - 5
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/UserServiceImpl.java

@@ -297,8 +297,8 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
                 userVO.setLeader(judgeIsLeader(userVO.getId()));
 
                 if(company.getId()==Constant.MLD_COMPANY_ID) {
-                    //检测是否是项目小组长,有没有权限进行添加计划
-                    userVO.setProjectLeader(judgeIsProjectLeader(userVO.getId(),company.getId()));
+                    //检测项目角色
+                    userVO.setProjectLeaderType(judgeIsProjectLeader(userVO.getId(),company.getId()));
                 }
 
                 userVO.setTimeType(timeTypeMapper.selectById(company.getId()));
@@ -763,9 +763,25 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
         return cnt>0;
     }
 
-    private boolean judgeIsProjectLeader(String userId,Integer companyId) {
-        int cnt = projectLeaderService.count(new QueryWrapper<ProjectLeader>().eq("leader_id", userId).eq("company_id", companyId));
-        return cnt>0;
+    private int judgeIsProjectLeader(String userId,Integer companyId) {
+        int LeaderCount = projectLeaderService.count(new QueryWrapper<ProjectLeader>().eq("leader_id", userId).eq("company_id", companyId));
+        int firstCheckCount = taskMapper.selectCount(
+                new QueryWrapper<Task>()
+                        .eq("company_id", companyId)
+                        .and(wrapper ->
+                                wrapper.eq("check_first_id", userId)
+                                        .or()
+                                        .eq("check_second_id", userId)
+                        )
+        );
+        if(LeaderCount > 0){
+            return 1;
+        } else if (firstCheckCount > 0) {
+            return 2;
+        }else {
+            return 0;
+        }
+
     }
 
     //获取用户信息
@@ -2825,7 +2841,30 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
         }
     }
 
+    @Override
+    public HttpRespMsg getUserByProject(Integer projectId, HttpServletRequest request) {
+        HttpRespMsg msg = new HttpRespMsg();
+        List<Map<String, Object>> mapList = participationMapper.getParticipator(projectId);
+        msg.setData(mapList);
+        return msg;
+    }
 
+    @Override
+    public HttpRespMsg getChargeUserByProjectId(Integer projectId, HttpServletRequest request) {
+        HttpRespMsg msg = new HttpRespMsg();
+
+        Project project = projectMapper.selectById(projectId);
+        if (project!=null&&project.getInchargerId()!=null){
+            User user = userMapper.selectById(project.getInchargerId());
+            HashMap<String, Object> map = new HashMap<>();
+            map.put("id",user.getId());
+            map.put("name",user.getName());
+            msg.setData(map);
+        }else {
+            msg.setData(new HashMap<>());
+        }
+        return msg;
+    }
 
 
     @Override

+ 5 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/WxCorpInfoServiceImpl.java

@@ -120,6 +120,8 @@ public class WxCorpInfoServiceImpl extends ServiceImpl<WxCorpInfoMapper, WxCorpI
 
     public static final int TEXT_CARD_MSG_TASK_FILE_CHECK = 28;//任务文件驳回
 
+    public static final int TEXT_CARD_MSG_TASK_PLAN_NEED_CHECK = 29;//工作计划待审核
+
     private static Object userLock = new Object();
 
     @Value("${suitId}")
@@ -403,6 +405,9 @@ public class WxCorpInfoServiceImpl extends ServiceImpl<WxCorpInfoMapper, WxCorpI
                 else if ("task".equals(pageRouter)) {
                     //费用报销
                     title = "工时管家:任务到期通知";
+                    if (msgType.equals(TEXT_CARD_MSG_TASK_PLAN_NEED_CHECK)) {
+                        title = "工作计划待审核";
+                    }
                 }
                 else if (pageRouter.contains("projectInside")) {
                     //预估工时审核

+ 327 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/task/DataCollectTask.java

@@ -0,0 +1,327 @@
+package com.management.platform.task;
+
+import com.management.platform.entity.BusinessTrip;
+import com.management.platform.entity.ErpOrderInfo;
+import com.management.platform.entity.LeaveSheet;
+import com.management.platform.entity.UserFvTime;
+import com.management.platform.mapper.BusinessTripMapper;
+import com.management.platform.mapper.ErpOrderInfoMapper;
+import com.management.platform.mapper.LeaveSheetMapper;
+import com.management.platform.mapper.UserFvTimeMapper;
+import org.springframework.core.ParameterizedTypeReference;
+import org.springframework.http.*;
+import org.springframework.scheduling.annotation.EnableScheduling;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+import org.springframework.util.CollectionUtils;
+import org.springframework.web.client.RestTemplate;
+
+import javax.annotation.Resource;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+@EnableScheduling
+@Component
+public class DataCollectTask {
+
+    @Resource
+    private UserFvTimeMapper userFvTimeMapper;
+    @Resource
+    private BusinessTripMapper businessTripMapper;
+    @Resource
+    private LeaveSheetMapper leaveSheetMapper;
+
+    @Resource
+    private ErpOrderInfoMapper erpOrderInfoMapper;
+
+    private static final String PREFIX_URL = "http://58.210.104.138:10020";
+
+
+
+    @Scheduled(cron = "0 0 1 * * ?")
+    public void sqlServerTask() {
+        System.out.println("开始测试任务定时=======================");
+        RestTemplate restTemplate = new RestTemplate();
+        String sumUrl = PREFIX_URL+"/dataCollect/getSqlServerDataSum";
+        String listUrl = PREFIX_URL+"/dataCollect/getSqlServerDataList";
+
+        try {
+            ResponseEntity<String> sumResponse = restTemplate.exchange(
+                    sumUrl,
+                    HttpMethod.GET,
+                    null,
+                    String.class
+            );
+            Integer totalNum = 0;
+            if (sumResponse.getStatusCode() == HttpStatus.OK) {
+                totalNum = Integer.parseInt(sumResponse.getBody());
+            } else {
+                System.out.println("请求失败,状态码: " + sumResponse.getStatusCode());
+            }
+            System.out.println("总数量为==== "+totalNum);
+            if(totalNum > 0){
+                int pageSize = 1000;
+                int offset = 0;
+                List<ErpOrderInfo> toAddList = new ArrayList<>();
+                List<ErpOrderInfo> toUpdateList = new ArrayList<>();
+                while (offset < totalNum) {
+                    HttpHeaders headers = new HttpHeaders();
+                    headers.setContentType(MediaType.APPLICATION_JSON);
+                    Map<String, Object> requestBody = new HashMap<>();
+                    requestBody.put("pageNo", offset);
+                    requestBody.put("pageSize", pageSize);
+                    HttpEntity<Object> requestEntity = new HttpEntity<>(requestBody, headers);
+                    ResponseEntity<List<ErpOrderInfo>> listResponse = restTemplate.exchange(
+                            listUrl,
+                            HttpMethod.POST,
+                            requestEntity,
+                            new  ParameterizedTypeReference<List<ErpOrderInfo>>(){}
+                    );
+                    if (listResponse.getStatusCode() == HttpStatus.OK) {
+                        List<ErpOrderInfo> dataList = listResponse.getBody();
+                        if(org.apache.commons.collections.CollectionUtils.isNotEmpty(dataList)){
+                            List<String> collect = dataList.stream().map(ErpOrderInfo::getMoDId).distinct().collect(Collectors.toList());
+                            List<String> existIds = erpOrderInfoMapper.getExistIds(collect);
+                            if(!CollectionUtils.isEmpty(existIds)){
+                                toUpdateList.addAll(dataList.stream().filter(t -> existIds.contains(t.getMoDId())).collect(Collectors.toList()));
+                                toAddList.addAll(dataList.stream().filter(t -> !existIds.contains(t.getMoDId())).collect(Collectors.toList()));
+                            }else{
+                                toAddList.addAll(dataList);
+                            }
+                            if(!CollectionUtils.isEmpty(toAddList)){
+                                erpOrderInfoMapper.batchInsert(toAddList);
+                            }
+                            if(!CollectionUtils.isEmpty(toUpdateList)){
+                                for (ErpOrderInfo orderInfo : toUpdateList) {
+                                    erpOrderInfoMapper.updateById(orderInfo);
+                                }
+                            }
+                            toUpdateList.clear();
+                            toAddList.clear();
+                        }
+                    }
+                    offset += pageSize;
+                }
+            }
+        } catch (Exception e) {
+            System.out.println("请求发生异常: " + e.getMessage());
+            e.printStackTrace();
+        }
+
+    }
+
+    @Scheduled(cron = "0 21 11 * * ?")
+    public void workDayTask(){
+        RestTemplate restTemplate = new RestTemplate();
+        String sumUrl = PREFIX_URL+"/dataCollect/getWorkDayDataSum";
+        String listUrl = PREFIX_URL+"/dataCollect/getWorkDayDataList";
+
+        try {
+            ResponseEntity<String> sumResponse = restTemplate.exchange(
+                    sumUrl,
+                    HttpMethod.GET,
+                    null,
+                    String.class
+            );
+            Integer totalNum = 0;
+            if (sumResponse.getStatusCode() == HttpStatus.OK) {
+                totalNum = Integer.parseInt(sumResponse.getBody());
+            } else {
+                System.out.println("请求失败,状态码: " + sumResponse.getStatusCode());
+            }
+            if(totalNum > 0){
+                int pageSize = 1000;
+                int offset = 0;
+                List<UserFvTime> toAddList = new ArrayList<>();
+                List<UserFvTime> toUpdateList = new ArrayList<>();
+                while (offset < totalNum) {
+                    HttpHeaders headers = new HttpHeaders();
+                    headers.setContentType(MediaType.APPLICATION_JSON);
+                    Map<String, Object> requestBody = new HashMap<>();
+                    requestBody.put("pageNo", offset);
+                    requestBody.put("pageSize", pageSize);
+                    HttpEntity<Object> requestEntity = new HttpEntity<>(requestBody, headers);
+                    ResponseEntity<List<UserFvTime>> listResponse = restTemplate.exchange(
+                            listUrl,
+                            HttpMethod.POST,
+                            requestEntity,
+                            new  ParameterizedTypeReference<List<UserFvTime>>(){}
+                    );
+                    if (listResponse.getStatusCode() == HttpStatus.OK) {
+                        List<UserFvTime> dataList = listResponse.getBody();
+                        if(org.apache.commons.collections.CollectionUtils.isNotEmpty(dataList)){
+                            List<String> collect = dataList.stream().map(UserFvTime::getProcinstId).distinct().collect(Collectors.toList());
+                            List<String> existIds = userFvTimeMapper.getExistIds(collect);
+                            if(!CollectionUtils.isEmpty(existIds)){
+                                toUpdateList.addAll(dataList.stream().filter(t -> existIds.contains(t.getProcinstId())).collect(Collectors.toList()));
+                                toAddList.addAll(dataList.stream().filter(t -> !existIds.contains(t.getProcinstId())).collect(Collectors.toList()));
+                            }else{
+                                toAddList.addAll(dataList);
+                            }
+                            if(!CollectionUtils.isEmpty(toAddList)){
+                                userFvTimeMapper.batchInsertCollect(toAddList);
+                            }
+                            if(!CollectionUtils.isEmpty(toUpdateList)){
+                                for (UserFvTime tmp : toUpdateList) {
+                                    userFvTimeMapper.updateById(tmp);
+                                }
+                            }
+                            toUpdateList.clear();
+                            toAddList.clear();
+                        }
+
+                    }
+                    offset += pageSize;
+                }
+            }
+        } catch (Exception e) {
+            System.out.println("请求发生异常: " + e.getMessage());
+            e.printStackTrace();
+        }
+
+    }
+
+    @Scheduled(cron = "0 0 2 * * ?")
+    public void leaveSheetTask(){
+        RestTemplate restTemplate = new RestTemplate();
+        String sumUrl = PREFIX_URL + "/dataCollect/getLeaveSheetDataSum";
+        String listUrl = PREFIX_URL + "/dataCollect/getLeaveSheetDataList";
+
+        try {
+            ResponseEntity<String> sumResponse = restTemplate.exchange(
+                    sumUrl,
+                    HttpMethod.GET,
+                    null,
+                    String.class
+            );
+            Integer totalNum = 0;
+            if (sumResponse.getStatusCode() == HttpStatus.OK) {
+                totalNum = Integer.parseInt(sumResponse.getBody());
+            } else {
+                System.out.println("请求失败,状态码: " + sumResponse.getStatusCode());
+            }
+            if(totalNum > 0){
+                int pageSize = 1000;
+                int offset = 0;
+                List<LeaveSheet> toAddList = new ArrayList<>();
+                List<LeaveSheet> toUpdateList = new ArrayList<>();
+                while (offset < totalNum) {
+                    HttpHeaders headers = new HttpHeaders();
+                    headers.setContentType(MediaType.APPLICATION_JSON);
+                    Map<String, Object> requestBody = new HashMap<>();
+                    requestBody.put("pageNo", offset);
+                    requestBody.put("pageSize", pageSize);
+                    HttpEntity<Object> requestEntity = new HttpEntity<>(requestBody, headers);
+                    ResponseEntity<List<LeaveSheet>> listResponse = restTemplate.exchange(
+                            listUrl,
+                            HttpMethod.POST,
+                            requestEntity,
+                            new  ParameterizedTypeReference<List<LeaveSheet>>(){}
+                    );
+                    if (listResponse.getStatusCode() == HttpStatus.OK) {
+                        List<LeaveSheet> dataList = listResponse.getBody();
+                        if(org.apache.commons.collections.CollectionUtils.isNotEmpty(dataList)){
+                            List<String> collect = dataList.stream().map(LeaveSheet::getProcinstId).distinct().collect(Collectors.toList());
+                            List<String> existIds = leaveSheetMapper.getExistIds(collect);
+                            if(!CollectionUtils.isEmpty(existIds)){
+                                toUpdateList.addAll(dataList.stream().filter(t -> existIds.contains(t.getProcinstId())).collect(Collectors.toList()));
+                                toAddList.addAll(dataList.stream().filter(t -> !existIds.contains(t.getProcinstId())).collect(Collectors.toList()));
+                            }else{
+                                toAddList.addAll(dataList);
+                            }
+                            if(!CollectionUtils.isEmpty(toAddList)){
+                                leaveSheetMapper.batchInsert(toAddList);
+                            }
+                            if(!CollectionUtils.isEmpty(toUpdateList)){
+                                for (LeaveSheet tmp : toUpdateList) {
+                                    leaveSheetMapper.updateById(tmp);
+                                }
+                            }
+                            toUpdateList.clear();
+                            toAddList.clear();
+                        }
+
+                    }
+                    offset += pageSize;
+                }
+            }
+        } catch (Exception e) {
+            System.out.println("请求发生异常: " + e.getMessage());
+            e.printStackTrace();
+        }
+    }
+
+    @Scheduled(cron = "0 30 2 * * ?")
+    public void businessTripTask(){
+        RestTemplate restTemplate = new RestTemplate();
+        String sumUrl = PREFIX_URL+"/dataCollect/getBusinessTripDataSum";
+        String listUrl = PREFIX_URL+"/dataCollect/getBusinessTripDataList";
+
+        try {
+            ResponseEntity<String> sumResponse = restTemplate.exchange(
+                    sumUrl,
+                    HttpMethod.GET,
+                    null,
+                    String.class
+            );
+            Integer totalNum = 0;
+            if (sumResponse.getStatusCode() == HttpStatus.OK) {
+                totalNum = Integer.parseInt(sumResponse.getBody());
+            } else {
+                System.out.println("请求失败,状态码: " + sumResponse.getStatusCode());
+            }
+            if(totalNum > 0){
+                int pageSize = 1000;
+                int offset = 0;
+                List<BusinessTrip> toAddList = new ArrayList<>();
+                List<BusinessTrip> toUpdateList = new ArrayList<>();
+                while (offset < totalNum) {
+                    HttpHeaders headers = new HttpHeaders();
+                    headers.setContentType(MediaType.APPLICATION_JSON);
+                    Map<String, Object> requestBody = new HashMap<>();
+                    requestBody.put("pageNo", offset);
+                    requestBody.put("pageSize", pageSize);
+                    HttpEntity<Object> requestEntity = new HttpEntity<>(requestBody, headers);
+                    ResponseEntity<List<BusinessTrip>> listResponse = restTemplate.exchange(
+                            listUrl,
+                            HttpMethod.POST,
+                            requestEntity,
+                            new  ParameterizedTypeReference<List<BusinessTrip>>(){}
+                    );
+                    if (listResponse.getStatusCode() == HttpStatus.OK) {
+                        List<BusinessTrip> dataList = listResponse.getBody();
+                        if(org.apache.commons.collections.CollectionUtils.isNotEmpty(dataList)){
+                            List<String> collect = dataList.stream().map(BusinessTrip::getProcinstId).distinct().collect(Collectors.toList());
+                            List<String> existIds = businessTripMapper.getExistIds(collect);
+                            if(!CollectionUtils.isEmpty(existIds)){
+                                toUpdateList.addAll(dataList.stream().filter(t -> existIds.contains(t.getProcinstId())).collect(Collectors.toList()));
+                                toAddList.addAll(dataList.stream().filter(t -> !existIds.contains(t.getProcinstId())).collect(Collectors.toList()));
+                            }else{
+                                toAddList.addAll(dataList);
+                            }
+                            if(!CollectionUtils.isEmpty(toAddList)){
+                                businessTripMapper.batchInsert(toAddList);
+                            }
+                            if(!CollectionUtils.isEmpty(toUpdateList)){
+                                for (BusinessTrip tmp : toUpdateList) {
+                                    businessTripMapper.updateById(tmp);
+                                }
+                            }
+                            toUpdateList.clear();
+                            toAddList.clear();
+                        }
+
+                    }
+                    offset += pageSize;
+                }
+            }
+        } catch (Exception e) {
+            System.out.println("请求发生异常: " + e.getMessage());
+            e.printStackTrace();
+        }
+    }
+
+}

+ 15 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/BusinessTripMapper.xml

@@ -38,6 +38,15 @@
     <sql id="Base_Column_List">
         id, company_id, owner_id, owner_name, reason, start_date, end_date, way, city_from, city_to, go_back, day_count, remark, status, deny_reason, indate, is_linked, procinst_id, gmt_finished, auditor_id, auditor_name, auditor_type, cur_audit_setting_id
     </sql>
+    <insert id="batchInsert">
+        insert into business_trip(company_id, owner_id, owner_name, reason, start_date, end_date
+        , way, city_from, city_to,day_count, status, indate,  procinst_id)
+        VALUES
+        <foreach collection="resList" separator="," item="res">
+            (#{res.companyId},#{res.ownerId},#{res.ownerName},#{res.reason},#{res.startDate},#{res.endDate}
+            ,#{res.way},#{res.cityFrom},#{res.cityTo},#{res.dayCount},#{res.status},#{res.indate},#{res.procinstId})
+        </foreach>
+    </insert>
 
     <select id="summaryData"  resultMap="BaseResultMap1">
         select owner_id, owner_name, sum(day_count) as day_count, department.department_name as department_name from business_trip
@@ -65,4 +74,10 @@
             and business_trip.start_date &lt;= #{endDate} and business_trip.end_date >= #{startDate}
         </if>
     </select>
+    <select id="getExistIds" resultType="java.lang.String">
+        select procinst_id
+        from business_trip
+        where procinst_id in
+        <foreach collection="procinstIds" item="procinstId" separator="," open="(" close=")">#{procinstId}</foreach>
+    </select>
 </mapper>

+ 18 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/ErpOrderInfoMapper.xml

@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
+<mapper namespace="com.management.platform.mapper.ErpOrderInfoMapper">
+
+    <insert id="batchInsert">
+        insert into erp_order_info(order_id, project_id, project_name, line, status)
+        VALUES
+            <foreach collection="resList" separator="," item="res">
+                (#{res.orderId},#{res.projectId},#{res.projectName},#{res.line},#{res.status})
+            </foreach>
+    </insert>
+    <select id="getExistIds" resultType="java.lang.String">
+        select moDId
+        from erp_order_info
+        where moDId in <foreach collection="moIds" item="moId" separator="," open="(" close=")">#{moId}</foreach>
+    </select>
+</mapper>

+ 14 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/LeaveSheetMapper.xml

@@ -31,6 +31,15 @@
     <sql id="Base_Column_List">
         id, company_id, owner_id, owner_name, start_date, end_date, leave_type, status, remark, operator_id, time_hours, time_days, indate, time_type, tel, auditor_id, auditor_name, auditor_type, procinst_id, gmt_finished, cur_audit_setting_id
     </sql>
+    <insert id="batchInsert">
+        insert into leave_sheet(company_id, owner_id, owner_name,start_date, end_date, leave_type, status, remark
+        , operator_id, time_hours, time_days, indate, time_type, tel, procinst_id) VALUES
+        <foreach collection="resList" separator="," item="res">
+            (#{res.companyId},#{res.ownerId},#{res.ownerName},#{res.startDate},#{res.endDate}
+            ,#{res.leaveType},#{res.status},#{res.remark},#{res.operatorId},#{res.timeHours},#{res.timeDays}
+            ,#{res.indate},#{res.timeType},#{res.tel},#{res.procinstId})
+        </foreach>
+    </insert>
     <select id="summaryData"  resultMap="BaseResultMap">
         select owner_id, owner_name, sum(time_hours) as time_hours, sum(time_days) as time_days from leave_sheet
         where start_date &gt;= #{startDate} and end_date &lt;= #{endDate}
@@ -99,4 +108,9 @@
                 group by owner_id
             ) tmp2 on tmp1.id = tmp2.userId
     </select>
+    <select id="getExistIds" resultType="java.lang.String">
+        select procinst_id
+        from leave_sheet
+        where procinst_id in <foreach collection="procinstIds" item="procinstId" separator="," open="(" close=")">#{procinstId}</foreach>
+    </select>
 </mapper>

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

@@ -731,7 +731,10 @@
 
     <select id="getTaskPlanByMemb" resultType="java.util.Map">
         SELECT user.`id` as user_id, user.`name`,project.id, project.`project_name`,task.id as task_id, task.name as task_name,task_executor.id as exe_id,
-        IFNULL(task.`start_date`, task.end_date) as start_date, task.`end_date`, task_executor.plan_hours as duration, task.task_level as level FROM user
+        IFNULL(task.`start_date`, task.end_date) as start_date, task.`end_date`, task_executor.plan_hours as duration, task.task_level as level ,
+        task.task_plan_type as taskPlanType,task.is_task_plan as isTaskPlan,task.check_first_id as checkFirstId,task.check_second_id as checkSecondId,
+        task.task_status as taskStatus,task.id as taskId,task.task_plan taskPlan
+        FROM user
         LEFT JOIN task_executor ON user.id = task_executor.`executor_id`
         left join task on task.id = task_executor.task_id
         LEFT JOIN project ON project.`id` = task.`project_id`
@@ -740,15 +743,20 @@
             #{item}
         </foreach>
         and ((IFNULL(task.start_date , task.end_date) between #{startDate} and #{endDate}) or (task.end_date between #{startDate} and #{endDate}))
-        and task.end_date is not null
+        and task.end_date is not null and task.task_plan =0
         AND project.`status` = 1
         ORDER BY user.id, task.start_date
     </select>
 
     <select id="getTaskPlanByProject" resultType="java.util.Map">
         SELECT task.executor_id as user_id, task.executor_name as `name`,project.id, project.`project_name`,task.id as task_id, task.name as task_name,
+        task.task_plan_type as taskPlanType,task.is_task_plan as isTaskPlan,task.check_first_id as checkFirstId,task.check_second_id as checkSecondId
+        ,task.task_status as taskStatus,task.id as taskId,task.task_plan taskPlan,
         IFNULL(task.`start_date`, task.end_date) as start_date, task.`end_date`, task.plan_hours as duration FROM project
         LEFT JOIN task ON task.project_id = project.id
+        <if test="groupName !=null and groupName !='' ">
+            LEFT JOIN task_group tg ON tg.project_id = project.id
+        </if>
         WHERE project.company_id = #{companyId}
         <if test="projectIds != null">
             and project.`id` IN
@@ -756,8 +764,14 @@
                 #{item}
             </foreach>
         </if>
+        <if test="groupName !=null and groupName !='' ">
+            and tg.name = #{groupName} and task.group_id=tg.id
+        </if>
+        <if test="taskType !=null  ">
+            and task.task_type = #{taskType}
+        </if>
         and ((IFNULL(task.start_date , task.end_date) between #{startDate} and #{endDate}) or (task.end_date between #{startDate} and #{endDate}))
-        and task.end_date is not null
+        and task.end_date is not null and task.task_plan =0
         AND project.`status` = 1
         ORDER BY project.id, task.start_date
     </select>
@@ -2707,5 +2721,234 @@
             </foreach>
         </if>
     </select>
+    <select id="getTaskPlanByGeneralMemb" resultType="java.util.Map">
+        SELECT user.`id` as user_id, user.`name`,project.id, project.`project_name`,task.id as task_id, task.name as task_name,task_executor.id as exe_id,
+        IFNULL(task.`start_date`, task.end_date) as start_date, task.`end_date`, task_executor.plan_hours as duration, task.task_level as level ,
+        task.task_plan_type as taskPlanType,task.is_task_plan as isTaskPlan,task.check_first_id as checkFirstId,task.check_second_id as checkSecondId,
+        task.task_status as taskStatus,task.id as taskId,task.task_plan taskPlan
+        FROM user
+        LEFT JOIN task_executor ON user.id = task_executor.`executor_id`
+        left join task on task.id = task_executor.task_id
+        LEFT JOIN project ON project.`id` = task.`project_id`
+        WHERE user.`id` IN
+        <foreach collection="userIds" close=")" open="(" separator="," index="" item="item">
+            #{item}
+        </foreach>
+        and ((IFNULL(task.start_date , task.end_date) between #{startDate} and #{endDate}) or (task.end_date between #{startDate} and #{endDate}))
+        and task.end_date is not null
+        <if test="targetUserId !=null and targetUserId !='' ">
+            and user.`id`=#{targetUserId}
+        </if>
+        AND project.`status` = 1
+        ORDER BY user.id, task.start_date
+    </select>
+    <select id="getTaskPlanWithLeave" resultType="java.util.Map">
+        SELECT user.`id` as user_id, user.`name`,task.id as task_id, task.name as task_name,task_executor.id as exe_id,
+        IFNULL(task.`start_date`, task.end_date) as start_date, task.`end_date`, task_executor.plan_hours as duration, task.task_level as level ,
+        task.task_plan_type as taskPlanType,task.is_task_plan as isTaskPlan,task.check_first_id as checkFirstId,task.check_second_id as checkSecondId,
+        task.task_status as taskStatus,task.id as taskId,task.task_plan taskPlan
+        FROM user
+        LEFT JOIN task_executor ON user.id = task_executor.`executor_id`
+        left join task on task.id = task_executor.task_id
+        WHERE
+        ((IFNULL(task.start_date , task.end_date) between #{startDate} and #{endDate}) or (task.end_date between #{startDate} and #{endDate}))
+        and task.end_date is not null and task.task_plan_type=3 and task.task_plan=1
+        <if test="targetUserId !=null and targetUserId !='' ">
+            and user.`id`=#{targetUserId}
+        </if>
+        ORDER BY user.id, task.start_date
+    </select>
+    <select id="getTaskPlanByProManager" resultType="java.util.Map">
+        SELECT user.`id` as user_id, user.`name`,project.id, project.`project_name`,task.id as task_id, task.name as task_name,task_executor.id as exe_id,
+        IFNULL(task.`start_date`, task.end_date) as start_date, task.`end_date`, task_executor.plan_hours as duration, task.task_level as level ,
+        task.task_plan_type as taskPlanType,task.is_task_plan as isTaskPlan,task.check_first_id as checkFirstId,task.check_second_id as checkSecondId,
+        task.task_status as taskStatus,task.id as taskId,task.task_plan taskPlan
+        FROM user
+        LEFT JOIN task_executor ON user.id = task_executor.`executor_id`
+        left join task on task.id = task_executor.task_id
+        LEFT JOIN project ON project.`id` = task.`project_id`
+        WHERE user.`id` IN
+        <foreach collection="userIds" close=")" open="(" separator="," index="" item="item">
+            #{item}
+        </foreach>
+        and ((IFNULL(task.start_date , task.end_date) between #{startDate} and #{endDate}) or (task.end_date between #{startDate} and #{endDate}))
+        and task.end_date is not null and task.is_task_plan=1 and task.task_status=3 and task.check_first_id=#{managerId}
+        AND project.`status` = 1
+        <if test="targetUserId !=null and targetUserId !='' ">
+            and user.`id`=#{targetUserId}
+        </if>
+        ORDER BY user.id, task.start_date
+    </select>
+    <select id="getTaskPlanByAreaManager" resultType="java.util.Map">
+        SELECT user.`id` as user_id, user.`name`,project.id, project.`project_name`,task.id as task_id, task.name as task_name,task_executor.id as exe_id,
+        IFNULL(task.`start_date`, task.end_date) as start_date, task.`end_date`, task_executor.plan_hours as duration, task.task_level as level ,
+        task.task_plan_type as taskPlanType,task.is_task_plan as isTaskPlan,task.check_first_id as checkFirstId,task.check_second_id as checkSecondId,
+        task.task_status as taskStatus,task.id as taskId,task.task_plan taskPlan
+        FROM user
+        LEFT JOIN task_executor ON user.id = task_executor.`executor_id`
+        left join task on task.id = task_executor.task_id
+        LEFT JOIN project ON project.`id` = task.`project_id`
+        WHERE user.`id` IN
+        <foreach collection="userIds" close=")" open="(" separator="," index="" item="item">
+            #{item}
+        </foreach>
+        and ((IFNULL(task.start_date , task.end_date) between #{startDate} and #{endDate}) or (task.end_date between #{startDate} and #{endDate}))
+        and task.end_date is not null and task.is_task_plan=1 and task.task_status=4 and task.check_second_id=#{managerId}
+        AND project.`status` = 1
+        <if test="targetUserId !=null and targetUserId !='' ">
+            and user.`id`=#{targetUserId}
+        </if>
+        ORDER BY user.id, task.start_date
+    </select>
+    <select id="getTaskPlanByProjectGeneralMemb" resultType="java.util.Map">
+        SELECT task.executor_id as user_id, task.executor_name as `name`,project.id, project.`project_name`,task.id as task_id, task.name as task_name,
+        task.task_plan_type as taskPlanType,task.is_task_plan as isTaskPlan,task.check_first_id as checkFirstId,task.check_second_id as checkSecondId
+        ,task.task_status as taskStatus,task.id as taskId,task.task_plan taskPlan,
+        IFNULL(task.`start_date`, task.end_date) as start_date, task.`end_date`, task.plan_hours as duration FROM project
+        LEFT JOIN task ON task.project_id = project.id
+        <if test="groupName !=null and groupName !='' ">
+            LEFT JOIN task_group tg ON tg.project_id = project.id
+        </if>
+        WHERE project.company_id = #{companyId}
+        <if test="projectIds != null">
+            and project.`id` IN
+            <foreach collection="projectIds" close=")" open="(" separator="," index="" item="item">
+                #{item}
+            </foreach>
+        </if>
+        <if test="groupName !=null and groupName !='' ">
+            and tg.name = #{groupName} and task.group_id=tg.id
+        </if>
+        <if test="taskType !=null  ">
+            and task.task_type = #{taskType}
+        </if>
+        <if test="targetProjectId !=null  ">
+            and project.`id` = #{targetProjectId}
+        </if>
+        and ((IFNULL(task.start_date , task.end_date) between #{startDate} and #{endDate}) or (task.end_date between #{startDate} and #{endDate}))
+        and task.end_date is not null
+        AND project.`status` = 1
+        ORDER BY project.id, task.start_date
+    </select>
+    <select id="getTaskPlanByProjectManager" resultType="java.util.Map">
+        SELECT task.executor_id as user_id, task.executor_name as `name`,project.id, project.`project_name`,task.id as task_id, task.name as task_name,
+        task.task_plan_type as taskPlanType,task.is_task_plan as isTaskPlan,task.check_first_id as checkFirstId,task.check_second_id as checkSecondId
+        ,task.task_status as taskStatus,task.id as taskId,task.task_plan taskPlan,
+        IFNULL(task.`start_date`, task.end_date) as start_date, task.`end_date`, task.plan_hours as duration FROM project
+        LEFT JOIN task ON task.project_id = project.id
+        <if test="groupName !=null and groupName !='' ">
+            LEFT JOIN task_group tg ON tg.project_id = project.id
+        </if>
+        WHERE project.company_id = #{companyId}
+        <if test="projectIds != null">
+            and project.`id` IN
+            <foreach collection="projectIds" close=")" open="(" separator="," index="" item="item">
+                #{item}
+            </foreach>
+        </if>
+        <if test="groupName !=null and groupName !='' ">
+            and tg.name = #{groupName} and task.group_id=tg.id
+        </if>
+        <if test="taskType !=null  ">
+            and task.task_type = #{taskType}
+        </if>
+        <if test="targetProjectId !=null  ">
+            and project.`id` = #{targetProjectId}
+        </if>
+        and ((IFNULL(task.start_date , task.end_date) between #{startDate} and #{endDate}) or (task.end_date between #{startDate} and #{endDate}))
+        and task.end_date is not null and task.is_task_plan=1 and task.task_status=3 and task.check_first_id=#{managerId}
+        AND project.`status` = 1
+        ORDER BY project.id, task.start_date
+    </select>
+    <select id="getTaskPlanByProjectAreaManager" resultType="java.util.Map">
+        SELECT task.executor_id as user_id, task.executor_name as `name`,project.id, project.`project_name`,task.id as task_id, task.name as task_name,
+        task.task_plan_type as taskPlanType,task.is_task_plan as isTaskPlan,task.check_first_id as checkFirstId,task.check_second_id as checkSecondId
+        ,task.task_status as taskStatus,task.id as taskId,task.task_plan taskPlan,
+        IFNULL(task.`start_date`, task.end_date) as start_date, task.`end_date`, task.plan_hours as duration FROM project
+        LEFT JOIN task ON task.project_id = project.id
+        <if test="groupName !=null and groupName !='' ">
+            LEFT JOIN task_group tg ON tg.project_id = project.id
+        </if>
+        WHERE project.company_id = #{companyId}
+        <if test="projectIds != null">
+            and project.`id` IN
+            <foreach collection="projectIds" close=")" open="(" separator="," index="" item="item">
+                #{item}
+            </foreach>
+        </if>
+        <if test="groupName !=null and groupName !='' ">
+            and tg.name = #{groupName} and task.group_id=tg.id
+        </if>
+        <if test="taskType !=null  ">
+            and task.task_type = #{taskType}
+        </if>
+        <if test="targetProjectId !=null  ">
+            and project.`id` = #{targetProjectId}
+        </if>
+        and ((IFNULL(task.start_date , task.end_date) between #{startDate} and #{endDate}) or (task.end_date between #{startDate} and #{endDate}))
+        and task.end_date is not null and task.is_task_plan=1 and task.task_status=4 and task.check_second_id=#{managerId}
+        AND project.`status` = 1
+        ORDER BY project.id, task.start_date
+    </select>
+    <select id="getFTETaskPlanData" resultType="java.util.Map">
+        select t.id,  u.plate1 area, p.project_code projectCode,p.project_name projectName,u.name userName, t.plan_hours planHours   from task t
+          left join project p on t.project_id=p.id
+          LEFT JOIN task_executor te on t.id=te.task_id
+          INNER JOIN user u on u.id=te.executor_id
+        WHERE u.company_id=#{companyId} and t.task_plan=1 and t.task_status &lt;3 and t.task_plan_type !=3
+        <if test="area!=null and area != '' ">
+            and u.plate1 = #{area}
+        </if>
+        <if test="userId!=null and userId != '' ">
+            and u.id = #{userId}
+        </if>
+        <if test="deptIds!=null and deptIds.size()>0">
+            and u.department_id in
+            <foreach collection="deptIds" open="(" item="item" close=")" separator=",">
+                #{item}
+            </foreach>
+        </if>
+        <if test=" startDate!= null and endDate!= null">
+            AND
+            (
+            (
+            (t.start_date IS NULL OR t.start_date &lt;= #{startDate}) AND (t.end_date &gt;= #{startDate} AND t.end_date &lt;= #{endDate})
+            )
+            OR
+            (
+            (t.end_date IS NULL OR t.end_date &gt;= #{endDate}) AND (t.start_date &gt;= #{startDate} AND t.start_date &lt;= #{endDate})
+            )
+            OR
+            (
+            t.start_date IS NOT NULL AND t.end_date IS NOT NULL AND t.start_date &gt;= #{startDate}
+            AND t.start_date &lt;= #{endDate} AND t.end_date &gt;= #{startDate} AND t.end_date &lt;= #{endDate}
+            )
+            OR
+            (
+            t.start_date IS NOT NULL AND t.end_date IS NOT NULL AND t.start_date &lt;= #{startDate} AND t.end_date &gt; #{endDate}
+            )
+            )
+        </if>
+        <if test=" startDate != null and endDate == null">
+            AND (t.end_date IS NOT NULL and t.end_date &gt;= #{startDate})
+        </if>
+        <if test=" startDate == null and endDate != null">
+            AND (t.start_date IS NOT NULL and t.start_date &lt;= #{endDate})
+        </if>
+    </select>
+    <select id="getRelatedProjectIds" resultType="java.lang.Integer">
+        SELECT DISTINCT pl.project_id
+        FROM project_leader pl
+        WHERE pl.leader_id = #{userId}
+
+        UNION
+
+        SELECT DISTINCT p.id
+        FROM project p
+        INNER JOIN task t ON t.project_id = p.id
+        WHERE p.company_id = #{companyId}
+        AND (t.check_first_id = #{userId} OR t.check_second_id = #{userId})
+    </select>
+
 
 </mapper>

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

@@ -20,7 +20,7 @@
         id, task_id, executor_id, executor_name, executor_color, plan_hours, project_id, service_id, real_cost, file_charge_one_id, file_charge_two_id
     </sql>
     <select id="getInfoWithFileCharge" resultType="com.management.platform.entity.TaskExecutor">
-        select task_id, executor_id, executor_name, executor_color, plan_hours, project_id
+        select te.id as id,   task_id, executor_id, executor_name, executor_color, plan_hours, project_id
              , service_id, real_cost, file_charge_one_id, file_charge_two_id
              , u1.name as fileChargeOneName,u1.corpwx_userid as chargeOneWxId
              ,u2.name as fileChargeTwoName,u2.corpwx_userid  as chargeTwoWxId

+ 10 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/UserFvTimeMapper.xml

@@ -26,5 +26,15 @@
             (#{toAdd.workDate},#{toAdd.userId},#{toAdd.companyId},#{toAdd.startTime},#{toAdd.endTime},#{toAdd.workHours},#{toAdd.overTimeHours})
             </foreach>
     </insert>
+    <insert id="batchInsertCollect">
+        insert into user_fv_time(work_date, user_id, company_id, start_time, end_time,work_hours,overtime_seconds,procinst_id) VALUES
+        <foreach collection="resList" separator="," item="res">
+            (#{res.workDate},#{res.userId},#{res.companyId},#{res.startTime},#{res.endTime},#{res.workHours},#{res.overTimeSeconds},#{res.procinstId})
+        </foreach>
+    </insert>
+    <select id="getExistIds" resultType="java.lang.String">
+        select procinst_id from user_fv_time where procinst_id in
+        <foreach collection="procinstIds" item="procinstId" separator="," open="(" close=")">#{procinstId}</foreach>
+    </select>
 
 </mapper>

+ 11 - 1
fhKeeper/formulahousekeeper/octopus/src/routes.js

@@ -51,7 +51,7 @@ import simpleReport from './views/simplereport/list';
 // import research from './views/research/list';
 import migrateData from './views/migrateData/migrateData'
 // 角色权限
-import quanx from './views/quanx/quanx'
+import expiredCompanyCleanup from './views/expiredCompanyCleanup/expiredCompanyCleanup'
 
 Vue.use(Router)
 
@@ -165,6 +165,16 @@ export const allRouters = [
             { path: '/signing', component: signing, name: '签约管理' }
         ]
     },
+    {
+        path: '/expiredCompanyCleanup',
+        component: Home,
+        name: '过期公司清理',
+        iconCls: 'iconfont firerock-iconkehu',
+        leaf: true,
+        children: [
+            { path: '/expiredCompanyCleanup', component: expiredCompanyCleanup, name: '过期公司清理' }
+        ]
+    },
     {
         path: '/404',
         component: NotFound,

+ 138 - 0
fhKeeper/formulahousekeeper/octopus/src/views/expiredCompanyCleanup/expiredCompanyCleanup.vue

@@ -0,0 +1,138 @@
+<template>
+  <div class="expiredCompanyCleanup">
+    <!-- <div class="expiredCompanyCleanup-header">
+      头部
+    </div> -->
+    <div class="expiredCompanyCleanup-content">
+      <el-table :data="tableData" @selection-change="handleSelectionChange" border height="80vh" v-loading="btnDeleteLoading" element-loading-text="删除中..." element-loading-background="rgba(255, 255, 255, 0.8)" style="width: 100%;">
+        <el-table-column type="selection" width="55" />
+        <el-table-column prop="id" label="企业ID" width="100" align="center" />
+        <el-table-column prop="companyName" label="企业名称" min-width="240" align="center" />
+        <el-table-column prop="setMeal" label="是否签约" min-width="80" align="center">
+          <template slot-scope="scope">{{ scope.row.setMeal ? "已签约" : "未签约" }}</template>
+        </el-table-column>
+        <el-table-column prop="expirationDate" label="有效期" min-width="160" align="center" />
+        <el-table-column prop="staffCountMax" label="人数上限" min-width="80" align="center" />
+      </el-table>
+    </div>
+    <!-- 底部 -->
+    <div class="pagination-container">
+      <el-button type="primary" :loading="btnDeleteLoading" :disabled="!multipleSelection.length"
+        @click="deleteEnterprise()" size="small">批量删除</el-button>
+
+      <el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="page"
+        :page-sizes="[100, 200, 300, 400]" :page-size="100" layout="total, prev, pager, next, sizes"
+        :total="total">
+      </el-pagination>
+    </div>
+  </div>
+</template>
+
+<script>
+export default {
+  name: "expiredCompanyCleanup",
+  data() {
+    return {
+      tableData: [],
+      multipleSelection: [],
+      btnDeleteLoading: false,
+      total: 0,
+      page: 1,
+      size: 100,
+    }
+  },
+  mounted() {
+    this.getTableData()
+  },
+  methods: {
+    handleCurrentChange(val) {
+      this.page = val
+      this.getTableData()
+    },
+    handleSizeChange(val) {
+      this.page = 1
+      this.size = val
+      this.getTableData()
+    },
+    deleteEnterprise() {
+      this.$confirm('此操作将永久删除选中的企业, 是否删除?', '删除企业', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).then(() => {
+        this.btnDeleteLoading = true
+        const companyIds = this.multipleSelection.map(item => item.id).join(',')
+        this.postData(`/company/delNeedDelList`, { companyIds }).then(res => {
+          this.$message({
+            message: '删除成功',
+            type: 'success'
+          })
+          this.page = 1
+          this.getTableData()
+        }).finally(() => {
+          this.btnDeleteLoading = false
+        })
+      })
+    },
+    handleSelectionChange(val) {
+      this.multipleSelection = val
+    },
+    getTableData() {
+      this.postData('/company/getNeedDelList', {
+        pageIndex: this.page,
+        pageSize: this.size
+      }).then(res => {
+        this.tableData = res.data.record || []
+        this.total = res.data.total
+      })
+    },
+    // 单独封装请求
+    async postData(urls, param = {}) {
+      return new Promise((resolve, reject) => {
+        this.http.post(urls, { ...param },
+          res => {
+            if (res.code == 'ok') {
+              resolve(res)
+            } else {
+              this.$message({
+                message: res.msg,
+                type: 'error'
+              })
+              reject(res)
+            }
+            resolve(res)
+          },
+          error => {
+            this.$message({
+              message: error,
+              type: "error"
+            });
+            reject(error)
+          }
+        )
+      });
+    },
+  }
+}
+</script>
+
+<style lang="scss">
+.expiredCompanyCleanup {
+  height: 100%;
+  display: flex;
+  flex-direction: column;
+  padding: 10px 20px;
+
+  .expiredCompanyCleanup-content {
+    flex: 1;
+  }
+
+  .pagination-container {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    width: 100%;
+    padding: 20px 0;
+  }
+}
+</style>

+ 116 - 31
fhKeeper/formulahousekeeper/ops-platform/src/main/java/com/management/platform/controller/CompanyController.java

@@ -29,10 +29,7 @@ import java.time.Duration;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.time.LocalTime;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Optional;
+import java.util.*;
 import java.util.stream.Collectors;
 
 /**
@@ -110,6 +107,52 @@ public class CompanyController {
     @Resource
     private UserCorpwxTimeMapper userCorpwxTimeMapper;
 
+    @Resource
+    private ProjectAuditorMapper projectAuditorMapper;
+
+    @Resource
+    private ProjectBasecostMapper projectBasecostMapper;
+
+    @Resource
+    private ProjectBasecostSettingMapper projectBasecostSettingMapper;
+
+    @Resource
+    private ProjectDocfolderMapper projectDocfolderMapper;
+
+    @Resource
+    private ProjectDocumentMapper projectDocumentMapper;
+
+    @Resource
+    private ProjectNotifyUserMapper projectNotifyUserMapper;
+
+    @Resource
+    private ProjectPercentageMapper projectPercentageMapper;
+
+    @Resource
+    private ProjectProfessionMapper projectProfessionMapper;
+
+    @Resource
+    private ProjectTimerMapper projectTimerMapper;
+
+    @Resource
+    private ProjectUserSalaryMapper projectUserSalaryMapper;
+
+    @Resource
+    private SubProjectMapper subProjectMapper;
+
+    @Resource
+    private ReportAuditLogMapper reportAuditLogMapper;
+
+    @Resource
+    private ReportExtraDegreeMapper reportExtraDegreeMapper;
+
+    @Resource
+    private ReportImportLogMapper reportImportLogMapper;
+
+    @Resource
+    private ReportProfessionProgressMapper reportProfessionProgressMapper;
+
+
 
 
 
@@ -315,34 +358,76 @@ public class CompanyController {
             return msg;
         }
         QueryWrapper<Company> queryWrapper = new QueryWrapper<Company>();
-        String[] strings = companyIds.split(",");
-        List<String> companyIdList = Arrays.asList(strings);
-        queryWrapper.in("id",companyIdList);
+        LocalDateTime localDateTime = LocalDateTime.now().plusYears(-2L);
+        queryWrapper.eq("set_meal",0).le("expiration_date",localDateTime).orderByAsc("expiration_date");
         List<Company> companyList = companyMapper.selectList(queryWrapper);
-        List<Integer> companyIdCollect = companyList.stream().map(Company::getId).collect(Collectors.toList());
-        companySigningMapper.delete(new QueryWrapper<CompanySigning>().in("company_id",companyIdCollect));
-        auditWorkflowTimeSettingMapper.delete(new QueryWrapper<AuditWorkflowTimeSetting>().in("company_id",companyIdCollect));
-        companyCustomerContactMapper.delete(new QueryWrapper<CompanyCustomerContact>().in("company_id",companyIdCollect));
-        companyDingdingMapper.delete(new QueryWrapper<CompanyDingding>().in("company_id",companyIdCollect));
-        companyReportMapper.delete(new QueryWrapper<CompanyReport>().in("company_id",companyIdCollect));
-        customerInfoMapper.delete(new QueryWrapper<CustomerInfo>().in("company_id",companyIdCollect));
-        departmentMapper.delete(new QueryWrapper<Department>().in("company_id",companyIdCollect));
-        operationRecordMapper.delete(new QueryWrapper<OperationRecord>().in("company_id",companyIdCollect));
-        projectMapper.delete(new QueryWrapper<Project>().in("company_id",companyIdCollect));
-        projectCategoryMapper.delete(new QueryWrapper<ProjectCategory>().in("company_id",companyIdCollect));
-        reportMapper.delete(new QueryWrapper<Report>().in("company_id",companyIdCollect));
-
-        sysRoleModuleMapper.deleteNeedToDel(companyIdCollect);
-        sysRoleFunctionMapper.deleteNeedToDel(companyIdCollect);
-        sysRoleMapper.delete(new QueryWrapper<SysRole>().in("company_id",companyIdCollect));
-
-        taskMapper.delete(new QueryWrapper<Task>().in("company_id",companyIdCollect));
-        timeTypeMapper.delete(new QueryWrapper<TimeType>().in("company_id",companyIdCollect));
-        userMapper.delete(new QueryWrapper<User>().in("company_id",companyIdCollect));
-        userCorpwxTimeMapper.delete(new QueryWrapper<UserCorpwxTime>().in("company_id",companyIdCollect));
-        wxCorpInfoMapper.delete(new QueryWrapper<WxCorpInfo>().in("company_id",companyIdCollect));
-
-        feishuInfoService.remove(new QueryWrapper<FeishuInfo>().in("company_id",companyIdCollect));
+        List<Integer> eligibleCompanyIds = companyList.stream().map(Company::getId).collect(Collectors.toList());
+
+        // 解析传入的公司ID
+        String[] strings = companyIds.split(",");
+        List<String> companyIdCollect = Arrays.asList(strings);
+        List<Integer> companyIdsToDelete = new ArrayList<>();
+
+        // 校验传入的公司ID是否都在符合条件的公司列表中
+        for (String idStr : companyIdCollect) {
+            try {
+                Integer id = Integer.parseInt(idStr);
+                if (!eligibleCompanyIds.contains(id)) {
+                    msg.setError("公司ID " + id + " 不符合删除条件(套餐为0且过期时间超过2年)");
+                    return msg;
+                }
+                companyIdsToDelete.add(id);
+            } catch (NumberFormatException e) {
+                msg.setError("公司ID格式不正确: " + idStr);
+                return msg;
+            }
+        }
+        companySigningMapper.delete(new QueryWrapper<CompanySigning>().in("company_id",companyIdsToDelete));
+        auditWorkflowTimeSettingMapper.delete(new QueryWrapper<AuditWorkflowTimeSetting>().in("company_id",companyIdsToDelete));
+        companyCustomerContactMapper.delete(new QueryWrapper<CompanyCustomerContact>().in("company_id",companyIdsToDelete));
+        companyDingdingMapper.delete(new QueryWrapper<CompanyDingding>().in("company_id",companyIdsToDelete));
+        companyReportMapper.delete(new QueryWrapper<CompanyReport>().in("company_id",companyIdsToDelete));
+        customerInfoMapper.delete(new QueryWrapper<CustomerInfo>().in("company_id",companyIdsToDelete));
+        departmentMapper.delete(new QueryWrapper<Department>().in("company_id",companyIdsToDelete));
+        operationRecordMapper.delete(new QueryWrapper<OperationRecord>().in("company_id",companyIdsToDelete));
+
+        List<Project> projectList = projectMapper.selectList(new QueryWrapper<Project>().in("company_id", companyIdsToDelete));
+        if (!projectList.isEmpty()){
+            List<Integer> projectIdList = projectList.stream().distinct().map(Project::getId).collect(Collectors.toList());
+            projectAuditorMapper.delete(new QueryWrapper<ProjectAuditor>().in("project_id", projectIdList));
+            projectBasecostMapper.delete(new QueryWrapper<ProjectBasecost>().in("project_id", projectIdList));
+            projectDocfolderMapper.delete(new QueryWrapper<ProjectDocfolder>().in("project_id", projectIdList));
+            projectDocumentMapper.delete(new QueryWrapper<ProjectDocument>().in("project_id", projectIdList));
+            projectNotifyUserMapper.delete(new QueryWrapper<ProjectNotifyUser>().in("project_id", projectIdList));
+            projectProfessionMapper.delete(new QueryWrapper<ProjectProfession>().in("project_id", projectIdList));
+            projectTimerMapper.delete(new QueryWrapper<ProjectTimer>().in("project_id", projectIdList));
+            projectUserSalaryMapper.delete(new QueryWrapper<ProjectUserSalary>().in("project_id", projectIdList));
+            reportProfessionProgressMapper.delete(new QueryWrapper<ReportProfessionProgress>().in("project_id", projectIdList));
+        }
+        projectMapper.delete(new QueryWrapper<Project>().in("company_id",companyIdsToDelete));
+        projectBasecostSettingMapper.delete(new QueryWrapper<ProjectBasecostSetting>().in("company_id",companyIdsToDelete));
+        projectPercentageMapper.delete(new QueryWrapper<ProjectPercentage>().in("company_id",companyIdsToDelete));
+        subProjectMapper.delete(new QueryWrapper<SubProject>().in("company_id",companyIdsToDelete));
+        projectCategoryMapper.delete(new QueryWrapper<ProjectCategory>().in("company_id",companyIdsToDelete));
+
+        reportMapper.delete(new QueryWrapper<Report>().in("company_id",companyIdsToDelete));
+        reportAuditLogMapper.delete(new QueryWrapper<ReportAuditLog>().in("company_id",companyIdsToDelete));
+        reportExtraDegreeMapper.delete(new QueryWrapper<ReportExtraDegree>().in("company_id",companyIdsToDelete));
+        reportImportLogMapper.delete(new QueryWrapper<ReportImportLog>().in("company_id",companyIdsToDelete));
+
+        sysRoleModuleMapper.deleteNeedToDel(companyIdsToDelete);
+        sysRoleFunctionMapper.deleteNeedToDel(companyIdsToDelete);
+        sysRoleMapper.delete(new QueryWrapper<SysRole>().in("company_id",companyIdsToDelete));
+
+        taskMapper.delete(new QueryWrapper<Task>().in("company_id",companyIdsToDelete));
+        timeTypeMapper.delete(new QueryWrapper<TimeType>().in("company_id",companyIdsToDelete));
+        userMapper.delete(new QueryWrapper<User>().in("company_id",companyIdsToDelete));
+        userCorpwxTimeMapper.delete(new QueryWrapper<UserCorpwxTime>().in("company_id",companyIdsToDelete));
+        wxCorpInfoMapper.delete(new QueryWrapper<WxCorpInfo>().in("company_id",companyIdsToDelete));
+
+        feishuInfoService.remove(new QueryWrapper<FeishuInfo>().in("company_id",companyIdsToDelete));
+
+        companyMapper.delete(new QueryWrapper<Company>().in("id",companyIdsToDelete));
         return msg;
     }
 }

+ 23 - 23
fhKeeper/formulahousekeeper/ops-platform/src/main/java/com/management/platform/entity/Project.java

@@ -167,29 +167,29 @@ public class Project extends Model<Project> {
     @TableField("base_fee")
     private Integer baseFee;
 
-    /**
-     * 一般费用
-     */
-    @TableField("fee_normal")
-    private Double feeNormal;
-
-    /**
-     * 差旅费
-     */
-    @TableField("fee_travel")
-    private Double feeTravel;
-
-    /**
-     * 外包费用
-     */
-    @TableField("fee_outsourcing")
-    private Double feeOutsourcing;
-
-    /**
-     * 人工成本
-     */
-    @TableField("fee_man")
-    private Double feeMan;
+//    /**
+//     * 一般费用
+//     */
+//    @TableField("fee_normal")
+//    private Double feeNormal;
+
+//    /**
+//     * 差旅费
+//     */
+//    @TableField("fee_travel")
+//    private Double feeTravel;
+
+//    /**
+//     * 外包费用
+//     */
+//    @TableField("fee_outsourcing")
+//    private Double feeOutsourcing;
+
+//    /**
+//     * 人工成本
+//     */
+//    @TableField("fee_man")
+//    private Double feeMan;
 
     @TableField(exist = false)
     private String inchargerName;

+ 25 - 0
fhKeeper/formulahousekeeper/ops-platform/src/main/java/com/management/platform/mapper/ProjectBasecostMapper.java

@@ -0,0 +1,25 @@
+package com.management.platform.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.management.platform.entity.Project;
+import com.management.platform.entity.ProjectBasecost;
+import com.management.platform.entity.vo.CustomerProject;
+import com.management.platform.entity.vo.ProjectWithStage;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Update;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * <p>
+ * Mapper 接口
+ * </p>
+ *
+ * @author 吴涛涛
+ * @since 2020-01-03
+ */
+public interface ProjectBasecostMapper extends BaseMapper<ProjectBasecost> {
+
+}

+ 17 - 0
fhKeeper/formulahousekeeper/ops-platform/src/main/java/com/management/platform/mapper/ProjectBasecostSettingMapper.java

@@ -0,0 +1,17 @@
+package com.management.platform.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.management.platform.entity.ProjectBasecost;
+import com.management.platform.entity.ProjectBasecostSetting;
+
+/**
+ * <p>
+ * Mapper 接口
+ * </p>
+ *
+ * @author 吴涛涛
+ * @since 2020-01-03
+ */
+public interface ProjectBasecostSettingMapper extends BaseMapper<ProjectBasecostSetting> {
+
+}

+ 17 - 0
fhKeeper/formulahousekeeper/ops-platform/src/main/java/com/management/platform/mapper/ProjectDocfolderMapper.java

@@ -0,0 +1,17 @@
+package com.management.platform.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.management.platform.entity.ProjectBasecost;
+import com.management.platform.entity.ProjectDocfolder;
+
+/**
+ * <p>
+ * Mapper 接口
+ * </p>
+ *
+ * @author 吴涛涛
+ * @since 2020-01-03
+ */
+public interface ProjectDocfolderMapper extends BaseMapper<ProjectDocfolder> {
+
+}

+ 17 - 0
fhKeeper/formulahousekeeper/ops-platform/src/main/java/com/management/platform/mapper/ProjectDocumentMapper.java

@@ -0,0 +1,17 @@
+package com.management.platform.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.management.platform.entity.ProjectDocfolder;
+import com.management.platform.entity.ProjectDocument;
+
+/**
+ * <p>
+ * Mapper 接口
+ * </p>
+ *
+ * @author 吴涛涛
+ * @since 2020-01-03
+ */
+public interface ProjectDocumentMapper extends BaseMapper<ProjectDocument> {
+
+}

+ 17 - 0
fhKeeper/formulahousekeeper/ops-platform/src/main/java/com/management/platform/mapper/ProjectNotifyUserMapper.java

@@ -0,0 +1,17 @@
+package com.management.platform.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.management.platform.entity.ProjectDocument;
+import com.management.platform.entity.ProjectNotifyUser;
+
+/**
+ * <p>
+ * Mapper 接口
+ * </p>
+ *
+ * @author 吴涛涛
+ * @since 2020-01-03
+ */
+public interface ProjectNotifyUserMapper extends BaseMapper<ProjectNotifyUser> {
+
+}

+ 16 - 0
fhKeeper/formulahousekeeper/ops-platform/src/main/java/com/management/platform/mapper/ProjectPercentageMapper.java

@@ -0,0 +1,16 @@
+package com.management.platform.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.management.platform.entity.ProjectPercentage;
+
+/**
+ * <p>
+ * Mapper 接口
+ * </p>
+ *
+ * @author 吴涛涛
+ * @since 2020-01-03
+ */
+public interface ProjectPercentageMapper extends BaseMapper<ProjectPercentage> {
+
+}

+ 17 - 0
fhKeeper/formulahousekeeper/ops-platform/src/main/java/com/management/platform/mapper/ProjectProfessionMapper.java

@@ -0,0 +1,17 @@
+package com.management.platform.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.management.platform.entity.ProjectPercentage;
+import com.management.platform.entity.ProjectProfession;
+
+/**
+ * <p>
+ * Mapper 接口
+ * </p>
+ *
+ * @author 吴涛涛
+ * @since 2020-01-03
+ */
+public interface ProjectProfessionMapper extends BaseMapper<ProjectProfession> {
+
+}

+ 16 - 0
fhKeeper/formulahousekeeper/ops-platform/src/main/java/com/management/platform/mapper/ProjectTimerMapper.java

@@ -0,0 +1,16 @@
+package com.management.platform.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.management.platform.entity.ProjectTimer;
+
+/**
+ * <p>
+ * Mapper 接口
+ * </p>
+ *
+ * @author 吴涛涛
+ * @since 2020-01-03
+ */
+public interface ProjectTimerMapper extends BaseMapper<ProjectTimer> {
+
+}

+ 17 - 0
fhKeeper/formulahousekeeper/ops-platform/src/main/java/com/management/platform/mapper/ProjectUserSalaryMapper.java

@@ -0,0 +1,17 @@
+package com.management.platform.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.management.platform.entity.ProjectTimer;
+import com.management.platform.entity.ProjectUserSalary;
+
+/**
+ * <p>
+ * Mapper 接口
+ * </p>
+ *
+ * @author 吴涛涛
+ * @since 2020-01-03
+ */
+public interface ProjectUserSalaryMapper extends BaseMapper<ProjectUserSalary> {
+
+}

+ 17 - 0
fhKeeper/formulahousekeeper/ops-platform/src/main/java/com/management/platform/mapper/ReportAuditLogMapper.java

@@ -0,0 +1,17 @@
+package com.management.platform.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.management.platform.entity.ProjectBasecost;
+import com.management.platform.entity.ReportAuditLog;
+
+/**
+ * <p>
+ * Mapper 接口
+ * </p>
+ *
+ * @author 吴涛涛
+ * @since 2020-01-03
+ */
+public interface ReportAuditLogMapper extends BaseMapper<ReportAuditLog> {
+
+}

+ 17 - 0
fhKeeper/formulahousekeeper/ops-platform/src/main/java/com/management/platform/mapper/ReportExtraDegreeMapper.java

@@ -0,0 +1,17 @@
+package com.management.platform.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.management.platform.entity.ReportAuditLog;
+import com.management.platform.entity.ReportExtraDegree;
+
+/**
+ * <p>
+ * Mapper 接口
+ * </p>
+ *
+ * @author 吴涛涛
+ * @since 2020-01-03
+ */
+public interface ReportExtraDegreeMapper extends BaseMapper<ReportExtraDegree> {
+
+}

+ 17 - 0
fhKeeper/formulahousekeeper/ops-platform/src/main/java/com/management/platform/mapper/ReportImportLogMapper.java

@@ -0,0 +1,17 @@
+package com.management.platform.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.management.platform.entity.ReportExtraDegree;
+import com.management.platform.entity.ReportImportLog;
+
+/**
+ * <p>
+ * Mapper 接口
+ * </p>
+ *
+ * @author 吴涛涛
+ * @since 2020-01-03
+ */
+public interface ReportImportLogMapper extends BaseMapper<ReportImportLog> {
+
+}

+ 17 - 0
fhKeeper/formulahousekeeper/ops-platform/src/main/java/com/management/platform/mapper/ReportProfessionProgressMapper.java

@@ -0,0 +1,17 @@
+package com.management.platform.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.management.platform.entity.ProjectDocument;
+import com.management.platform.entity.ReportProfessionProgress;
+
+/**
+ * <p>
+ * Mapper 接口
+ * </p>
+ *
+ * @author 吴涛涛
+ * @since 2020-01-03
+ */
+public interface ReportProfessionProgressMapper extends BaseMapper<ReportProfessionProgress> {
+
+}

+ 17 - 0
fhKeeper/formulahousekeeper/ops-platform/src/main/java/com/management/platform/mapper/SubProjectMapper.java

@@ -0,0 +1,17 @@
+package com.management.platform.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.management.platform.entity.ProjectUserSalary;
+import com.management.platform.entity.SubProject;
+
+/**
+ * <p>
+ * Mapper 接口
+ * </p>
+ *
+ * @author 吴涛涛
+ * @since 2020-01-03
+ */
+public interface SubProjectMapper extends BaseMapper<SubProject> {
+
+}

+ 473 - 247
fhKeeper/formulahousekeeper/timesheet/src/components/taskComponent.vue

@@ -2,54 +2,76 @@
   <div>
     <div style="height: 72vh;overflow: auto;">
         <el-form ref="form1" :model="addForm" :rules="taskRules" label-width="120px">
-            <el-form-item :label="$t('subordinatetotheproject')" v-if="showOrNot" prop="projectId">
-                <el-select v-model="addForm.projectId" :placeholder="$t('defaultText.pleaseChoose')" @change="agentCreatesEvents(1)" filterable="true" style="width:100%;">
-                    <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">
-                            <span style="float: left; color: #8492a6; font-size: 13px;">{{ item.projectCode }}</span>
-                            <span style="float: right;">{{ item.projectName }}</span>
-                        </el-option>
-                    </el-option-group>
-                </el-select>
-            </el-form-item>
-            <el-form-item :label="$t('suoShuRenWuFenZu')" v-if="showOrNot" prop="groupId">
-                <el-select v-model="addForm.groupId" :placeholder="$t('defaultText.pleaseChoose')" @change="agentCreatesEvents(2)" filterable="true" style="width:100%;">
-                    <el-option v-for="item in groupList" :key="item.id" :label="item.name" :value="item.id"></el-option>
-                </el-select>
-            </el-form-item>
-            <el-form-item :label="$t('suoShuRenWuLieBiao')" v-if="showOrNot" prop="stagesId">
-                <el-select v-model="addForm.stagesId" :placeholder="$t('defaultText.pleaseChoose')" filterable="true" style="width:100%;">
-                    <el-option v-for="item in stageList" :key="item.id" :label="item.stagesName" :value="item.id"></el-option>
-                </el-select>
-            </el-form-item>
-            <!--子任务需要选择任务列表 -->
-            <el-form-item :label="$t('tasklist')" prop="stages" v-if="addForm.parentTid != null">
-                <el-select v-model="addForm.stagesId" style="width:100%;" >
-                    <el-option v-for="item in stageList" :key="item.id" :label="item.stagesName" :value="item.id"></el-option>
+            <el-form-item :label="'类型'" v-if="showMmeiLaiDe" prop="taskPlanType">
+                <el-select v-model="addForm.taskPlanType" :placeholder="$t('defaultText.pleaseChoose')" style="width:100%;" :disabled="doYouWantToDisableAll">
+                    <el-option label="出差" :value="1"></el-option>
+                    <el-option label="在办公事处" :value="2"></el-option>
+                    <el-option label="请假" :value="3"></el-option>
                 </el-select>
             </el-form-item>
-            <el-form-item :label="$t('qianZhiRenWu')" prop="aheadTidList" >
-                <el-select v-model="addForm.aheadTidList" style="width:100%;" multiple filterable @change="$forceUpdate()">
-                    <el-option v-for="item in relationdata" :key="item.id" :label="item.name" :value="item.id"></el-option>
-                </el-select>
-            </el-form-item>
-            <el-form-item :label="$t('types')">
-                <el-select v-model="addForm.taskType" style="width:100%;" :disabled="((this.addForm.id != null && user.id != this.addForm.createrId && currentProject.inchargerId != user.id) && !permissions.projectManagement && !permissions.editAnyTask) && !(groupResponsibleId == user.id)" @change="selchg()">
-                    <el-option v-for="item in taskTypeList" :key="item.id" :label="item.name" :value="item.id">
-                        <i :class="item.icon" ></i>
-                        <span>{{item.name}}</span>
-                    </el-option>
-                </el-select>
-            </el-form-item>
-            <el-form-item label="任务完成校验" v-if="user.timeType.taskFileCharge">
-                <el-checkbox v-model="addForm.attachFileRequired" >是否必须上传成果文件</el-checkbox>
-            </el-form-item>
-            <el-form-item  :label="$t('taskdefinition')" prop="name">
-                <el-input v-model="addForm.name" :maxlength="40" :disabled="(this.addForm.id != null && user.id != this.addForm.createrId && currentProject.inchargerId != user.id) && !permissions.projectManagement && !permissions.editAnyTask && !(groupResponsibleId == user.id)" :placeholder="$t('enterthetaskcontent')" clearable></el-input>
-            </el-form-item>
-            <el-form-item  :label="$t('planCost')" prop="planCost" v-if="user.timeType.taskPlanCost">
-                <el-input v-model.number="addForm.planCost" :maxlength="40" :disabled="(this.addForm.id != null && user.id != this.addForm.createrId && currentProject.inchargerId != user.id) && !permissions.projectManagement && !permissions.editAnyTask && !(groupResponsibleId == user.id)" :placeholder="$t('planCostHint')" clearable></el-input>
-            </el-form-item>
+            <template v-if="addForm.taskPlanType != 3">
+                <el-form-item :label="$t('subordinatetotheproject')" v-if="showOrNot" prop="projectId">
+                    <el-select v-model="addForm.projectId" :placeholder="$t('defaultText.pleaseChoose')" @change="agentCreatesEvents(1)" filterable="true" style="width:100%;" :disabled="doYouWantToDisableAll">
+                        <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">
+                                <span style="float: left; color: #8492a6; font-size: 13px;">{{ item.projectCode }}</span>
+                                <span style="float: right;">{{ item.projectName }}</span>
+                            </el-option>
+                        </el-option-group>
+                    </el-select>
+                </el-form-item>
+                <el-form-item :label="$t('suoShuRenWuFenZu')" v-if="showOrNot" prop="groupId">
+                    <el-select v-model="addForm.groupId" :placeholder="$t('defaultText.pleaseChoose')" @change="agentCreatesEvents(2)" filterable="true" style="width:100%;" :disabled="doYouWantToDisableAll">
+                        <el-option v-for="item in groupList" :key="item.id" :label="item.name" :value="item.id"></el-option>
+                    </el-select>
+                </el-form-item>
+                <el-form-item :label="$t('suoShuRenWuLieBiao')" v-if="showOrNot" prop="stagesId">
+                    <el-select v-model="addForm.stagesId" :placeholder="$t('defaultText.pleaseChoose')" filterable="true" style="width:100%;" :disabled="doYouWantToDisableAll">
+                        <el-option v-for="item in stageList" :key="item.id" :label="item.stagesName" :value="item.id"></el-option>
+                    </el-select>
+                </el-form-item>
+                <!--子任务需要选择任务列表 -->
+                <el-form-item :label="$t('tasklist')" prop="stages" v-if="addForm.parentTid != null">
+                    <el-select v-model="addForm.stagesId" style="width:100%;" >
+                        <el-option v-for="item in stageList" :key="item.id" :label="item.stagesName" :value="item.id"></el-option>
+                    </el-select>
+                </el-form-item>
+                <el-form-item :label="$t('qianZhiRenWu')" prop="aheadTidList" >
+                    <el-select v-model="addForm.aheadTidList" style="width:100%;" multiple filterable @change="$forceUpdate()" :disabled="doYouWantToDisableAll">
+                        <el-option v-for="item in relationdata" :key="item.id" :label="item.name" :value="item.id"></el-option>
+                    </el-select>
+                </el-form-item>
+                <el-form-item :label="$t('types')" v-if="!showMmeiLaiDe">
+                    <el-select v-model="addForm.taskType" style="width:100%;" :disabled="((this.addForm.id != null && user.id != this.addForm.createrId && currentProject.inchargerId != user.id) && !permissions.projectManagement && !permissions.editAnyTask) && !(groupResponsibleId == user.id)" @change="selchg()">
+                        <el-option v-for="item in taskTypeList" :key="item.id" :label="item.name" :value="item.id">
+                            <i :class="item.icon" ></i>
+                            <span>{{item.name}}</span>
+                        </el-option>
+                    </el-select>
+                </el-form-item>
+                <el-form-item label="任务完成校验" v-if="user.timeType.taskFileCharge">
+                    <el-checkbox v-model="addForm.attachFileRequired" >是否必须上传成果文件</el-checkbox>
+                </el-form-item>
+                <el-form-item label="审核人" v-if="showMmeiLaiDe && user.roleId != 2283" prop="checkSecondId">
+                    <div class="customizedReviewer">
+                        <el-select v-model="addForm.checkFirstId" :disabled="true" size="small">
+                            <el-option v-for="item in users" :key="item.id" :label="item.name" :value="item.id"></el-option>
+                        </el-select>
+                        <div style="margin: 0 20px;"> ------------------ > </div> 
+                        <el-select v-model="addForm.checkSecondId" :disabled="!addForm.checkFirstId || doYouWantToDisableAll" size="small">
+                            <el-option v-for="item in pmUserList" :key="item.id" :label="item.name" :value="item.id"></el-option>
+                        </el-select>
+                    </div>
+                    
+                </el-form-item>
+                <el-form-item  :label="$t('taskdefinition')" prop="name">
+                    <el-input v-model="addForm.name" :maxlength="40" :disabled="(this.addForm.id != null && user.id != this.addForm.createrId && currentProject.inchargerId != user.id) && !permissions.projectManagement && !permissions.editAnyTask && !(groupResponsibleId == user.id)" :placeholder="$t('enterthetaskcontent')" clearable></el-input>
+                </el-form-item>
+                <el-form-item  :label="$t('planCost')" prop="planCost" v-if="user.timeType.taskPlanCost">
+                    <el-input v-model.number="addForm.planCost" :maxlength="40" :disabled="(this.addForm.id != null && user.id != this.addForm.createrId && currentProject.inchargerId != user.id) && !permissions.projectManagement && !permissions.editAnyTask && !(groupResponsibleId == user.id)" :placeholder="$t('planCostHint')" clearable></el-input>
+                </el-form-item>
+            </template>
+           
             <!-- {{timelabel}}{{mileageCup}} -->
             <el-form-item :label="!timelabel ? $t('starttimes') : $t('jie-zhi-shi-jian')" prop="startDate">
                 <el-date-picker v-model="addForm.startDate" type="date" style="width:40%;" value-format="yyyy-MM-dd"  
@@ -137,216 +159,220 @@
             groupResponsibleId == user.id)" 
             style="margin:0 0 10px 35px;position: relative;z-index: 999;" @click.stop="addExecutorLine">{{ $t('addinganexecutor') }}</el-link>
             </div>
-            <el-form-item :label="$t('priority')">
-                <el-select v-model="addForm.taskLevel" style="width:100%;" >
-                    <el-option v-for="item in importanceList" :key="item.id" :label="item.name" :value="item.id"></el-option>
-                </el-select>
-            </el-form-item>
-            <!-- 富文本 -->
-            <el-form-item :label="$t('detaileddescription')" style="height: 200px">
-                <!-- <Editor id="tinymce" v-model="tinymceHtml" :init="editorInit"></Editor> -->
-                <!-- <el-input type="textarea" v-model="addForm.taskDesc" :rows="3"></el-input> -->
-                <!-- <quill-edito v-model="addForm.taskDesc"></quill-edito> -->
-                <quill-editor style="height: 150px" ref="text" v-model="addForm.taskDesc" class="myQuillEditor" :options="editorOption" @blur="onEditorBlur($event)" @focus="onEditorFocus($event)"/>
-            </el-form-item>
-            <!-- 富文本 -->
-            <div v-if="addForm.id != null">
-                <el-divider ></el-divider>
-                <!-- 任务进展 -->
-                <template v-if="!timelabel || isRelationItem">
-                
-                <p ><i class="iconfont firerock-icontree themeFontColor" style="margin-left:10px;">{{ $t('taskprogress') }}</i>
-                    <span ref="addPro" style="display: block; float:right;"><el-link @click="addprogress">{{ $t('addtaskprogress') }}</el-link></span>
-                </p>
-                <!-- 任务进展展示 -->
-                <div style="display: none;" ref="proBox" class="progress">
-                    <!-- <el-form :model="> -->
-                    <el-radio-group v-model="radio">
-                        <el-radio :label="0" class="rala1">{{ $t('normals') }}</el-radio>
-                        <el-radio :label="1" class="rala2">{{ $t('atrisk') }}</el-radio>
-                        <el-radio :label="2" class="rala3">{{ $t('withinthetimelimit') }}</el-radio>
-                    </el-radio-group>
-                    <el-input
-                    type="textarea"
-                    border="0"
-                    :autosize="{ minRows: 2, maxRows: 6}"
-                    :placeholder="$t('detailedprogressdescription')"
-                    v-model="text2"
-                    style="margin:10px 0 0 0">
-                    </el-input>
-                    <h4 style="font-weight: normal;">{{ $t('tixiang') }}{{checkLists.length}}</h4>
-                    <i class="el-icon-circle-plus pron_i themeFontColor" style="font-size: 28px;" @click="addI(0)"></i>
-                    <div class="remind" ref="addRem" style="display: none">
-                        <el-checkbox-group v-model="checkboxGrounp" v-for="item in users" :key="item.id">
-                            <p>
-                                <el-checkbox :label="item.name" @change="kkk(item)">
-                                    <span>
-                                        <span v-if="user.userNameNeedTranslate != '1'">
-                                            {{item.name}}
-                                        </span>
-                                        <span v-if="user.userNameNeedTranslate == '1'">
-                                            <TranslationOpenDataText type='userName' :openid='item.name'></TranslationOpenDataText>
+
+            <template v-if="addForm.taskPlanType != 3">
+                <el-form-item :label="$t('priority')">
+                    <el-select v-model="addForm.taskLevel" style="width:100%;" :disabled="doYouWantToDisableAll">
+                        <el-option v-for="item in importanceList" :key="item.id" :label="item.name" :value="item.id"></el-option>
+                    </el-select>
+                </el-form-item>
+                <!-- 富文本 -->
+                <el-form-item :label="$t('detaileddescription')" style="height: 200px">
+                    <!-- <Editor id="tinymce" v-model="tinymceHtml" :init="editorInit"></Editor> -->
+                    <!-- <el-input type="textarea" v-model="addForm.taskDesc" :rows="3"></el-input> -->
+                    <!-- <quill-edito v-model="addForm.taskDesc"></quill-edito> -->
+                    <quill-editor style="height: 150px" ref="text" v-model="addForm.taskDesc" class="myQuillEditor" :options="editorOption" @blur="onEditorBlur($event)" @focus="onEditorFocus($event)" :disabled="doYouWantToDisableAll"/>
+                </el-form-item>
+                <!-- 富文本 -->
+                <div v-if="addForm.id != null">
+                    <el-divider ></el-divider>
+                    <!-- 任务进展 -->
+                    <template v-if="!timelabel || isRelationItem">
+                    
+                    <p ><i class="iconfont firerock-icontree themeFontColor" style="margin-left:10px;">{{ $t('taskprogress') }}</i>
+                        <span ref="addPro" style="display: block; float:right;"><el-link @click="addprogress">{{ $t('addtaskprogress') }}</el-link></span>
+                    </p>
+                    <!-- 任务进展展示 -->
+                    <div style="display: none;" ref="proBox" class="progress">
+                        <!-- <el-form :model="> -->
+                        <el-radio-group v-model="radio">
+                            <el-radio :label="0" class="rala1">{{ $t('normals') }}</el-radio>
+                            <el-radio :label="1" class="rala2">{{ $t('atrisk') }}</el-radio>
+                            <el-radio :label="2" class="rala3">{{ $t('withinthetimelimit') }}</el-radio>
+                        </el-radio-group>
+                        <el-input
+                        type="textarea"
+                        border="0"
+                        :autosize="{ minRows: 2, maxRows: 6}"
+                        :placeholder="$t('detailedprogressdescription')"
+                        v-model="text2"
+                        style="margin:10px 0 0 0">
+                        </el-input>
+                        <h4 style="font-weight: normal;">{{ $t('tixiang') }}{{checkLists.length}}</h4>
+                        <i class="el-icon-circle-plus pron_i themeFontColor" style="font-size: 28px;" @click="addI(0)"></i>
+                        <div class="remind" ref="addRem" style="display: none">
+                            <el-checkbox-group v-model="checkboxGrounp" v-for="item in users" :key="item.id">
+                                <p>
+                                    <el-checkbox :label="item.name" @change="kkk(item)">
+                                        <span>
+                                            <span v-if="user.userNameNeedTranslate != '1'">
+                                                {{item.name}}
+                                            </span>
+                                            <span v-if="user.userNameNeedTranslate == '1'">
+                                                <TranslationOpenDataText type='userName' :openid='item.name'></TranslationOpenDataText>
+                                            </span>
                                         </span>
-                                    </span>
-                                </el-checkbox>
-                            </p>
-                        </el-checkbox-group>
-                    </div>
-                    <div class="ssp" @click="sss"></div>
-                    <!-- </el-form> -->
-                    <div class="pro_btn">
-                        <el-button size="mini" @click="shutPro">{{ $t('btn.cancel') }}</el-button>
-                        <el-button size="mini" type="primary" @click="addTaskProgress">{{ $t('fa-bu') }}</el-button>
+                                    </el-checkbox>
+                                </p>
+                            </el-checkbox-group>
+                        </div>
+                        <div class="ssp" @click="sss"></div>
+                        <!-- </el-form> -->
+                        <div class="pro_btn">
+                            <el-button size="mini" @click="shutPro">{{ $t('btn.cancel') }}</el-button>
+                            <el-button size="mini" type="primary" @click="addTaskProgress">{{ $t('fa-bu') }}</el-button>
+                        </div>
                     </div>
-                </div>
-                
-                <div class="ddl" v-if="recentProgressInfo != null && recentProgressInfo.id != null">
-                    <div class="elCard" style="margin-bottom: 10px; height:" >
-                        <i class="el-icon-success" style="color: #43d14f;" v-if="recentProgressInfo.status == 0"></i>
-                        <i class="el-icon-success" style="color: #fd7624;" v-else-if="recentProgressInfo.status == 1"></i>
-                        <i class="el-icon-success" style="color: #fd4d47;" v-else></i>
-                        <span v-if="recentProgressInfo.status == 0">{{ $t('normals') }}</span>
-                        <span v-else-if="recentProgressInfo.status == 1">{{ $t('normals') }}</span>
-                        <span v-else>{{ $t('withinthetimelimit') }}</span>
-                        <el-dropdown trigger="click" style="float:right;cursor:pointer; float: right;">
-                                <i class="el-icon-more" ></i>
-                                <el-dropdown-menu slot="dropdown">
-                                    <el-dropdown-item divided>
-                                        <span @click="deleteTaskProgress(recentProgressInfo.id)"><i class="el-icon-delete"></i>{{ $t('deleteList ') }}</span></el-dropdown-item>
-                                </el-dropdown-menu>
-                        </el-dropdown>
-                        <!-- <div class="elCard_qu">{{recentProgressInfo.creatorName}}{{ $t('geng-xin-yu') }}{{recentProgressInfo.indate | relativeTime}}</div> -->
-                        <div class="elCard_qu">
-                            <span>
-                                <span v-if="user.userNameNeedTranslate != '1'">
-                                    {{recentProgressInfo.creatorName}}
-                                </span>
-                                <span v-if="user.userNameNeedTranslate == '1'">
-                                    <TranslationOpenDataText type='userName' :openid='recentProgressInfo.creatorName'></TranslationOpenDataText>
+                    
+                    <div class="ddl" v-if="recentProgressInfo != null && recentProgressInfo.id != null">
+                        <div class="elCard" style="margin-bottom: 10px; height:" >
+                            <i class="el-icon-success" style="color: #43d14f;" v-if="recentProgressInfo.status == 0"></i>
+                            <i class="el-icon-success" style="color: #fd7624;" v-else-if="recentProgressInfo.status == 1"></i>
+                            <i class="el-icon-success" style="color: #fd4d47;" v-else></i>
+                            <span v-if="recentProgressInfo.status == 0">{{ $t('normals') }}</span>
+                            <span v-else-if="recentProgressInfo.status == 1">{{ $t('normals') }}</span>
+                            <span v-else>{{ $t('withinthetimelimit') }}</span>
+                            <el-dropdown trigger="click" style="float:right;cursor:pointer; float: right;">
+                                    <i class="el-icon-more" ></i>
+                                    <el-dropdown-menu slot="dropdown">
+                                        <el-dropdown-item divided>
+                                            <span @click="deleteTaskProgress(recentProgressInfo.id)"><i class="el-icon-delete"></i>{{ $t('deleteList ') }}</span></el-dropdown-item>
+                                    </el-dropdown-menu>
+                            </el-dropdown>
+                            <!-- <div class="elCard_qu">{{recentProgressInfo.creatorName}}{{ $t('geng-xin-yu') }}{{recentProgressInfo.indate | relativeTime}}</div> -->
+                            <div class="elCard_qu">
+                                <span>
+                                    <span v-if="user.userNameNeedTranslate != '1'">
+                                        {{recentProgressInfo.creatorName}}
+                                    </span>
+                                    <span v-if="user.userNameNeedTranslate == '1'">
+                                        <TranslationOpenDataText type='userName' :openid='recentProgressInfo.creatorName'></TranslationOpenDataText>
+                                    </span>
                                 </span>
-                            </span>
-                            {{ $t('geng-xin-yu') }}{{recentProgressInfo.indate | relativeTime}}
+                                {{ $t('geng-xin-yu') }}{{recentProgressInfo.indate | relativeTime}}
+                            </div>
+                            <p style="padding-left: 20px;">{{recentProgressInfo.content}}</p>
+                            <div class="examine"><el-button type="text" @click="innerVisibless = true" style="color: #8F87A3;">{{ $t('viewingHistory') }}</el-button></div>
                         </div>
-                        <p style="padding-left: 20px;">{{recentProgressInfo.content}}</p>
-                        <div class="examine"><el-button type="text" @click="innerVisibless = true" style="color: #8F87A3;">{{ $t('viewingHistory') }}</el-button></div>
                     </div>
-                </div>
-                <!-- 任务列表没有数据的时候展示 -->
-                <div class="nones" v-if="ProgressList.length <= 0">
-                    {{ $t('nodata') }} 
-                </div>
-                <!-- 任务进展完整状态 -->
-                <el-dialog :title="$t('other.prompts')" :visible.sync="innerVisibless" append-to-body width="500px">
-                <div class="integrity">
-                    <h3 style="font-weight: normal;display: inline-block;margin: 0 0 20px 0;">{{ $t('taskprogress') }} :{{ProgressList.length}}</h3>
-                    <!-- <span class="write"><i class="el-icon-circle-plus"></i>填写进展</span> -->
-                    <el-divider></el-divider>
-                    <!--  -->
-                        <div class="block" style="height: 200px;">
-                            <el-timeline style="padding:20px 0 0 0;">
-                                <el-timeline-item
-                                v-for="(activity, index) in ProgressList"
-                                :key="index">
-                                <div class="tb">
-                                    <span v-if="activity.status == 0" style="color: #43D14F" class="icon"></span>
-                                    <span v-if="activity.status == 1" style="color: #FD7624" class="icon"></span>
-                                    <span v-if="activity.status == 2" style="color: red" class="icon"></span>
-                                    <div>
-                                        <span v-if="activity.status == 0" style="color: #43D14F">{{ $t('normals') }}</span>
-                                        <span v-if="activity.status == 1" style="color: #FD7624">{{ $t('atrisk') }}</span>
-                                        <span v-if="activity.status == 2" style="color: red">{{ $t('withinthetimelimit') }}</span>
-                                        <span style="display: inline-block; float: right; color: #8C8C8C">{{activity.indate | relativeTime}}</span>
+                    <!-- 任务列表没有数据的时候展示 -->
+                    <div class="nones" v-if="ProgressList.length <= 0">
+                        {{ $t('nodata') }} 
+                    </div>
+                    <!-- 任务进展完整状态 -->
+                    <el-dialog :title="$t('other.prompts')" :visible.sync="innerVisibless" append-to-body width="500px">
+                    <div class="integrity">
+                        <h3 style="font-weight: normal;display: inline-block;margin: 0 0 20px 0;">{{ $t('taskprogress') }} :{{ProgressList.length}}</h3>
+                        <!-- <span class="write"><i class="el-icon-circle-plus"></i>填写进展</span> -->
+                        <el-divider></el-divider>
+                        <!--  -->
+                            <div class="block" style="height: 200px;">
+                                <el-timeline style="padding:20px 0 0 0;">
+                                    <el-timeline-item
+                                    v-for="(activity, index) in ProgressList"
+                                    :key="index">
+                                    <div class="tb">
+                                        <span v-if="activity.status == 0" style="color: #43D14F" class="icon"></span>
+                                        <span v-if="activity.status == 1" style="color: #FD7624" class="icon"></span>
+                                        <span v-if="activity.status == 2" style="color: red" class="icon"></span>
+                                        <div>
+                                            <span v-if="activity.status == 0" style="color: #43D14F">{{ $t('normals') }}</span>
+                                            <span v-if="activity.status == 1" style="color: #FD7624">{{ $t('atrisk') }}</span>
+                                            <span v-if="activity.status == 2" style="color: red">{{ $t('withinthetimelimit') }}</span>
+                                            <span style="display: inline-block; float: right; color: #8C8C8C">{{activity.indate | relativeTime}}</span>
+                                        </div>
+                                        <p style="color: #8C8C8C">{{activity.content}}</p>
+                                        
                                     </div>
-                                    <p style="color: #8C8C8C">{{activity.content}}</p>
-                                    
-                                </div>
-                                </el-timeline-item>
-                            </el-timeline>
-                        </div>
-                    <!--  -->
-                </div>
-                <span slot="footer" class="dialog-footer foooot">
-                    <el-button type="primary" @click="innerVisibless = false">{{ $t('Shutdown') }}</el-button>
-                </span>
-                </el-dialog>
-                </template>
-                <!-- 子任务/关联任务 -->
-                <p ><i class="iconfont firerock-icontree themeFontColor" style="margin-left:10px;">{{timelabel && !isRelationItem ? $t('guanlian') : $t('zirwu')}}</i>
-                    <el-link style="float:right;" @click="addRelation" v-if="timelabel && !isRelationItem">{{ $t('associatedTask') }}</el-link>
-                    <el-link style="float:right;" @click="addSubTask" v-else>{{ $t('addingsubtask') }}</el-link>
-                </p>
-                <!-- 关联任务列表 -->
-                <el-table key="guanlian" :data="relationSubTaskList" v-if="timelabel && !isRelationItem"
-                :header-cell-style="{'font-weight':'normal'}"
-                highlight-current-row
-                v-loading="listLoading"
-                style="width: 100%;margin-top:10px;"
-                @row-click="relationTaskClick">
-                    <el-table-column prop="taskStatus" :label="$t('wan-cheng')" width="50" >
-                        <template slot-scope="scope">
-                            <el-checkbox :disabled="scope.row.taskStatus==2" :checked="scope.row.taskStatus==1?true:false" size="large" class="cb" @change="relationFinishTask(scope.row)"></el-checkbox>
-                        </template>
-                    </el-table-column>
-                    <el-table-column prop="taskName" :label="$t('biao-ti')" >
-                        <template slot-scope="scope">
-                            <el-tooltip class="item themeFontColor" effect="dark" :content="scope.row.taskName" placement="top" style="cursor:pointer;">
-                                <span style="overflow: hidden;text-overflow:ellipsis;white-space: nowrap;" > {{scope.row.taskName}}</span>
-                            </el-tooltip>
-                        </template>
-                    </el-table-column>
-                    <el-table-column :label="$t('operation')" width="130" align="left">
-                        <template slot-scope="scope">
-                            <el-button @click.stop.native="deleteRelationItem(scope.row.id)" size="mini">{{ $t('dissociated') }}</el-button>
-                        </template>
-                    </el-table-column>
-                </el-table>
-                <!--子任务列表 -->
-                <el-table key="zi" :data="addForm.subTaskList" v-else
-                        :header-cell-style="{'font-weight':'normal'}"
-                        highlight-current-row v-loading="listLoading" style="width: 100%;margin-top:10px;" @row-click="taskLineClick">
-                            <el-table-column prop="taskStatus" :label="$t('wan-cheng')" width="50" >
+                                    </el-timeline-item>
+                                </el-timeline>
+                            </div>
+                        <!--  -->
+                    </div>
+                    <span slot="footer" class="dialog-footer foooot">
+                        <el-button type="primary" @click="innerVisibless = false">{{ $t('Shutdown') }}</el-button>
+                    </span>
+                    </el-dialog>
+                    </template>
+                    <!-- 子任务/关联任务 -->
+                    <p ><i class="iconfont firerock-icontree themeFontColor" style="margin-left:10px;">{{timelabel && !isRelationItem ? $t('guanlian') : $t('zirwu')}}</i>
+                        <el-link style="float:right;" @click="addRelation" v-if="timelabel && !isRelationItem">{{ $t('associatedTask') }}</el-link>
+                        <el-link style="float:right;" @click="addSubTask" v-else>{{ $t('addingsubtask') }}</el-link>
+                    </p>
+                    <!-- 关联任务列表 -->
+                    <el-table key="guanlian" :data="relationSubTaskList" v-if="timelabel && !isRelationItem"
+                    :header-cell-style="{'font-weight':'normal'}"
+                    highlight-current-row
+                    v-loading="listLoading"
+                    style="width: 100%;margin-top:10px;"
+                    @row-click="relationTaskClick">
+                        <el-table-column prop="taskStatus" :label="$t('wan-cheng')" width="50" >
                             <template slot-scope="scope">
-                            <el-checkbox :disabled="scope.row.taskStatus==2" :checked="scope.row.taskStatus==1?true:false" size="large" class="cb"  
-                                            @change="finishTask(scope.row)"
-                                            ></el-checkbox>
+                                <el-checkbox :disabled="scope.row.taskStatus==2" :checked="scope.row.taskStatus==1?true:false" size="large" class="cb" @change="relationFinishTask(scope.row)"></el-checkbox>
                             </template>
                         </el-table-column>
-                        <el-table-column prop="name" :label="$t('biao-ti')" >
+                        <el-table-column prop="taskName" :label="$t('biao-ti')" >
                             <template slot-scope="scope">
-                                <el-tooltip class="item" effect="dark" :content="scope.row.name" placement="top">
-                                <span style="overflow: hidden;text-overflow:ellipsis;white-space: nowrap;" > {{scope.row.name}}</span>
+                                <el-tooltip class="item themeFontColor" effect="dark" :content="scope.row.taskName" placement="top" style="cursor:pointer;">
+                                    <span style="overflow: hidden;text-overflow:ellipsis;white-space: nowrap;" > {{scope.row.taskName}}</span>
                                 </el-tooltip>
                             </template>
                         </el-table-column>
-                        <el-table-column prop="executorName" :label="$t('zhi-hang-ren')" width="100" >
+                        <el-table-column :label="$t('operation')" width="130" align="left">
                             <template slot-scope="scope">
-                                <span v-if="user.userNameNeedTranslate != 1">
-                                    {{scope.row.executorName == null?$t('dai-fen-pei'):scope.row.executorName}}
-                                </span>
-                                <span v-if="user.userNameNeedTranslate == 1">
-                                    <span v-if="scope.row.executorName == null">
-                                        {{$t('dai-fen-pei')}}
+                                <el-button @click.stop.native="deleteRelationItem(scope.row.id)" size="mini">{{ $t('dissociated') }}</el-button>
+                            </template>
+                        </el-table-column>
+                    </el-table>
+                    <!--子任务列表 -->
+                    <el-table key="zi" :data="addForm.subTaskList" v-else
+                            :header-cell-style="{'font-weight':'normal'}"
+                            highlight-current-row v-loading="listLoading" style="width: 100%;margin-top:10px;" @row-click="taskLineClick">
+                                <el-table-column prop="taskStatus" :label="$t('wan-cheng')" width="50" >
+                                <template slot-scope="scope">
+                                <el-checkbox :disabled="scope.row.taskStatus==2" :checked="scope.row.taskStatus==1?true:false" size="large" class="cb"  
+                                                @change="finishTask(scope.row)"
+                                                ></el-checkbox>
+                                </template>
+                            </el-table-column>
+                            <el-table-column prop="name" :label="$t('biao-ti')" >
+                                <template slot-scope="scope">
+                                    <el-tooltip class="item" effect="dark" :content="scope.row.name" placement="top">
+                                    <span style="overflow: hidden;text-overflow:ellipsis;white-space: nowrap;" > {{scope.row.name}}</span>
+                                    </el-tooltip>
+                                </template>
+                            </el-table-column>
+                            <el-table-column prop="executorName" :label="$t('zhi-hang-ren')" width="100" >
+                                <template slot-scope="scope">
+                                    <span v-if="user.userNameNeedTranslate != 1">
+                                        {{scope.row.executorName == null?$t('dai-fen-pei'):scope.row.executorName}}
                                     </span>
-                                    <span v-else>
-                                        <span v-for="item,index in scope.row.executorName" :key="index">
-                                            <TranslationOpenDataText type='userName' :openid='item'></TranslationOpenDataText>
-                                            <span v-if="index < scope.row.executorName.length - 1">,</span>
+                                    <span v-if="user.userNameNeedTranslate == 1">
+                                        <span v-if="scope.row.executorName == null">
+                                            {{$t('dai-fen-pei')}}
+                                        </span>
+                                        <span v-else>
+                                            <span v-for="item,index in scope.row.executorName" :key="index">
+                                                <TranslationOpenDataText type='userName' :openid='item'></TranslationOpenDataText>
+                                                <span v-if="index < scope.row.executorName.length - 1">,</span>
+                                            </span>
                                         </span>
                                     </span>
-                                </span>
-                            </template>
-                        </el-table-column>
-                        <el-table-column prop="endDate" :label="$t('deadline')" width="100" >
-                            <template slot-scope="scope">
-                                <p v-if="scope.row.endDate >= times">{{scope.row.endDate}}</p>
-                                <p v-else style="background: #e62412; color: #fff;text-align: center; border-radius: 3px;">{{scope.row.endDate}}</p>
-                            </template>
-                        </el-table-column>
-                </el-table>
-            </div>
+                                </template>
+                            </el-table-column>
+                            <el-table-column prop="endDate" :label="$t('deadline')" width="100" >
+                                <template slot-scope="scope">
+                                    <p v-if="scope.row.endDate >= times">{{scope.row.endDate}}</p>
+                                    <p v-else style="background: #e62412; color: #fff;text-align: center; border-radius: 3px;">{{scope.row.endDate}}</p>
+                                </template>
+                            </el-table-column>
+                    </el-table>
+                </div>
+            </template>
+            
         </el-form>
         <!-- 关联文件列表 -->
-        <template v-if="isEditFile">
+        <template v-if="isEditFile && addForm.taskPlanType != 3">
             <div style="width:100%;margin:1em 0;">
                 <i class="iconfont firerock-icontree themeFontColor" style="margin-left:10px;">{{ $t('jiafuchengguo') }}</i>
                 <el-link @click="relationFileClick()" style="float:right;margin-left:10px">{{ $t('associatedfiles') }}</el-link>
@@ -465,9 +491,20 @@
         </el-dialog>
     </div>
     <div slot="footer" class="dialog-footer foooot">
-        <el-button v-if="(user.id == addForm.createrId || currentProject.inchargerId == user.id || currentProject.creatorId == user.id || permissions.projectManagement) && canAddTask" @click.native="deleteTask()" style="float:left;">{{ $t('btn.delete') }}</el-button>
+        <template v-if="!showMmeiLaiDe">
+            <el-button v-if="(user.id == addForm.createrId || currentProject.inchargerId == user.id || currentProject.creatorId == user.id || permissions.projectManagement) && canAddTask" @click.native="deleteTask()" style="float:left;">{{ $t('btn.delete') }}</el-button>
+        </template>
+        <template v-if="showMmeiLaiDe">
+            <el-button v-if="[0, 1, 2, 3, 5, 6].includes(showMmeiLaiDeData.taskStatus)" @click.native="deleteTask()" style="float:left;">{{ $t('btn.delete') }}</el-button>
+        </template>
         <el-button type="primary" v-if="user.userNameNeedTranslate == 1 && !meetingId && !integrationTask.stage && addForm.executorListFront[0].executorId" @click="meetingCli()">{{ $t('faQiHuiYi') }}</el-button>
         <el-button @click.native="closeBounceds()">{{ $t('btn.cancel') }}</el-button>
+        <template v-if="showMmeiLaiDe && addForm.id && millerSReviewer.includes(user.id) && [3, 4].includes(showMmeiLaiDeData.taskStatus) && showMmeiLaiDeData.leaderOrManager == 2">
+            <template v-if="(showMmeiLaiDeData.taskStatus == 3 && user.id == showMmeiLaiDeData.checkFirstId) || (showMmeiLaiDeData.taskStatus == 4 && user.id == showMmeiLaiDeData.checkSecondId)">
+                <el-button type="danger" @click="planOperation(false)" :loading="addLoading">驳回</el-button>
+                <el-button type="success" @click="planOperation(true)" :loading="addLoading">通过</el-button>
+            </template>
+        </template>
         <el-button type="primary" @click="submitInsert" :loading="addLoading">{{ $t('btn.submit') }}</el-button>
     </div>
     
@@ -475,7 +512,7 @@
         <el-page-header  @back="backToParentTask" :title="timelabel ? $t('returnmilestone') : $t('parenttask')" :content="timelabel ? relationPar.name : addForm.parentTname"></el-page-header>
     </div> -->
     <!-- 评论 -->
-    <div class="remark" v-show="addForm.id != null">
+    <div class="remark" v-show="addForm.id != null && !showMmeiLaiDe">
         <span class="zh">
                 <div class="player">
                     <p>{{ $t('participantin') }}</p>
@@ -746,6 +783,15 @@ export default {
     showOrNot: {
         type: Boolean,
         default: false
+    },
+    // 是否属于美莱得定制化的工作计划
+    showMmeiLaiDe: {
+        type: Boolean,
+        default: false
+    },
+    showMmeiLaiDeData: {
+        type: Object,
+        default: {}
     }
   },
   components: {
@@ -755,6 +801,7 @@ export default {
   },
   data() {
     return { 
+        doYouWantToDisableAll: false,
         startNum: 0,
         endNum: 5,
         shownumber: 5,
@@ -854,6 +901,8 @@ export default {
             groupId: [{ required: true, message: this.$t('qingXuanZeSuoShuRenWuFenZu'), trigger: "blur" }],
             stagesId: [{ required: true, message: this.$t('qingXuanZeSuoShuRenWuLieBiao'), trigger: "blur" }],
             planCost: [{ required: true, message: this.$t('planCostHint'), trigger: "blur" }],
+            taskPlanType: [{ required: true, message: '请选择类型', trigger: "blur" }],
+            checkSecondId: [{ required: true, message: '请选择审核人', trigger: "blur" }]
         },
         formGrouping: {
             name: [{ required: true, message: this.$t('pleaseenteragroupname'), trigger: "blur" }],
@@ -972,7 +1021,9 @@ export default {
             startTime: '',
             endTime: '',
             taskId: ''
-        }
+        },
+        pmUserList: [],
+        millerSReviewer: [],
     };
   },
   computed: {
@@ -1009,8 +1060,20 @@ export default {
     this.getSapServiceList()
 
     this.timess();
+
+    if(this.showMmeiLaiDe) {
+        this.getPmUserList()
+        this.setDisabledPermission()
+    }
   },
   methods: {
+    setDisabledPermission() {
+        const { taskStatus } = this.showMmeiLaiDeData
+        this.doYouWantToDisableAll = taskStatus == 3 || taskStatus == 4
+        if(this.millerSReviewer.includes(this.user.id)) {
+            this.doYouWantToDisableAll = false
+        }
+    },
     viewOnline(row) {
         sessionStorage.setItem("fileName",row.documentName);
         sessionStorage.setItem("fileUrl",row.url);
@@ -1056,7 +1119,7 @@ export default {
         this.refreshData()
     },
     confirmMeeting() {
-        this.http.post('/task//operateMeeting',{...this.initiateAMeetingForm},
+        this.http.post('/task/operateMeeting',{...this.initiateAMeetingForm},
         res => {
             if (res.code == "ok") {
                 this.meetingVisable=false,
@@ -1080,6 +1143,35 @@ export default {
             });
         });
     },
+    planOperation(type) {
+        this.http.post('/task/taskPlanPassOrReject', {
+            taskId: this.addForm.id, type
+        },
+        res => {
+            if (res.code == "ok") {
+                this.$message({
+                    message: '操作成功',
+                    type: "success"
+                });
+                let obj = {
+                    submitInsert: true,
+                    showOrNot: this.showOrNot
+                }
+                this.$emit('closeBounced', obj)
+            } else {
+                this.$message({
+                    message: res.msg,
+                    type: "error"
+                });
+            }
+        },
+        error => {
+            this.$message({
+                message: error,
+                type: "error"
+            });
+        });
+    },
     // 触发外层的会议
     meetingCli() {
         // this.$parent.$parent.parentMeetingCli(this.integrationTask.id)
@@ -1095,17 +1187,38 @@ export default {
     triggerEvent(obj) {
         console.log(obj, '触发事件')
         this.curProjectId = obj.curProjectId
-        this.getProjectList()
+        if(!this.showMmeiLaiDe) {
+            this.getProjectList()
+        } else {
+            this.getProjectListTwo()
+        }
         if(!obj.taskVue) {
             this.getStageList(obj.integrationTaskNingwai)
         }
         if(obj.create) {
+            console.log(obj, '<=== 双击获取的')
             this.getUsers(); // 获取名单数据
             this.mileageCup = false
             this.addFormVisible = true;
             this.curProjectId = obj.stage.projectId;
-            this.addForm = {projectId: obj.stage.projectId, groupId: obj.stage.groupId, stagesId: obj.stage.id, taskLevel:0, planHours: 8, taskType: 0};
-            this.addForm.executorListFront = [{executorId:null, planHours:this.user.timeType.allday}];
+            this.addForm = {
+                projectId: obj.stage.projectId, 
+                groupId: obj.stage.groupId, 
+                stagesId: obj.stage.id, 
+                startDate: obj.addForm.startDate,
+                taskLevel:0, 
+                planHours: 8, 
+                taskType: 0
+            };
+            // this.addForm.executorListFront = [
+            //     {executorId:obj.executorListFront[0] && obj.executorListFront[0].executorId, planHours:this.user.timeType.allday}
+            // ];
+            this.addForm.executorListFront = (obj.executorListFront || []).map(em => {
+                return {
+                    executorId: em.executorId,
+                    planHours: this.user.timeType.allday
+                }
+            })
             this.gstimhour = [this.user.timeType.allday]
             this.gstimday = [1]
             this.addLoading = false;
@@ -1113,6 +1226,7 @@ export default {
             this.title=this.$t('createtask ');
             this.commentList = [];
             this.timelabel = false
+            console.log(this.addForm, '<====== this.addForm')
         } else {
             if(!obj.taskVue) {
                 this.isEditFile = true;
@@ -1125,6 +1239,10 @@ export default {
             this.getDailyList(obj.id) // 获取来自日报
             this.getRelationTaskList(obj.num, obj.id)
             this.getTaskFileList(obj.num,obj.id)
+            const { integrationTaskNingwai = {} } = obj
+            if(integrationTaskNingwai.groupId) {
+                this.getTaskGrouping(obj.curProjectId)
+            }
             setTimeout(() => {
                 this.getTaskDetail(obj.id);
             }, 200)
@@ -1138,11 +1256,60 @@ export default {
             this.addForm.stagesId = ''
             this.getTaskGrouping()
             this.getrelation();
+            if(this.showMmeiLaiDe) {
+                this.getProjectManager()
+            }
         } else if(num == 2) {
             this.addForm.stagesId = ''
             this.getTaskList()
         }
     },
+    getProjectManager() {
+        const { projectId } = this.addForm
+        this.http.post('/user/getChargeUserByProjectId', { projectId },
+        res => {
+            if (res.code == "ok") {
+                if(!res.data.id) {
+                    this.$message({
+                        message: '当前项目没有项目经理',
+                        type: "warning"
+                    });
+                    return
+                }
+                this.addForm.checkFirstId = res.data.id || '';
+            } else {
+                this.$message({
+                    message: res.msg,
+                    type: "error"
+                });
+            }
+        },
+        error => {
+            this.$message({
+                message: error,
+                type: "error"
+            });
+        });
+    },
+    getPmUserList() {
+        this.http.post('/user/getSecondCheckUser', {  },
+        res => {
+            if (res.code == "ok") {
+                this.pmUserList = res.data || [];
+            } else {
+                this.$message({
+                    message: res.msg,
+                    type: "error"
+                });
+            }
+        },
+        error => {
+            this.$message({
+                message: error,
+                type: "error"
+            });
+        });
+    },
     //获取项目列表
     getProjectList() {
         this.http.post(this.port.project.list, {},
@@ -1164,6 +1331,34 @@ export default {
             });
         });
     },
+    getProjectListTwo() {
+        let obj = {}
+        if(this.curProjectId) {
+            obj.projectId = this.curProjectId
+        }
+        this.http.post(`/project/getProjectByLeader`, {
+            ...obj
+        },
+        res => {
+            if (res.code == "ok") {
+                this.projectList = res.data;
+                this.integrationProjectList = [
+                    { label: '相关项目', peojectList: res.data }
+                ]
+            } else {
+                this.$message({
+                    message: res.msg,
+                    type: "error"
+                });
+            }
+        },
+        error => {
+            this.$message({
+                message: error,
+                type: "error"
+            });
+        });
+    },
     // 获取最近项目列表
     getRecentlyProject() {
         this.http.post('/project/nearProject',{},res => {
@@ -1192,8 +1387,8 @@ export default {
         })
     },
     // 获取任务分组
-    getTaskGrouping() {
-        this.http.post('/task-group/list', {projectId:this.addForm.projectId},
+    getTaskGrouping(projectId) {
+        this.http.post('/task-group/list', {projectId: projectId ? projectId : this.addForm.projectId},
         res => {
             if (res.code == "ok") {
                 this.groupList = res.data;
@@ -1301,6 +1496,10 @@ export default {
         this.http.post('/task/getTask',{id: id},
         res => {
             if (res.code == "ok") {
+                this.millerSReviewer = [res.data.checkFirstId, res.data.checkSecondId]
+                if(this.showMmeiLaiDe) {
+                    this.setDisabledPermission()
+                }
                 this.meetingId = res.data.meetingId
                 console.log(this.meetingId, '看看打印纸')
                 if(this.user.userNameNeedTranslate == 1) {
@@ -1708,6 +1907,14 @@ export default {
                 });
             }
         }
+
+        if(this.showMmeiLaiDe && !this.addForm.endDate) {
+            return this.$message({
+                    showClose: true,
+                    message: '请选择截止时间',
+                    type: 'warning'
+                });
+        }
         this.$refs.form1.validate(valid => {
             if (valid) {
                 delete this.addForm.subTaskList;
@@ -1720,9 +1927,20 @@ export default {
                     this.addForm.executorListFront.serviceId= this.addForm.executorListFront.serviceId;
                 }
                 this.addForm.executorListStr = JSON.stringify(this.addForm.executorListFront);
+                // this.addForm.executorList = this.addForm.aheadTidList;
                 this.addForm.aheadTid = JSON.stringify(this.addForm.aheadTidList);
+
+                let addFormData = { ...this.addForm }
+                if(this.addForm.taskPlanType == 3) {
+                    addFormData = {
+                        taskPlanType: 3,
+                        startDate: this.addForm.startDate,
+                        endDate: this.addForm.endDate,
+                        executorListStr: this.addForm.executorListStr
+                    }
+                }
                 this.addLoading = true;
-                this.http.post('/task/save',this.addForm,
+                this.http.post('/task/save',{ ...addFormData, isTaskPlan: this.showMmeiLaiDe ? 1 : 0},
                     res => {
                         this.addLoading = false;
                         if (res.code == "ok") {
@@ -1814,6 +2032,10 @@ export default {
             this.http.post('/task/delete',{id: this.addForm.id},
             res => {
                 if (res.code == "ok") {
+                    this.$message({
+                        message: '删除成功',
+                        type: 'success'
+                    });
                     this.$emit('closeBounced', {deleteTask: true})
                 } else {
                     this.$message({
@@ -2402,6 +2624,10 @@ export default {
 .themeFontColor {
     @include font_color("color");
 }
+.customizedReviewer {
+    display: flex;
+    align-items: center;
+}
 .editingTask {
     display: flex;
     flex-wrap: wrap;

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

@@ -103,6 +103,8 @@ const StringUtil = {
         reportResponsibleManhourCost: false, // 负责项目子项目工时成本 //
         reportFTEAll: false, // 全部部门FTE报表 //
         reportFTEPart: false, // 负责部门FTE报表 // 
+        reportFTEPlanAll: false, // 全部部门FTE计划报表 // 
+        reportFTEPlanPart: false, // 负责部门FTE计划报表 // 
         reportEfficent: false, // 有效工时率 // 
         reportSortScaleTable: false, // 项目分类工时占比表 // 
         reportSortDetailTable: false, // 分类全部工时明细表 // 
@@ -256,6 +258,8 @@ const StringUtil = {
         arr[i] == '负责项目分组阶段工时' ? obj.reportStageWorkingTime = true : ''
         arr[i] == '全部部门FTE报表' ? obj.reportFTEAll = true : ''
         arr[i] == '负责部门FTE报表' ? obj.reportFTEPart = true : ''
+        arr[i] == '全部部门FTE计划报表' ? obj.reportFTEPlanAll = true : ''
+        arr[i] == '负责部门FTE计划报表' ? obj.reportFTEPlanPart = true : ''
         arr[i] == '有效工时率表' ? obj.reportEfficent = true : ''
         arr[i] == '项目预估工时表' ? obj.reportProjectEstimated = true : ''
         arr[i] == '任务研发报表' ? obj.taskPlanCost = true : ''

+ 3 - 0
fhKeeper/formulahousekeeper/timesheet/src/views/Home.vue

@@ -771,6 +771,9 @@
                             sessionStorage.action = action
                             this.$router.push("/projectInside/"+date);
                             this.drawer = false;
+                        } else if(type == 11) {
+                            this.$router.push("/list");
+                            this.drawer = false;
                         }
                         
                         

+ 89 - 9
fhKeeper/formulahousekeeper/timesheet/src/views/corpreport/list.vue

@@ -50,6 +50,7 @@
                   <el-menu-item index="1-28" v-if="permissions.reportProjectEstimated" @click="ssl(27)"><p>{{ $t('xiangMuYuGuGongShiBiao') }}</p></el-menu-item>
                   <el-menu-item index="1-29" v-if="permissions.takCompletedStatus" @click="ssl(28)"><p>{{ $t('yuanGongRenWuWanChengQingKuangBiao') }}</p></el-menu-item>
                   <el-menu-item index="1-30" v-if="permissions.taskPlanCost" @click="ssl(29)"><p>{{ $t('taskPlanCostReport') }}</p></el-menu-item>
+                  <el-menu-item index="1-31" v-if="permissions.reportFTEPlanAll || permissions.reportFTEPlanPart" @click="ssl(30)"><p>FTE计划报表</p></el-menu-item>
                 </el-submenu>
               </el-menu>
           </el-col>
@@ -204,7 +205,7 @@
           </el-select>
           
           <!-- 地区筛选 -->
-          <el-select v-if="ins == 19" v-model="areaName" :placeholder="customNameChoose" @change="selcts()" clearable filterable size="small" style="margin-left:2px;width:150px">
+          <el-select v-if="ins == 19 || ins == 30" v-model="areaName" :placeholder="customNameChoose" @change="selcts()" clearable filterable size="small" style="margin-left:2px;width:150px">
             <el-option :label="item" :value="item" v-for="item,index in areaList" :key="index"></el-option>
           </el-select>
 
@@ -1506,6 +1507,27 @@
               <el-table-column align="center" prop="noOnTimeNum" :label="$t('yanChiWanChengShuLiang')" min-width="150"></el-table-column>
               <el-table-column align="center" prop="onTimePercent" :label="$t('anShiWanChengShuai')" min-width="150"></el-table-column>
             </el-table>
+
+            <!-- FTE 计划报表 -->
+            <el-table v-if="ins == 30"  key="30" border :data="fTEPlanDataList" highlight-current-row v-loading="listLoading" :height="+tableHeight - 1" style="width: 100%;" @sort-change="tableSort">
+              <el-table-column align="center" prop="area" :label="customName" min-width="150"></el-table-column>
+              <el-table-column align="center" prop="projectCode" :label="user.companyId == '7030' ? '项目令号' : $t('Itemno')" min-width="250"></el-table-column>
+              <el-table-column align="center" prop="projectName" :label="$t('headerTop.projectName')" min-width="250"></el-table-column>
+              <el-table-column align="center" prop="userName" :label="$t('renMing')" min-width="150" sortable="custom">
+                <template slot-scope="scope">
+                  <div>
+                    <span v-if="user.userNameNeedTranslate == '1'">
+                      <TranslationOpenDataText type='userName' :openid='scope.row.userName'></TranslationOpenDataText>
+                    </span>
+                    <span v-if="user.userNameNeedTranslate != '1'">
+                      {{scope.row.userName}}
+                    </span>
+                  </div>
+                </template>
+              </el-table-column>
+              <el-table-column align="center" prop="planHours" label="计划工时" min-width="150"></el-table-column>
+              <el-table-column align="center" prop="FTE" :label="'计划FTE(计划工时/当月计划工时基数)'" min-width="250"></el-table-column>
+          </el-table>
         <!--工具条-->
         <el-col :span="24" class="toolbar" v-if="ins != 6 && ins != 20 && ins != 21 && tabPosition==0 && tabsType == 'all'">
           <el-pagination
@@ -1879,11 +1901,11 @@ export default {
     return {
       themeColor: getThemeColor(),
       screeningCondition: { // 筛选条件的判断
-        project: [4, 8, 9, 10, 11, 14, 15, 17, 19, 20, 21, 22,28], // 项目筛选条件 (不等于)
+        project: [4, 8, 9, 10, 11, 14, 15, 17, 19, 20, 21, 22, 28, 30], // 项目筛选条件 (不等于)
         months: [14, 15], // 月份筛选条件 (等于)
-        monthRange: [19], // 月份区间筛选条件 (等于)
-        staff: [6, 8, 9, 19, 11, 14, 18, 23, 25, 26,28], // 人员筛选条件 (等于)
-        departments: [14, 15, 23,21,26,28,19], // 部门筛选条件 (等于)
+        monthRange: [19, 30], // 月份区间筛选条件 (等于)
+        staff: [6, 8, 9, 19, 11, 14, 18, 23, 25, 26,28, 30], // 人员筛选条件 (等于)
+        departments: [14, 15, 23,21,26,28,19, 30], // 部门筛选条件 (等于)
         timePeriod: [5, 6, 8, 9, 10, 11, 12, 16, 17, 18, 20, 21, 22, 24, 25, 26,28], // 时间段筛选条件 (等于)
       },
       efficentList:[],
@@ -1943,14 +1965,14 @@ export default {
       this.$t('statisticsofovertimework'),this.$t('timecostearlywarningtable'),this.$t('personneltimeallocationtable'),
       this.$t('statisticsofstafffillingintimerate'),this.$t('dailyreporttobereviewedstatistics'),this.$t('statisticsofpersonnelhours'),this.$t('taskgrouptimesheet'),this.$t('projectcostbaselinetable'),
       this.$t('ren-yuan-yue-du-gong-shi-biao'), this.$t('bumenchanyuqingkuang'), this.$t('ge-fen-zu-yu-jie-duan-gong-shi-biao'), this.$t('ziXiangMuGongShiChengBenBiao'), this.$t('renWuZhongQiBiao'), this.$t('fteBaoBiao'), this.$t('youXiaoGongShiShuaiBiao'), this.$t('xiangMuFenLeiGongShiZhanBiBiao'), this.$t('fenLeiGongShiMingXiBiao'),
-      this.$t('yuanGongXiangMuJinDuBiao'), this.$t('fenZuHaoYongJinDuBiao'), this.$t('xiangMuHaoYongJinDuBiao'), this.$t('yuanGongRenWuJinDuBiao'), this.$t('xiangMuYuGuGongShiBiao'),this.$t('yuanGongRenWuWanChengQingKuangBiao')],
+      this.$t('yuanGongXiangMuJinDuBiao'), this.$t('fenZuHaoYongJinDuBiao'), this.$t('xiangMuHaoYongJinDuBiao'), this.$t('yuanGongRenWuJinDuBiao'), this.$t('xiangMuYuGuGongShiBiao'),this.$t('yuanGongRenWuWanChengQingKuangBiao'), this.$t('taskPlanCostReport'), 'FTE计划报表'],
 
       shuzArr: [this.$t('projectreport'),this.$t('projectTaskReport'),this.$t('projectcoststatement'),
       this.$t('projectbalancesheet'),this.$t('customerprojectincomestatement'),this.$t('projectphasetimesheet'),
       this.$t('statisticsofovertimework'),this.$t('timecostearlywarningtable'),this.$t('personneltimeallocationtable'),
       this.$t('employeereporttimelinessrate'),this.$t('dailyreporttobereviewedstatistics'),this.$t('statisticsofpersonnelhours'),this.$t('taskgrouptimesheet'),this.$t('projectcostbaselinetable'),
       this.$t('ren-yuan-yue-du-gong-shi-biao'), this.$t('bumenchanyuqingkuang'), this.$t('ge-fen-zu-yu-jie-duan-gong-shi-biao'), this.$t('ziXiangMuGongShiChengBenBiao'), this.$t('renWuZhongQiBiao'), this.$t('fteBaoBiao'),this.$t('youXiaoGongShiShuaiBiao'), this.$t('xiangMuFenLeiGongShiZhanBiBiao'), this.$t('fenLeiGongShiMingXiBiao'),
-      this.$t('yuanGongXiangMuJinDuBiao'), this.$t('fenZuHaoYongJinDuBiao'), this.$t('xiangMuHaoYongJinDuBiao'), this.$t('yuanGongRenWuJinDuBiao'), this.$t('xiangMuYuGuGongShiBiao'),this.$t('yuanGongRenWuWanChengQingKuangBiao')],
+      this.$t('yuanGongXiangMuJinDuBiao'), this.$t('fenZuHaoYongJinDuBiao'), this.$t('xiangMuHaoYongJinDuBiao'), this.$t('yuanGongRenWuJinDuBiao'), this.$t('xiangMuYuGuGongShiBiao'),this.$t('yuanGongRenWuWanChengQingKuangBiao'), this.$t('taskPlanCostReport'), 'FTE计划报表'],
 
       ins: 10000,
       user: JSON.parse(sessionStorage.user),
@@ -2026,6 +2048,7 @@ export default {
 
       taskRestartArr: [], // 任务重启表数据
       fTEDataList: [], // FTE数据
+      fTEPlanDataList: [], // FTE计划数据
 
       baobiaoList: [],
 
@@ -2596,7 +2619,7 @@ export default {
                 this.getGroupWorktimeAll()
             },
             getList(e) {
-              let noUserList = [16, 17, 18, 19, 20, 21, 22, 24, 25, 26,27,29]
+              let noUserList = [16, 17, 18, 19, 20, 21, 22, 24, 25, 26,27,29,30]
               if(this.ins == 24) {
                 if(this.tabsType == 'all') {
                   this.rangeDatas = []
@@ -2653,6 +2676,9 @@ export default {
                 } else if(this.ins == 19) {
                   this.getETF()
                   this.getArea()
+                } else if(this.ins == 30) {
+                  this.getETFPlan()
+                  this.getArea()
                 } else if (this.ins == 20) {
                   this.getEffectiveLaborHourRate();
                 }
@@ -2847,7 +2873,14 @@ export default {
           sl.monthEnd= this.monthRange[1]+"-01"
           sl.area = this.areaName || null
           sl.departmentId = this.departmentIdArray.length > 0 ? this.departmentIdArray[this.departmentIdArray.length - 1] : ''
-        }else if(this.ins == 20) {
+        } else if(this.ins == 30) {
+          fName = 'FTE计划报表' + '.xlsx'
+          url += "/exportTaskPlanFTEData"
+          sl.monthStart= this.monthRange[0]+"-01"
+          sl.monthEnd= this.monthRange[1]+"-01"
+          sl.area = this.areaName || null
+          sl.departmentId = this.departmentIdArray.length > 0 ? this.departmentIdArray[this.departmentIdArray.length - 1] : ''
+        } else if(this.ins == 20) {
           fName = this.$t('youXiaoGongShiShuaiBiao') + '.xlsx'
           url = "/project/exportEffectiveLaborHourRate"
           sl.startDate = this.rangeDatas[0]
@@ -3123,6 +3156,53 @@ export default {
           });
       });
     },
+    getETFPlan() {
+      this.getCustomName();
+      this.listLoading = true;
+      let parameter = {
+        monthStart: this.monthRange[0]+"-01",
+        monthEnd: this.monthRange[1]+"-01",
+        area: this.areaName || null,
+        userId:this.userId,
+        pageIndex: this.page,
+        pageSize: this.size
+      }
+      if(this.departmentIdArray.length != 0){
+        parameter.departmentId = this.departmentIdArray[this.departmentIdArray.length - 1]
+      }
+      if(this.sortOrder){
+          if(this.sortProp == 'userName'){
+              parameter.sortProp = "id"
+          }
+          if(this.sortOrder == 'descending'){
+              parameter.sortOrder = 0
+          }else if(this.sortOrder == 'ascending'){
+              parameter.sortOrder = 1
+          }
+      }
+      this.http.post('/project/getProjectTaskPlanFTEData', parameter,
+      res => {
+          if (res.code == "ok") {
+              for (var i in res.data.resultList) {
+                res.data.resultList[i].FTE = res.data.resultList[i].FTE.toFixed(2)
+              }
+              this.fTEPlanDataList = res.data.resultList;
+              this.total = res.data.total;
+              this.listLoading = false; 
+          } else {
+              this.$message({
+              message: res.msg,
+              type: "error"
+              });
+          }
+      },
+      error => {
+          this.$message({
+              message: error,
+              type: "error"
+          });
+      });
+    },
     getArea() {
       this.http.post('/user/areaData', {},
       res => {

+ 360 - 194
fhKeeper/formulahousekeeper/timesheet/src/views/project/gantt.vue

@@ -1,98 +1,179 @@
-{{ src/components/Gantt.vue }}
 <template>
-  <div ref="ganttContainer">
-  </div>
+  <div class="ganttContainerBox">
+    <div ref="ganttContainer" style="height: 100%;">
+    </div>
     <!-- 任务详情信息弹出框 -->
-    <!-- <el-dialog :class="addForm.id==null?'':'jm'" :title="title" v-if="taskFormVisible" :visible.sync="taskFormVisible" 
-      :close-on-click-modal="false" customClass="customWidth" width="840px" :top="'6vh'">
-          <taskComponent ref="thskComponents" :integrationTask="integrationTask" :showOrNot="showOrNot" @closeBounced="closeBounced"></taskComponent>
-          <div slot="title" v-if="addForm.parentTid != null">
-              <el-page-header  @back="backToParentTask" :title="$t('parenttask')" :content="addForm.parentTname"></el-page-header>
-          </div>
-      </el-dialog> -->
-  
+    <el-dialog :class="''" :title="title" v-if="addFormVisible" append-to-body
+      :visible.sync="addFormVisible" :close-on-click-modal="false" customClass="customWidth" width="840px" :top="'6vh'">
+      <taskComponent ref="thskComponents" :integrationTask="integrationTask" :showOrNot="showOrNot"
+        @closeBounced="closeBounced" :showMmeiLaiDe="true" :showMmeiLaiDeData="showMmeiLaiDeData"></taskComponent>
+      <div slot="title" v-if="addForm.parentTid != null">
+        <el-page-header @back="backToParentTask" :title="$t('parenttask')"
+          :content="addForm.parentTname"></el-page-header>
+      </div>
+    </el-dialog>
+  </div>
 </template>
 
 <script>
-
-   
-import {gantt} from 'dhtmlx-gantt';
+import { gantt } from 'dhtmlx-gantt';
 // import 'dhtmlx-gantt/codebase/dhtmlxgantt.css'
 // import 'dhtmlx-gantt/codebase/locale/locale_cn'  // 本地化
+import taskComponent from "@/components/taskComponent.vue"
 export default {
   name: 'gantt',
+  components: {
+    taskComponent
+  },
   props: {
     tasks: {
       type: Object,
-      default () {
-        return {data: [], links: []}
+      default() {
+        return { data: [], links: [] }
       }
     },
     stafforpro: '',
-    valueDate:[],
+    valueDate: [],
   },
   data() {
     return {
-      containerRect:null,
+      containerRect: null,
       taskFormVisible: false,
-      addForm:null,
+      addForm: {},
       addLoading: false,
-      title: this.$t('createtask '),
-      commentList:[],
+      title: '创建计划',
+      commentList: [],
+      dynamicTab: true,
       showOrNot: false,
-      integrationTask:null,
+      integrationTask: null,
       taskComponentFlg: false,
+      addFormVisible: false,
+      integrationTaskNingwai: {},
+      integrationTask: {},
+      user: JSON.parse(sessionStorage.getItem("user")),
+      showMmeiLaiDeData: {},
     };
   },
-  created:function(){
+  created: function () {
     // gantt.clearAll()
     // console.log("tasks",this.$props.tasks);
   },
- 
+
   methods: {
-    handleEmptyClick(event) {
-      const x = event.clientX - this.containerRect.left;
-      const y = event.clientY - this.containerRect.top;
+    getDistanceToParent(element, parent) {
+      let distance = 0;
+      while (element && element !== parent) {
+        distance += element.offsetTop;  // 获取当前元素相对于父元素顶部的距离
+        element = element.offsetParent; // 获取上一级父元素
+      }
+      return distance;
+    },
+    closeBounced(obj) {
+      console.log(obj, '<======== 点击事件')
+      if (!obj.backToParentTaskSub) {
+        this.addFormVisible = false
+        this.taskComponentFlg = false
 
-      // 获取点击位置对应的时间轴日期
-      const date = gantt.dateFromPos(x);
-      console.log(date);
+        if (obj.submitInsert) {
+          this.$emit('closeBounced', obj)
+        }
 
-      // this.addTask();
+        if(obj.deleteTask) {
+          this.$emit('closeBounced', obj)
+        }
+      }
+    },
+    backToParentTask() {
+      console.log('点击, <======== 点击了backToParentTask')
     },
-    addTask() {
-        this.taskFormVisible = true;
-        // this.addForm = {projectId: stage.projectId, groupId: stage.groupId, stagesId: stage.id, taskLevel:0, planHours: 8, taskType: 0};
-        this.addForm = {projectId: '', groupId: '', stagesId: '', taskLevel:0, planHours: 8, taskType: 0};
-        this.addLoading = false;
-        this.title=this.$t('createtask ');
-        this.commentList = [];
-        this.showOrNot = true
-
-        let obj = {
-            create: true,
-            addForm: this.addForm,
-            executorListFront: [{executorId:null, planHours:8}],
-            stage: this.addForm,
-            integrationTaskNingwai: this.integrationTaskNingwai,
-            taskVue: true,         
-            meetingId: this.addForm.meetingId
+    addTask(row) {
+      this.showOrNot = true
+      this.addForm = {
+        projectId: '', groupId: '', stagesId: '', taskLevel: 0, planHours: 8, taskType: 0, startDate: row.date
+      }
+      const userIdList = (row.userId && row.userId.split(',')) || []
+      const executorListFront = userIdList.map(item => {
+        return {
+          executorId: item,
+          planHours: 8
         }
-        this.integrationTask = obj
+      })
+      let obj = {
+        create: true,
+        addForm: this.addForm,
+        executorListFront,
+        stage: this.addForm,
+        integrationTaskNingwai: this.integrationTaskNingwai,
+        taskVue: true,
+        meetingId: this.addForm.meetingId
+      }
+      this.integrationTask = obj
+      this.addFormVisible = true
+    },
+    editTask(row) {
+      this.showOrNot = true
+      this.http.post('/task/getTask', { id: row.taskId },
+        res => {
+          if (res.code == "ok") {
+            const data = res.data
+            if(this.user.roleId != 2283 && !data.executorId) {
+              this.$message({
+                message: '这条数据只有区域经理才能分配',
+                type: 'warning'
+              });
+              return
+            }
+            this.addForm = {
+              id: data.id
+            }
+            this.integrationTask = {
+              id: data.id,
+              task: data,
+              num: 1,
+              curProjectId: data.projectId || '',
+              create: false,
+              integrationTaskNingwai: {
+                groupId: data.groupId,
+                isDesc: false,
+                order: "seq",
+                projectId: data.projectId || '',
+              },
+              taskVue: data.projectId ? false : true,
+              meetingId: this.addForm.meetingId
+            }
 
-        this.taskComponentFlg = true
+            this.addFormVisible = true
+          } else {
+            this.$message({ message: res.msg, type: "error" });
+          }
+        },
+        error => {
+          this.$message({ message: error, type: "error" });
+        });
+    },
+    handleEmptyClick(row) {
+      if (row.taskId) {
+        // 编辑任务
+        this.title = '编辑计划'
+        this.editTask(row)
+      } else {
+        // 新增任务
+        this.title = '创建计划'
+        this.addTask(row)
+      }
     },
   },
   mounted: function () {
+    const userInfo = JSON.parse(sessionStorage.getItem("user"));
     gantt.clearAll()
-    gantt.locale={
-    date: {
+    gantt.locale = {
+      date: {
         month_full: [this.$t('yiYue'), this.$t('erYue'), this.$t('sanYue'), this.$t('siYue'), this.$t('thisTWuyue'), this.$t('liuYue'), this.$t('qiYue'), this.$t('baYue'), this.$t('jiuYue'), this.$t('shiYue'), this.$t('shiYiYue'), this.$t('shiErYue')],
         month_short: [this.$t('1Yue'), this.$t('2Yue'), this.$t('3Yue'), this.$t('4Yue'), this.$t('5Yue'), this.$t('6Yue'), this.$t('7Yue'), this.$t('8Yue'), this.$t('9Yue'), this.$t('10Yue'), this.$t('11Yue'), this.$t('12Yue')],
         day_full: [this.$t('xingQiRi'), this.$t('xingQiYi'), this.$t('xingQiEr'), this.$t('xingQiSan'), this.$t('xingQiSi'), this.$t('xingQiWu'), this.$t('xingQiLiu')],
         day_short: [this.$t('ri'), "一", "二", "三", "四", "五", "六"]
-    },
-    labels: {
+      },
+      labels: {
         dhx_cal_today_button: this.$t('jinTian'),
         day_tab: this.$t('weekDay.day'),
         week_tab: this.$t('zhou'),
@@ -133,68 +214,27 @@ export default {
         weeks: this.$t('zhou'),
         months: this.$t('weekDay.month'),
         years: this.$t('nian')
-    }
-};
+      }
+    };
     // gantt.config.autosize = true;
     // gantt.config.duration_unit = "hour";
     gantt.config.fit_tasks = true;
     gantt.config.drag_move = false;
     gantt.config.xml_date = "%Y-%m-%d";
-    gantt.config.columns=[
-        {name:"text",label:(this.stafforpro == this.$t('anRenYuanChaKan') ? this.$t('lable.name') : this.$t('headerTop.projectName')), align: "left", tree:true},
-        // {name:"time",label:"计划工时(h)", align: "center" }
-        // {name:"start_date", label:"开始时间", width:'*' , align: "center" },
-        // {name:"duration",   label:"工时(天)", width:'*' ,   align: "center" }
+    gantt.config.columns = [
+      { name: "text", label: (this.stafforpro == this.$t('anRenYuanChaKan') ? this.$t('lable.name') : this.$t('headerTop.projectName')), align: "left", tree: true },
+      // {name:"time",label:"计划工时(h)", align: "center" }
+      // {name:"start_date", label:"开始时间", width:'*' , align: "center" },
+      // {name:"duration",   label:"工时(天)", width:'*' ,   align: "center" }
     ];
     gantt.config.scale_unit = "month";	//按月显示
-	  gantt.config.date_scale = "%F, %Y";		//设置时间刻度的格式(X轴) 多个尺度
+    gantt.config.date_scale = "%F, %Y";		//设置时间刻度的格式(X轴) 多个尺度
 
-	  gantt.config.scale_height = 50; //设置时间刻度的高度和网格的标题
+    gantt.config.scale_height = 50; //设置时间刻度的高度和网格的标题
     gantt.config.open_tree_initially = true;
-// gantt.config.layout = {
-//     css: "gantt_container",
-//     rows:[
-//         {
-//            cols: [
-//             {
-//               // the default grid view  
-//               view: "grid",  
-//               scrollX:"scrollHor", 
-//               scrollY:"scrollVer"
-//             },
-//             { resizer: true, width: 2 },
-//             {
-//               // the default timeline view
-//               view: "timeline", 
-//               scrollX:"scrollHor", 
-//               scrollY:"scrollVer"
-//             },
-//             {
-//               view: "scrollbar", 
-//               id:"scrollVer"
-//             }
-//         ]},
-//         {
-//             view: "scrollbar", 
-//             id:"scrollHor"
-//         }
-//     ]
-// }
-// gantt.templates.task_time = function(start,end,task){
-//   console.log('startend',start,end,task);
-//   let Jstart = JSON.parse(JSON.stringify(start))
-//   let Jend = JSON.parse(JSON.stringify(end))
-//   let estartmonth = Jstart.getMonth() + 1
-//   let estartday = Jstart.getDate()
-//   let estart = Jstart.getFullYear() + '-' + (estartmonth < 10 ? '0' + estartmonth : estartmonth) + '-' + (estartday < 10 ? '0' + estartday : estartday)
-//   let tend = new Date(Jend.setDate(end.getDate() - 1))
-//   let eendmonth = tend.getMonth() + 1
-//   let eendday = tend.getDate()
-//   let eend = tend.getFullYear() + '-' + (eendmonth < 10 ? '0' + eendmonth : eendmonth) + '-' + (eendday < 10 ? '0' + eendday : eendday)
-//   return estart + ' ' + eend
-// };
+
     gantt.config.subscales = [
-      {unit: "day", step: 1, date: "周%D,%d"}
+      { unit: "day", step: 1, date: "周%D,%d" }
     ];
     gantt.config.buttons_left = []
     gantt.config.buttons_right = ["gantt_cancel_btn"]
@@ -203,7 +243,7 @@ export default {
     gantt.config.drag_progress = false
     gantt.config.details_on_dblclick = false
     gantt.config.lightbox.sections = [
-      {name:"description", height:76, map_to:"text", type:"textarea",focus:true}
+      { name: "description", height: 76, map_to: "text", type: "textarea", focus: true }
     ];
 
     gantt.config.start_date = new Date(this.valueDate[0]);
@@ -211,126 +251,252 @@ export default {
 
     //设置任务条样式
     gantt.templates.task_class = function (start, end, item) {
-      return item.parent == 0 ? "person_line" : ""
+      return item.taskPlanType == 3 ? "error_line" : "person_line"
+    };
+
+    // 设置任务条内容显示
+    gantt.templates.task_text = function (start, end, task) {
+      const { leaderOrManager, taskPlan, taskStatus } = task
+      // 都审核通过
+      if(taskPlan == 1 && taskStatus == 0 && task.text == '请假') {
+        return `<div class="task_text">
+            <div style="background: '#ff5757'">${task.text}</div>
+          </div>`
+      }
+
+      if(taskPlan == 1 && taskStatus == 0) {
+        return `<div class="task_text">
+            <div class="exclamation-circle circle" style="color: ${task.taskPlanType == 3 ? '#f56c6c' : '#8ecaf8'}">V</div>
+            <div class="exclamation-circle circle" style="color: ${task.taskPlanType == 3 ? '#f56c6c' : '#8ecaf8'}">V</div>
+            <div>${task.text}</div>
+          </div>`
+      }
+
+      // 小组长
+      // if (userInfo.projectLeaderType == 1) {
+      if (leaderOrManager == 1) {
+        return `<div class="task_text">
+          ${task.taskStatus == 3 ? `<div class="circle" style="color: ${task.taskPlanType == 3 ? '#f56c6c' : '#8ecaf8'}">!</div> <div class="circle"></div>` : ''}
+          ${task.taskStatus == 4 ? `<div class="exclamation-circle circle" style="color: ${task.taskPlanType == 3 ? '#f56c6c' : '#8ecaf8'}">V</div> <div class="circle"></div>` : ''}
+          ${task.taskStatus == 5 ? `<div class="exclamation-circle circle" style="color: ${task.taskPlanType == 3 ? '#f56c6c' : '#8ecaf8'}">!</div> <div class="circle"></div>` : ''}
+          ${task.taskStatus == 6 ? `<div class="exclamation-circle circle" style="color: ${task.taskPlanType == 3 ? '#f56c6c' : '#8ecaf8'}">V</div> <div class="exclamation-circle circle" style="color: ${task.taskPlanType == 3 ? '#f56c6c' : '#8ecaf8'}">!</div>` : ''}
+          <div>${task.text}</div>
+        </div>`;
+      }
+
+      // 审核人
+      // if (userInfo.projectLeaderType == 2) {
+      if (leaderOrManager == 2) {
+        return `<div class="task_text statuss">
+            ${task.taskStatus == 3 || task.taskStatus == 4 ? `<div class="circle">
+              <div class="pendingReviewOfCornerMarkers">!</div>
+            </div>` : ''}
+            <div>${task.text}</div>
+          </div>`
+      }
+
+      // 正常人
+      return `<div class="task_text">
+          <div>${task.text}</div>
+        </div>`;
     };
     gantt.config.grid_width = 350;
-    gantt.plugins({tooltip: true});
+    gantt.plugins({ tooltip: true });
     gantt.templates.tooltip_text = function (start, end, task) {
       return
     };
-            
-    // gantt.ext.tooltips.tooltip.show = function(event){
-    //   // console.log('show', event);
-     
-    // }
-    // console.log('show',gantt.ext.tooltips.tooltip.show);
-    // gantt.ext.tooltips.tooltip = {
-    //   getNode: function (params) {
-    //     // console.log('getNode',params);
-    //   },
-    //   hide: function(){
-    //     // console.log('hide');
-    //   },
-    //   setContent: function(){
-    //     // console.log('setContent');
-    //   },
-    //   show: function(event){
-    //     console.log('show',event);
-    //   },
-
-    // }
-    // 给每行增加双击事件 ,亲测事件会重复注册,用这个方法拦截一下
-    if (this.onTaskDblClick) gantt.detachEvent(this.onTaskDblClick);
-    // 双击bar任务事件(单击会有问题,点击展开时也会触发)
-    this.onTaskDblClick = gantt.attachEvent("onTaskDblClick", (id, e) => {
-      console.log('=====在这里,开始显示任务弹窗编辑任务===id=='+id+", e="+e);
-        this.$emit('rowDbClick',id)
-        return true;
-    }, { id: 'onTaskDblClick' })
 
     gantt.ext.tooltips.attach({
       selector: '.gantt_grid [' + gantt.config.task_attribute + ']',
-      onmouseenter: (event,node) => {
-        if(node.textContent.length > 19){
+      onmouseenter: (event, node) => {
+        if (node.textContent.length > 19) {
           let sdom = document.createElement('span')
           sdom.innerText = node.innerText
           sdom.className = 'tooltiptext'
           node.appendChild(sdom)
         }
-        
+
       },
-      onmousemove: () => {},
-      onmouseleave: (event,node) => {
+      onmousemove: () => { },
+      onmouseleave: (event, node) => {
         let sdom = document.getElementsByClassName('tooltiptext')[0]
-        if(sdom){node.removeChild(sdom)}
-        
+        if (sdom) { node.removeChild(sdom) }
+
       },
-      // html: (event,node) => {
-      //   const targetTaskId = gantt.locate(event)
-      //   const task = gantt.getTask(targetTaskId)
-      //   return gantt.templates.tooltip_text(null,null,task)
-      // },
       global: true
     })
 
-    // 绑定空白点击事件
-    gantt.attachEvent("onEmptyClick", (event) => {
-      this.handleEmptyClick(event);
-      return true; // 阻止默认行为
+    // 双击事件
+    this.$refs.ganttContainer.addEventListener('dblclick', (event) => {
+      const taskIdStr = gantt.locate(event);
+      if(userInfo.projectLeaderType != 1 && userInfo.projectLeaderType != 2) {
+        return
+      }
+      this.showMmeiLaiDeData = {}
+      if (taskIdStr && gantt.isTaskExists(taskIdStr)) {
+        // 编辑任务
+        const rows = gantt.getTask(taskIdStr)
+        if (rows.id.indexOf('任务') != '-1') {
+          const value = taskIdStr.split('任务_')[1]
+          const taskId = value.split('_')[0]
+          this.showMmeiLaiDeData = rows
+          this.handleEmptyClick({ taskId })
+        }
+      } else {
+        if(userInfo.projectLeaderType != 1) {
+          return
+        }
+        // 获取 gantt_grid_data 容器
+        const ganttGrid = document.querySelector('.gantt_grid_data');
+        if (!ganttGrid) return;
+        // // 计算点击位置
+        const gridRect = ganttGrid.getBoundingClientRect();
+        // const clickY = event.clientY - gridRect.top; // 相对 gantt_grid_data 的 Y 轴偏移量
+
+        // // 获取任务行
+        // const rows = ganttGrid.querySelectorAll('.gantt_row');
+        // const rowHeight = rows.length > 0 ? rows[0].offsetHeight : 34; // 获取行高 (默认 40px)
+        // // 计算索引
+        // const rowIndex = Math.floor(clickY / rowHeight);
+        // if (rowIndex >= rows.length || rowIndex < 0) return;
+
+        // // 获取任务 ID
+        // const rowElement = rows[rowIndex];
+
+        // 新写的
+        const rows = ganttGrid.querySelectorAll('.gantt_row');
+        const clickedElement = event.toElement;  // 当前点击的元素
+        const parentElement = clickedElement.closest('.gantt_task_row');
+        const yzhozhi = this.getDistanceToParent(parentElement) - 219 // 219 固定值
+        const yCoordinate = +((yzhozhi / 35).toFixed(0)) * 35
+        let rowIndexs = 0
+        for(const em in rows) {
+          const str = (rows[em].style && rows[em].style.top) || '-1px'
+          const nums = str.split('px')[0]
+          if(nums == yCoordinate) {
+            rowIndexs = em
+          }
+        }
+        const rowElement = rows[rowIndexs]
+        console.log(yCoordinate, rowIndexs)
+        console.log(rowElement, '<,,,,,,,,,,=============== rowElement')
+
+        const taskIdFromRow = rowElement.getAttribute('task_id'); // 获取任务 ID
+        if (taskIdFromRow && gantt.isTaskExists(taskIdFromRow)) {
+          const taskData = gantt.getTask(taskIdFromRow);
+          console.log(taskData, '<=== taskData')
+          if (taskData.userId) {
+            // 新增任务
+            let rollingDistance = 0
+            const scrollElement = this.$refs.ganttContainer.querySelector('.gantt_hor_scroll');
+            if (scrollElement) {
+              rollingDistance = scrollElement.scrollLeft || 0
+            }
+            const userId = taskData.userId;
+            const gridX = event.clientX - gridRect.left; // 相对 gantt_grid_data 的 X 轴偏移量
+            const date = gantt.dateFromPos((gridX - 349) + rollingDistance);
+            console.log('点击的日期:', date, this.dayjs(date).format('YYYY-MM-DD'));
+            this.handleEmptyClick({ userId, date: this.dayjs(date).format('YYYY-MM-DD') })
+          }
+        }
+      }
     });
-    
-    
+
     gantt.init(this.$refs.ganttContainer);
-    console.log('===初始化Init gantt===');
-    console.log(this.$refs.ganttContainer)
     this.containerRect = this.$refs.ganttContainer.getBoundingClientRect();
-    // this.$props.tasks.data[31].render = "split"
     gantt.parse(this.$props.tasks);
-    
-    // gantt.groupBy({
-    //     relation_property: "owner",
-    //     groups: [{key:'seya', label: "seya"},{key:'tina', label: "tina"}],
-    //     group_id: "key",
-    //     group_text: "label"
-    // });
-    // console.log("props",gantt);
   }
 }
 
 </script>
- 
+
 <style>
-    @import "~dhtmlx-gantt/codebase/dhtmlxgantt.css";
-    .person_line {
-      background:#8ecaf8;
-      border: 1px solid;
-      @include border_color("border_color");
-    }
-    /* .gantt_tooltip{
+@import "~dhtmlx-gantt/codebase/dhtmlxgantt.css";
+
+.person_line {
+  background: #8ecaf8;
+  border: 1px solid;
+  @include border_color("border_color");
+}
+
+.error_line {
+  background: #ff5757;
+  border: 1px solid;
+  border: #ff5757;
+}
+
+.task_text {
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+  white-space: nowrap;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  width: 100%;
+}
+
+.task_text>div {
+  flex: 0 0 auto;
+}
+
+.circle {
+  width: 10px;
+  height: 10px;
+  border-radius: 50%;
+  border: 2px solid #fff;
+  margin-left: 4px;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+}
+
+.exclamation-circle {
+  background: #fff;
+  font-size: 12px;
+  font-weight: bold;
+}
+
+.pendingReviewOfCornerMarkers {
+  width: 100%;
+  height: 100%;
+  border-radius: 50%;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  background: #fdba6e;
+  font-weight: bold;
+}
+
+.statuss .circle {
+  border-color: #fdba6e;
+}
+
+
+/* .gantt_tooltip{
       z-index: 10000;
       top: 10px !important;
       left: 10px !important;
     } */
-    .tooltiptext{
-      visibility: visible;
-      background-color: #fff;
-      color: #454545;
-      box-shadow: 3px 3px 3px rgba(0,0,0,.07);
-      border-left: 1px solid rgba(0,0,0,.07);
-      border-top: 1px solid rgba(0,0,0,.07);
-      font-size: 8pt;
-      line-height: 20px;
-      padding: 10px;
-      /* opacity: 0;
+.tooltiptext {
+  visibility: visible;
+  background-color: #fff;
+  color: #454545;
+  box-shadow: 3px 3px 3px rgba(0, 0, 0, .07);
+  border-left: 1px solid rgba(0, 0, 0, .07);
+  border-top: 1px solid rgba(0, 0, 0, .07);
+  font-size: 8pt;
+  line-height: 20px;
+  padding: 10px;
+  /* opacity: 0;
       transition: 0.5s; */
 
-      position: absolute;
-      z-index: 10000;
-      bottom: 120%;
-      left: 25px;
-      max-width: 300px;
-      /* word-wrap: break-word;
+  position: absolute;
+  z-index: 10000;
+  bottom: 120%;
+  left: 25px;
+  max-width: 300px;
+  /* word-wrap: break-word;
       word-break: break-all; */
-      white-space: pre-wrap;
-    }
+  white-space: pre-wrap;
+}
 </style>

+ 27 - 6
fhKeeper/formulahousekeeper/timesheet/src/views/project/list.vue

@@ -502,7 +502,7 @@
                         </el-select>
                     </el-form-item>
 
-                    <el-form-item :label="yonghuUser.customDegreeName" v-if="yonghuUser.customDegreeActive == 1">
+                    <el-form-item :label="yonghuUser.customDegreeName" v-if="yonghuUser.customDegreeActive == 1 && user.timeType.customDegreeWithPro != 0">
                         <el-select v-model="auseList" multiple :placeholder="$t('defaultText.pleaseChoose')" filterable="true" style="width: 100%" :disabled="canOnlyModParticipator">
                             <span v-for="(item, index) in ause" :key="index">
                             <el-option :label="item.name" :value="item.id"></el-option>
@@ -516,12 +516,12 @@
                     </el-form-item> -->
                     <el-form-item :label="$t('Allparticipants')" v-show="addForm.isPublic == 0" :class="title == $t('newproject') && user.companyId == 936 ? 'wpgCssClass' : ''">
                         <el-tooltip placement="top" effect="light" v-if="user.userNameNeedTranslate != 1">
-                            <div slot="content" style="width:780px">{{addForm.userNames}}</div>
+                            <div slot="content" style="width:580px">{{addForm.userNames}}</div>
                             <el-input  @focus="showChooseMembTree" v-model="addForm.userNames"></el-input>
                         </el-tooltip>
 
                         <el-tooltip placement="top" effect="light" v-if="user.userNameNeedTranslate == 1">
-                            <div slot="content" style="max-width: 780px;max-height: 400px;overflow-y: auto;">
+                            <div slot="content" style="max-width: 580px;max-height: 400px;overflow-y: auto;">
                                 <span v-for="(item, index) in addFormUserNames" :key="index">
                                     <TranslationOpenDataText type='userName' :openid='item'></TranslationOpenDataText>
                                     <span v-if="index < addFormUserNames.length - 1">,</span>
@@ -539,7 +539,7 @@
                         </el-tooltip>
                     </el-form-item>
                     <el-form-item :label="$t('projectmanager')" :class="title == $t('newproject') && user.companyId == 936 ? 'wpgCssClass' : ''" v-if="user.company.nonProjectSimple == 0 || (user.company.nonProjectSimple == 1 && addForm.isPublic == 0)">
-                       <el-select v-if="user.userNameNeedTranslate != 1" v-model="addForm.inchargerId" filterable :placeholder="$t('defaultText.pleaseChoose')" style="width:32%;" :disabled="canOnlyModParticipator || projectManagerEdit">
+                       <el-select v-if="user.userNameNeedTranslate != 1" v-model="addForm.inchargerId" filterable :placeholder="$t('defaultText.pleaseChoose')" style="width:32%;" :disabled="canOnlyModParticipator || projectManagerEdit" @change="changeInchargerId">
                             <el-option v-for="item in participator" :key="item.id" :label="item.name" :value="item.id">
                                 <span style="float: left">{{ item.name }}</span>
                                 <span style="float: right; color: #8492a6;" v-if="user.companyId == 936">{{ item.jobNumber }}</span>
@@ -558,6 +558,12 @@
                         <selectCat v-if="user.timeType.reportAuditType == 8 && user.userNameNeedTranslate == 1" :filterable="true" :size="'medium'" :subject="users" :subjectId="addForm.reviwerId" :distinction="'4'" @selectCal="selectCal" :disabled="canOnlyModParticipator || projectManagerEdit || isShowProjectName"></selectCat>
                     </el-form-item>
 
+                    <el-form-item label="LA" v-if="user.companyId == 876">
+                        <el-select v-model="addForm.leaderId" multiple placeholder="请选择LA" filterable style="width: 100%">
+                            <el-option v-for="item in (participator || []).filter(em => em.id != addForm.inchargerId)" :key="item.id" :label="item.name" :value="item.id"></el-option>
+                          </el-select>
+                    </el-form-item>
+
                     <span v-if="user.companyId != 469">
                         <el-form-item :label="$t('newspaperauditor')" v-show="user.timeType.reportAuditType == 0 || user.timeType.reportAuditType == 4 || user.timeType.reportAuditType == 6 || user.timeType.reportAuditType == 9" v-if="user.company.nonProjectSimple == 0 || (user.company.nonProjectSimple == 1 && addForm.isPublic == 0)">
                             <el-select v-if="user.userNameNeedTranslate != '1'" @change="$forceUpdate()" v-model="addForm.auditUserIds"  :disabled="!(permissions.projectManagement|| user.id == addForm.inchargerId || user.id == addForm.creatorId)" filterable :placeholder="$t('defaultistheprojectleader')" style="width:100%;" :multiple="user.timeType.reportAuditType != 6 && user.timeType.reportAuditType != 9" >
@@ -3933,7 +3939,12 @@ a {
                 var list = chosenList.filter(item=>item.isUser == 1);
                 this.chosenMembCount = list.length;
             },
-
+            changeInchargerId() {
+                if(this.user.companyId == 876) {
+                    const userList = this.addForm.leaderId || []
+                    this.addForm.leaderId = userList.filter(item => item != this.addForm.inchargerId)
+                }
+            },
             showChooseMembTree() {
                 this.deptMembData = JSON.parse(JSON.stringify(this.allMembData))
                 this.chosenMembCount = this.participator.length;
@@ -5076,6 +5087,7 @@ a {
                         this.$set(this.addForm, 'region', '')
                         this.$set(this.addForm, 'bu', '')
                     }
+                    
                     if(this.user.timeType.projectManDay){
                         this.$set(this.addForm, 'manDay',0)
                         this.$set(this.addForm, 'manDayStartDate','')
@@ -5227,7 +5239,12 @@ a {
                             this.$set(this.addForm, 'bu', '')
                         }
                     }
-                    console.log(111111)
+                    // 米莱的的LA
+                    if(this.user.companyId == 876) {
+                        const leaderListList = item.leaderList || []
+                        const leaderListListId = leaderListList.map(id => id.leaderId)
+                        this.$set(this.addForm, 'leaderId', leaderListListId)
+                    }
                     // 判断是否有供应商
                     if(this.user.company.packageProvider) {
                         if(item.providerIds) {
@@ -5614,6 +5631,10 @@ a {
                             formData.append('reviwerId', this.addForm.reviwerId);
                         }
 
+                        if((this.addForm.leaderId || []).length > 0) {
+                            formData.append('leaderIds', this.addForm.leaderId);
+                        }
+
                         const deptListNew = this.addForm.deptIds.filter(item => item)
                         formData.append('deptIds', deptListNew.join(','))
                         this.http.uploadFile(this.port.project.add,formData,

+ 6 - 1
fhKeeper/formulahousekeeper/timesheet/src/views/project/project_gantt.vue

@@ -78,7 +78,7 @@
     <gantt v-if="isDataLoaded && user.userNameNeedTranslate != 1" ref="ganttTable1" class="left-container" :tasks="tasks" 
     :stafforpro="radio1"
     :valueDate="valueDate"
-    :key="updatakey1"></gantt>
+    :key="updatakey1" @closeBounced="closeBounced"></gantt>
     <vueGantt v-if="isDataLoaded && user.userNameNeedTranslate == 1" ref="ganttTable1" :stafforpro="radio1"
     :valueDate="valueDate"
     :key="updatakey1" :tasks="tasks"></vueGantt>
@@ -242,6 +242,11 @@ export default {
     this.isDataLoaded = true
   },
   methods: {
+    closeBounced(obj) {
+      if(obj.submitInsert) {
+        this.dateupdata()
+      }
+    },
     selectCal(obj) {
       if(obj.distinction == '1') {
           this.valuex = obj.id