Explorar o código

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

ggooalice %!s(int64=2) %!d(string=hai) anos
pai
achega
46e58003d3
Modificáronse 36 ficheiros con 1375 adicións e 80 borrados
  1. 81 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/CompanyController.java
  2. 5 2
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/ProjectController.java
  3. 1 2
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/ProjectProfessionController.java
  4. 1 1
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/ProjectRequirementController.java
  5. 192 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/ProviderInfoController.java
  6. 6 4
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/ReportController.java
  7. 2 1
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/UserController.java
  8. 483 26
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/WeiXinCorpController.java
  9. 12 6
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/Company.java
  10. 8 1
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/Department.java
  11. 21 8
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/Project.java
  12. 84 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/ProviderInfo.java
  13. 8 1
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/SysModule.java
  14. 1 1
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/mapper/ProjectRequirementMapper.java
  15. 16 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/mapper/ProviderInfoMapper.java
  16. 1 1
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/ProjectProfessionService.java
  17. 2 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/ProjectService.java
  18. 21 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/ProviderInfoService.java
  19. 2 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/ReportService.java
  20. 1 1
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/UserService.java
  21. 1 1
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/DingDingServiceImpl.java
  22. 6 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/PermissionServiceImpl.java
  23. 20 10
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ProjectProfessionServiceImpl.java
  24. 14 2
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ProjectServiceImpl.java
  25. 148 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ProviderInfoServiceImpl.java
  26. 77 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ReportServiceImpl.java
  27. 14 2
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/UserServiceImpl.java
  28. 105 0
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/application-dev2.yml
  29. 2 1
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/CompanyMapper.xml
  30. 2 2
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/DepartmentMapper.xml
  31. 4 3
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/ProjectMapper.xml
  32. 8 2
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/ProjectRequirementMapper.xml
  33. 23 0
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/ProviderInfoMapper.xml
  34. 2 1
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/SysModuleMapper.xml
  35. BIN=BIN
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/upload/供应商导入模板.xlsx
  36. 1 1
      fhKeeper/formulahousekeeper/timesheet/src/views/provider/provider.vue

+ 81 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/CompanyController.java

@@ -1,12 +1,23 @@
 package com.management.platform.controller;
 
 
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.management.platform.entity.CompanyDingding;
+import com.management.platform.entity.User;
+import com.management.platform.entity.vo.UserMonthWork;
+import com.management.platform.mapper.CompanyDingdingMapper;
+import com.management.platform.mapper.UserMapper;
+import com.management.platform.service.CompanyDingdingService;
 import com.management.platform.service.CompanyService;
+import com.management.platform.service.DingDingService;
 import com.management.platform.util.HttpRespMsg;
+import com.taobao.api.ApiException;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 
 import javax.annotation.Resource;
+import javax.servlet.http.HttpServletRequest;
+import java.util.HashMap;
 
 /**
  * <p>
@@ -19,11 +30,81 @@ import javax.annotation.Resource;
 @RestController
 @RequestMapping("/company")
 public class CompanyController {
+    @Resource
+    private HttpServletRequest request;
+
     @Resource
     private CompanyService companyService;
+    @Resource
+    private DingDingService dingDingService;
+    @Resource
+    private UserMapper userMapper;
+    @Resource
+    private CompanyDingdingMapper companyDingdingMapper;
+    public static final HashMap<String, Long> syncLog = new HashMap();
+
+
     @RequestMapping("/dataMigration")
     public HttpRespMsg dataMigration(Integer oldCompanyId,Integer targetCompanyId){
        return companyService.dataMigration(oldCompanyId,targetCompanyId);
     }
+
+    //同步钉钉
+    @RequestMapping("/syncCorpMembs")
+    public HttpRespMsg syncCorpMembs() {
+        try {
+            HttpRespMsg msg = new HttpRespMsg();
+            String token = request.getHeader("TOKEN");
+            User user = userMapper.selectById(token);
+            //判断时间
+            long now = System.currentTimeMillis();
+            if (syncLog.get(token) == null) {
+                syncLog.put(token, now);
+                syncLog.put(user.getCompanyId()+"_status", 1L);
+            } else {
+                if (now - syncLog.get(token) < 30*1000) {
+                    msg.setError("调用过于频繁,请稍后再试");
+                    return msg;
+                } else {
+                    //检查是否当前公司有同步的正在进行
+                    if (syncLog.get(user.getCompanyId()+"_status") == null) {
+                        //没有进行中的任务,更新最近同步的时间
+                        syncLog.put(token, now);
+                        syncLog.put(user.getCompanyId()+"_status", 1L);
+                    } else {
+                        if (now - syncLog.get(token) > 0.5*3600*1000) {
+                            //更新最近同步的时间
+                            syncLog.put(token, now);
+                        } else {
+                            msg.setError("同步正在进行中,请稍后再试");
+                            return msg;
+                        }
+                    }
+                }
+            }
+
+            CompanyDingding companyDingding = companyDingdingMapper.selectOne(new QueryWrapper<CompanyDingding>().eq("company_id", user.getCompanyId()));
+            if (companyDingding != null) {
+                System.out.println("===========同步钉钉===========");
+                String rest = dingDingService.syncCorpMembs(companyDingding.getCorpid());
+                syncLog.remove(user.getCompanyId()+"_status");
+                if (rest.startsWith("调用失败")) {
+                    msg.setError(rest);
+                } else {
+                    msg.data = rest;
+                }
+            } else {
+                msg.setError("非钉钉企业,无法同步");
+            }
+            return msg;
+        } catch (ApiException e) {
+            e.printStackTrace();
+            System.err.println(e.getMessage());
+            HttpRespMsg msg = new HttpRespMsg();
+            msg.setError(e.getMessage());
+            return msg;
+        }
+    }
+
 }
 

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

@@ -104,11 +104,14 @@ public class ProjectController {
                                    String auditUserIds,
                                    Integer category,
                                    String projectDesc,
-                                   Integer projectMainId
+                                   Integer projectMainId,
+                                   String providerIds,
+                                   String providerNames
                                    ) {
         return projectService.editProject(id, name, code, userId, inchargerId, isPublic, planStartDate, planEndDate, level, contractAmount,
                 projectBaseCostData,
-                 budget,customerId,chosenLeaders, associateDegrees, associateDegreeNames, taskGpIncharge,auditUserIds, category, projectDesc,projectMainId, request);
+                 budget,customerId,chosenLeaders, associateDegrees, associateDegreeNames,
+                taskGpIncharge,auditUserIds, category, projectDesc,projectMainId, providerIds, providerNames, request);
     }
 
     @RequestMapping("/adjustBase")

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

@@ -32,8 +32,7 @@ public class ProjectProfessionController {
     ProjectProfessionService projectProfessionService;
     @RequestMapping("/modify")
     public HttpRespMsg modify(Integer projectId, String json) {
-        projectProfessionService.modify(projectId, json);
-        return projectProfessionService.get(projectId);
+        return projectProfessionService.modify(projectId, json);
     }
 
     //获取项目相关的工程专业列表

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

@@ -101,7 +101,7 @@ public class ProjectRequirementController {
                 }
             });
         });
-        long total=projectRequirementMapper.selectCountByDate(companyId, startDate, projectId, projectIds.size()==0?null:projectIds, startIndex, pageSize,reStartDate,reEndDate);
+        long total=projectRequirementMapper.selectCountByDate(companyId, startDate, projectId, projectIds.size()==0?null:projectIds, null, null,reStartDate,reEndDate,taskGroupUserIds.size()==0?null:taskGroupUserIds);
         HashMap map = new HashMap();
         map.put("total", total);
         map.put("records", projectRequirements);

+ 192 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/ProviderInfoController.java

@@ -0,0 +1,192 @@
+package com.management.platform.controller;
+
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.management.platform.entity.ProviderInfo;
+import com.management.platform.entity.Project;
+import com.management.platform.entity.User;
+import com.management.platform.mapper.ProviderInfoMapper;
+import com.management.platform.mapper.ProjectMapper;
+import com.management.platform.mapper.ProviderInfoMapper;
+import com.management.platform.mapper.UserMapper;
+import com.management.platform.service.ProviderInfoService;
+import com.management.platform.service.ProviderInfoService;
+import com.management.platform.util.HttpRespMsg;
+import org.springframework.util.StringUtils;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletRequest;
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * <p>
+ *  前端控制器
+ * </p>
+ *
+ * @author Seyason
+ * @since 2022-07-07
+ */
+@RestController
+@RequestMapping("/provider-info")
+public class ProviderInfoController {
+    @Resource
+    private HttpServletRequest request;
+    @Resource
+    UserMapper userMapper;
+    @Resource
+    ProjectMapper projectMapper;
+    @Resource
+    ProviderInfoMapper providerInfoMapper;
+    @Resource
+    ProviderInfoService providerInfoService;
+
+    @RequestMapping("/addOrMod")
+    public HttpRespMsg addOrMod(ProviderInfo info) {
+        HttpRespMsg msg = new HttpRespMsg();
+        String token = request.getHeader("TOKEN");
+        User user = userMapper.selectById(token);
+        List<ProviderInfo> providerInfoMapperAll = providerInfoMapper.selectList(new QueryWrapper<ProviderInfo>().select("id, provider_name,provider_code").eq("company_id", user.getCompanyId()).orderByDesc("id"));
+        List<String> nameList=new ArrayList<>();
+        List<String> codeList=new ArrayList<>();
+        providerInfoMapperAll.forEach(cu->{
+            nameList.add(cu.getProviderName());
+            if(cu.getProviderCode()!=null){
+                codeList.add(cu.getProviderCode());
+            }
+        });
+        if (info.getId() == null) {
+            if(nameList.contains(info.getProviderName())){
+                msg.setError("客户名称已存在");
+                return msg;
+            }
+            if(codeList.contains(info.getProviderCode())){
+                msg.setError("客户编号已存在");
+                return msg;
+            }
+            info.setCompanyId(user.getCompanyId());
+            providerInfoMapper.insert(info);
+        } else {
+            ProviderInfo customerInfo = providerInfoMapper.selectById(info.getId());
+            nameList.remove(customerInfo.getProviderName());
+            codeList.remove(customerInfo.getProviderCode());
+            if(nameList.contains(info.getProviderName())){
+                msg.setError("客户名称已存在");
+                return msg;
+            }
+            if(codeList.contains(info.getProviderCode())){
+                msg.setError("客户编号已存在");
+                return msg;
+            }
+            info.setCompanyId(user.getCompanyId());
+            providerInfoMapper.updateById(info);
+            //更新项目表中的客户名称
+            Project p = new Project();
+            p.setCustomerName(info.getProviderName());
+            projectMapper.update(p, new QueryWrapper<Project>().eq("customer_id", info.getId()));
+        }
+        return msg;
+    }
+
+    @RequestMapping("/delete")
+    public HttpRespMsg delete(Integer id) {
+        HttpRespMsg msg = new HttpRespMsg();
+        String token = request.getHeader("TOKEN");
+        User user = userMapper.selectById(token);
+        ProviderInfo providerInfo = providerInfoMapper.selectById(id);
+        List<Project> projectList = projectMapper.selectList(new QueryWrapper<Project>().select("id, project_name, provider_ids, provider_names").like("provider_ids", id+"").like("provider_names", providerInfo.getProviderName()));
+        if (projectList.size() > 0) {
+            String containProjectNames = projectList.stream().filter(p->{
+                String[] split = p.getProviderIds().split(",");
+                boolean containId = Arrays.stream(split).anyMatch(s->s.equals(id+""));
+                return containId;
+            }).map(Project::getProjectName).collect(Collectors.joining(","));
+            if (!StringUtils.isEmpty(containProjectNames)) {
+                msg.setError("无法删除,以下项目已关联此供应商:"+containProjectNames);
+                return msg;
+            }
+        }
+        int r = providerInfoMapper.delete(new QueryWrapper<ProviderInfo>().eq("id", id).eq("company_id", user.getCompanyId()));
+        if (r <= 0) {
+            msg.setError("无权删除");
+        }
+        return msg;
+    }
+    @RequestMapping("/batchDelete")
+    public HttpRespMsg batchDelete(String batchIds) {
+        HttpRespMsg msg = new HttpRespMsg();
+        if(!StringUtils.isEmpty(batchIds)){
+            String[] split = batchIds.split(",");
+            List<String> list = Arrays.asList(split);
+            String token = request.getHeader("TOKEN");
+            User user = userMapper.selectById(token);
+
+            List<Project> projectList = projectMapper.selectList(new QueryWrapper<Project>().select("id, project_name, provider_ids, provider_names").eq("company_id", user.getCompanyId()).isNotNull("provider_ids"));
+            if(projectList.size()>0){
+                String str = null;
+                for (String providerId: list) {
+                    String names = projectList.stream().filter(p->{
+                        String[] hasIds = p.getProviderIds().split(",");
+                        boolean containId = Arrays.stream(hasIds).anyMatch(s->s.equals(providerId+""));
+                        return containId;
+                    }).map(Project::getProjectName).collect(Collectors.joining(","));
+                    if (!StringUtils.isEmpty(names)) {
+                        str = providerInfoMapper.selectById(Integer.valueOf(providerId)).getProviderName()+"已被以下项目关联:"+ names;
+                        break;
+                    }
+                }
+                if (str != null) {
+                    msg.setError(str);
+                    return msg;
+                }
+            }
+            providerInfoMapper.deleteBatchIds(list);
+        }
+        return msg;
+    }
+
+
+    @RequestMapping("/list")
+    public HttpRespMsg list(@RequestParam Integer pageIndex, @RequestParam Integer pageSize, String keyword) {
+        HttpRespMsg msg = new HttpRespMsg();
+        String token = request.getHeader("TOKEN");
+        User user = userMapper.selectById(token);
+        QueryWrapper<ProviderInfo> queryWrapper = new QueryWrapper<ProviderInfo>().eq("company_id", user.getCompanyId()).orderByDesc("id");
+        if (!StringUtils.isEmpty(keyword)) {
+            queryWrapper.like("provider_name", keyword);
+        }
+        IPage<ProviderInfo> projectIPage = providerInfoMapper.selectPage(new Page<>(pageIndex, pageSize),
+                queryWrapper);
+        List<ProviderInfo> list = projectIPage.getRecords();
+        Long total = projectIPage.getTotal();
+        Map<String, Object> map = new HashMap<>();
+        map.put("records", list);
+        map.put("total", total);
+        msg.data = map;
+        return msg;
+    }
+
+    @RequestMapping("/getAll")
+    public HttpRespMsg getAll() {
+        HttpRespMsg msg = new HttpRespMsg();
+        String token = request.getHeader("TOKEN");
+        User user = userMapper.selectById(token);
+        List<ProviderInfo> all = providerInfoMapper.selectList(new QueryWrapper<ProviderInfo>().select("id, provider_name,provider_code").eq("company_id", user.getCompanyId()).orderByDesc("id"));
+        msg.data = all;
+        return msg;
+    }
+
+    @RequestMapping("/importData")
+    public HttpRespMsg importData(HttpServletRequest request, MultipartFile file){
+        return providerInfoService.importData(request,file);
+    }
+
+}
+

+ 6 - 4
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/ReportController.java

@@ -16,10 +16,7 @@ import com.management.platform.service.UserService;
 import com.management.platform.util.HttpRespMsg;
 import com.management.platform.util.WorkDayCalculateUtils;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestParam;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.*;
 import org.springframework.web.multipart.MultipartFile;
 
 import javax.annotation.Resource;
@@ -1186,5 +1183,10 @@ public class ReportController {
     public HttpRespMsg getReportListByToken(@RequestParam String token, @RequestParam String startDate, @RequestParam String endDate){
         return reportService.getReportListByToken(token,startDate,endDate);
     }
+
+    @GetMapping("/fixIssue")
+    public HttpRespMsg fixIssue(){
+        return reportService.fixIssue();
+    }
 }
 

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

@@ -66,8 +66,9 @@ public class UserController {
     @RequestMapping("/getEmployeeList")
     public HttpRespMsg getEmployeeList(@RequestParam Integer departmentId, String keyword,
                                        Integer status, Integer roleId,
+                                       Integer onlyDirect,
                                        @RequestParam Integer pageIndex, @RequestParam Integer pageSize) {
-        return userService.getEmployeeList(departmentId, keyword, status, roleId, pageIndex, pageSize, request);
+        return userService.getEmployeeList(departmentId, keyword, status, roleId, onlyDirect, pageIndex, pageSize, request);
     }
 
     /**

+ 483 - 26
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/WeiXinCorpController.java

@@ -32,6 +32,13 @@ import java.util.stream.Collectors;
 @RequestMapping("/wxcorp")
 @Slf4j
 public class WeiXinCorpController {
+    //中转的服务器获取部门详情
+    public static final String TRANSMIT_SERVER_GET_DEPTDETAIL = "http://47.101.180.183:10010/wxcorp/getCorpDeptDetail?accessToken=ACCESS_TOKEN&deptId=DEPTID";
+    public static final String TRANSMIT_SERVER_GET_DEPTMEMBDETAIL = "http://47.101.180.183:10010/wxcorp/getDeptUserDetail?accessToken=ACCESS_TOKEN&deptId=DEPTID";
+    public static final String TRANSMIT_SERVER_GET_CONTACT_TOKEN = "http://47.101.180.183:10010/wxcorp/getCorpConcactAccessToken?corpid=CORPID&contactSecret=CONTACT_SECRET";
+
+    public static final String POST_CONVERT_USERID = "https://qyapi.weixin.qq.com/cgi-bin/batch/userid_to_openuserid?access_token=ACCESS_TOKEN";
+
     public static final String GET_SUITE_ACCESS_TOKEN_URL = "https://qyapi.weixin.qq.com/cgi-bin/service/get_suite_token";
     public static final String GET_PREAUTH_CODE_URL = "https://qyapi.weixin.qq.com/cgi-bin/service/get_pre_auth_code?suite_access_token=SUITE_ACCESS_TOKEN";
     //获取企业永久授权码
@@ -43,6 +50,7 @@ public class WeiXinCorpController {
     //获取部门列表
     public static final String GET_ALL_DEPARTMENT_URL = "https://qyapi.weixin.qq.com/cgi-bin/department/list?access_token=ACCESS_TOKEN";
     public static final String GET_DEPARTMENT_URL = "https://qyapi.weixin.qq.com/cgi-bin/department/list?access_token=ACCESS_TOKEN&id=1";//获取某个部门下的子部门
+    public static final String GET_DEPARTMENT_DETAIL_URL = "https://qyapi.weixin.qq.com/cgi-bin/department/get?access_token=ACCESS_TOKEN&id=ID";//获取部门详情
     //获取部门成员详情
     public static final String GET_DEPARTMENT_USER_DETAIL_URL = "https://qyapi.weixin.qq.com/cgi-bin/user/list?access_token=ACCESS_TOKEN&department_id=DEPARTMENT_ID&fetch_child=0";
     public static final String GET_DEPARTMENT_USER_SIMPLE_URL = "https://qyapi.weixin.qq.com/cgi-bin/user/simplelist?access_token=ACCESS_TOKEN&department_id=DEPARTMENT_ID&fetch_child=0";
@@ -183,23 +191,6 @@ public class WeiXinCorpController {
         return msg;
     }
 
-    //获取企业通讯录的accessToken
-    private String getCorpConcactAccessToken(WxCorpInfo corpInfo) throws Exception {
-        String url = GET_CORP_TOKEN.replace("ID", corpInfo.getCorpid()).replace("SECRET", corpInfo.getContactSecret());
-        ResponseEntity<String> responseEntity = this.restTemplate.exchange(url,
-                HttpMethod.GET, null, String.class);
-        if (responseEntity.getStatusCode() == HttpStatus.OK) {
-            String resp = responseEntity.getBody();
-            JSONObject json = JSONObject.parseObject(resp);
-            if (json.getIntValue("errcode") == 0) {
-                String access_token = json.getString("access_token");
-                corpInfo.setAccessToken(access_token);
-            } else {
-                throw new Exception(json.toJSONString());
-            }
-        }
-        return corpInfo.getAccessToken();
-    }
 
     //获取企业AccessToken
     private String getCorpAccessToken(WxCorpInfo corpInfo) throws Exception {
@@ -387,7 +378,14 @@ public class WeiXinCorpController {
     @ResponseBody
     public HttpRespMsg getAuthPage() {
         HttpRespMsg msg = new HttpRespMsg();
-        String preAuthCode = getAuthCode();
+        String preAuthCode = null;
+        try {
+            preAuthCode = getAuthCode();
+        } catch (Exception exception) {
+            exception.printStackTrace();
+            msg.setError(exception.getMessage());
+            return msg;
+        }
 
         String url = "https://open.work.weixin.qq.com/3rdapp/install?suite_id=SUITE_ID&pre_auth_code=PRE_AUTH_CODE&redirect_uri=REDIRECT_URI&state=STATE";
         url = url.replace("SUITE_ID", suitId).replace("PRE_AUTH_CODE", preAuthCode)
@@ -409,7 +407,7 @@ public class WeiXinCorpController {
 
 
 
-    private void handleCorpAuth(String authCode) {
+    private void handleCorpAuth(String authCode) throws Exception {
         String suitAccessToken = getSuiteAccessToken();
         String url = GET_CORP_PERMANENT_CODE_URL.replace("SUITE_ACCESS_TOKEN", suitAccessToken);
         //失效了,需要重新获取
@@ -691,13 +689,49 @@ public class WeiXinCorpController {
     private JSONArray getDeptUserInfo(String accessToken, int deptId) {
         String url = GET_DEPARTMENT_USER_DETAIL_URL.replace("ACCESS_TOKEN", accessToken).replace("DEPARTMENT_ID", ""+deptId);
         String result = restTemplate.getForObject(url, String.class);
-        System.out.println("部门人员详情:"+result);
+        System.out.println("第三方应用获取部门人员详情:"+result);
+        JSONObject obj = JSONObject.parseObject(result);
+        JSONArray userlist = obj.getJSONArray("userlist");
+        return userlist;
+    }
+
+    private JSONArray getTransDeptUserInfo(String accessToken, int deptId) {
+        String url = GET_DEPARTMENT_USER_DETAIL_URL.replace("ACCESS_TOKEN", accessToken).replace("DEPARTMENT_ID", ""+deptId);
+        String result = restTemplate.getForObject(url, String.class);
+        System.out.println("中转服务获取部门人员详情:"+result);
         JSONObject obj = JSONObject.parseObject(result);
         JSONArray userlist = obj.getJSONArray("userlist");
 
         return userlist;
     }
 
+    //企业通讯录获取到的userid转化为open_userid
+    private JSONArray convertUserIdToOpenUserId(String accessToken, List<String> userIdList) throws Exception {
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(MediaType.APPLICATION_JSON);
+        JSONObject reqParam = new JSONObject();
+        reqParam.put("userid_list",  userIdList);
+
+        HttpEntity<String> requestEntity = new HttpEntity<String>(reqParam.toJSONString(), headers);
+        String url = POST_CONVERT_USERID.replaceAll("ACCESS_TOKEN", accessToken);
+        ResponseEntity<String> responseEntity = this.restTemplate.exchange(url,
+                HttpMethod.POST, requestEntity, String.class);
+        if (responseEntity.getStatusCode() == HttpStatus.OK) {
+            String resp = responseEntity.getBody();
+            System.out.println(resp);
+
+            JSONObject obj = JSONObject.parseObject(resp);
+            if (obj.getIntValue("errcode") == 0) {
+                JSONArray openUseridList = obj.getJSONArray("open_userid_list");
+                return openUseridList;
+            } else {
+                //抛出异常
+                throw new Exception(obj.getString("errmsg"));
+            }
+        }
+        return null;
+    }
+
     private JSONObject getDepartments(String accessToken) {
         String url = GET_DEPARTMENT_URL.replace("ACCESS_TOKEN", accessToken);
         String result = restTemplate.getForObject(url, String.class);
@@ -707,6 +741,17 @@ public class WeiXinCorpController {
         return obj;
     }
 
+    //获取部门详情
+    private JSONObject getDeptDetail(String accessToken, int deptId) {
+        String url = GET_DEPARTMENT_DETAIL_URL.replace("ACCESS_TOKEN", accessToken).replace("ID", ""+deptId);
+        String result = restTemplate.getForObject(url, String.class);
+        log.info("部门详情:"+result);
+        JSONObject obj = JSONObject.parseObject(result);
+        return obj;
+    }
+
+
+
     private JSONObject getAllDepartments(String accessToken) {
         String url = GET_ALL_DEPARTMENT_URL.replace("ACCESS_TOKEN", accessToken);
         String result = restTemplate.getForObject(url, String.class);
@@ -725,7 +770,7 @@ public class WeiXinCorpController {
 
 
     //获取预授权码
-    private String getAuthCode() {
+    private String getAuthCode() throws Exception {
         if (PRE_AUTH_CODE == null || expireTime < System.currentTimeMillis()) {
             //失效了,需要重新获取
             String resp = restTemplate.getForObject(GET_PREAUTH_CODE_URL.replaceAll("SUITE_ACCESS_TOKEN", getSuiteAccessToken()), String.class);
@@ -740,7 +785,7 @@ public class WeiXinCorpController {
     }
 
     //获取第三方应用临时凭证
-    private String getSuiteAccessToken() {
+    private String getSuiteAccessToken() throws Exception {
         if (SUITE_ACCESS_TOKEN == null || suiteTokenExpireTime < System.currentTimeMillis()) {
             //失效了,需要重新获取
             HttpHeaders headers = new HttpHeaders();
@@ -759,10 +804,14 @@ public class WeiXinCorpController {
             if (responseEntity.getStatusCode() == HttpStatus.OK) {
                 String resp = responseEntity.getBody();
                 log.info(resp);
+
                 JSONObject obj = JSONObject.parseObject(resp);
                 if (obj.getIntValue("errcode") == 0) {
                     SUITE_ACCESS_TOKEN = obj.getString("suite_access_token");
                     suiteTokenExpireTime = System.currentTimeMillis() + obj.getIntValue("expires_in")*1000;
+                } else {
+                    //抛出异常
+                    throw new Exception(obj.getString("errmsg"));
                 }
             }
         }
@@ -778,7 +827,14 @@ public class WeiXinCorpController {
             msg.setError("该用户不存在,请退出重新登录");
             return msg;
         }
-        String url = GET_CORP_USERINFO_URL.replace("SUITE_ACCESS_TOKEN", getSuiteAccessToken()).replace("CODE", code);
+        String url = null;
+        try {
+            url = GET_CORP_USERINFO_URL.replace("SUITE_ACCESS_TOKEN", getSuiteAccessToken()).replace("CODE", code);
+        } catch (Exception exception) {
+            exception.printStackTrace();
+            msg.setError(exception.getMessage());
+            return msg;
+        }
         String forObject = this.restTemplate.getForObject(url, String.class);
         JSONObject obj = JSONObject.parseObject(forObject);
         String wxUserId = obj.getString("UserId");
@@ -819,7 +875,14 @@ public class WeiXinCorpController {
     public HttpRespMsg corpWeiXinLogin(String code) {
         HttpRespMsg msg = new HttpRespMsg();
 
-        String url = GET_CORP_USERINFO_URL.replace("SUITE_ACCESS_TOKEN", getSuiteAccessToken()).replace("CODE", code);
+        String url = null;
+        try {
+            url = GET_CORP_USERINFO_URL.replace("SUITE_ACCESS_TOKEN", getSuiteAccessToken()).replace("CODE", code);
+        } catch (Exception exception) {
+            exception.printStackTrace();
+            msg.setError(exception.getMessage());
+            return msg;
+        }
         String forObject = this.restTemplate.getForObject(url, String.class);
         JSONObject obj = JSONObject.parseObject(forObject);
         String wxUserId = obj.getString("UserId");
@@ -1051,9 +1114,324 @@ public class WeiXinCorpController {
         return new HttpRespMsg();
     }
 
-    //新版本
+    //新版本, 由于是第三方服务商,需要先获取授权范围内的组织架构(没有部门和人员的名称),再从中转服务器去获取名称
     @RequestMapping("/getCorpMembs")
     public HttpRespMsg getCorpMembs(String corpId) {
+        System.out.println("============新版getCorpMembs=========");
+        WxCorpInfo wxCorpInfo = wxCorpInfoMapper.selectById(corpId);
+        HttpRespMsg msg = new HttpRespMsg();
+        if (wxCorpInfo.getContactSecret() == null) {
+            msg.setError("请先设置企业通讯录同步Secret");
+            return msg;
+        }
+        Company company = companyMapper.selectById(wxCorpInfo.getCompanyId());
+        String corpContactAccessToken = null;
+        try {
+            corpContactAccessToken = getRemoteCorpConcactAccessToken(wxCorpInfo);
+        } catch (Exception exception) {
+            exception.printStackTrace();
+            msg.setError("同步失败:"+exception.getMessage());
+            return msg;
+        }
+
+        String curCorpAccessToken = null;
+        try {
+            curCorpAccessToken = getCorpAccessToken(wxCorpInfo);
+        } catch (Exception exception) {
+            exception.printStackTrace();
+            msg.setError("同步失败:"+exception.getMessage());
+            return msg;
+        }
+        int companyId = company.getId();
+        //获取公司根部门人员,也就是没有分配部门的人员
+        int companyRootDeptId = 1;
+        JSONArray unAssignedUserList = getDeptUserInfo(curCorpAccessToken, companyRootDeptId);
+        //获取远程的带姓名的详情,通过企业通讯录的token获取
+        JSONArray remoteUnAUserList = null;
+        if (unAssignedUserList.size() > 0) {
+            remoteUnAUserList = remoteGetDeptUserDetail(corpContactAccessToken, companyRootDeptId);
+            //做id转化
+            List<String> userIds = new ArrayList<>();
+            for (int i=0;i<remoteUnAUserList.size(); i++) {
+                userIds.add(remoteUnAUserList.getJSONObject(i).getString("userid"));
+            }
+            try {
+                JSONArray array = convertUserIdToOpenUserId(curCorpAccessToken, userIds);
+                for (int i=0;i<array.size(); i++) {
+                    JSONObject jsonObject = array.getJSONObject(i);
+                    String userid = jsonObject.getString("userid");
+                    String openUserid = jsonObject.getString("open_userid");
+                    //替换userid
+                    for (int m=0;m<remoteUnAUserList.size(); m++) {
+                        JSONObject remoteUser = remoteUnAUserList.getJSONObject(m);
+                        if (remoteUser.getString("userid").equals(userid)) {
+                            remoteUser.put("userid", openUserid);
+                            break;
+                        }
+                    }
+                }
+            } catch (Exception exception) {
+                exception.printStackTrace();
+                msg.setError("同步失败:"+exception.getMessage());
+                return msg;
+            }
+        }
+
+        SysRole defaultRole = sysRoleMapper.selectOne(
+                new QueryWrapper<SysRole>().eq("company_id", companyId).eq("is_default", 1));
+        List<JSONObject> hasDirectLdMembs = new ArrayList<>();
+        for (int m=0;m<unAssignedUserList.size(); m++) {
+            JSONObject userJson = unAssignedUserList.getJSONObject(m);
+            String curUserid = userJson.getString("userid");
+            //跳过非激活状态的员工
+            if (userJson.getInteger("status") != 1) continue;
+            System.out.println("userid="+curUserid+", name=" + userJson.getString("name")+", department="+userJson.getJSONArray("department"));
+            if (userJson.getJSONArray("direct_leader").size() > 0) {
+                hasDirectLdMembs.add(userJson);
+            }
+            //不存在的人员, 进行插入
+            User user = new User();
+
+            user.setId(SnowFlake.nextId()+"")
+                    .setRoleId(defaultRole.getId())//默认普通员工
+                    .setRoleName(defaultRole.getRolename())
+                    .setCompanyId(companyId)
+                    .setName(userJson.getString("name"))
+                    .setPhone(userJson.getString("mobile"))
+                    .setCorpwxUserid(curUserid)
+                    .setColor(ColorUtil.randomColor());
+            //获取姓名
+            if (remoteUnAUserList != null) {
+                for (int i=0;i<remoteUnAUserList.size(); i++) {
+                    JSONObject remoteUserJson = remoteUnAUserList.getJSONObject(i);
+                    if (remoteUserJson.getString("userid").equals(curUserid)) {
+                        user.setName(remoteUserJson.getString("name"));
+                        break;
+                    }
+                }
+            }
+            //检查用户是否已经存在
+            User oldUser = userMapper.selectOne(new QueryWrapper<User>().select("id, name").eq("corpwx_userid", curUserid).eq("company_id", companyId));
+            if (oldUser == null) {
+                //先检查姓名+手机号是否存在,如果存在,则更新corpwxId
+                User sameNameUser = userMapper.selectOne(new QueryWrapper<User>().eq("name", user.getName()).eq("mobile", user.getPhone()).eq("company_id", companyId).isNull("corpwx_userid").last("limit 1"));
+                if (sameNameUser != null) {
+                    User upUser = new User();
+                    upUser.setId(sameNameUser.getId());
+                    upUser.setCorpwxUserid(user.getCorpwxUserid());
+                    userMapper.updateById(upUser);
+                } else {
+                    userMapper.insert(user);
+                }
+            } else if (oldUser.getRoleName().equals("超级管理员") && !oldUser.getName().equals(user.getName())){
+                //姓名不一致,需要更新
+                System.out.println("===更新超管姓名==="+user.getName());
+                user.setId(oldUser.getId());
+                oldUser.setName(user.getName());
+                userMapper.updateById(oldUser);
+            }
+        }
+
+        //获取公司全部部门,不需要递归
+        JSONObject deptObj = getAllDepartments(curCorpAccessToken);
+        JSONArray deptObjJSONArray = deptObj.getJSONArray("department");
+
+        List<Department> sysDeptList = new ArrayList<>();
+        for (int i=0;i<deptObjJSONArray.size(); i++) {
+            int deptId = deptObjJSONArray.getJSONObject(i).getIntValue("id");
+            Department department = new Department();
+//            department.setDepartmentName(deptObjJSONArray.getJSONObject(i).getString("name"));
+            department.setCompanyId(companyId);
+            //设置企业微信的部门id
+            department.setCorpwxDeptid(deptObjJSONArray.getJSONObject(i).getInteger("id"));
+            System.out.println("开始远程获取部门详情=====");
+            String url = TRANSMIT_SERVER_GET_DEPTDETAIL.replace("ACCESS_TOKEN", corpContactAccessToken).replace("DEPTID", ""+deptId);
+            String result = restTemplate.getForObject(url, String.class);
+            System.out.println("部门返回数据:"+result);
+            JSONObject resultObj = JSONObject.parseObject(JSONObject.parseObject(result).getString("data"));
+            if (resultObj.getInteger("errcode") == 0) {
+                JSONObject serverDept = resultObj.getJSONObject("department");
+                String name = serverDept.getString("name");
+                department.setDepartmentName(name);
+            } else {
+                System.err.println("同步获取部门详情报错:"+resultObj.toString());
+            }
+
+            //检查是否已经有了
+            Department oldDept = departmentMapper.selectOne(new QueryWrapper<Department>().eq("company_id", companyId).eq("corpwx_deptid", department.getCorpwxDeptid()).last("limit 1"));
+            if (oldDept == null) {
+                if (deptId != 1) {
+                    //忽略根,根是公司名称
+                    //按名称比对
+                    oldDept = departmentMapper.selectOne(new QueryWrapper<Department>().eq("company_id", companyId).eq("department_name", department.getDepartmentName()).last("limit 1"));
+                    if (oldDept == null) {
+                        departmentMapper.insert(department);
+                    } else {
+                        //按照企业微信部门id进行更新
+                        oldDept.setCorpwxDeptid(department.getCorpwxDeptid());
+                        departmentMapper.updateById(oldDept);
+                    }
+                }
+            } else {
+                department = oldDept;
+            }
+
+            sysDeptList.add(department);
+            deptObjJSONArray.getJSONObject(i).put("sys_dept_id", department.getDepartmentId());
+            Integer departmentId = department.getDepartmentId();
+            JSONArray userList = getDeptUserInfo(curCorpAccessToken, deptId);
+            JSONArray remoteDeptUserList = null;
+            if (userList.size() > 0) {
+                remoteDeptUserList = remoteGetDeptUserDetail(corpContactAccessToken, deptId);
+                //做id转化
+                List<String> userIds = new ArrayList<>();
+                for (int p=0;p<remoteDeptUserList.size(); p++) {
+                    userIds.add(remoteDeptUserList.getJSONObject(p).getString("userid"));
+                }
+                try {
+                    JSONArray array = convertUserIdToOpenUserId(curCorpAccessToken, userIds);
+                    for (int w=0;w<array.size(); w++) {
+                        JSONObject jsonObject = array.getJSONObject(w);
+                        String userid = jsonObject.getString("userid");
+                        String openUserid = jsonObject.getString("open_userid");
+                        //替换userid
+                        for (int m=0;m<remoteDeptUserList.size(); m++) {
+                            JSONObject remoteUser = remoteDeptUserList.getJSONObject(m);
+                            if (remoteUser.getString("userid").equals(userid)) {
+                                remoteUser.put("userid", openUserid);
+                                break;
+                            }
+                        }
+                    }
+                } catch (Exception exception) {
+                    exception.printStackTrace();
+                    msg.setError("同步失败:"+exception.getMessage());
+                    return msg;
+                }
+            }
+
+            for (int m=0;m<userList.size(); m++) {
+                JSONObject userJson = userList.getJSONObject(m);
+                String curUserid = userJson.getString("userid");
+                if (userJson.getInteger("status") != 1) continue;
+                log.info("userid="+curUserid+", name=" + userJson.getString("name")+", mobile="+userJson.getString("mobile"));
+                if (userJson.getJSONArray("direct_leader").size() > 0) {
+                    hasDirectLdMembs.add(userJson);
+                }
+                //不存在的人员, 进行插入
+                User user = new User();
+
+                user.setId(SnowFlake.nextId()+"")
+                        .setRoleId(defaultRole.getId())
+                        .setRoleName(defaultRole.getRolename())
+                        .setCompanyId(companyId)
+                        .setDepartmentId(departmentId)
+                        .setPhone(userJson.getString("mobile"))
+                        .setName(userJson.getString("name"))
+                        .setCorpwxUserid(curUserid)
+                        .setColor(ColorUtil.randomColor());
+                //获取姓名
+                if (remoteDeptUserList != null) {
+                    for (int t=0;t<remoteDeptUserList.size(); t++) {
+                        JSONObject remoteUserJson = remoteDeptUserList.getJSONObject(t);
+                        if (remoteUserJson.getString("userid").equals(curUserid)) {
+                            //匹配到了。设置姓名
+                            System.out.println("远程的用户匹配到了:"+remoteUserJson.getString("name"));
+                            user.setName(remoteUserJson.getString("name"));
+                            break;
+                        }
+                    }
+                }
+                //检查用户是否已经存在
+                User oldUser = userMapper.selectOne(new QueryWrapper<User>().eq("corpwx_userid", curUserid).eq("company_id", companyId));
+                if (oldUser == null) {
+                    //先检查姓名是否存在,如果存在,则更新corpwxId
+                    User sameNameUser = userMapper.selectOne(new QueryWrapper<User>().eq("name", user.getName()).eq("mobile", user.getPhone()).eq("company_id", companyId).isNull("corpwx_userid").last("limit 1"));
+                    if (sameNameUser != null) {
+                        User upUser = new User();
+                        upUser.setId(sameNameUser.getId());
+                        upUser.setCorpwxUserid(user.getCorpwxUserid());
+                        userMapper.updateById(upUser);
+                    } else {
+                        //姓名也不存在,则插入新记录
+                        userMapper.insert(user);
+                    }
+                } else if (oldUser.getRoleName().equals("超级管理员") && !oldUser.getName().equals(user.getName())){
+                    //姓名不一致,需要更新
+                    System.out.println("===更新超管姓名==="+user.getName());
+                    user.setId(oldUser.getId());
+                    oldUser.setName(user.getName());
+                    userMapper.updateById(oldUser);
+                }
+            }
+        }
+
+        //再来更新部门的层级关系
+        List<Department> needUpdateDepts = new ArrayList<>();
+        for (int i=0;i<deptObjJSONArray.size(); i++) {
+            JSONObject deptJson = deptObjJSONArray.getJSONObject(i);
+            int pid = deptJson.getInteger("parentid");
+            if (pid != 1) {
+                //根部门Id = 1
+                Integer sysDeptId = deptJson.getInteger("sys_dept_id");
+                if (sysDeptId != null) {
+                    Department department = sysDeptList.stream().filter(d -> d.getDepartmentId() != null && d.getDepartmentId().equals(sysDeptId)).findFirst().get();
+                    //从deptjson数组中寻找parent item
+                    for (int m=0;m<deptObjJSONArray.size(); m++) {
+                        JSONObject item = deptObjJSONArray.getJSONObject(m);
+                        if (item.getInteger("id").equals(pid)) {
+                            department.setSuperiorId(item.getInteger("sys_dept_id"));
+                            break;
+                        }
+                    }
+                    needUpdateDepts.add(department);
+                }
+            }
+        }
+        if (needUpdateDepts.size() > 0) {
+            departmentService.updateBatchById(needUpdateDepts);
+        }
+        //更新人员的直属上级
+        if (hasDirectLdMembs.size() > 0) {
+            List<String> corpwxUids = new ArrayList<>();
+            for (JSONObject userJson : hasDirectLdMembs) {
+                String curUserid = userJson.getString("userid");
+                //取第一个leaderId
+                JSONArray directLeader = userJson.getJSONArray("direct_leader");
+                String string = directLeader.getString(0);
+                corpwxUids.add(curUserid);
+                if (!corpwxUids.contains(string)) {
+                    corpwxUids.add(string);
+                }
+            }
+            List<User> userList = userMapper.selectList(new QueryWrapper<User>().select("id, corpwx_userid, superior_id").in("corpwx_userid", corpwxUids));
+            List<User> updateUserList = new ArrayList<>();
+            for (JSONObject userJson : hasDirectLdMembs) {
+                String curUserid = userJson.getString("userid");
+                User user = userList.stream().filter(u -> u.getCorpwxUserid().equals(curUserid)).findFirst().get();
+                JSONArray directLeader = userJson.getJSONArray("direct_leader");
+                String leaderCorpWxuid = directLeader.getString(0);
+                //查找leader
+                User leader = userList.stream().filter(u -> u.getCorpwxUserid().equals(leaderCorpWxuid)).findFirst().get();
+                if (!leader.getId().equals(user.getSuperiorId())) {
+                    user.setSuperiorId(leader.getId());
+                    updateUserList.add(user);
+                }
+            }
+            if (updateUserList.size() > 0) {
+                //批量更新上级领导
+                userService.updateBatchById(updateUserList);
+            }
+        }
+
+        return new HttpRespMsg();
+    }
+
+
+
+    //直接通过企业的通讯录secret获取到组织架构,但是如果调用的服务器是第三方服务商会被腾讯识别并拦截
+    @RequestMapping("/getCorpMembsWithContactSEC")
+    public HttpRespMsg getCorpMembsWithContactSEC(String corpId) {
         WxCorpInfo wxCorpInfo = wxCorpInfoMapper.selectById(corpId);
         HttpRespMsg msg = new HttpRespMsg();
         if (wxCorpInfo.getContactSecret() == null) {
@@ -1167,7 +1545,8 @@ public class WeiXinCorpController {
                 User user = new User();
 
                 user.setId(SnowFlake.nextId()+"")
-                        .setRole(0)//默认普通员工
+                        .setRoleId(defaultRole.getId())
+                        .setRoleName(defaultRole.getRolename())
                         .setCompanyId(companyId)
                         .setDepartmentId(departmentId)
                         .setPhone(userJson.getString("mobile"))
@@ -1265,10 +1644,88 @@ public class WeiXinCorpController {
                 //批量更新上级领导
                 userService.updateBatchById(updateUserList);
             }
+
         }
         return new HttpRespMsg();
     }
 
+    private JSONArray remoteGetDeptUserDetail(String accessToken, int deptId) {
+        String url = TRANSMIT_SERVER_GET_DEPTMEMBDETAIL.replace("ACCESS_TOKEN", accessToken).replace("DEPTID", ""+deptId);
+        String result = restTemplate.getForObject(url, String.class);
+        System.out.println("远程部门人员详情:"+result);
+        JSONArray obj = JSONObject.parseArray(JSONObject.parseObject(result).getString("data"));
+        return obj;
+    }
+
+    //通过中转服务器,调用通讯录的accessToken
+    private String getRemoteCorpConcactAccessToken(WxCorpInfo corpInfo) throws Exception {
+        String url = TRANSMIT_SERVER_GET_CONTACT_TOKEN.replace("CORPID", corpInfo.getCorpid()).replace("CONTACT_SECRET", corpInfo.getContactSecret());
+        String result = restTemplate.getForObject(url, String.class);
+        System.out.println("远程获取Contact AccessToken:"+result);
+        JSONObject obj = JSONObject.parseObject(result);
+        if (obj.getString("code").equals("ok")) {
+            return obj.getString("data");
+        } else {
+            throw new Exception(obj.getString("msg"));
+        }
+    }
+
+    //提供接口,用于中转获取企业通讯录accessToken,因为直接在sass上访问会被屏蔽
+    @RequestMapping("/getCorpConcactAccessToken")
+    public HttpRespMsg getCorpConcactAccessToken(String corpid, String contactSecret) {
+        String url = GET_CORP_TOKEN.replace("ID", corpid).replace("SECRET", contactSecret);
+        ResponseEntity<String> responseEntity = this.restTemplate.exchange(url,
+                HttpMethod.GET, null, String.class);
+        HttpRespMsg msg = new HttpRespMsg();
+        if (responseEntity.getStatusCode() == HttpStatus.OK) {
+            String resp = responseEntity.getBody();
+            JSONObject json = JSONObject.parseObject(resp);
+            if (json.getIntValue("errcode") == 0) {
+                String access_token = json.getString("access_token");
+                msg.data = access_token;
+            } else {
+                msg.setError(json.toJSONString());
+            }
+        }
+        return msg;
+    }
+
+    //获取企业通讯录的accessToken,在私有化部署的企业内部服务器上跑
+    private String getCorpConcactAccessToken(WxCorpInfo corpInfo) throws Exception {
+        String url = GET_CORP_TOKEN.replace("ID", corpInfo.getCorpid()).replace("SECRET", corpInfo.getContactSecret());
+        ResponseEntity<String> responseEntity = this.restTemplate.exchange(url,
+                HttpMethod.GET, null, String.class);
+        if (responseEntity.getStatusCode() == HttpStatus.OK) {
+            String resp = responseEntity.getBody();
+            JSONObject json = JSONObject.parseObject(resp);
+            if (json.getIntValue("errcode") == 0) {
+                String access_token = json.getString("access_token");
+                corpInfo.setAccessToken(access_token);
+            } else {
+                throw new Exception(json.toJSONString());
+            }
+        }
+        return corpInfo.getAccessToken();
+    }
+
+
+    //用于从中转服务器获取企业通讯录的部门详情数据
+    @RequestMapping("/getCorpDeptDetail")
+    public HttpRespMsg getCorpDeptDetail(String accessToken, int deptId) {
+        JSONObject deptDetail = getDeptDetail(accessToken, deptId);
+        HttpRespMsg msg = new HttpRespMsg();
+        msg.data = deptDetail.toString();
+        return msg;
+    }
+
+    //用于从中转服务器获取企业通讯录的部门人员详情
+    @RequestMapping("/getDeptUserDetail")
+    public HttpRespMsg getDeptUserDetail(String accessToken, int deptId) {
+        JSONArray userList = getTransDeptUserInfo(accessToken, deptId);
+        HttpRespMsg msg = new HttpRespMsg();
+        msg.data = userList.toString();
+        return msg;
+    }
 
     private boolean judgeIsLeader(String userId) {
         int cnt = projectAuditorMapper.selectCount(new QueryWrapper<ProjectAuditor>().eq("auditor_id", userId));

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

@@ -1,23 +1,22 @@
 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 com.baomidou.mybatisplus.annotation.TableId;
+import java.time.LocalDateTime;
+import com.baomidou.mybatisplus.annotation.TableField;
+import java.io.Serializable;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
 import lombok.experimental.Accessors;
 
-import java.io.Serializable;
-import java.time.LocalDateTime;
-
 /**
  * <p>
  * 
  * </p>
  *
  * @author Seyason
- * @since 2022-04-01
+ * @since 2022-07-07
  */
 @Data
 @EqualsAndHashCode(callSuper = false)
@@ -117,6 +116,13 @@ public class Company extends Model<Company> {
     private Integer packageFinance;
 
 
+    /**
+     * 供应商模块
+     */
+    @TableField("package_provider")
+    private Integer packageProvider;
+
+
     @Override
     protected Serializable pkVal() {
         return this.id;

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

@@ -16,7 +16,7 @@ import lombok.experimental.Accessors;
  * </p>
  *
  * @author Seyason
- * @since 2022-01-05
+ * @since 2022-07-05
  */
 @Data
 @EqualsAndHashCode(callSuper = false)
@@ -62,6 +62,13 @@ public class Department extends Model<Department> {
     private String reportAuditUserid;
 
 
+    /**
+     * 企业微信的部门id
+     */
+    @TableField("corpwx_deptid")
+    private Integer corpwxDeptid;
+
+
     @Override
     protected Serializable pkVal() {
         return this.departmentId;

+ 21 - 8
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/Project.java

@@ -1,27 +1,27 @@
 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 java.time.LocalDate;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableField;
+import java.io.Serializable;
+import java.util.List;
+import java.util.Map;
+
 import com.fasterxml.jackson.annotation.JsonFormat;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
 import lombok.experimental.Accessors;
 import org.springframework.format.annotation.DateTimeFormat;
 
-import java.io.Serializable;
-import java.time.LocalDate;
-import java.util.List;
-import java.util.Map;
-
 /**
  * <p>
  * 
  * </p>
  *
  * @author Seyason
- * @since 2022-06-28
+ * @since 2022-07-07
  */
 @Data
 @EqualsAndHashCode(callSuper = false)
@@ -264,6 +264,19 @@ public class Project extends Model<Project> {
     private Integer projectMainId;
 
 
+    /**
+     * 供应商id
+     */
+    @TableField("provider_ids")
+    private String providerIds;
+
+    /**
+     * 供应商名称
+     */
+    @TableField("provider_names")
+    private String providerNames;
+
+
     @Override
     protected Serializable pkVal() {
         return this.id;

+ 84 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/ProviderInfo.java

@@ -0,0 +1,84 @@
+package com.management.platform.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.extension.activerecord.Model;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableField;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+/**
+ * <p>
+ * 
+ * </p>
+ *
+ * @author Seyason
+ * @since 2022-07-07
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+public class ProviderInfo extends Model<ProviderInfo> {
+
+    private static final long serialVersionUID=1L;
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Integer id;
+
+    /**
+     * 客户编码
+     */
+    @TableField("provider_code")
+    private String providerCode;
+
+    /**
+     * 客户公司名称
+     */
+    @TableField("provider_name")
+    private String providerName;
+
+    /**
+     * 联系人
+     */
+    @TableField("contact_name")
+    private String contactName;
+
+    /**
+     * 联系人电话
+     */
+    @TableField("contact_phone")
+    private String contactPhone;
+
+    /**
+     * 邮箱
+     */
+    @TableField("email")
+    private String email;
+
+    /**
+     * 地址
+     */
+    @TableField("address")
+    private String address;
+
+    /**
+     * 系统公司id
+     */
+    @TableField("company_id")
+    private Integer companyId;
+
+    /**
+     * 备注
+     */
+    @TableField("remark")
+    private String remark;
+
+
+    @Override
+    protected Serializable pkVal() {
+        return this.id;
+    }
+
+}

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

@@ -17,7 +17,7 @@ import lombok.experimental.Accessors;
  * </p>
  *
  * @author Seyason
- * @since 2022-04-05
+ * @since 2022-07-07
  */
 @Data
 @EqualsAndHashCode(callSuper = false)
@@ -151,6 +151,13 @@ public class SysModule extends Model<SysModule> {
     @TableField(exist = false)
     private List<SysFunction> functionList;
 
+    /**
+     * 是否属于供应商模块
+     */
+    @TableField("package_provider")
+    private Integer packageProvider;
+
+
     @Override
     protected Serializable pkVal() {
         return this.id;

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

@@ -17,5 +17,5 @@ public interface ProjectRequirementMapper extends BaseMapper<ProjectRequirement>
 
     public List<ProjectRequirement> customSelect(Integer companyId, String startDate, Integer projectId, List<Integer> refProjectIdList, Integer startIndex, Integer pageSize,String reStartDate,String reEndDate,List<String> refTaskGroupUserIdList);
 
-    long selectCountByDate(Integer companyId, String startDate, Integer projectId, List<Integer> refProjectIdList, int startIndex, Integer pageSize, String reStartDate, String reEndDate);
+    long selectCountByDate(Integer companyId, String startDate, Integer projectId, List<Integer> refProjectIdList, Integer startIndex, Integer pageSize, String reStartDate, String reEndDate,List<String> refTaskGroupUserIdList);
 }

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

@@ -0,0 +1,16 @@
+package com.management.platform.mapper;
+
+import com.management.platform.entity.ProviderInfo;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+ * <p>
+ *  Mapper 接口
+ * </p>
+ *
+ * @author Seyason
+ * @since 2022-07-07
+ */
+public interface ProviderInfoMapper extends BaseMapper<ProviderInfo> {
+
+}

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

@@ -14,7 +14,7 @@ import com.management.platform.util.HttpRespMsg;
  */
 public interface ProjectProfessionService extends IService<ProjectProfession> {
 
-    void modify(Integer projectId, String json);
+    HttpRespMsg modify(Integer projectId, String json);
 
     HttpRespMsg get(Integer projectId);
 

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

@@ -39,6 +39,8 @@ public interface ProjectService extends IService<Project> {
                             Integer category,
                             String projectDesc,
                             Integer projectMainId,
+                            String providerIds,
+                            String providerNames,
                             HttpServletRequest request);
 
     HttpRespMsg deleteProject(Integer id, Integer force);

+ 21 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/ProviderInfoService.java

@@ -0,0 +1,21 @@
+package com.management.platform.service;
+
+import com.management.platform.entity.ProviderInfo;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.management.platform.util.HttpRespMsg;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * <p>
+ *  服务类
+ * </p>
+ *
+ * @author Seyason
+ * @since 2022-07-07
+ */
+public interface ProviderInfoService extends IService<ProviderInfo> {
+
+    HttpRespMsg importData(HttpServletRequest request, MultipartFile file);
+}

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

@@ -88,4 +88,6 @@ public interface ReportService extends IService<Report> {
     HttpRespMsg denyHisReport(Integer hisId, String reason, HttpServletRequest request);
 
     HttpRespMsg getReportListByToken(String token, String startDate, String endDate);
+
+    HttpRespMsg fixIssue();
 }

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

@@ -23,7 +23,7 @@ public interface UserService extends IService<User> {
 
     HttpRespMsg getUserInfo(String id);
 
-    HttpRespMsg getEmployeeList(Integer departmentId, String keyword, Integer status, Integer roleId, Integer pageIndex, Integer pageSize, HttpServletRequest request);
+    HttpRespMsg getEmployeeList(Integer departmentId, String keyword, Integer status, Integer roleId, Integer onlyDirect, Integer pageIndex, Integer pageSize, HttpServletRequest request);
 
     HttpRespMsg deleteUser(String userId, HttpServletRequest request);
 

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

@@ -314,7 +314,7 @@ public class DingDingServiceImpl implements DingDingService {
 
         if (accessToken == null) {
             System.out.println("获取第三方企业accessToke失败");
-            return "调用失败";
+            return "调用失败:获取第三方企业accessToke失败";
         } else {
             System.out.println("syncCorpMembs 开始获取部门, accessToken="+accessToken);
             //获取授权的部门

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

@@ -186,6 +186,9 @@ public class PermissionServiceImpl extends ServiceImpl<PermissionMapper, Permiss
             if (company.getPackageFinance() == 1) {
                 wrapper.or().eq("package_finance", 1);
             }
+            if (company.getPackageProvider() == 1) {
+                wrapper.or().eq("package_provider", 1);
+            }
             if (timeType.getReportWorkflow() == 1) {
                 wrapper.or().eq("report_workflow", 1);
             }
@@ -229,6 +232,9 @@ public class PermissionServiceImpl extends ServiceImpl<PermissionMapper, Permiss
             if (company.getPackageFinance() == 1) {
                 wrapper.or().eq("package_finance", 1);
             }
+//            if (company.getPackageProvider() == 1) {
+//                wrapper.or().eq("package_provider", 1);
+//            }
             if (timeType.getSyncCorpwxTime() == 1) {
                 wrapper.or().eq("sync_corpwx_time", 1);
             }

+ 20 - 10
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ProjectProfessionServiceImpl.java

@@ -3,14 +3,8 @@ package com.management.platform.service.impl;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
-import com.management.platform.entity.PpMembs;
-import com.management.platform.entity.Profession;
-import com.management.platform.entity.ProjectProfession;
-import com.management.platform.entity.User;
-import com.management.platform.mapper.PpMembsMapper;
-import com.management.platform.mapper.ProfessionMapper;
-import com.management.platform.mapper.ProjectProfessionMapper;
-import com.management.platform.mapper.UserMapper;
+import com.management.platform.entity.*;
+import com.management.platform.mapper.*;
 import com.management.platform.service.PpMembsService;
 import com.management.platform.service.ProjectProfessionService;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
@@ -49,11 +43,13 @@ public class ProjectProfessionServiceImpl extends ServiceImpl<ProjectProfessionM
     PpMembsMapper ppMembsMapper;
     @Resource
     ProfessionMapper professionMapper;
+    @Resource
+    ReportProfessionProgressMapper reportProfessionProgressMapper;
+
 
 
     @Override
-    public void modify(Integer projectId, String json) {
-        System.out.println(json);
+    public HttpRespMsg modify(Integer projectId, String json) {
         List<ProjectProfession> professionList = new ArrayList<>();
         JSONArray array = JSONArray.parseArray(json);
         for (int i=0;i<array.size(); i++) {
@@ -62,6 +58,19 @@ public class ProjectProfessionServiceImpl extends ServiceImpl<ProjectProfessionM
             projectProfession.setProjectId(projectId);
             professionList.add(projectProfession);
         }
+        //比较差异
+        List<ProjectProfession> oldPPList = projectProfessionMapper.selectList(new QueryWrapper<ProjectProfession>().eq("project_id", projectId));
+        List<Integer> removedProfessionIds = oldPPList.stream().filter(old -> !professionList.stream().anyMatch(p -> p.getProfessionId().equals(old.getProfessionId()))).map(ProjectProfession::getProfessionId).collect(Collectors.toList());
+        //检查日报
+        if (removedProfessionIds.size() > 0) {
+            long cnt = reportProfessionProgressMapper.selectCount(new QueryWrapper<ReportProfessionProgress>().eq("project_id", projectId).in("profession_id", removedProfessionIds).eq("audit_state", 0));
+            if (cnt > 0) {
+                HttpRespMsg msg = new HttpRespMsg();
+                msg.setError("尚存在日报在该专业上待审核,审核通过后才能移除");
+                return msg;
+            }
+        }
+
 //        //之前的数据都删掉
         projectProfessionMapper.delete(new QueryWrapper<ProjectProfession>().eq("project_id", projectId));
 //        //插入新的数据
@@ -84,6 +93,7 @@ public class ProjectProfessionServiceImpl extends ServiceImpl<ProjectProfessionM
         if (ppList.size() > 0) {
             ppMembsService.saveBatch(ppList);
         }
+        return get(projectId);
     }
 
     @Override

+ 14 - 2
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ProjectServiceImpl.java

@@ -258,6 +258,8 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
                                    Integer category,
                                    String projectDesc,
                                    Integer projectMainId,
+                                   String providerIds,
+                                   String providerNames,
                                    HttpServletRequest request) {
         HttpRespMsg httpRespMsg = new HttpRespMsg();
         User user = userMapper.selectById(request.getHeader("Token"));
@@ -313,7 +315,9 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
                             .setCustomerId(customerId)
                             .setProjectDesc(projectDesc)
                             .setProjectMainId(projectMainId)
-                            .setTaskGpIncharge(taskGpIncharge);
+                            .setTaskGpIncharge(taskGpIncharge)
+                            .setProviderIds(providerIds)
+                            .setProviderNames(providerNames);
                     if (category != null) {
                         ProjectCategory projectCategory = projectCategoryMapper.selectById(category);
                         if (projectCategory != null) {
@@ -381,7 +385,9 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
                         .setCustomerId(customerId)
                         .setProjectDesc(projectDesc)
                         .setProjectMainId(projectMainId)
-                        .setTaskGpIncharge(taskGpIncharge);
+                        .setTaskGpIncharge(taskGpIncharge)
+                        .setProviderIds(providerIds)
+                        .setProviderNames(providerNames);
                 if (category != null) {
                     ProjectCategory projectCategory = projectCategoryMapper.selectById(category);
                     if (projectCategory != null) {
@@ -2385,6 +2391,9 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
         if (timeType.getCustomDegreeActive() == 1) {
             headList.add(timeType.getCustomDegreeName());
         }
+        if (company.getPackageProvider() == 1) {
+            headList.add("供应商");
+        }
         if (company.getPackageProject() == 1) {
             //项目管理专业版以上的,导出的数据更全面
             headList.add("客户");
@@ -2415,6 +2424,9 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
             if (timeType.getCustomDegreeActive() == 1) {
                 rowData.add((String)map.get("associate_degree_names"));
             }
+            if (company.getPackageProvider() == 1) {
+                rowData.add((String)map.get("provider_names"));
+            }
             if (company.getPackageProject() == 1) {
                 Integer level = (Integer)map.get("level");
                 if (level == null) {

+ 148 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ProviderInfoServiceImpl.java

@@ -0,0 +1,148 @@
+package com.management.platform.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.management.platform.entity.CustomerInfo;
+import com.management.platform.entity.ProviderInfo;
+import com.management.platform.mapper.CustomerInfoMapper;
+import com.management.platform.mapper.ProviderInfoMapper;
+import com.management.platform.mapper.UserMapper;
+import com.management.platform.service.ProviderInfoService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.management.platform.util.ExcelUtil;
+import com.management.platform.util.HttpRespMsg;
+import org.apache.poi.EncryptedDocumentException;
+import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
+import org.apache.poi.ss.usermodel.*;
+import org.springframework.stereotype.Service;
+import org.springframework.util.StringUtils;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletRequest;
+import java.io.*;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * <p>
+ *  服务实现类
+ * </p>
+ *
+ * @author Seyason
+ * @since 2022-07-07
+ */
+@Service
+public class ProviderInfoServiceImpl extends ServiceImpl<ProviderInfoMapper, ProviderInfo> implements ProviderInfoService {
+
+    @Resource
+    ProviderInfoMapper providerInfoMapper;
+    @Resource
+    UserMapper userMapper;
+    @Override
+    public HttpRespMsg importData(HttpServletRequest request, MultipartFile multipartFile) {
+        HttpRespMsg msg=new HttpRespMsg();
+        Integer companyId=userMapper.selectById(request.getHeader("token")).getCompanyId();
+        String fileName=multipartFile.getOriginalFilename();
+        File file=new File(fileName == null ? "file" : fileName);
+        InputStream inputStream=null;
+        OutputStream outputStream=null;
+        try {
+            inputStream= multipartFile.getInputStream();
+            outputStream=new FileOutputStream(file);
+            byte[] buffer = new byte[4096];
+            int temp = 0;
+            while ((temp = inputStream.read(buffer, 0, 4096)) != -1) {
+                outputStream.write(buffer, 0, temp);
+            }
+            inputStream.close();
+            outputStream.close();
+
+            //然后解析表格
+            Workbook workbook = WorkbookFactory.create(new FileInputStream(file));
+            DateFormat df = new SimpleDateFormat("yyyy-MM");
+            //获取公司所有客户
+            List<ProviderInfo> allCustomerInfo = providerInfoMapper.selectList(new QueryWrapper<ProviderInfo>().eq("company_id", companyId));
+            Sheet sheet = workbook.getSheetAt(0);
+            //由于第一行需要指明列对应的标题
+            int rowNum = sheet.getLastRowNum();
+            if (rowNum == 0) {
+                msg.setError("请填写供应商数据");
+                return msg;
+            }
+            List<String> nameList=new ArrayList<>();
+            int dataCount = 0;
+            for (int rowIndex = 1; rowIndex <= rowNum; rowIndex++) {
+                Row row = sheet.getRow(rowIndex);
+                dataCount++;
+                if (row == null) {
+                    continue;
+                }
+                if (ExcelUtil.isRowEmpty(row)) {
+                    continue;
+                }
+                if (row.getCell(1) == null) {
+                    msg.setError("第"+dataCount+"行缺少供应商名称");
+                    return msg;
+                }
+                if(nameList.contains(row.getCell(1).toString())){
+                    msg.setError("当前导入数据存在重复供应商名称["+row.getCell(1).toString()+"]");
+                    return msg;
+                }
+                nameList.add(row.getCell(1).toString());
+                ProviderInfo customerInfo=new ProviderInfo();
+                List<ProviderInfo> collect = allCustomerInfo.stream().filter(sv -> sv.getProviderName().equals(row.getCell(1).toString())).collect(Collectors.toList());
+                customerInfo.setProviderCode(StringUtils.isEmpty(row.getCell(0))?"":row.getCell(0).toString());
+                customerInfo.setProviderName(StringUtils.isEmpty(row.getCell(1))?"":row.getCell(1).toString());
+                customerInfo.setContactName(StringUtils.isEmpty(row.getCell(2))?"":row.getCell(2).toString());
+                if(StringUtils.isEmpty(row.getCell(3))){
+                    customerInfo.setContactPhone("");
+                }else {
+                    row.getCell(3).setCellType(CellType.STRING);
+                    customerInfo.setContactPhone(row.getCell(3).getStringCellValue());
+                }
+                customerInfo.setEmail(StringUtils.isEmpty(row.getCell(3))?"":row.getCell(3).toString());
+                customerInfo.setAddress(StringUtils.isEmpty(row.getCell(4))?"":row.getCell(4).toString());
+                customerInfo.setRemark(StringUtils.isEmpty(row.getCell(5))?"":row.getCell(5).toString());
+                customerInfo.setCompanyId(companyId);
+                if(collect.size()>0){
+                    Integer id=collect.get(0).getId();
+                    customerInfo.setId(id);
+                    providerInfoMapper.updateById(customerInfo);
+                }else{
+                    providerInfoMapper.insert(customerInfo);
+                }
+            }
+            msg.data=dataCount;
+            return msg;
+        } catch (IOException e){
+            e.printStackTrace();
+            msg.setError("文件处理出错");
+            return msg;
+        } catch (InvalidFormatException e) {
+            e.printStackTrace();
+            msg.setError("文件格式错误,如果安装了加密软件需要先解密再上传");
+            return msg;
+        } catch (EncryptedDocumentException e) {
+            e.printStackTrace();
+            msg.setError("文件加密状态,需要先解除加密状态再上传");
+            return msg;
+        }finally {
+            //关闭流
+            try {
+                if (outputStream != null && inputStream != null) {
+                    outputStream.close();
+                    inputStream.close();
+                    System.out.println("流已关闭");
+                }
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+//            file.deleteOnExit();//程序退出时删除临时文件
+            System.out.println(file.delete());
+        }
+    }
+
+}

+ 77 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ReportServiceImpl.java

@@ -497,6 +497,9 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
                 r.setTaskList(taskList.stream().filter(t->t.getProjectId().equals(r.getProjectId()) && t.getUserId().equals(r.getCreatorId())).collect(Collectors.toList()));
                 //获取当前项目的工程专业进度
                 List<ReportProfessionProgress> progressList = reportProfessionProgressService.list(new QueryWrapper<ReportProfessionProgress>().eq("report_id", r.getId()));
+                //去掉当前项目上已经不存在的专业
+                List<ProjectProfession> projectProfessions = projectProfessionMapper.selectList(new QueryWrapper<ProjectProfession>().eq("project_id", r.getProjectId()));
+                progressList = progressList.stream().filter(p->projectProfessions.stream().anyMatch(pp->pp.getProfessionId().equals(p.getProfessionId()))).collect(Collectors.toList());
                 progressList.stream().forEach(p->{
                     p.setProfessionName(professions.stream().filter(m->m.getId().equals(p.getProfessionId())).findFirst().get().getName());
                 });
@@ -3522,4 +3525,78 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
         return msg;
     }
 
+    @Override
+    public HttpRespMsg fixIssue() {
+        Integer companyId = 862;
+        Company company = companyMapper.selectById(companyId);
+        System.out.println("========处理公司======="+company.getCompanyName());
+        //查找某日某天的日报,项目上已经都审核通过,但是state = 0,并且没有走到下一个阶段的
+        List<Report> reportList = reportMapper.selectList(new QueryWrapper<Report>().eq("company_id", companyId));
+        List<String> creatorIds = reportList.stream().map(Report::getCreatorId).distinct().collect(Collectors.toList());
+        List<LocalDate> dateList = reportList.stream().map(Report::getCreateDate).distinct().collect(Collectors.toList());
+        List<User> userList = userMapper.selectList(new QueryWrapper<User>().eq("company_id", companyId));
+        List<Department> allDepts = departmentMapper.selectList(new QueryWrapper<Department>().eq("company_id", companyId));
+        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+
+        for (String creator : creatorIds) {
+            User user = userList.stream().filter(u -> u.getId().equals(creator)).findFirst().get();
+            String creatorName = user.getName();
+            String dateStr = "";
+            for (LocalDate date : dateList) {
+                //某人某天的全部日报
+                List<Report> userDayReport = reportList.stream().filter(r -> r.getCreatorId().equals(creator) && r.getCreateDate().isEqual(date)).collect(Collectors.toList());
+                if (userDayReport.size() > 0) {
+                    //有当前的日报
+                    boolean isAllProjectAuditPass = !userDayReport.stream().anyMatch(r->r.getProjectAuditState() != 1);
+                    boolean isAllState0 = !userDayReport.stream().anyMatch(r->r.getState() != 0);
+
+                    if (isAllProjectAuditPass && isAllState0) {
+                        //当前的日报项目全部通过,但是日报本身还是待审核状态的,需要更新
+                        dateStr +=dtf.format(date) + ", ";
+                        List<Integer> rids = userDayReport.stream().map(Report::getId).collect(Collectors.toList());
+                        //测试: 翁浩勃
+//                        if ("翁浩勃".equals(creatorName)) {
+//
+//                        }
+                        selfUpdateToNextWorkFlow(companyId, user, rids, allDepts);
+                    }
+                }
+            }
+            if (!StringUtils.isEmpty(dateStr)) {
+                System.out.println(creatorName+"  " + dateStr);
+            }
+        }
+
+        return new HttpRespMsg();
+    }
+
+    private void selfUpdateToNextWorkFlow(Integer companyId, User auditTargetUser, List<Integer> targetRids, List<Department> allDepts) {
+        List<AuditWorkflowTimeSetting> settings = auditWorkflowTimeSettingMapper.selectList(
+                new QueryWrapper<AuditWorkflowTimeSetting>().eq("company_id", companyId)
+                        .orderByAsc("seq"));
+        LocalDateTime now = LocalDateTime.now();
+        List<AuditWorkflowTimeSetting> deptSettings = settings.stream().filter(s->s.getDeptId().equals(auditTargetUser.getDepartmentId())).collect(Collectors.toList());
+        Report upR = new Report();
+        if (deptSettings.size() == 0) {
+            //直接进行项目经理审核
+            upR.setState(1).setProjectAuditTime(now);
+        } else {
+            for (int m=0;m<deptSettings.size(); m++) {
+                if (deptSettings.get(m).getIsDeptAudit()== 0) {//找到项目审核的那个节点
+                    AuditWorkflowTimeSetting nextNode = deptSettings.get(m + 1);
+                    upR.setIsDeptAudit(nextNode.getIsDeptAudit());
+                    if (upR.getIsDeptAudit() == 1) {
+                        upR.setAuditDeptid(nextNode.getAuditDeptId());
+                        Department department = allDepts.stream()
+                                .filter(ad -> ad.getDepartmentId().equals(nextNode.getAuditDeptId())).findFirst().get();
+                        System.out.println("更新到下个部门审核的节点:" + department.getDepartmentName());
+                        upR.setAuditDeptManagerid(department.getManagerId());
+                    }
+                    upR.setIsFinalAudit(nextNode.getIsFinal());
+                    break;
+                }
+            }
+        }
+        reportMapper.update(upR, new QueryWrapper<Report>().in("id", targetRids));
+    }
 }

+ 14 - 2
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/UserServiceImpl.java

@@ -229,6 +229,9 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
         if (company.getPackageFinance() == 1) {
             queryWrapper.or().eq("package_finance", 1);
         }
+        if (company.getPackageProvider() == 1) {
+            queryWrapper.or().eq("package_provider", 1);
+        }
         if (timeType.getReportWorkflow() == 1) {
             queryWrapper.or().eq("report_workflow", 1);
         }
@@ -396,7 +399,7 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
 
     //获取员工的列表
     @Override
-    public HttpRespMsg getEmployeeList(Integer departmentId, String keyword, Integer status, Integer roleId, Integer pageIndex, Integer pageSize, HttpServletRequest request) {
+    public HttpRespMsg getEmployeeList(Integer departmentId, String keyword, Integer status, Integer roleId, Integer onlyDirect, Integer pageIndex, Integer pageSize, HttpServletRequest request) {
         HttpRespMsg httpRespMsg = new HttpRespMsg();
         try {
             Integer companyId = userMapper.selectById(request.getHeader("Token")).getCompanyId();
@@ -414,7 +417,16 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
                 total = page.getTotal();
             } else {
                 //范围查找
-                list = userMapper.getUserByDepartmentList(page, companyId, getBranchDepartment(departmentId, companyId), keyword, status, roleId);
+                List<Integer> ids = new ArrayList<>();
+                if (onlyDirect != null && onlyDirect == 1) {
+                    //只看直属的
+                    ids.add(departmentId);
+                } else {
+                    //查看当前部门包括子部门的人员
+                    ids = getBranchDepartment(departmentId, companyId);
+                }
+
+                list = userMapper.getUserByDepartmentList(page, companyId, ids, keyword, status, roleId);
                 total = page.getTotal();
             }
             Map<String, Object> resultMap = new HashMap<>();

+ 105 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/resources/application-dev2.yml

@@ -0,0 +1,105 @@
+server:
+  port: 10010
+  tomcat:
+    uri-encoding: utf-8
+    max-http-form-post-size: -1
+    connection-timeout: 18000000s
+spring:
+  servlet:
+    multipart:
+      # 配置上传文件的大小设置
+      # Single file max size  即单个文件大小
+      max-file-size: 100MB
+      max-request-size: 100MB
+  datasource:
+    driver-class-name: com.mysql.cj.jdbc.Driver
+    url: jdbc:mysql://127.0.0.1:3306/man_hour_manager?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&rewriteBatchedStatements=true&&useSSL=false
+    username: root
+    password: HuoshiDB@2022
+    hikari:
+      maximum-pool-size: 10
+      minimum-idle: 3
+      max-lifetime: 30000
+      connection-test-query: SELECT 1
+    #######redis配置######
+    # redis
+    redis:
+      host: 127.0.0.1
+      port: 6479
+      timeout: 3
+      # password:
+      pool:
+        minIdle: 1
+        maxIdle: 10
+        maxWait: 3
+        maxActive: 8
+    ####全局配置时间返回格式#####
+  jackson:
+    #参数意义:
+    #JsonInclude.Include.ALWAYS       默认
+    #JsonInclude.Include.NON_DEFAULT   属性为默认值不序列化
+    #JsonInclude.Include.NON_EMPTY     属性为 空(””) 或者为 NULL 都不序列化
+    #JsonInclude.Include.NON_NULL      属性为NULL  不序列化
+    default-property-inclusion: ALWAYS
+    time-zone: GMT+8
+    date-format: yyyy-MM-dd HH:mm:ss
+
+##########日志配置
+logging:
+  level:
+    root: info
+    org.mybatis: error
+    java.sql: error
+    org.springframework.web: error
+    #打印sql语句
+    com.management.platform.mapper: error
+  path: /log/
+  file: worktime.log
+##########
+mybatis-plus:
+  #  mapper-locations: classpath:mapper/*/*.xml
+  #  #实体扫描,多个package用逗号或者分号分隔
+  #  typeAliasesPackage: com.hssx.cloudmodel
+  global-config:
+    #主键类型  0:"数据库ID自增", 1:"用户输入ID",2:"全局唯一ID (数字类型唯一ID)", 3:"全局唯一ID UUID";
+    id-type: 0
+    #字段策略 0:"忽略判断",1:"非 NULL 判断"),2:"非空判断"
+    field-strategy: 2
+    db-column-underline: true
+    refresh-mapper:
+    #################插入和更新非null判断
+    db-config:
+      insert-strategy: not_null
+      update-strategy: not_null
+  configuration:
+    map-underscore-to-camel-case: true
+    cache-enabled: false
+######mybstis配置#######
+mybatis:
+  type-aliases-package: com.management.platform.entity
+  mapper-locations: mappers/*Mapper.xml
+#####配置图片上传路径####
+upload:
+  path: /www/staticproject/timesheet/upload/
+
+
+
+
+
+##actuator健康检查配置
+management:
+  security:
+    enabled:false:
+  server:
+    port: 10011
+  #  endpoints:
+  #    web:
+  #      exposure:
+  #        include: "*"
+
+  health:
+    redis:
+      enabled: false
+
+configEnv:
+  isDev: true

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

@@ -19,11 +19,12 @@
         <result column="package_engineering" property="packageEngineering" />
         <result column="package_simple" property="packageSimple" />
         <result column="package_finance" property="packageFinance" />
+        <result column="package_provider" property="packageProvider" />
     </resultMap>
 
     <!-- 通用查询结果列 -->
     <sql id="Base_Column_List">
-        id, company_name, staff_count_max, expiration_date, set_meal, package_worktime, package_project, package_contract, package_oa, package_etimecard, package_expense, package_customer, package_engineering, package_simple, package_finance
+        id, company_name, staff_count_max, expiration_date, set_meal, package_worktime, package_project, package_contract, package_oa, package_etimecard, package_expense, package_customer, package_engineering, package_simple, package_finance, package_provider
     </sql>
 
 </mapper>

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

@@ -10,14 +10,14 @@
         <result column="company_id" property="companyId" />
         <result column="manager_id" property="managerId" />
         <result column="report_audit_userid" property="reportAuditUserid" />
+        <result column="corpwx_deptid" property="corpwxDeptid" />
     </resultMap>
 
     <!-- 通用查询结果列 -->
     <sql id="Base_Column_List">
-        department_id, department_name, superior_id, company_id, manager_id, report_audit_userid
+        department_id, department_name, superior_id, company_id, manager_id, report_audit_userid, corpwx_deptid
     </sql>
 
-
     <!--根据部门获取成本-->
     <select id="getCostByDepartment" resultType="java.util.Map">
         SELECT SUM(b.working_time) AS time, SUM(b.cost) AS money

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

@@ -39,14 +39,15 @@
         <result column="category_name" property="categoryName" />
         <result column="project_desc" property="projectDesc" />
         <result column="project_main_id" property="projectMainId" />
+        <result column="provider_ids" property="providerIds" />
+        <result column="provider_names" property="providerNames" />
     </resultMap>
 
     <!-- 通用查询结果列 -->
     <sql id="Base_Column_List">
-        id, project_name, company_id, project_code, incharger_id, plan_start_date, plan_end_date, progress, level, status, finish_date, creator_id, creator_name, create_date, contract_amount, budget, base_man, base_outsourcing, base_risk1, base_risk2, base_fee, fee_normal, fee_travel, fee_outsourcing, fee_man, customer_id, customer_name, is_public, associate_degrees, associate_degree_names, task_gp_incharge, category, category_name, project_desc, project_main_id
+        id, project_name, company_id, project_code, incharger_id, plan_start_date, plan_end_date, progress, level, status, finish_date, creator_id, creator_name, create_date, contract_amount, budget, base_man, base_outsourcing, base_risk1, base_risk2, base_fee, fee_normal, fee_travel, fee_outsourcing, fee_man, customer_id, customer_name, is_public, associate_degrees, associate_degree_names, task_gp_incharge, category, category_name, project_desc, project_main_id, provider_ids, provider_names
     </sql>
 
-
     <resultMap id="BaseResultMap2" type="com.management.platform.entity.vo.ProjectWithStage">
         <result column="id" property="id" />
         <result column="project_name" property="projectName" />
@@ -654,7 +655,7 @@
     <select id="getExportData" resultType="java.util.HashMap" >
         SELECT project.id, project_name, project_code,category_name,is_public,plan_start_date, d.name AS incharger_name,GROUP_CONCAT(u.name) AS participators,
         plan_end_date, progress, LEVEL, STATUS, finish_date, creator_id, creator_name, create_date, contract_amount,
-        customer_name, associate_degree_names
+        customer_name, associate_degree_names, provider_names
         FROM project LEFT JOIN sub_project ON sub_project.id = project.`id`
         LEFT JOIN participation c ON c.project_id = project.`id`
         LEFT JOIN user u ON u.id = c.user_id

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

@@ -59,8 +59,14 @@
     </select>
     <select id="selectCountByDate" resultType="java.lang.Long">
         select count(*)
-        from (SELECT project_requirement.id, project.id AS project_id, project.`project_name`, project.`project_code`, project_requirement.`memb_req`, project_requirement.`task_req`,project_requirement.start_date,project_requirement.end_date,
-        (SELECT GROUP_CONCAT(DISTINCT user.`name`) FROM report LEFT JOIN `user` ON user.`id` = report.`creator_id` WHERE report.company_id=#{companyId} AND report.create_time >= #{startDate} AND report.`project_id` = project.id) AS active_users
+        from ( SELECT project_requirement.id, project.id AS project_id, project.`project_name`, project.`project_code`, project_requirement.`memb_req`, project_requirement.`task_req`,project_requirement.contract_req,project_requirement.department_speed,project_requirement.start_date,project_requirement.end_date,
+        (SELECT GROUP_CONCAT(DISTINCT user.`name`) FROM report LEFT JOIN `user` ON user.`id` = report.`creator_id` WHERE report.company_id=#{companyId} AND report.create_time >= #{startDate} AND report.`project_id` = project.id
+        <if test="refTaskGroupUserIdList!=null">
+            and user.`id` in
+            <foreach collection="refTaskGroupUserIdList" open="(" close=")" separator="," item="item">
+                #{item}
+            </foreach>
+        </if> ) AS active_users
         FROM project LEFT JOIN project_requirement ON project.id = project_requirement.`project_id`
         WHERE project.`company_id` = #{companyId}
         <if test="projectId != null">

+ 23 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/ProviderInfoMapper.xml

@@ -0,0 +1,23 @@
+<?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.ProviderInfoMapper">
+
+    <!-- 通用查询映射结果 -->
+    <resultMap id="BaseResultMap" type="com.management.platform.entity.ProviderInfo">
+        <id column="id" property="id" />
+        <result column="provider_code" property="providerCode" />
+        <result column="provider_name" property="providerName" />
+        <result column="contact_name" property="contactName" />
+        <result column="contact_phone" property="contactPhone" />
+        <result column="email" property="email" />
+        <result column="address" property="address" />
+        <result column="company_id" property="companyId" />
+        <result column="remark" property="remark" />
+    </resultMap>
+
+    <!-- 通用查询结果列 -->
+    <sql id="Base_Column_List">
+        id, provider_code, provider_name, contact_name, contact_phone, email, address, company_id, remark
+    </sql>
+
+</mapper>

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

@@ -23,11 +23,12 @@
         <result column="report_workflow" property="reportWorkflow" />
         <result column="package_finance" property="packageFinance" />
         <result column="need_dept_audit" property="needDeptAudit" />
+        <result column="package_provider" property="packageProvider" />
     </resultMap>
 
     <!-- 通用查询结果列 -->
     <sql id="Base_Column_List">
-        id, name, path, parent_id, icon, orderitem, is_menu, use_state, package_time, package_project, package_oa, package_expense, package_customer, package_engineering, package_contract, package_etimecard, report_workflow, package_finance, need_dept_audit
+        id, name, path, parent_id, icon, orderitem, is_menu, use_state, package_time, package_project, package_oa, package_expense, package_customer, package_engineering, package_contract, package_etimecard, report_workflow, package_finance, need_dept_audit, package_provider
     </sql>
 
 </mapper>

BIN=BIN
fhKeeper/formulahousekeeper/management-platform/src/main/resources/upload/供应商导入模板.xlsx


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

@@ -106,7 +106,7 @@
         </el-dialog>
          <el-dialog title="导入供应商数据" v-if="intocustomerDialog" :visible.sync="intocustomerDialog" customClass="customWidth" width="500px">
             <p>1. 下载
-            <el-link type="primary" style="margin-left:5px;" :underline="false" href="./upload/新增供应商导入模板.xlsx" download="新增供应商导入模板.xlsx">新增供应商导入模板.xlsx</el-link>
+            <el-link type="primary" style="margin-left:5px;" :underline="false" href="./upload/供应商导入模板.xlsx" download="供应商导入模板.xlsx">供应商导入模板.xlsx</el-link>
             </p>
             <!-- <p>2. 填写excel模板,请确保模板中的项目和人员已添加到系统中。</p> -->
             <p style="display: flex;justify-content: center;padding:1em 0">