Sfoglia il codice sorgente

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

cs 2 anni fa
parent
commit
ff1d166782
31 ha cambiato i file con 1108 aggiunte e 313 eliminazioni
  1. 15 1
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/GroupTemplateController.java
  2. 4 2
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/ProjectRequirementController.java
  3. 37 44
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/WeiXinCorpController.java
  4. 14 2
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/TimeType.java
  5. 1 1
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/ExcelExportService.java
  6. 24 18
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/DepartmentServiceImpl.java
  7. 47 2
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ExcelExportServiceImpl.java
  8. 1 1
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/FinanceServiceImpl.java
  9. 10 3
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/GroupTemplateServiceImpl.java
  10. 31 13
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ProjectServiceImpl.java
  11. 68 18
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ReportServiceImpl.java
  12. 64 3
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/TaskServiceImpl.java
  13. 55 5
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/UserServiceImpl.java
  14. 17 2
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/task/TimingTask.java
  15. 1 1
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/DepartmentMapper.xml
  16. 4 4
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/ParticipationMapper.xml
  17. 2 2
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/ProjectMapper.xml
  18. 3 3
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/ReportMapper.xml
  19. 2 1
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/TimeTypeMapper.xml
  20. 39 8
      fhKeeper/formulahousekeeper/ops-platform/src/main/java/com/management/platform/entity/TimeType.java
  21. 6 1
      fhKeeper/formulahousekeeper/ops-platform/src/main/resources/mapper/TimeTypeMapper.xml
  22. 10 10
      fhKeeper/formulahousekeeper/timesheet/config/index.js
  23. 1 1
      fhKeeper/formulahousekeeper/timesheet/src/components/cascader.vue
  24. 6 3
      fhKeeper/formulahousekeeper/timesheet/src/components/select.vue
  25. 47 6
      fhKeeper/formulahousekeeper/timesheet/src/views/project/cost.vue
  26. 180 129
      fhKeeper/formulahousekeeper/timesheet/src/views/project/custom_data.vue
  27. 3 1
      fhKeeper/formulahousekeeper/timesheet/src/views/project/list.vue
  28. 60 6
      fhKeeper/formulahousekeeper/timesheet/src/views/workReport/daily.vue
  29. 141 3
      fhKeeper/formulahousekeeper/timesheet_h5/src/views/edit/index.vue
  30. 133 2
      fhKeeper/formulahousekeeper/timesheet_h5/src/views/edit/weekEdit.vue
  31. 82 17
      fhKeeper/formulahousekeeper/timesheet_h5/src/views/review/index.vue

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

@@ -4,9 +4,11 @@ package com.management.platform.controller;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.management.platform.entity.GroupTemplate;
 import com.management.platform.entity.GroupTmpstages;
+import com.management.platform.entity.OperationRecord;
 import com.management.platform.entity.User;
 import com.management.platform.service.GroupTemplateService;
 import com.management.platform.service.GroupTmpstagesService;
+import com.management.platform.service.OperationRecordService;
 import com.management.platform.service.UserService;
 import com.management.platform.util.HttpRespMsg;
 import com.management.platform.util.MessageUtils;
@@ -16,6 +18,7 @@ import org.springframework.web.bind.annotation.RestController;
 
 import javax.annotation.Resource;
 import javax.servlet.http.HttpServletRequest;
+import java.time.LocalDateTime;
 import java.util.List;
 
 /**
@@ -37,6 +40,8 @@ public class GroupTemplateController {
     private GroupTmpstagesService groupTmpstagesService;
     @Resource
     private UserService userService;
+    @Resource
+    private OperationRecordService operationRecordService;
 
     @RequestMapping("/initData")
     public HttpRespMsg initData() {
@@ -104,7 +109,16 @@ public class GroupTemplateController {
 
     @RequestMapping("/deleteTemplate")
     public HttpRespMsg deleteTemplate(Integer id) {
-        groupTemplateService.removeById(id);
+        User user = userService.getById(request.getHeader("token"));
+        if(groupTemplateService.removeById(id)){
+            OperationRecord operationRecord=new OperationRecord();
+            operationRecord.setOperatorName(user.getName());
+            operationRecord.setModuleName("项目管理");
+            operationRecord.setCompanyId(user.getCompanyId());
+            operationRecord.setOperationTime(LocalDateTime.now());
+            operationRecord.setContent("删除了模板");
+            operationRecordService.save(operationRecord);
+        }
         return new HttpRespMsg();
     }
 }

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

@@ -99,7 +99,8 @@ public class ProjectRequirementController {
             taskGroupUserIds=groupParticipatorList.stream().map(GroupParticipator::getUserId).collect(Collectors.toList());
             taskGroupUserIds.add("-1");
         }
-        List<ProjectRequirement> projectRequirements = projectRequirementMapper.customSelect(wxCorpInfo.getSaasSyncContact(),companyId, startDate, projectId, projectIds.size()==0?null:projectIds, startIndex, pageSize,reStartDate,reEndDate,taskGroupUserIds.size()==0?null:taskGroupUserIds);
+        int needCorpwxUserId = (wxCorpInfo != null && wxCorpInfo.getSaasSyncContact() == 1) ?1 : 0;
+        List<ProjectRequirement> projectRequirements = projectRequirementMapper.customSelect(needCorpwxUserId,companyId, startDate, projectId, projectIds.size()==0?null:projectIds, startIndex, pageSize,reStartDate,reEndDate,taskGroupUserIds.size()==0?null:taskGroupUserIds);
         List<Integer> ids = projectRequirements.stream().map(pr -> pr.getProjectId()).collect(Collectors.toList());
         List<Task> milepostList=taskMapper.selectMilepost(ids.size()==0?null:ids);
         projectRequirements.forEach(pr->{
@@ -137,7 +138,8 @@ public class ProjectRequirementController {
             taskGroupUserIds=groupParticipatorList.stream().map(GroupParticipator::getUserId).collect(Collectors.toList());
             taskGroupUserIds.add("-1");
         }
-        List<ProjectRequirement> projectRequirementList = projectRequirementMapper.customSelect(wxCorpInfo.getSaasSyncContact(),companyId,startDate, projectId,  projectIds.size()==0?null:projectIds, null, null,null,null,taskGroupUserIds.size()==0?null:taskGroupUserIds);
+        int needCorpwxUserId = (wxCorpInfo != null && wxCorpInfo.getSaasSyncContact() == 1) ?1 : 0;
+        List<ProjectRequirement> projectRequirementList = projectRequirementMapper.customSelect(needCorpwxUserId,companyId,startDate, projectId,  projectIds.size()==0?null:projectIds, null, null,null,null,taskGroupUserIds.size()==0?null:taskGroupUserIds);
         List<Integer> collect = projectRequirementList.stream().map(pr -> pr.getProjectId()).collect(Collectors.toList());
         List<Task> milepostList=taskMapper.selectMilepost(collect);
         projectRequirementList.forEach(pr->{

+ 37 - 44
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/WeiXinCorpController.java

@@ -9,6 +9,9 @@ import com.management.platform.entity.vo.UserVO;
 import com.management.platform.mapper.*;
 import com.management.platform.service.*;
 import com.management.platform.service.impl.ExcelExportServiceImpl;
+import com.management.platform.service.impl.ReportServiceImpl;
+import com.management.platform.service.impl.TaskServiceImpl;
+import com.management.platform.service.impl.UserServiceImpl;
 import com.management.platform.util.*;
 import com.qq.weixin.mp.aes.AesException;
 import com.qq.weixin.mp.aes.WXBizMsgCrypt;
@@ -143,7 +146,8 @@ public class WeiXinCorpController {
         public LocalDateTime expireTime = null;
     }
     public static Map<String, AgentItem> agentCorpTicketMap = new HashMap<String,AgentItem>();
-
+    @Value("${configEnv.isDev}")
+    boolean isDev;
     @Resource
     SysConfigMapper sysConfigMapper;
     @Resource
@@ -415,6 +419,9 @@ public class WeiXinCorpController {
                     result.setJobType(jobType);
                     corpwxJobResultMapper.insert(result);
                     ExcelExportServiceImpl.corpwxJobCenter.put(jobId, result);
+                    ReportServiceImpl.corpwxJobCenter.put(jobId, result);
+                    UserServiceImpl.corpwxJobCenter.put(jobId, result);
+                    TaskServiceImpl.corpwxJobCenter.put(jobId, result);
                 }
             }
         } catch (Exception e) {
@@ -846,7 +853,7 @@ public class WeiXinCorpController {
         HttpEntity<String> requestEntity = new HttpEntity<String>(reqParam.toJSONString(), headers);
         ResponseEntity<String> responseEntity = this.restTemplate.exchange(url,
                 HttpMethod.POST, requestEntity, String.class);
-        boolean enableNewVersion = false;
+        boolean enableNewVersion = true;
         if (responseEntity.getStatusCode() == HttpStatus.OK) {
             String resp = responseEntity.getBody();
             log.info(resp);
@@ -1599,6 +1606,7 @@ public class WeiXinCorpController {
                     .setCorpwxUserid(openUserid)
                     .setCorpwxRealUserid(curUserid)
                     .setColor(ColorUtil.randomColor())
+                    .setPassword(MD5Util.getPassword("000000"))
                     .setJobNumber(curUserid)
                     .setCorpwxDeptid(maxDeptId);
             allCorpWxUserList.add(user);
@@ -1656,6 +1664,7 @@ public class WeiXinCorpController {
                                 .setCorpwxRealUserid(curUserid)
                                 .setColor(ColorUtil.randomColor())
                                 .setJobNumber(curUserid)
+                                .setPassword(MD5Util.getPassword("000000"))
                                 .setCorpwxDeptid(curDept.getCorpwxDeptid());
                         allCorpWxUserList.add(user);
                     }
@@ -1692,7 +1701,7 @@ public class WeiXinCorpController {
                 }
                 if (!userItem.getName().equals(oldUser.getName())) {
                     changeUser.setId(oldUser.getId());
-                    changeUser.setName(oldUser.getName());
+                    changeUser.setName(userItem.getName());
                 }
                 if (!userItem.getCorpwxDeptid().equals(oldUser.getCorpwxDeptid())) {
                     changeUser.setId(oldUser.getId());
@@ -1713,6 +1722,8 @@ public class WeiXinCorpController {
                     //有变动
                     finalUpdateUserList.add(changeUser);
                 }
+            } else {
+                System.out.println("没找到用户:"+userItem.getName()+", "+userItem.getCorpwxUserid());
             }
         }
 
@@ -1762,10 +1773,10 @@ public class WeiXinCorpController {
 
         int companyRootDeptId = 1;
         if (syncMembs == 1) {
-            JSONArray allCorpWxUserJsonArray = getDeptUserInfo(curCorpAccessToken, companyRootDeptId);
+            JSONArray rootCorpUserJsonArray = getDeptUserInfo(curCorpAccessToken, companyRootDeptId);
             //获取远程的带姓名的详情,通过企业通讯录的token获取
             JSONArray remoteUnAUserList = null;
-            if (allCorpWxUserJsonArray.size() > 0) {
+            if (rootCorpUserJsonArray.size() > 0) {
                 remoteUnAUserList = remoteGetDeptUserDetail(wxCorpInfo, corpContactAccessToken, companyRootDeptId);
                 //做id转化
                 List<String> corpUserIds = new ArrayList<>();
@@ -1797,15 +1808,12 @@ public class WeiXinCorpController {
 
             List<User> updateUserList = new ArrayList<>();
 
-            for (int m=0;m<allCorpWxUserJsonArray.size(); m++) {
-                JSONObject userJson = allCorpWxUserJsonArray.getJSONObject(m);
+            for (int m=0;m<rootCorpUserJsonArray.size(); m++) {
+                JSONObject userJson = rootCorpUserJsonArray.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();
 
@@ -2045,39 +2053,6 @@ public class WeiXinCorpController {
         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);
-//            }
-//        }
-
         //更新人员的deptcascade
         updateUserDeptCascade(companyId);
 
@@ -2135,7 +2110,7 @@ public class WeiXinCorpController {
             return msg;
         }
         int companyId = company.getId();
-        //获取公司根部门人员,也就是没有分配部门的人员
+        //获取公司根部门人员,属于公司这个组织下面的人员
         int companyRootDeptId = 1;
         JSONArray unAssignedUserList = getDeptUserInfo(curCorpAccessToken, companyRootDeptId);
         SysRole defaultRole = sysRoleMapper.selectOne(
@@ -2506,6 +2481,24 @@ public class WeiXinCorpController {
         return msg;
     }
 
+    @RequestMapping("/updateSuiteTicket")
+    public HttpRespMsg updateSuiteTicket(String suiteTicket) {
+        HttpRespMsg msg = new HttpRespMsg();
+        String remoteHost = request.getRemoteHost();
+        System.out.println("请求来自:"+remoteHost);
+        if ("47.100.37.243".equals(remoteHost) && isDev) {
+            SysConfig config = sysConfigMapper.selectOne(new QueryWrapper<SysConfig>().eq("param_key", "wx_suite_ticket"));
+            if (config != null) {
+                config.setParamValue(suiteTicket);
+                config.setIndate(LocalDateTime.now());
+                sysConfigMapper.updateById(config);
+            }
+        }
+        return msg;
+    }
+
+
+
     //将部门id转换为部门层级
     private String convertDepartmentIdToCascade(Integer id, List<Department> allDeptList) {
         StringBuilder cascade = new StringBuilder();

+ 14 - 2
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/TimeType.java

@@ -17,7 +17,7 @@ import lombok.experimental.Accessors;
  * </p>
  *
  * @author Seyason
- * @since 2022-09-30
+ * @since 2022-10-12
  */
 @Data
 @EqualsAndHashCode(callSuper = false)
@@ -285,7 +285,7 @@ public class TimeType extends Model<TimeType> {
     private Integer mainProjectState;
 
     /**
-     * 日报的审核类型, 0-项目审核人审核,1-分组负责人审核,2-先分组负责人审核再项目负责人(PM)审核
+     * 日报的审核类型, 0-项目审核人审核,1-分组负责人审核,2-先分组负责人审核再项目负责人(PM)审核;3-员工自由选择审批人
      */
     @TableField("report_audit_type")
     private Integer reportAuditType;
@@ -365,6 +365,12 @@ public class TimeType extends Model<TimeType> {
     @TableField("max_report_time")
     private Float maxReportTime;
 
+    /**
+     * 是否同步泛微考勤打卡和出差
+     */
+    @TableField("sync_fanwei")
+    private Integer syncFanwei;
+
     /**
      * 员工自由选择审核人的方式下的审核层级:默认为2
      */
@@ -377,6 +383,12 @@ public class TimeType extends Model<TimeType> {
     @TableField("stage_has_evtime")
     private Integer stageHasEvtime;
 
+    /**
+     * 考勤为0不可填报
+     */
+    @TableField("no_work_to_report")
+    private Integer noWorkToReport;
+
 
     @Override
     protected Serializable pkVal() {

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

@@ -8,6 +8,6 @@ import java.util.List;
 public interface ExcelExportService {
     public void testRead(String jobId);
     public HttpRespMsg exportGeneralExcelByTitleAndList(WxCorpInfo wxCorpInfo, String title, List<List<String>> list, String downloadPath) throws Exception;
-
+    public HttpRespMsg exportMultiSheetGeneralExcelByTitleAndList(WxCorpInfo wxCorpInfo,String title, List<List<String>>[] multiSheetList, String downloadPath,String[] sheetsName) throws Exception;
     void testAdd(String jobId);
 }

+ 24 - 18
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/DepartmentServiceImpl.java

@@ -478,6 +478,7 @@ public class DepartmentServiceImpl extends ServiceImpl<DepartmentMapper, Departm
         try {
             User targetUser = userMapper.selectById(request.getHeader("Token"));
             Integer companyId =targetUser.getCompanyId();
+            List<User> allUserList = userMapper.selectList(new QueryWrapper<User>().eq("company_id", companyId));
             Map<String, Object> resultMap = new HashMap<>();
             //当前用户管理部门
             List<Integer> deptIds=null;
@@ -523,9 +524,9 @@ public class DepartmentServiceImpl extends ServiceImpl<DepartmentMapper, Departm
             BigDecimal totalCostMoney = new BigDecimal(0);
             List<User> userList = new ArrayList<>();
             for (Map<String, Object> map : list) {
-                if (tempMap.containsKey(map.get("user"))) {
+                if (tempMap.containsKey(map.get("id"))) {
                     //这个名字已经装进数组中了
-                    List<Map<String, Object>> tempList = tempMap.get(map.get("user"));
+                    List<Map<String, Object>> tempList = tempMap.get(map.get("id"));
                     Map<String, Object> dataMap = new HashMap<>();
                     dataMap.put("project", map.get("project"));
                     BigDecimal money = (BigDecimal) map.getOrDefault("money", 0);
@@ -553,14 +554,15 @@ public class DepartmentServiceImpl extends ServiceImpl<DepartmentMapper, Departm
                         dataMap.put("time", time);
                         tempList.add(dataMap);
                     }
-                    tempMap.put((String) map.get("user"), tempList);
+                    tempMap.put((String) map.get("id"), tempList);
                 }
             }
             Map<String, Object> finalMap = new HashMap<>();
             List<Map<String, Object>> finalList = new ArrayList<>();
             for (String key : tempMap.keySet()) {
                 Map<String, Object> map = new HashMap<>();
-                map.put("name", key);
+                String name = allUserList.stream().filter(ul -> ul.getId().equals(key)).findFirst().get().getName();
+                map.put("name", name);
                 map.put("project", tempMap.get(key));
                 map.put("type","userName");
                 finalList.add(map);
@@ -601,6 +603,7 @@ public class DepartmentServiceImpl extends ServiceImpl<DepartmentMapper, Departm
             User targetUser = userMapper.selectById(request.getHeader("Token"));
             Integer companyId =targetUser.getCompanyId();
             WxCorpInfo wxCorpInfo = wxCorpInfoMapper.selectOne(new QueryWrapper<WxCorpInfo>().eq("company_id", companyId));
+            List<User> userList = userMapper.selectList(new QueryWrapper<User>().eq("company_id", companyId));
             //当前用户管理部门
             List<Integer> deptIds=null;
             List<Department> departmentList = departmentMapper.selectList(new QueryWrapper<Department>().eq("manager_id", targetUser.getId()).eq("company_id", companyId));
@@ -644,9 +647,10 @@ public class DepartmentServiceImpl extends ServiceImpl<DepartmentMapper, Departm
             List<String> names = new ArrayList<>();
             BigDecimal totalCostMoney = new BigDecimal(0);
             for (Map<String, Object> map : list) {
-                if (tempMap.containsKey(map.get("user"))) {
+                if (tempMap.containsKey(map.get("id"))) {
                     //这个名字已经装进数组中了
-                    List<Map<String, Object>> tempList = tempMap.get(map.get("user"));
+                    List<Map<String, Object>> tempList;
+                    tempList = tempMap.get(map.get("id"));
                     Map<String, Object> dataMap = new HashMap<>();
                     dataMap.put("project", map.get("project"));
                     BigDecimal money = (BigDecimal) map.getOrDefault("money", 0);
@@ -656,11 +660,7 @@ public class DepartmentServiceImpl extends ServiceImpl<DepartmentMapper, Departm
                     dataMap.put("time", time);
                     tempList.add(dataMap);
                 } else {
-                    if(wxCorpInfo!=null&&wxCorpInfo.getSaasSyncContact()==1){
-                        names.add("$userName="+(String)map.get("corpwxUseid")+"$");
-                    }else {
-                        names.add((String)map.get("user"));
-                    }
+                    names.add((String)map.get("id"));
                     //这个名字尚未装进数组中
                     List<Map<String, Object>> tempList = new ArrayList<>();
                     if (map.containsKey("project")) {
@@ -673,7 +673,7 @@ public class DepartmentServiceImpl extends ServiceImpl<DepartmentMapper, Departm
                         dataMap.put("time", time);
                         tempList.add(dataMap);
                     }
-                    tempMap.put((String) map.get("user"), tempList);
+                    tempMap.put((String) map.get("id"), tempList);
                 }
             }
 //            Map<String, Object> finalMap = new HashMap<>();
@@ -697,11 +697,15 @@ public class DepartmentServiceImpl extends ServiceImpl<DepartmentMapper, Departm
             BigDecimal totalMoneyCost = BigDecimal.valueOf(0);
             double totalCostTime = 0;
             for (String key : names) {
-                Map<String, Object> map = new HashMap<>();
-                map.put("name", key);
-                map.put("project", tempMap.get(key));
                 List<String> nameList = new ArrayList<String>();
-                nameList.add(key);//姓名
+                String name;
+                if(wxCorpInfo!=null&&wxCorpInfo.getSaasSyncContact()==1){
+                    String corpwxUserId = userList.stream().filter(ul -> ul.getId().equals(key)).findFirst().get().getCorpwxUserid();
+                    name ="$userName="+corpwxUserId==null?"":corpwxUserId+"$";
+                }else {
+                     name = userList.stream().filter(ul -> ul.getId().equals(key)).findFirst().get().getName();
+                }
+                nameList.add(name);//姓名
                 nameList.add("");//空着
                 List<Map<String, Object>> tempList = tempMap.get(key);
                 //统计个人的时间和成本
@@ -741,7 +745,8 @@ public class DepartmentServiceImpl extends ServiceImpl<DepartmentMapper, Departm
             List<String> sumRow = new ArrayList<String>();
             //sumRow.add("合计");
             //sumRow.add("合计");
-            sumRow.add("entry.total");
+            sumRow.add(MessageUtils.message("entry.total"));
+            sumRow.add("");
             if(functionTimeList.size()>0){
                 sumRow.add(""+df.format(totalCostTime));
             }
@@ -758,6 +763,7 @@ public class DepartmentServiceImpl extends ServiceImpl<DepartmentMapper, Departm
                 e.printStackTrace();
             }
         } catch (NullPointerException e) {
+            e.printStackTrace();
             //httpRespMsg.setError("验证失败");
             httpRespMsg.setError(MessageUtils.message("access.verificationError"));
             return httpRespMsg;
@@ -1164,7 +1170,7 @@ public class DepartmentServiceImpl extends ServiceImpl<DepartmentMapper, Departm
             for (DepartmentMasterVO departmentMasterVO : costList) {
                 List<String> item=new ArrayList<>();
                 if(wxCorpInfo!=null&&wxCorpInfo.getSaasSyncContact()==1){
-                    item.add("$userName="+(departmentMasterVO.getCorpwxDeptid()==null?"":departmentMasterVO.getCorpwxDeptid())+"$");
+                    item.add("$departmentName="+(departmentMasterVO.getCorpwxDeptid()==null?"":departmentMasterVO.getCorpwxDeptid())+"$");
                 }else {
                     item.add(departmentMasterVO.getDepartmentName());
                 }

+ 47 - 2
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ExcelExportServiceImpl.java

@@ -7,11 +7,18 @@ import com.management.platform.service.ExcelExportService;
 import com.management.platform.service.WxCorpInfoService;
 import com.management.platform.util.ExcelUtil;
 import com.management.platform.util.HttpRespMsg;
+import org.apache.poi.hssf.usermodel.*;
+import org.apache.poi.ss.usermodel.BorderStyle;
+import org.apache.poi.ss.usermodel.CellStyle;
+import org.apache.poi.ss.usermodel.FillPatternType;
+import org.apache.poi.ss.usermodel.HorizontalAlignment;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Isolation;
 import org.springframework.transaction.annotation.Transactional;
 
 import javax.annotation.Resource;
+import java.io.File;
+import java.io.FileOutputStream;
 import java.util.HashMap;
 import java.util.List;
 
@@ -52,8 +59,6 @@ public class ExcelExportServiceImpl implements ExcelExportService {
     }
 
     public HttpRespMsg exportGeneralExcelByTitleAndList(WxCorpInfo wxCorpInfo, String title, List<List<String>> list, String downloadPath) throws Exception {
-        String result = "系统提示:Excel文件导出成功!";
-        String fileName = title + ".xls";
         HttpRespMsg httpRespMsg = new HttpRespMsg();
         String resp = ExcelUtil.exportGeneralExcelByTitleAndList(title, list, downloadPath);
         String fileUrlSuffix = title + ".xls";
@@ -92,6 +97,46 @@ public class ExcelExportServiceImpl implements ExcelExportService {
         return httpRespMsg;
     }
 
+
+    public  HttpRespMsg exportMultiSheetGeneralExcelByTitleAndList(WxCorpInfo wxCorpInfo,String title, List<List<String>>[] multiSheetList, String downloadPath,String[] sheetsName) throws Exception {
+        HttpRespMsg httpRespMsg = new HttpRespMsg();
+        String resp = ExcelUtil.exportMultiSheetGeneralExcelByTitleAndList(title,multiSheetList, downloadPath,sheetsName);
+        String fileUrlSuffix = title + ".xls";
+        if(wxCorpInfo != null && wxCorpInfo.getSaasSyncContact() == 1){
+            String mediaId = wxCorpInfoService.getTranslationMediaId(fileUrlSuffix);
+            String jobId = wxCorpInfoService.syncTranslation(wxCorpInfo.getCorpid(),mediaId,fileUrlSuffix, null);
+            int i = 0;
+            String syncTranslationResult = null;
+            /**
+             * 异步上传转译文件的任务完成时会触发回调,在WeiXinCorpController中的commonDevCallbackPost实现了对回调的处理,存储到corpwxJobResult表中
+             * 此处轮询查询本地数据库,检测到有任务的回调数据时继续执行查询操作
+             */
+            while (i < 10) {
+                Thread.sleep(300);
+                CorpwxJobResult corpwxJobResult = corpwxJobCenter.get(jobId);
+                if (corpwxJobResult != null) {
+                    if (corpwxJobResult.getErrCode() == 0) {
+                        syncTranslationResult = wxCorpInfoService.getSyncTranslationResult(jobId);
+                        corpwxJobCenter.remove(jobId);
+                    } else {
+                        httpRespMsg.setError(corpwxJobResult.getErrMsg());
+                        return httpRespMsg;
+                    }
+                    break;
+                }
+                i++;
+            }
+            if (syncTranslationResult != null) {
+                httpRespMsg.data = syncTranslationResult;
+            } else {
+                httpRespMsg.setError("处理超时...");
+            }
+        }else {
+            httpRespMsg.data = resp;
+        }
+        return httpRespMsg;
+    }
+
     @Override
     public void testAdd(String jobId) {
         CorpwxJobResult corpwxJobResult = new CorpwxJobResult();

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

@@ -893,7 +893,7 @@ public class FinanceServiceImpl extends ServiceImpl<FinanceMapper, Finance> impl
                             BigDecimal field2 = userFinance.getCustomField2() == null? new BigDecimal(0):userFinance.getCustomField2().multiply(new BigDecimal(workingTime)).divide(userTime.get(creatorId).workingTime, 4, BigDecimal.ROUND_HALF_UP);
                             BigDecimal field3 = userFinance.getCustomField3() == null? new BigDecimal(0):userFinance.getCustomField3().multiply(new BigDecimal(workingTime)).divide(userTime.get(creatorId).workingTime, 4, BigDecimal.ROUND_HALF_UP);
                             if(wxCorpInfo!=null&&wxCorpInfo.getSaasSyncContact()==1){
-                                membRowData.add(us.getCorpwxUserid()==null?"":us.getCorpwxUserid());
+                                membRowData.add("$userName="+(us.getCorpwxUserid()==null?"":us.getCorpwxUserid())+"$");
                             }else {
                                 membRowData.add(us.getName());
                             }

+ 10 - 3
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/GroupTemplateServiceImpl.java

@@ -13,6 +13,7 @@ import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
 import javax.annotation.Resource;
+import java.time.LocalDateTime;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Optional;
@@ -42,6 +43,8 @@ public class GroupTemplateServiceImpl extends ServiceImpl<GroupTemplateMapper, G
     @Resource
     GtemplateTaskService gtemplateTaskService;
     @Resource
+    OperationRecordMapper operationRecordMapper;
+    @Resource
     TaskMapper taskMapper;
 
     @Override
@@ -66,7 +69,13 @@ public class GroupTemplateServiceImpl extends ServiceImpl<GroupTemplateMapper, G
                 template.setName(name);
                 template.setCreWithPro(automatically);
                 groupTemplateMapper.insert(template);
-
+                OperationRecord operationRecord=new OperationRecord();
+                operationRecord.setContent("新增了模板");
+                operationRecord.setOperationTime(LocalDateTime.now());
+                operationRecord.setCompanyId(user.getCompanyId());
+                operationRecord.setModuleName("项目管理");
+                operationRecord.setOperatorName(user.getName());
+                operationRecordMapper.insert(operationRecord);
                 //保存相关的任务列表名称
                 List<GroupTmpstages> tmpstagesList = new ArrayList<GroupTmpstages>();
                 for (Stages s : stagesList) {
@@ -101,9 +110,7 @@ public class GroupTemplateServiceImpl extends ServiceImpl<GroupTemplateMapper, G
                             }
                         });
                     }
-
                     gtemplateTaskService.saveBatch(gtemplateTaskList);
-
                 }
             }
         }

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

@@ -830,7 +830,7 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
 
             //日报审核人表
             List<String> auditorIds = new ArrayList<>();
-            if (StringUtils.isEmpty(auditUserIds) || "[]".equals(auditUserIds)) {
+            if (StringUtils.isEmpty(auditUserIds) || "[]".equals(auditUserIds) || "undefined".equals(auditUserIds)) {
                 if (inchargerId != null) {
                     auditorIds.add(inchargerId);
                 }
@@ -1812,9 +1812,9 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
             data.add(task.get("project_name") == null?"":task.get("project_name").toString());
             data.add(task.get("name") != null?task.get("name").toString():"");
             if(wxCorpInfo!=null&&wxCorpInfo.getSaasSyncContact()==1){
-                if(task.get("executor_id")!=null){
-                    User us = userList.stream().filter(ul -> ul.getId().equals(task.get("executor_id"))).findFirst().get();
-                    data.add(us.getCorpwxUserid() == null?"":us.getCorpwxUserid());
+                Optional<User> first = userList.stream().filter(ul -> ul.getId().equals(task.get("executor_id"))).findFirst();
+                if(first.isPresent()){
+                    data.add("$userName="+(first.get().getCorpwxUserid() == null?"":first.get().getCorpwxUserid())+"$");
                 }else {
                     data.add("");
                 }
@@ -2705,6 +2705,7 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
         try {
             String token = request.getHeader("TOKEN");
             User user = userMapper.selectById(token);
+            WxCorpInfo wxCorpInfo = wxCorpInfoMapper.selectOne(new QueryWrapper<WxCorpInfo>().eq("company_id", user.getCompanyId()));
             TimeType timeType = timeTypeMapper.selectById(user.getCompanyId());
             List<SysRichFunction> functionAllList = sysFunctionMapper.getRoleFunctions(user.getRoleId(), "全公司加班情况");
             List<SysRichFunction> functionDeptList = sysFunctionMapper.getRoleFunctions(user.getRoleId(), "负责部门加班情况");
@@ -2768,9 +2769,15 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
                 rowData.add((String)map.get("projectCode"));
                 rowData.add((String)map.get("projectName"));
                 rowData.add((String)map.get("degreeName"));
-                rowData.add((String)map.get("username"));
-                rowData.add(String.valueOf(StringUtils.isEmpty(map.get("jobNumber"))?"":map.get("jobNumber")));
-                rowData.add((String)map.get("departmentName"));
+                if(wxCorpInfo!=null&&wxCorpInfo.getSaasSyncContact()==1){
+                    rowData.add("$userName="+(map.get("corpwxUserId")==null?"":map.get("corpwxUserId"))+"$");
+                    rowData.add(String.valueOf(StringUtils.isEmpty(map.get("jobNumber"))?"":map.get("jobNumber")));
+                    rowData.add("$departmentName="+(map.get("corpwxDeptId")==null?"":map.get("corpwxDeptId"))+"$");
+                }else {
+                    rowData.add((String)map.get("username"));
+                    rowData.add(String.valueOf(StringUtils.isEmpty(map.get("jobNumber"))?"":map.get("jobNumber")));
+                    rowData.add((String)map.get("departmentName"));
+                }
                 rowData.add((String)map.get("createDate"));
                 rowData.add(((Double)map.get("workingTime")).toString());
                 rowData.add(((Double)map.get("overtimeHours")).toString());
@@ -2905,7 +2912,11 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
             for (Map<String, Object> map : byMembList) {
                 List<String> rowData = new ArrayList<String>();
                 rowData.add(""+seq);
-                rowData.add((String)map.get("username"));
+                if(wxCorpInfo!=null&&wxCorpInfo.getSaasSyncContact()==1){
+                    rowData.add("$userName="+(map.get("corpwxUserId")==null?"":map.get("corpwxUserId"))+"$");
+                }else {
+                    rowData.add((String)map.get("username"));
+                }
                 rowData.add(((Double)map.get("workingTime")).toString());
                 rowData.add(((Double)map.get("overtimeHours")).toString());
                 if (hasViewSalary) {
@@ -2936,9 +2947,11 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
             sheetNames[0] = MessageUtils.message("Statistics.OvertimeDet");
             sheetNames[1] = MessageUtils.message("Statistics.ByPro");
             sheetNames[2] = MessageUtils.message("Statistics.ByPeople");
-            String resp = ExcelUtil.exportMultiSheetGeneralExcelByTitleAndList(fileName , totalList, path, sheetNames);
-
-            httpRespMsg.data = resp;
+            try {
+                return excelExportService.exportMultiSheetGeneralExcelByTitleAndList(wxCorpInfo,fileName , totalList, path, sheetNames);
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
         } catch (NullPointerException e) {
             //httpRespMsg.setError("验证失败"+e.getMessage());
             httpRespMsg.setError(MessageUtils.message("access.verificationErrorByParam",e.getMessage()));
@@ -4356,7 +4369,12 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
             LocalDate end = projectVO.getPlanEndDate();
             rowData.add(end==null?"":sdf.format(end));
             if(wxCorpInfo!=null&&wxCorpInfo.getSaasSyncContact()==1){
-                rowData.add("$userName="+projectVO.getCreatorId()+"$");
+                Optional<User> first = userList.stream().filter(ul -> ul.getId().equals(projectVO.getCreatorId())).findFirst();
+                if(first.isPresent()){
+                    rowData.add("$userName="+(first.get().getCorpwxUserid()==null?"":first.get().getCorpwxUserid())+"$");
+                }else {
+                    rowData.add("");
+                }
             }else {
                 rowData.add(projectVO.getCreatorName());
             }
@@ -4503,7 +4521,7 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
             item.add((String) map.get("groupName")==null?"":(String)map.get("groupName"));
             if(wxCorpInfo!=null&&wxCorpInfo.getSaasSyncContact()==1){
                 item.add((String) map.get("corpwxUserId")==null?"":("$userName="+(String)map.get("corpwxUserId")+"$"));
-                if(!map.get("participatorsCorp").equals("")){
+                if(map.get("participatorsCorp")!=null&&!map.get("participatorsCorp").equals("")){
                     String participatorsCorp = (String) map.get("participatorsCorp");
                     List<String> asList = Arrays.asList(participatorsCorp.split(","));
                     List<String> thisList=new ArrayList<>();

+ 68 - 18
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ReportServiceImpl.java

@@ -70,6 +70,8 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
 //    @Resource
 //    AsyncTaskExecutor asyncTaskExecutor;//注入线程池对象
     private final static Executor executor = Executors.newFixedThreadPool(3);//启用多线程
+    //用于控制线程锁
+    public static HashMap<String, CorpwxJobResult> corpwxJobCenter = new HashMap();
     @Value("${wx.template_report_pass}")
     public String TEMPLATE_REPORT_PASS;
     @Value("${wx.template_report_reject}")
@@ -183,6 +185,8 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
     private DepartmentOtherManagerMapper departmentOtherManagerMapper;
     @Resource
     private ExcelExportService excelExportService;
+    @Resource
+    private CorpwxJobResultMapper corpwxJobResultMapper;
     @Autowired
     RestTemplate restTemplate;
 
@@ -2983,7 +2987,7 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
             String name = (String)data.get("name");
             String departmentName = (String) data.get("departmentName");
             String corpwxUserId = (String) data.get("corpwxUserId");
-            String corpwxDeptId = (String) data.get("corpwxDeptId");
+            Integer corpwxDeptId = (Integer) data.get("corpwxDeptId");
             Map<String, Object> map = new HashMap<>();
             String date = new SimpleDateFormat("yyyy-MM-dd").format((Date)data.get("createDate"));
             String corpwxUserid = (String) data.get("corpwxUserId");
@@ -3503,6 +3507,7 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
             TimeType timeType = timeTypeMapper.selectOne(new QueryWrapper<TimeType>().eq("company_id", user.getCompanyId()));
             Company company = companyMapper.selectById(user.getCompanyId());
             Integer companyId = company.getId();
+            WxCorpInfo wxCorpInfo = wxCorpInfoMapper.selectOne(new QueryWrapper<WxCorpInfo>().eq("company_id", companyId));
             SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
             //准备导出
             HSSFWorkbook workbook = new HSSFWorkbook();
@@ -3749,8 +3754,13 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
                 HSSFRow row = sheet.createRow(rowNum);
                 row.createCell(0).setCellValue(rowNum);
                 row.createCell(1).setCellValue((String) map.get("jobNumber"));
-                row.createCell(2).setCellValue((String) map.get("name"));
-                row.createCell(3).setCellValue((String) map.get("departmentName"));
+                if(wxCorpInfo!=null&&wxCorpInfo.getSaasSyncContact()==1){
+                    row.createCell(2).setCellValue("$userName="+(map.get("corpwxUserId")==null?"":map.get("corpwxUserId"))+"$");
+                    row.createCell(3).setCellValue("$departmentName="+(map.get("corpwxDeptId")==null?"":map.get("corpwxDeptId"))+"$");
+                }else {
+                    row.createCell(2).setCellValue((String) map.get("name"));
+                    row.createCell(3).setCellValue((String) map.get("departmentName"));
+                }
                 row.createCell(4).setCellValue((String) map.get("projectCode"));
                 row.createCell(5).setCellValue((String) map.get("project"));
                 row.createCell(6).setCellValue((String) map.get("categoryName"));
@@ -3884,8 +3894,44 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
             workbook.write(fos);
             fos.flush();
             fos.close();
-            //返回生成的文件地址/upload文件夹下
-            httpRespMsg.data = "/upload/" + fileUrlSuffix;
+            if(wxCorpInfo!=null&&wxCorpInfo.getSaasSyncContact()==1){
+                String mediaId = wxCorpInfoService.getTranslationMediaId(fileUrlSuffix);
+                String jobId = wxCorpInfoService.syncTranslation(wxCorpInfo.getCorpid(),mediaId,fileUrlSuffix, null);
+            /*if(jobId!=null&&!jobId.equals("")){
+                File file=new File(path + fileUrlSuffix);
+                if(file.exists()){
+                    file.delete();
+                }
+            }*/
+                int i = 0;
+                String syncTranslationResult = null;
+                /**
+                 * 异步上传转译文件的任务完成时会触发回调,在WeiXinCorpController中的commonDevCallbackPost实现了对回调的处理,存储到corpwxJobResult表中
+                 * 此处轮询查询本地数据库,检测到有任务的回调数据时继续执行查询操作
+                 */
+                while (i < 10) {
+                    Thread.sleep(300);
+                    CorpwxJobResult corpwxJobResult = corpwxJobCenter.get(jobId);
+                    if (corpwxJobResult != null) {
+                        if (corpwxJobResult.getErrCode() == 0) {
+                            syncTranslationResult = wxCorpInfoService.getSyncTranslationResult(jobId);
+                            corpwxJobCenter.remove(jobId);
+                        } else {
+                            httpRespMsg.setError(corpwxJobResult.getErrMsg());
+                            return httpRespMsg;
+                        }
+                        break;
+                    }
+                    i++;
+                }
+                if (syncTranslationResult != null) {
+                    httpRespMsg.data = syncTranslationResult;
+                } else {
+                    httpRespMsg.setError("处理超时...");
+                }
+            }else {
+                httpRespMsg.data = "/upload/" + fileUrlSuffix;
+            }
         } catch (NullPointerException e) {
             //httpRespMsg.setError("验证失败或缺少数据");
             httpRespMsg.setError(MessageUtils.message("access.verErrorOrDataLack"));
@@ -3895,6 +3941,9 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
             //httpRespMsg.setError("文件生成错误");
             httpRespMsg.setError(MessageUtils.message("file.generateError"));
             return httpRespMsg;
+        } catch (Exception e){
+            e.printStackTrace();
+            return httpRespMsg;
         }
         return httpRespMsg;
     }
@@ -4633,7 +4682,7 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
         LocalDate endDate = LocalDate.parse(dateStr,df);
         endDate=endDate.plusMonths(1);
         List<Map<String,Object>> resultList=reportMapper.getUploadThirdReportData(companyId,startDate,endDate);
-        String url="http://10.20.35.48:8009/dataservice/apiInfo/queryData/test/sap/sysLaborhour";
+        String url="http://116.236.135.252:18009/dataservice/apiInfo/queryData/test/sap/sysLaborhour";
         //认证的账号和密码
         HttpHeaders headers=new HttpHeaders();
         JSONObject param = new JSONObject();
@@ -4650,19 +4699,22 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
             object.put("ZDEP",rl.get("departmentName"));
             array.add(object);
         });
-        param.put("IT_TAB",array);
-        HttpEntity<String> requestEntity = new HttpEntity<String>(param.toJSONString(), headers);
         String username = "WPG_GS";
         String password = "Sys_GS@12345";
         String authorization =username + ":" + password;
+        JSONObject header=new JSONObject();
+        String s = "Basic "+Base64.getEncoder().encodeToString(authorization.getBytes());
+        header.put("Authorization",s);
+        param.put("IT_TAB",array);
+        JSONObject item=new JSONObject();
+        item.put("headers",header);
+        item.put("body",param);
         //在请求头信息中携带Basic认证信息(这里才是实际Basic认证传递用户名密码的方式)
-        headers.set("authorization", "Basic " + Base64.getEncoder().encodeToString(authorization.getBytes()));
-        MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter();
-        mappingJackson2HttpMessageConverter.setSupportedMediaTypes(Arrays.asList(MediaType.APPLICATION_JSON, MediaType.APPLICATION_OCTET_STREAM));
-        restTemplate.getMessageConverters().add(mappingJackson2HttpMessageConverter);
-        //设置编码格式
-        MediaType type = MediaType.parseMediaType("application/json; charset=UTF-8");
-        headers.setContentType(type);
+        headers.set("app_id","3bf356d5-bdba-48d4-b1f5-e91468beefa3");
+        headers.set("app_key","f2960f3bf3c5ca58ee0c6970c1242e87-1655272886142-371814");
+        headers.set("Authorization",s);
+        headers.setContentType(MediaType.APPLICATION_JSON);
+        HttpEntity<String> requestEntity = new HttpEntity<String>(item.toJSONString(), headers);
         //过滤掉账号认证失败的时候抛出的401异常
         restTemplate.setErrorHandler(new DefaultResponseErrorHandler(){
             @Override
@@ -4676,10 +4728,8 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
         ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.POST,requestEntity,String.class);
         if (response.getStatusCode() == HttpStatus.OK) {
             String resp = response.getBody();
-            System.out.println(resp);
-
             JSONObject obj = JSONObject.parseObject(resp);
-            if (obj.getString("code").equals("S")) {
+            if (obj.getString("msg").equals("SUCCESS")) {
                 httpRespMsg.data=obj;
                 return httpRespMsg;
             } else {

+ 64 - 3
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/TaskServiceImpl.java

@@ -10,6 +10,7 @@ import com.management.platform.mapper.*;
 import com.management.platform.service.CompanyDingdingService;
 import com.management.platform.service.TaskExecutorService;
 import com.management.platform.service.TaskService;
+import com.management.platform.service.WxCorpInfoService;
 import com.management.platform.util.HttpRespMsg;
 import com.management.platform.util.MessageUtils;
 import org.apache.poi.hssf.usermodel.*;
@@ -43,6 +44,10 @@ import java.util.stream.Collectors;
 @Service
 @Transactional
 public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task> implements TaskService {
+
+    //用于控制线程锁
+    public static HashMap<String, CorpwxJobResult> corpwxJobCenter = new HashMap();
+
     @Value(value = "${upload.path}")
     private String path;
     @Resource
@@ -67,6 +72,10 @@ public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task> implements Ta
     private ParticipationMapper participationMapper;
     @Resource
     private ReportMapper reportMapper;
+    @Resource
+    private HttpServletRequest request;
+    @Resource
+    private WxCorpInfoService wxCorpInfoService;
 
     @Override
     public HttpRespMsg getExecutorPanel(Integer projectId) {
@@ -207,6 +216,9 @@ public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task> implements Ta
         HttpRespMsg httpRespMsg = new HttpRespMsg();
         List<TimeTask> list= taskMapper.getTaskWithWorktime(projectId, taskType);
         Project project = projectMapper.selectById(projectId);
+        Integer companyId = userMapper.selectById(request.getHeader("token")).getCompanyId();
+        WxCorpInfo wxCorpInfo = wxCorpInfoService.getOne(new QueryWrapper<WxCorpInfo>().eq("company_id", companyId));
+        List<User> userList = userMapper.selectList(new QueryWrapper<User>().eq("company_id", companyId));
         try {
             DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
             //准备导出
@@ -282,7 +294,16 @@ public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task> implements Ta
                 HSSFRow row = sheet.createRow(rowNum);
                 row.createCell(0).setCellValue(task.getName());
                 row.createCell(1).setCellValue(project.getProjectName());
-                row.createCell(2).setCellValue(task.getExecutorName());
+                if(wxCorpInfo!=null&&wxCorpInfo.getSaasSyncContact()==1){
+                    Optional<User> first = userList.stream().filter(ul -> ul.getId().equals(task.getExecutorId())).findFirst();
+                    if(first.isPresent()){
+                        row.createCell(2).setCellValue("$userName="+(first.get().getCorpwxUserid()==null?"":first.get().getCorpwxUserid())+"$");
+                    }else {
+                        row.createCell(2).setCellValue("");
+                    }
+                }else {
+                    row.createCell(2).setCellValue(task.getExecutorName());
+                }
                 row.createCell(3).setCellValue(dateTimeFormatter.format(task.getCreateDate()));
                 row.createCell(4).setCellValue(task.getEndDate() != null?dateTimeFormatter.format(task.getEndDate()):"");
                 row.createCell(5).setCellValue(task.getFinishDate() !=null?dateTimeFormatter.format(task.getFinishDate()):"");
@@ -303,8 +324,44 @@ public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task> implements Ta
             workbook.write(fos);
             fos.flush();
             fos.close();
-            //返回生成的文件地址/upload文件夹下
-            httpRespMsg.data = "/upload/" + fileUrlSuffix;
+            if(wxCorpInfo!=null&&wxCorpInfo.getSaasSyncContact()==1){
+                String mediaId = wxCorpInfoService.getTranslationMediaId(fileUrlSuffix);
+                String jobId = wxCorpInfoService.syncTranslation(wxCorpInfo.getCorpid(),mediaId,fileUrlSuffix, null);
+            /*if(jobId!=null&&!jobId.equals("")){
+                File file=new File(path + fileUrlSuffix);
+                if(file.exists()){
+                    file.delete();
+                }
+            }*/
+                int i = 0;
+                String syncTranslationResult = null;
+                /**
+                 * 异步上传转译文件的任务完成时会触发回调,在WeiXinCorpController中的commonDevCallbackPost实现了对回调的处理,存储到corpwxJobResult表中
+                 * 此处轮询查询本地数据库,检测到有任务的回调数据时继续执行查询操作
+                 */
+                while (i < 10) {
+                    Thread.sleep(300);
+                    CorpwxJobResult corpwxJobResult = corpwxJobCenter.get(jobId);
+                    if (corpwxJobResult != null) {
+                        if (corpwxJobResult.getErrCode() == 0) {
+                            syncTranslationResult = wxCorpInfoService.getSyncTranslationResult(jobId);
+                            corpwxJobCenter.remove(jobId);
+                        } else {
+                            httpRespMsg.setError(corpwxJobResult.getErrMsg());
+                            return httpRespMsg;
+                        }
+                        break;
+                    }
+                    i++;
+                }
+                if (syncTranslationResult != null) {
+                    httpRespMsg.data = syncTranslationResult;
+                } else {
+                    httpRespMsg.setError("处理超时...");
+                }
+            }else {
+                httpRespMsg.data = "/upload/" + fileUrlSuffix;
+            }
         } catch (NullPointerException e) {
             e.printStackTrace();
             //httpRespMsg.setError("验证失败或缺少数据");
@@ -315,6 +372,10 @@ public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task> implements Ta
             //httpRespMsg.setError("文件生成错误");
             httpRespMsg.setError(MessageUtils.message("file.generateError"));
             return httpRespMsg;
+        }catch (Exception e){
+            e.printStackTrace();
+            httpRespMsg.setError(MessageUtils.message("access.verErrorOrDataLack"));
+            return httpRespMsg;
         }
         return httpRespMsg;
     }

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

@@ -69,6 +69,9 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
     private String providerSecret;
     public static final String GET_TOKEN_URL = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code";
     public static final String GET_USERINFO_URL = "https://api.weixin.qq.com/sns/userinfo?access_token=accessToken&openid=openId&lang=zh_CN";
+
+    //用于控制线程锁
+    public static HashMap<String, CorpwxJobResult> corpwxJobCenter = new HashMap();
     @Resource
     private RedisUtil redisUtil;
 
@@ -1630,10 +1633,11 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
                  */
                 while (i < 10) {
                     Thread.sleep(300);
-                    CorpwxJobResult corpwxJobResult = corpwxJobResultMapper.selectById(jobId);
+                    CorpwxJobResult corpwxJobResult = corpwxJobCenter.get(jobId);
                     if (corpwxJobResult != null) {
                         if (corpwxJobResult.getErrCode() == 0) {
                             syncTranslationResult = wxCorpInfoService.getSyncTranslationResult(jobId);
+                            corpwxJobCenter.remove(jobId);
                         } else {
                             httpRespMsg.setError(corpwxJobResult.getErrMsg());
                             return httpRespMsg;
@@ -1764,6 +1768,7 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
             User user = userMapper.selectById(userId);
             List<String> strings = ListUtil.convertLongIdsArrayToList(ids);
             List<Department> deptList = departmentMapper.selectList(new QueryWrapper<Department>().eq("company_id", user.getCompanyId()));
+            WxCorpInfo wxCorpInfo = wxCorpInfoMapper.selectOne(new QueryWrapper<WxCorpInfo>().eq("company_id", user.getCompanyId()));
             List<User> userList = userMapper.selectList(new QueryWrapper<User>().in("id", strings));
             userList.forEach(u->{
                 Optional<Department> first = deptList.stream().filter(d -> d.getDepartmentId().equals(u.getDepartmentId())).findFirst();
@@ -1806,8 +1811,13 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
             for (User item : userList) {
                 HSSFRow row = sheet.createRow(rowNum);
                 row.createCell(0).setCellValue(rowNum);
-                row.createCell(1).setCellValue(item.getName());
-                row.createCell(2).setCellValue(item.getDepartmentName());
+                if(wxCorpInfo!=null&&wxCorpInfo.getSaasSyncContact()==1){
+                    row.createCell(1).setCellValue("$userName="+(item.getCorpwxUserid()==null?"":item.getCorpwxUserid())+"$");
+                    row.createCell(2).setCellValue("$departmentName="+(item.getCorpwxDeptid()==null?"":item.getCorpwxDeptid())+"$");
+                }else {
+                    row.createCell(1).setCellValue(item.getName());
+                    row.createCell(2).setCellValue(item.getDepartmentName());
+                }
                 rowNum++;
             }
             //生成Excel文件
@@ -1817,8 +1827,44 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
             workbook.write(fos);
             fos.flush();
             fos.close();
-            //返回生成的文件地址/upload文件夹下
-            httpRespMsg.data = "/upload/" + fileUrlSuffix;
+            if(wxCorpInfo!=null&&wxCorpInfo.getSaasSyncContact()==1){
+                String mediaId = wxCorpInfoService.getTranslationMediaId(fileUrlSuffix);
+                String jobId = wxCorpInfoService.syncTranslation(wxCorpInfo.getCorpid(),mediaId,fileUrlSuffix, null);
+            /*if(jobId!=null&&!jobId.equals("")){
+                File file=new File(path + fileUrlSuffix);
+                if(file.exists()){
+                    file.delete();
+                }
+            }*/
+                int i = 0;
+                String syncTranslationResult = null;
+                /**
+                 * 异步上传转译文件的任务完成时会触发回调,在WeiXinCorpController中的commonDevCallbackPost实现了对回调的处理,存储到corpwxJobResult表中
+                 * 此处轮询查询本地数据库,检测到有任务的回调数据时继续执行查询操作
+                 */
+                while (i < 10) {
+                    Thread.sleep(300);
+                    CorpwxJobResult corpwxJobResult = corpwxJobCenter.get(jobId);
+                    if (corpwxJobResult != null) {
+                        if (corpwxJobResult.getErrCode() == 0) {
+                            syncTranslationResult = wxCorpInfoService.getSyncTranslationResult(jobId);
+                            corpwxJobCenter.remove(jobId);
+                        } else {
+                            httpRespMsg.setError(corpwxJobResult.getErrMsg());
+                            return httpRespMsg;
+                        }
+                        break;
+                    }
+                    i++;
+                }
+                if (syncTranslationResult != null) {
+                    httpRespMsg.data = syncTranslationResult;
+                } else {
+                    httpRespMsg.setError("处理超时...");
+                }
+            }else {
+                httpRespMsg.data = "/upload/" + fileUrlSuffix;
+            }
         } catch (NullPointerException e) {
             //httpRespMsg.setError("验证失败或缺少数据");
             httpRespMsg.setError(MessageUtils.message("access.verErrorOrDataLack"));
@@ -1827,6 +1873,10 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
             //httpRespMsg.setError("文件生成错误");
             httpRespMsg.setError(MessageUtils.message("file.generateError"));
             return httpRespMsg;
+        }catch (Exception e){
+            e.printStackTrace();
+            httpRespMsg.setError(MessageUtils.message("access.verErrorOrDataLack"));
+            return httpRespMsg;
         }
         return httpRespMsg;
     }

+ 17 - 2
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/task/TimingTask.java

@@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.injector.methods.SelectById;
+import com.management.platform.controller.WeiXinCorpController;
 import com.management.platform.entity.*;
 import com.management.platform.mapper.*;
 import com.management.platform.service.*;
@@ -65,7 +66,8 @@ public class TimingTask {
     public String appSecret;
     @Autowired
     private RedisUtil redisUtil;
-
+    @Autowired
+    RestTemplate restTemplate;
     @Resource
     private CompanyMapper companyMapper;
     @Resource
@@ -537,7 +539,20 @@ public class TimingTask {
         }
 
     }
-
+    //推送到开发环境,每10分钟一次
+    @Scheduled(fixedRate = 600 * 1000)
+    private void genRandomCode() {
+        if (isDev) {
+            return;
+        }
+        String url = "http://47.101.180.183:10010/wxcorp/updateSuiteTicket?suiteTicket="
+                +sysConfigMapper.selectOne(new QueryWrapper<SysConfig>().eq("param_key", "wx_suite_ticket")).getParamValue();
+        String forObject = this.restTemplate.getForObject(url, String.class);
+        JSONObject json = JSONObject.parseObject(forObject);
+        if (json.getString("code").equals("error")) {
+            System.out.println("推送失败:"+json.getString("msg"));
+        }
+    }
     //每分钟校验是否有需要提醒的填报
     @Scheduled(fixedRate = 60 * 1000)
     private void process() {

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

@@ -37,7 +37,7 @@
 
     <!--根据人员获取成本-->
     <select id="getCostByUser" resultType="java.util.Map">
-        SELECT a.id as id, a.name AS user,a.corpwx_userid as corpwxUserid, a.job_number as jobNumber, c.project_name AS project, SUM(b.working_time) AS time, SUM(b.cost) AS
+        SELECT a.id as id, a.name AS user,a.corpwx_userid as corpwxUserId, a.job_number as jobNumber, c.project_name AS project, SUM(b.working_time) AS time, SUM(b.cost) AS
         money
         FROM user AS a
         LEFT JOIN report AS b ON a.id = b.creator_id

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

@@ -17,16 +17,16 @@
     <!--根据项目id获取所有参与者id和name-->
     <select id="getParticipator" resultType="java.util.Map">
         SELECT a.user_id AS id, b.name
-        FROM participation AS a
-        LEFT JOIN user AS b ON a.user_id = b.id
+        FROM participation  a
+        LEFT JOIN user  b ON a.user_id = b.id
         WHERE a.project_id = #{projectId}
     </select>
 
 
     <select id="getAllParticipator" resultType="java.util.Map">
         SELECT a.user_id AS id,b.corpwx_userid as corpwxUserId, b.name,a.project_id as projectId
-        FROM participation AS a
-        LEFT JOIN user AS b ON a.user_id = b.id
+        FROM participation a
+        LEFT JOIN user b ON a.user_id = b.id
         WHERE a.project_id in
             <foreach collection="projectIdList" open="(" close=")" separator="," item="item">
                 #{item}

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

@@ -653,8 +653,8 @@
     <!-- 获取某个员工的某时间段内的加班详情 -->
     <select id="getOvertimeDetail" resultType="java.util.Map">
         SELECT date_format(report.`create_date`, '%Y-%m-%d') AS createDate,
-        report.`creator_id` AS userId, user.`name` AS username,user.job_number as jobNumber, report.`working_time` AS workingTime,
-        IFNULL(report.`overtime_hours`, 0) AS overtimeHours,project.id as projectId,
+        report.`creator_id` AS userId, user.`name` AS username,user.corpwx_userid as corpwxUserId,user.job_number as jobNumber, report.`working_time` AS workingTime,
+        IFNULL(report.`overtime_hours`, 0) AS overtimeHours,project.id as projectId,user.corpwx_deptid as corpwxDeptId,
         project.project_name as projectName,project.project_code as projectCode,
         IFNULL(report.overtime_cost, 0) AS cost,
         IFNULL(report_extra_degree.name,'') as degreeName, department.department_name as departmentName FROM report LEFT JOIN user ON user.id = report.`creator_id`

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

@@ -57,7 +57,7 @@
 
     <!--根据日期获取全部报告信息-->
     <select id="getAllReportByDate" resultType="java.util.Map">
-        SELECT a.id, c.name,c.job_number as jobNumber,c.corpwx_userid as corpwxUserId, b.project_name AS project,b.project_code as projectCode,b.category_name as categoryName, a.working_time AS duration, a.content, a.create_time   AS time,a.create_date as createDate,
+        SELECT a.id, c.name,c.job_number as jobNumber,c.corpwx_userid as corpwxUserId,c.corpwx_deptid as corpwxDeptId, b.project_name AS project,b.project_code as projectCode,b.category_name as categoryName, a.working_time AS duration, a.content, a.create_time   AS time,a.create_date as createDate,
         a.state, a.time_type as timeType, a.cost, a.report_time_type as reportTimeType,a.start_time as startTime,u.job_number as jobNumber,
         a.end_time  as endTime, d.name as subProjectName,d.code as subProjectCode,a.task_id as taskId, task.name as taskName, a.is_overtime as isOvertime,a.progress as progress,
         a.department_audit_state as departmentAuditState, a.stage, a.pic_str as picStr, multi_worktime as multiWorktime
@@ -132,7 +132,7 @@
     </select>
 
     <select id="getProjectMembReportByDate" resultType="java.util.Map">
-        SELECT a.id, c.name,c.job_number as jobNumber,c.corpwx_userid as corpwxUserId, b.project_name AS project, b.category_name as categoryName,a.working_time AS duration,
+        SELECT a.id, c.name,c.job_number as jobNumber,c.corpwx_userid as corpwxUserId,c.corpwx_deptid as corpwxDeptId, b.project_name AS project, b.category_name as categoryName,a.working_time AS duration,
         a.content, a.create_time AS time, a.create_date as createDate,
         a.state, a.time_type as timeType, a.cost, a.report_time_type as reportTimeType, a.start_time as startTime,
         a.end_time as endTime, d.name as subProjectName,a.task_id as taskId, task.name as taskName, a.is_overtime as
@@ -185,7 +185,7 @@
     </select>
 
     <select id="getDeptMembReportByDate" resultType="java.util.Map">
-        SELECT a.id, c.name,c.job_number as jobNumber,c.corpwx_userid as corpwxUserId, b.project_name AS project, a.working_time AS duration, a.content, a.create_time AS time,a.create_date as createDate,
+        SELECT a.id, c.name,c.job_number as jobNumber,c.corpwx_userid as corpwxUserId,c.corpwx_deptid as corpwxDeptId, b.project_name AS project, a.working_time AS duration, a.content, a.create_time AS time,a.create_date as createDate,
         a.state, a.time_type as timeType, a.cost, a.report_time_type as reportTimeType, a.start_time as startTime,
         a.end_time as endTime, d.name as subProjectName,a.task_id as taskId, task.name as taskName, a.is_overtime as isOvertime,a.progress as progress,
         a.department_audit_state as departmentAuditState,a.stage, a.pic_str as picStr, multi_worktime as multiWorktime

File diff suppressed because it is too large
+ 2 - 1
fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/TimeTypeMapper.xml


+ 39 - 8
fhKeeper/formulahousekeeper/ops-platform/src/main/java/com/management/platform/entity/TimeType.java

@@ -1,23 +1,23 @@
 package com.management.platform.entity;
 
-import com.baomidou.mybatisplus.annotation.TableField;
-import com.baomidou.mybatisplus.annotation.TableId;
+import java.math.BigDecimal;
 import com.baomidou.mybatisplus.extension.activerecord.Model;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableField;
+import java.io.Serializable;
+import java.util.List;
+
 import lombok.Data;
 import lombok.EqualsAndHashCode;
 import lombok.experimental.Accessors;
 
-import java.io.Serializable;
-import java.math.BigDecimal;
-import java.util.List;
-
 /**
  * <p>
  * 
  * </p>
  *
  * @author Seyason
- * @since 2022-08-24
+ * @since 2022-10-12
  */
 @Data
 @EqualsAndHashCode(callSuper = false)
@@ -285,7 +285,7 @@ public class TimeType extends Model<TimeType> {
     private Integer mainProjectState;
 
     /**
-     * 日报的审核类型, 0-项目审核人审核,1-分组负责人审核,2-先分组负责人审核再项目负责人(PM)审核
+     * 日报的审核类型, 0-项目审核人审核,1-分组负责人审核,2-先分组负责人审核再项目负责人(PM)审核;3-员工自由选择审批人
      */
     @TableField("report_audit_type")
     private Integer reportAuditType;
@@ -359,6 +359,37 @@ public class TimeType extends Model<TimeType> {
     @TableField(exist = false)
     private List<User> userList;
 
+    /**
+     * 日报填报时长上限,默认12小时
+     */
+    @TableField("max_report_time")
+    private Float maxReportTime;
+
+    /**
+     * 是否同步泛微考勤打卡和出差
+     */
+    @TableField("sync_fanwei")
+    private Integer syncFanwei;
+
+    /**
+     * 员工自由选择审核人的方式下的审核层级:默认为2
+     */
+    @TableField("audit_level")
+    private Integer auditLevel;
+
+    /**
+     * 任务列表是否有预估工时功能
+     */
+    @TableField("stage_has_evtime")
+    private Integer stageHasEvtime;
+
+    /**
+     * 考勤为0不可填报
+     */
+    @TableField("no_work_to_report")
+    private Integer noWorkToReport;
+
+
     @Override
     protected Serializable pkVal() {
         return this.companyId;

File diff suppressed because it is too large
+ 6 - 1
fhKeeper/formulahousekeeper/ops-platform/src/main/resources/mapper/TimeTypeMapper.xml


+ 10 - 10
fhKeeper/formulahousekeeper/timesheet/config/index.js

@@ -1,19 +1,19 @@
 var path = require('path')
 
 //  var ip = '127.0.0.1'
-var ip = '47.101.180.183'
+// var ip = '47.101.180.183'
 // var ip = '192.168.10.6'
 // var ip = '192.168.2.6'
 
-// var os = require('os'), ip = '', ifaces = os.networkInterfaces() // 获取本机ip
-// for (var i in ifaces) {
-//     for (var j in ifaces[i]) {
-//         var val = ifaces[i][j]
-//         if (val.family === 'IPv4' && val.address !== '127.0.0.1') {
-//             ip = val.address
-//         }
-//     }
-// }
+var os = require('os'), ip = '', ifaces = os.networkInterfaces() // 获取本机ip
+for (var i in ifaces) {
+    for (var j in ifaces[i]) {
+        var val = ifaces[i][j]
+        if (val.family === 'IPv4' && val.address !== '127.0.0.1') {
+            ip = val.address
+        }
+    }
+}
 // 1196735749
 module.exports = {
   build: {

+ 1 - 1
fhKeeper/formulahousekeeper/timesheet/src/components/cascader.vue

@@ -2,7 +2,7 @@
   <div tabindex="0" @blur="selectClihide()" style="display: inline-block;position: relative;">  
     <div :class="disabled ? 'disabledTrue' : 'disabledFalse'" @mouseenter="moveIonDiv" @mouseleave="outIonDiv">
         <div :style="`width:${selectWidth}px;height:${selectHeight}px`" :class="classDiv ? 'select selectDiv' : 'select'" @click.stop="selectCli" :ref="disabled ? '' : 'selectDiv'">
-            <div :style="'line-height: '+selectHeight+'px;font-size: '+selectFontSize+'px;'" :class="(selectName == $t('defaultText.pleaseChoose') || selectName == $t('qing-xuan-ze-bu-men')) ? 'selecttex selecttexXuan' : 'selecttex'">
+            <div :style="'line-height: '+selectHeight+'px;font-size: '+selectFontSize+'px;'" :class="(selectName == $t('defaultText.pleaseChoose') || selectName == $t('qing-xuan-ze-bu-men') || selectName == $t('other.allDepartments')) ? 'selecttex selecttexXuan' : 'selecttex'">
                 <ww-open-data type='departmentName' :openid='selectName'></ww-open-data>
                 <!-- {{selectName}} -->
             </div>

+ 6 - 3
fhKeeper/formulahousekeeper/timesheet/src/components/select.vue

@@ -274,7 +274,8 @@ export default {
                         distinction: this.distinction,
                         index: this.index, // 选中的索引
                         other: this.other,
-                        arrUserList: this.multiSelectList
+                        arrUserList: this.multiSelectList,
+                        name: this.selectName
                     }
                     this.$emit("selectCal", obj)
                 }
@@ -298,7 +299,8 @@ export default {
                         id: nameId,
                         distinction: this.distinction,
                         index: this.index, // 选中的索引
-                        other: this.other
+                        other: this.other,
+                        name: this.selectName
                     }
                     this.$emit("selectCal", obj)
                 }
@@ -379,7 +381,8 @@ export default {
                 distinction: this.distinction,
                 index: this.index, // 选中的索引
                 other: this.other,
-                arrUserList: this.multiSelectList
+                arrUserList: this.multiSelectList,
+                name: this.selectName
             }
             this.$emit("selectCal", obj)
         }

+ 47 - 6
fhKeeper/formulahousekeeper/timesheet/src/views/project/cost.vue

@@ -42,12 +42,16 @@
                 <el-option v-for="item in customList" :key="item.id" :label="item.name" :value="item.name"></el-option>
             </el-select> -->
 
-            <el-select v-model="personnelValue" filterable clearable :placeholder="$t('pleaseselectpersonnel')"  size="small" style="margin-top: 10px;width: 350px" v-if="radio == $t('ren-yuan')" @change="personnel()">
+            <el-select v-model="personnelValue" filterable clearable :placeholder="$t('pleaseselectpersonnel')"  size="small" style="margin-top: 10px;width: 350px" v-if="radio == $t('ren-yuan') && user.userNameNeedTranslate != '1'" @change="personnel()">
                 <el-option v-for="item in hasReportUserList" :key="item.id" :label="item.name" :value="item.name">
                     <span style="float: left">{{ item.name }}</span>
                     <span style="float: right; color: #8492a6; font-size: 13px;margin-left: 20px" v-if="item.jobNumber">{{ item.jobNumber }}</span>
                 </el-option>
             </el-select>
+            <span style="text-align: left">
+            <selectCat v-if="radio == $t('ren-yuan') && user.userNameNeedTranslate == '1'" :size="'small'" :widthStr="'350'" :distinction="'2'" :subject="hasReportUserList" :clearable="true" @selectCal="selectCal"></selectCat>
+            </span>
+
         </el-col>
         <el-col :span="4">
             <el-button @click="exportProjectData" v-if="theCustomListFlg"  size="small">{{ $t('reporderived') }}</el-button>
@@ -88,12 +92,15 @@
                             <span style="float: right;font-size: 13px;">{{ item.projectName }}</span>
                         </el-option>
                     </el-select>
+
                 </el-form-item>
 
                 <el-form-item :label="$t('departmentchoice')" v-if="radio == $t('other.project')">
-                    <el-cascader v-model="exportParam.deptId" :options="departmentList" :placeholder="$t('defaultText.pleaseChoose')"
+                    <el-cascader v-if="user.userNameNeedTranslate != 1" v-model="exportParam.deptId" :options="departmentList" :placeholder="$t('defaultText.pleaseChoose')"
                         :props="{ checkStrictly: true, expandTrigger: 'hover' }" clearable filterable style="width:350px;"
                     ></el-cascader>
+
+                    <vueCascader :size="'medium'" :widthStr="'350'" :clearable="true" :subject="departmentList" :radios="true" :distinction="'1'" @vueCasader="vueCasader" v-if="user.userNameNeedTranslate == 1"></vueCascader>
                 </el-form-item>
 
                 <el-form-item prop="projectCategoryId" :label="$t('projectclassification')" v-if="radio == $t('projectclassification')">
@@ -103,9 +110,11 @@
                     </el-select>
                 </el-form-item>
                 <el-form-item prop="userIds" :label="$t('screening.selectPeople')" v-if="radio == $t('ren-yuan')">
-                    <el-select v-model="exportParam.userIds" :placeholder="$t('lable.allStaff')" multiple="true"  clearable style="width:350px;" filterable="true">
+                    <el-select v-if="user.userNameNeedTranslate != '1'" v-model="exportParam.userIds" :placeholder="$t('lable.allStaff')" multiple="true"  clearable style="width:350px;" filterable="true">
                         <el-option v-for="item in hasReportUserList"  :key="item.id" :label="item.name" :value="item.id"></el-option>
                     </el-select>
+
+                    <selectCat v-if="user.userNameNeedTranslate == '1'" :size="'medium'" :widthStr="'350'" :subject="hasReportUserList" :clearable="true" :multiSelect="true" @selectCal="selectCal"></selectCat>
                 </el-form-item>
                 <el-form-item prop="projectId" :label="user.timeType.fixMonthcost==0?$t('time.dateRange'):$t('Selectmonth')">
                     <el-date-picker v-show="user.timeType.fixMonthcost==0"
@@ -161,8 +170,17 @@
 </template>
 
 <script>
+// 引入自定义组件
+    import selectCat from "@/components/select.vue"
+    //引入自定义级联组件
+    import vueCascader from "@/components/cascader.vue"
+
     import util from "../../common/js/util";
     export default {
+        components: {
+            selectCat,
+            vueCascader
+        },
         data() {
             return {
                 allListData: [],
@@ -206,7 +224,6 @@
         methods: {
             echartsCurrentChange(val){
                 this.page = val
-                // console.log('CurrentChange');
                 if(this.radio == this.$t('ren-yuan')){
                     this.gtff()
                 }else{
@@ -451,6 +468,7 @@
                         } else {
                             this.personnelAll = res.data
                             this.allListData = res.data
+                            console.log('人员返回', this.allListData);
                             this.gtff()
                         }
                     } else {
@@ -956,8 +974,8 @@
                         else {
                             // list = res.data
                             // this.allListData = res.data
-                            this.total = this.allListData.length
-                            list = this.allListData.slice(0+50*(this.page-1),49+50*(this.page-1))
+                            this.total = this.allListData.list.length
+                            list = this.allListData.list.slice(0+50*(this.page-1),49+50*(this.page-1))
                             
                             for(var i in list) {
                                 // console.log(list[i].name, list[i].costMoney, list[i].cost)
@@ -1210,6 +1228,29 @@
                 }
                 return arr;
             },
+            // 自定义事件
+            selectCal(obj) {
+                console.log(obj)
+                if(obj.distinction == 1) {
+                    let arr = []
+                    for(var i in obj.arrUserList) {
+                        arr.push(obj.arrUserList[i].id) 
+                    }
+                    this.exportParam.userIds = arr
+                } else if(obj.distinction == 2) {
+                    console.log(obj)
+                    this.personnelValue = obj.name
+                    this.personnel()
+                }
+            },
+            vueCasader(obj) {
+                if(obj.distinction == 1) {
+                    console.log(obj, '数据')
+                    let arr = []
+                    arr.push(obj.id)
+                    this.exportParam.deptId = arr
+                }
+            }
         },
         created() {
             this.myChart = null

+ 180 - 129
fhKeeper/formulahousekeeper/timesheet/src/views/project/custom_data.vue

@@ -248,137 +248,22 @@
                     var _this = this;
                     this.hasReportUserList = [];
                     if (res.code == "ok") {
-                        //工时总成本
-                        this.hasReportUserList = this.radio == '人员' ? res.data.userList : res.data.department;
-                        var xList = [] , yList = [] , list = res.data.list, array = [] , series = [];
-                        
-                        var totalHours = 0.0;
-                        if (list.length > 0) {
-                            var num = list.length==0?0:list[0].project.length;
-                            for(var i in list) {
-                                xList.push(list[i].name);
-                                var pro = list[i].project;
-                                for(var j in pro) {
-                                    if(array.indexOf(pro[j].project) == -1) {
-                                        array.push(pro[j].project)
-                                    }
-                                }
-                            }
-
-                            for(var i in array) {
-                                yList.push(array[i]);
-                                var dataList = [];
-                                for(var j in list) {
-                                    var project = list[j].project , num = 0;
-                                    if(project.length != 0) {
-                                        for(var k in project) {
-                                            if(project[k].project == array[i]) {
-                                                dataList.push({
-                                                    "value": project[k].cost,
-                                                    "cost": project[k].cost
-                                                })
-                                                totalHours += parseFloat(project[k].cost);
-                                            } else {
-                                                num++;
-                                            }
-                                            if(k == project.length-1 && num != project.length-1) {
-                                                dataList.push({
-                                                    "value": 0,
-                                                    "cost": 0
-                                                })
-                                            }
-                                        }
-                                    } else {
-                                        dataList.push({
-                                            "value": 0,
-                                            "cost": 0,
-                                        })
-                                    }
+                        if(this.user.userNameNeedTranslate == 1 && (this.radio == '人员' || this.radio == '部门')) {
+                            let arr = []
+                            for(var i in res.data.list) {
+                                let obj = {}
+                                if(this.radio == '人员') {
+                                    obj.type = 'userName'
+                                } else {
+                                    obj.type = 'departmentName'
                                 }
-                                series.push({
-                                    name: array[i],
-                                    type: 'bar',
-                                    stack:'1',
-                                    barMaxWidth: 30,
-                                    data: dataList,
-                                })
+                                obj.id = res.data.list[i].name
+                                arr.push(obj)
                             }
-                        } 
-                            
-                            
-                            var myChart = echarts.init(document.getElementById("container"));
-                            totalHours = totalHours.toFixed(1);
-                            _this.myChart = myChart;
-                            var option = {
-                                //总成本
-                                title: {
-                                    text: _this.user.timeType.customDataName + '总计' + totalHours,
-                                    left:'left',
-                                },
-                                
-                                // 工具箱
-                                legend: {
-                                    x: 80,
-                                    y: 10,
-                                    data: yList,
-                                    show: true,
-                               top:"5%",//与上方的距离 可百分比% 可像素px
-                                },
-                                grid : {
-                                    top : 80,    //距离容器上边界40像素
-                                    bottom: 35   //距离容器下边界30像素
-                                },
-                                toolbox: {
-                                    show: true,
-                                    feature:{
-                                        saveAsImage:{
-                                            show:true
-                                        },
-                                        restore:{
-                                            show:true
-                                        },
-                                        // dataView:{
-                                        //     show:true
-                                        // },
-                                        // dataZoom:{
-                                        //     show:true
-                                        // },
-                                        magicType:{
-                                            type:['line','bar']
-                                        }
-                                    }
-                                },
-                                tooltip:{
-                                    trigger:'axis',
-                                    formatter: function (params,ticket,callback) {
-                                        var totalTime = 0;
-                                        var res = "";
-                                        for(var i in params) {
-                                            if (params[i].data.value > 0) {
-                                                res += "<div style='margin-top:3px;font-size:12px;'><font color='#ddd'>项目名称:" + params[i].seriesName 
-                                                    + "</font><br/>"+_this.user.timeType.customDataName+" : " + params[i].data.cost+"</div>";
-                                                totalTime += Number(params[i].data.cost);
-                                            }
-                                        }
-                                        res = res +'<br/>'+ params[0].name+ '<br/>总计: ' + totalTime.toFixed(1);
-                                        return res;
-                                    }
-                                },
-                                xAxis: {
-                                    data: xList,
-                                    axisLabel: {
-                                        interval:0,rotate:20
-                                    }
-                                },
-                                yAxis: [{
-                                    type : 'value',
-                                    axisLabel: {
-                                        formatter:'{value}'
-                                    }
-                                }],
-                                series: series,
-                            };
-                            myChart.setOption(option,{notMerge:true});
+                            this.dealWithTranslationPlone(arr, res)
+                        } else {
+                            this.choli(res)
+                        }
                     } else {
                         this.$message({
                         message: res.msg,
@@ -394,6 +279,172 @@
                     });
                 });
             },
+            dealWithTranslationPlone(items, dataList) {
+                console.log(items, '处理的值')
+                    if (WWOpenData.initCanvas) {
+                        WWOpenData.initCanvas()
+                    }
+                    const myFunOne = async () => {
+                        const result = await new Promise((resolve, reject) => {
+                            if(WWOpenData.prefetch) {
+                                 WWOpenData.prefetch({ items }, (err, data) => {
+                                    if (err) { return reject(err) }
+                                    resolve(data)
+                                })
+                            }
+                        })
+                        for(var i in dataList.data.list) {
+                            dataList.data.list[i].name = result.items[i].data
+                        }
+                        this.choli(dataList)
+                    }
+                    myFunOne()
+            },
+            choli(data) {
+                console.log('过来的值', data)
+                var _this = this;
+                //工时总成本
+                    // this.hasReportUserList = this.radio == '人员' ? res.data.userList : res.data.department;
+                    // var xList = [] , yList = [] , list = res.data.list, array = [] , series = [];
+
+                    this.hasReportUserList = this.radio == '人员' ? data.data.userList : data.data.department;
+                    var xList = [] , yList = [] , list = data.data.list, array = [] , series = [];
+
+                    var totalHours = 0.0;
+                    if (list.length > 0) {
+                        var num = list.length==0?0:list[0].project.length;
+                        for(var i in list) {
+                            xList.push(list[i].name);
+                            var pro = list[i].project;
+                            for(var j in pro) {
+                                if(array.indexOf(pro[j].project) == -1) {
+                                    array.push(pro[j].project)
+                                }
+                            }
+                        }
+                        for(var i in array) {
+                            yList.push(array[i]);
+                            var dataList = [];
+                            for(var j in list) {
+                                var project = list[j].project , num = 0;
+                                if(project.length != 0) {
+                                    for(var k in project) {
+                                        if(project[k].project == array[i]) {
+                                            dataList.push({
+                                                "value": project[k].cost,
+                                                "cost": project[k].cost
+                                            })
+                                            totalHours += parseFloat(project[k].cost);
+                                        } else {
+                                            num++;
+                                        }
+                                        if(k == project.length-1 && num != project.length-1) {
+                                            dataList.push({
+                                                "value": 0,
+                                                "cost": 0
+                                            })
+                                        }
+                                    }
+                                } else {
+                                    dataList.push({
+                                        "value": 0,
+                                        "cost": 0,
+                                    })
+                                }
+                            }
+                            series.push({
+                                name: array[i],
+                                type: 'bar',
+                                stack:'1',
+                                barMaxWidth: 30,
+                                data: dataList,
+                            })
+                        }
+                    } 
+                        
+                        
+                    var myChart = echarts.init(document.getElementById("container"));
+                    totalHours = totalHours.toFixed(1);
+                    _this.myChart = myChart;
+                    var option = {
+                        //总成本
+                        title: {
+                            text: _this.user.timeType.customDataName + '总计' + totalHours,
+                            left:'left',
+                        },
+                        
+                        // 工具箱
+                        legend: {
+                            x: 80,
+                            y: 10,
+                            data: yList,
+                            show: true,
+                          top:"5%",//与上方的距离 可百分比% 可像素px
+                        },
+                        grid : {
+                            top : 80,    //距离容器上边界40像素
+                            bottom: 35   //距离容器下边界30像素
+                        },
+                        toolbox: {
+                            show: true,
+                            feature:{
+                                saveAsImage:{
+                                    show:true
+                                },
+                                restore:{
+                                    show:true
+                                },
+                                // dataView:{
+                                //     show:true
+                                // },
+                                // dataZoom:{
+                                //     show:true
+                                // },
+                                magicType:{
+                                    type:['line','bar']
+                                }
+                            }
+                        },
+                        tooltip:{
+                            trigger:'axis',
+                            formatter: function (params,ticket,callback) {
+                                var totalTime = 0;
+                                var res = "";
+                                for(var i in params) {
+                                    if (params[i].data.value > 0) {
+                                        res += "<div style='margin-top:3px;font-size:12px;'><font color='#ddd'>项目名称:" + params[i].seriesName 
+                                            + "</font><br/>"+_this.user.timeType.customDataName+" : " + params[i].data.cost+"</div>";
+                                        totalTime += Number(params[i].data.cost);
+                                    }
+                                }
+                                if(_this.user.userNameNeedTranslate != 1) {
+                                    res = res +'<br/>'+ params[0].name+ '<br/>总计: ' + totalTime.toFixed(1);
+                                } else {
+                                    if(_this.radio == '人员' || _this.radio == '部门') {
+                                        res = res +'<br/>'+ '' + '<br/>总计: ' + totalTime.toFixed(1);
+                                    } else {
+                                        res = res +'<br/>'+ params[0].name+ '<br/>总计: ' + totalTime.toFixed(1);
+                                    }
+                                }
+                                return res;
+                            }
+                        },
+                        xAxis: {
+                            data: xList,
+                            axisLabel: {
+                                interval:0,rotate:20
+                            }
+                        },
+                        yAxis: [{
+                            type : 'value',
+                            axisLabel: {
+                                formatter:'{value}'
+                            }
+                        }],
+                        series: series,
+                    };
+                    myChart.setOption(option,{notMerge:true});
+            },
             yanjiu() {
                 // console.log('触发')
             },

+ 3 - 1
fhKeeper/formulahousekeeper/timesheet/src/views/project/list.vue

@@ -3834,7 +3834,9 @@ a {
                         formData.append("associateDegrees", listId)
                         formData.append("associateDegreeNames", listName)
                         //日报审核人
-                        formData.append("auditUserIds", JSON.stringify(this.addForm.auditUserIds));
+                        if (this.addForm.auditUserIds) {
+                            formData.append("auditUserIds", JSON.stringify(this.addForm.auditUserIds));
+                        }
 
                         if(this.addForm.category != null) {
                             formData.append("category", this.addForm.category);

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

@@ -319,8 +319,19 @@
         <el-dialog :title="editTitle[isBatch]" :visible.sync="dialogVisible" width="60%" style="height:95%" :close-on-click-modal="false" @closed="guanbi()" custom-class="editReportDialog" ref="editReportDialog">
             <el-form ref="workForm" :model="workForm" :rules="workRules" label-width="120px">
                 <el-form-item :label="$t('screening.selectPeople')" v-if="isSubstitude">
-                    <el-input @focus="showChooseMembTree" v-model="workForm.userNames"
+                    <el-input v-if="user.userNameNeedTranslate != 1" @focus="showChooseMembTree" v-model="workForm.userNames"
                     :placeholder="$t('defaultText.pleaseSelectAsubstitute')" ></el-input>
+                    <div class="daitianrbao"  @click="showChooseMembTree" v-if="user.userNameNeedTranslate == 1">
+                        <span class="spnn" v-if="workForm.userNames">
+                            <span v-for="(item, index) in workForm.userNames" :key="index">
+                                <span><ww-open-data type='userName' :openid='item'></ww-open-data></span>
+                                <span v-if="index < workForm.userNames.length - 1">,</span>
+                            </span>
+                        </span>
+                        <span class="spnn hover" v-else>
+                            {{$t('defaultText.pleaseSelectAsubstitute')}}
+                        </span>
+                    </div>
                 </el-form-item>
                 <el-form-item :label="$t('screening.workingDate')" prop="createDate">
                     <el-date-picker v-model="workForm.createDate" :editable="false" format="yyyy-MM-dd" value-format="yyyy-MM-dd" 
@@ -467,7 +478,7 @@
 
                     </el-form-item>
                     <!-- 111111 -->
-                    <el-form-item label="审核人" v-if="user.timeType.reportAuditType == 3">
+                    <el-form-item :label="$t('other.reviewer')" v-if="user.timeType.reportAuditType == 3">
                         <el-select v-model="domain.auditorFirst" placeholder="第一审核人" :disabled="!domain.canEdit" style="width:200px;">
                             <el-option v-for="item in allUsersList" :key="item.id" :label="item.name" :value="item.id"></el-option>
                         </el-select>
@@ -955,7 +966,11 @@
                     </el-select>
                 </el-form-item>
                 <el-form-item prop="departmentId" :label="$t('other.selectdepartment')" v-if="permissions.reportsCompany">
-                    <el-cascader v-model="exportParam.departmentId" :placeholder="$t('other.allDepartments')" :options="departmentList" :props="{ checkStrictly: true, value: 'id' }" clearable style="width: 350px;"></el-cascader>
+
+                    <el-cascader v-if="user.userNameNeedTranslate != 1" v-model="exportParam.departmentId" :placeholder="$t('other.allDepartments')" :options="departmentList" :props="{ checkStrictly: true, value: 'id' }" clearable style="width: 350px;"></el-cascader>
+
+                    <vueCascader :size="'medium'" :widthStr="'350'" :clearable="true" :subject="departmentList" :radios="true" :distinction="'1'" @vueCasader="vueCasader" v-if="user.userNameNeedTranslate == 1" :selectNameChuan="$t('other.allDepartments')"></vueCascader>
+
                 </el-form-item>
                 <el-form-item prop="projectId" :label="$t('time.dateRange')">
                     <el-date-picker
@@ -1544,12 +1559,16 @@
 
     // 自定义select组件
     import selectCat from "@/components/select.vue"
+
+     // 引入自定义级联组件
+    import vueCascader from "@/components/cascader.vue"
     
     let _that = this
     export default {
         mixins: [dragMixin],
         components: {
-            selectCat
+            selectCat,
+            vueCascader
         },
         data() {
             return {
@@ -2831,6 +2850,12 @@
                 if (this.workForm.userNames.length > 0) {
                     this.workForm.userNames = this.workForm.userNames.substring(0, this.workForm.userNames.length-1);
                 }
+
+                if(this.user.userNameNeedTranslate == 1) {
+                    if(this.workForm.userNames) {
+                        this.workForm.userNames = this.workForm.userNames.split(',')
+                    }
+                }
                 
             },
 
@@ -5531,11 +5556,11 @@
                                     audItem.auditorFirst = this.workForm.domains[i].auditorFirst
                                 }
                                 if(this.user.timeType.auditLevel > 1){
-                                    if(!this.workForm.domains[i].auditorFirst){ auditRule += '第二、' }
+                                    if(!this.workForm.domains[i].auditorSec){ auditRule += '第二、' }
                                     audItem.auditorSec = this.workForm.domains[i].auditorSec
                                 }
                                 if(this.user.timeType.auditLevel > 2){
-                                    if(!this.workForm.domains[i].auditorFirst){ auditRule += '第三、' }
+                                    if(!this.workForm.domains[i].auditorThird){ auditRule += '第三、' }
                                     audItem.auditorThird = this.workForm.domains[i].auditorThird
                                 }
                                 if(this.workForm.domains[i].ccUserid){
@@ -5940,6 +5965,14 @@
                 // obj.id 是 选中人员的id, obj.idx 是 当前的索引
                 this.workForm.domains[obj.idx].projectAuditorId = obj.id
             },
+            vueCasader(obj) {
+                console.log(obj, '看看值')
+                if(obj.distinction == 1) {
+                    let arr = []
+                    arr.push(obj.item.id)
+                    this.exportParam.departmentId = arr
+                }
+            },
             //分页
             handleCurrentChange(val) {
                 this.toViewForm.pageIndex = val;
@@ -6290,4 +6323,25 @@
         font-size: 14px;
         padding-right: 8px;
     }
+    .daitianrbao {
+        width: 100%;
+        box-sizing: border-box;
+        height: 40px;
+        border-radius: 4px;
+        border: 1px solid #DCDFE6;
+        overflow: hidden;
+        text-overflow: ellipsis;
+        display: flex;
+        // align-items: center;
+    }
+    .daitianrbao .spnn {
+        display: inline-block;
+        box-sizing: border-box;
+        padding: 0 15px;
+        overflow: hidden;
+        text-overflow: ellipsis;
+    }
+    .daitianrbao .hover {
+        color: #DCDFE6 !important;
+    }
 </style>

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

@@ -75,6 +75,7 @@
                             @cancel="item.showPickerCostId = false;$forceUpdate();" />
                     </van-popup>
                     <!-- 审核人 -->
+                <template v-if="user.timeType.reportAuditType != 3">
                     <van-field  readonly  name="projectAuditorId" v-if="item.auditUserList != null && item.auditUserList.length > 0" clickable
                         :value="item.projectAuditorName" :label="user.companyId==781?'审核人':'项目审核人'" placeholder="请选择审核人" 
                     @click="clickPickAuditor(index, item)">
@@ -92,6 +93,51 @@
                             </template>
                         </van-picker>
                     </van-popup>
+                </template>
+
+                    <!-- 自选审批人 -->
+                <template v-if="user.timeType.reportAuditType == 3">
+                    <van-field readonly clickable label="第一审核人" @click="auditorClick(index,'auditorFirst')">
+                        <template #input>
+                            <span v-if="!item.auditorFirst"></span>
+                            <span v-else-if="user.userNameNeedTranslate == '1'"><ww-open-data type='userName' :openid='item.auditorFirst.name'></ww-open-data></span>
+                            <span v-else>{{item.auditorFirst.name}}</span>
+                        </template>
+                    </van-field>
+                    <van-field readonly clickable label="第二审核人" @click="auditorClick(index,'auditorSec')" v-if="user.timeType.auditLevel > 1">
+                        <template #input>
+                            <span v-if="!item.auditorSec"></span>
+                            <span v-else-if="user.userNameNeedTranslate == '1'"><ww-open-data type='userName' :openid='item.auditorSec.name'></ww-open-data></span>
+                            <span v-else>{{item.auditorSec.name}}</span>
+                        </template>
+                    </van-field>
+                    <van-field readonly clickable label="第三审核人" @click="auditorClick(index,'auditorThird')" v-if="user.timeType.auditLevel > 2">
+                        <template #input>
+                            <span v-if="!item.auditorThird"></span>
+                            <span v-else-if="user.userNameNeedTranslate == '1'"><ww-open-data type='userName' :openid='item.auditorThird.name'></ww-open-data></span>
+                            <span v-else>{{item.auditorThird.name}}</span>
+                        </template>
+                    </van-field>
+                    <van-field readonly clickable label="抄送人" @click="auditorClick(index,'ccUserid')">
+                        <template #input>
+                            <span v-if="!item.ccUserid"></span>
+                            <span v-else-if="user.userNameNeedTranslate == '1'"><ww-open-data type='userName' :openid='item.ccUserid.name'></ww-open-data></span>
+                            <span v-else>{{item.ccUserid.name}}</span>
+                        </template>
+                    </van-field>
+                    <van-popup v-model="auditorShow" position="bottom">
+                        <van-search v-model="auditor.searchText" placeholder="输入员工姓名搜索" @search="onSearch" v-if="user.userNameNeedTranslate != '1'"></van-search>
+                        <div style="minHeight:300px;">
+                            <van-radio-group v-model="auditor.item">
+                                <van-radio v-for="uitem in auditor.searchList" :key="uitem.id" :name="uitem" style="padding:10px">
+                                    <span v-if="user.userNameNeedTranslate == '1'"><ww-open-data type='userName' :openid='uitem.name'></ww-open-data></span>
+                                    <span v-else>{{uitem.name ? uitem.name : ''}}</span>
+                                </van-radio>
+                            </van-radio-group>
+                            <van-button style="width:100%;position: -webkit-sticky;position: sticky;bottom: 0;" @click="searchAuditor()">确定</van-button>
+                        </div>
+                    </van-popup>
+                </template>
 
 
                     <!-- 相关维度 -->
@@ -410,7 +456,17 @@ import timetoolVue from '../timetool/timetool.vue';
                 userName: '',
                 flgLg: true,
                 reportBasecostList: [],
-                isWeekend: false
+                isWeekend: false,
+
+                auditorShow: false,
+                auditor: {
+                    index: 0,
+                    auditorIndex: 'auditorFirst',
+                    searchText: '',
+                    item: {},
+                    list: [],
+                    searchList: []
+                }
             };
         },
 
@@ -419,6 +475,46 @@ import timetoolVue from '../timetool/timetool.vue';
         },
 
         methods: {
+            auditorClick(domainIndex,auditorIndex){
+                this.auditor.index = domainIndex
+                this.auditor.auditorIndex = auditorIndex
+                this.auditor.searchList.forEach(u=>{
+                    if(u.id == this.form.domains[domainIndex][auditorIndex].id){
+                        this.auditor.item = u
+                    }
+                })
+                this.auditorShow = true
+                
+            },
+            onSearch(val){
+                console.log(val);
+                this.auditor.searchList = [];
+                this.auditor.list.forEach(u=>{if (u.name.startsWith(val)) {
+                    this.auditor.searchList.push(u);
+                }})
+            },
+            searchAuditor(){
+                this.form.domains[this.auditor.index][this.auditor.auditorIndex] = this.auditor.item
+                this.auditorShow = false
+                console.log('searchAuditor');
+            },
+            getAllUsersList(){
+                this.$axios.post('/user/getSimpleActiveUserList',{})
+                .then(res => {
+                    if(res.code == 'ok'){
+                        this.auditor.list = res.data
+                        this.auditor.searchList = res.data
+                    }else{
+                        this.$toast.fail('获取失败:'+res.msg);
+                    }
+                }).catch(err => {this.$toast.clear();})
+            },
+            requiredRule(val){
+                console.log('requiredRule',val);
+                return false
+            },
+
+
             // 获取预算来源
             getReportBasecostList(){
                 this.$axios.post('/project-basecost-setting/getReportBasecostList',{
@@ -979,7 +1075,12 @@ import timetoolVue from '../timetool/timetool.vue';
                                     auditUserList: list[i].auditUserList,
                                     overtimeHours: list[i].overtimeHours,
                                     customText: list[i].customText,
-                                    canEdit: list[i].state >= 2 ? true : false
+                                    canEdit: list[i].state >= 2 ? true : false,
+
+                                    auditorFirst: list[i].auditorSetting && list[i].auditorSetting.auditorFirst ? list[i].auditorSetting.auditorFirst : {name:'',id:''},
+                                    auditorSec: list[i].auditorSetting && list[i].auditorSetting.auditorSec ? list[i].auditorSetting.auditorSec : {name:'',id:''},
+                                    auditorThird: list[i].auditorSetting && list[i].auditorSetting.auditorThird ? list[i].auditorSetting.auditorThird : {name:'',id:''},
+                                    ccUserid: list[i].auditorSetting && list[i].auditorSetting.ccUserid ? list[i].auditorSetting.ccUserid : {name:'',id:''},
                                 })
                                 if (list[i].state >= 2) {
                                     this.canEdit = true;
@@ -1010,7 +1111,12 @@ import timetoolVue from '../timetool/timetool.vue';
                                 professionProgress:[],
                                 multiWorktime:t.multiWorktime,
                                 worktimeList:[{}],  
-                                canEdit: true
+                                canEdit: true,
+
+                                auditorFirst: {name:'',id:''},
+                                auditorSec: {name:'',id:''},
+                                auditorThird: {name:'',id:''},
+                                ccUserid: {name:'',id:''}
                             }]
                             if(this.isWeekend && this.user.timeType.lockWorktime != 1){
                                 this.$set(this.form.domains[0],'isOvertime',true)
@@ -1425,6 +1531,37 @@ import timetoolVue from '../timetool/timetool.vue';
                             }
                     //填字段
                     for(var i in this.form.domains) {
+                        if(this.user.timeType.reportAuditType == 3){
+                            let audItem = {}
+                            let auditRule = ''
+                            if(this.form.domains[i].id){
+                                audItem.reportId = this.form.domains[i].id
+                            }
+                            if(this.user.timeType.auditLevel > 0){
+                                if(!this.form.domains[i].auditorFirst.id){ auditRule += '第一、' }
+                                audItem.auditorFirst = this.form.domains[i].auditorFirst.id
+                            }
+                            if(this.user.timeType.auditLevel > 1){
+                                if(!this.form.domains[i].auditorSec.id){ auditRule += '第二、' }
+                                audItem.auditorSec = this.form.domains[i].auditorSec.id
+                            }
+                            if(this.user.timeType.auditLevel > 2){
+                                if(!this.form.domains[i].auditorThird.id){ auditRule += '第三、' }
+                                audItem.auditorThird = this.form.domains[i].auditorThird.id
+                            }
+                            if(this.form.domains[i].ccUserid.id){
+                                audItem.ccUserid = this.form.domains[i].ccUserid.id
+                            }
+                            if(auditRule){
+                                auditRule = auditRule.substring(0,auditRule.length - 1)
+                                this.$toast.fail('请指定[' + auditRule + ']审核人')
+                                return
+                            }
+                            formData.append("auditorSettingArray", JSON.stringify(audItem).replace(/,/g,"@"));
+                        }
+
+
+
                         if (this.user.timeType.customDegreeActive == 1) {
                             if(this.form.domains[i].degreeId) {
                                 formData.append("degreeId", this.form.domains[i].degreeId);
@@ -1695,6 +1832,7 @@ import timetoolVue from '../timetool/timetool.vue';
             
             // this.getProject();
             this.getReport();
+            this.getAllUsersList()
             this.getTimeType();
             
             //初始化微信js-sdk参数

+ 133 - 2
fhKeeper/formulahousekeeper/timesheet_h5/src/views/edit/weekEdit.vue

@@ -80,6 +80,7 @@
                             @cancel="item.showPickerCostId = false;$forceUpdate();" />
                     </van-popup>
                     <!-- 审核人 -->
+                <template v-if="user.timeType.reportAuditType != 3">
                     <van-field  readonly  name="projectAuditorId" v-if="item.auditUserList != null && item.auditUserList.length > 0" clickable
                         :value="item.projectAuditorName" :label="user.companyId==781?'审核人':'项目审核人'" placeholder="请选择审核人" 
                     @click="clickPickAuditor(index, item)">
@@ -97,6 +98,51 @@
                             </template>
                         </van-picker>
                     </van-popup>
+                </template>
+
+
+                    <!-- 自选审批人 -->
+                <template v-if="user.timeType.reportAuditType == 3">
+                    <van-field readonly clickable label="第一审核人" @click="auditorClick(index,'auditorFirst')">
+                        <template #input>
+                            <span v-if="!item.auditorFirst"></span>
+                            <span v-else-if="user.userNameNeedTranslate == '1'"><ww-open-data type='userName' :openid='item.auditorFirst.name'></ww-open-data></span>
+                            <span v-else>{{item.auditorFirst.name}}</span>
+                        </template>
+                    </van-field>
+                    <van-field readonly clickable label="第二审核人" @click="auditorClick(index,'auditorSec')" v-if="user.timeType.auditLevel > 1">
+                        <template #input>
+                            <span v-if="!item.auditorSec"></span>
+                            <span v-else-if="user.userNameNeedTranslate == '1'"><ww-open-data type='userName' :openid='item.auditorSec.name'></ww-open-data></span>
+                            <span v-else>{{item.auditorSec.name}}</span>
+                        </template>
+                    </van-field>
+                    <van-field readonly clickable label="第三审核人" @click="auditorClick(index,'auditorThird')" v-if="user.timeType.auditLevel > 2">
+                        <template #input>
+                            <span v-if="!item.auditorThird"></span>
+                            <span v-else-if="user.userNameNeedTranslate == '1'"><ww-open-data type='userName' :openid='item.auditorThird.name'></ww-open-data></span>
+                            <span v-else>{{item.auditorThird.name}}</span>
+                        </template>
+                    </van-field>
+                    <van-field readonly clickable label="抄送人" @click="auditorClick(index,'ccUserid')">
+                        <template #input>
+                            <span v-if="!item.ccUserid"></span>
+                            <span v-else-if="user.userNameNeedTranslate == '1'"><ww-open-data type='userName' :openid='item.ccUserid.name'></ww-open-data></span>
+                            <span v-else>{{item.ccUserid.name}}</span>
+                        </template>
+                    </van-field>
+                    <van-popup v-model="auditorShow" position="bottom">
+                        <van-search v-model="auditor.searchText" placeholder="输入员工姓名搜索" @search="onSearch" v-if="user.userNameNeedTranslate != '1'"></van-search>
+                        <div style="minHeight:300px;">
+                            <van-radio-group v-model="auditor.item">
+                                <van-radio v-for="uitem in auditor.searchList" :key="uitem.id" :name="uitem" style="padding:10px">
+                                    <span>{{uitem.name}}</span>
+                                </van-radio>
+                            </van-radio-group>
+                            <van-button style="width:100%;position: -webkit-sticky;position: sticky;bottom: 0;" @click="searchAuditor()">确定</van-button>
+                        </div>
+                    </van-popup>
+                </template>
 
 
                     <!-- 相关维度 -->
@@ -390,10 +436,55 @@
                 kaoqinText: false,
                 workTimeText: false,
 
-                reportBasecostList: []
+                reportBasecostList: [],
+
+                auditorShow: false,
+                auditor: {
+                    index: 0,
+                    auditorIndex: 'auditorFirst',
+                    searchText: '',
+                    item: {},
+                    list: [],
+                    searchList: []
+                }
             };
         },
         methods: {
+            auditorClick(domainIndex,auditorIndex){
+                this.auditor.index = domainIndex
+                this.auditor.auditorIndex = auditorIndex
+                this.auditor.searchList.forEach(u=>{
+                    if(u.id == this.form.domains[domainIndex][auditorIndex].id){
+                        this.auditor.item = u
+                    }
+                })
+                this.auditorShow = true
+                
+            },
+            onSearch(val){
+                console.log(val);
+                this.auditor.searchList = [];
+                this.auditor.list.forEach(u=>{if (u.name.startsWith(val)) {
+                    this.auditor.searchList.push(u);
+                }})
+            },
+            searchAuditor(){
+                this.currentForm.domains[this.auditor.index][auditorIndex] = this.auditor.item
+                this.auditorShow = false
+                console.log('searchAuditor');
+            },
+            getAllUsersList(){
+                this.$axios.post('/user/getSimpleActiveUserList',{})
+                .then(res => {
+                    if(res.code == 'ok'){
+                        this.auditor.list = res.data
+                        this.auditor.searchList = res.data
+                    }else{
+                        this.$toast.fail('获取失败:'+res.msg);
+                    }
+                }).catch(err => {this.$toast.clear();})
+            },
+
             // 预算来源
             clickPickCostId(i, item) {
                 // if (!item.canEdit) return;
@@ -539,7 +630,12 @@
                                 state: 2,
                                 multiWorktime:0,
                                 worktimeList:[{}],
-                                degreeId: ''
+                                degreeId: '',
+
+                                auditorFirst: {name:'',id:''},
+                                auditorSec: {name:'',id:''},
+                                auditorThird: {name:'',id:''},
+                                ccUserid: {name:'',id:''}
                             }],
                         }
                     this.form.push(formItem)
@@ -1515,6 +1611,40 @@
                         if (!this.form[formIndex].domains[i].projectId) {
                             continue;
                         }
+
+
+                        if(this.user.timeType.reportAuditType == 3){
+                            let audItem = {}
+                            let auditRule = ''
+                            if(this.form[formIndex].domains[i].id){
+                                audItem.reportId = this.form[formIndex].domains[i].id
+                            }
+                            if(this.user.timeType.auditLevel > 0){
+                                if(!this.form[formIndex].domains[i].auditorFirst.id){ auditRule += '第一、' }
+                                audItem.auditorFirst = this.form[formIndex].domains[i].auditorFirst.id
+                            }
+                            if(this.user.timeType.auditLevel > 1){
+                                if(!this.form[formIndex].domains[i].auditorSec.id){ auditRule += '第二、' }
+                                audItem.auditorSec = this.form[formIndex].domains[i].auditorSec.id
+                            }
+                            if(this.user.timeType.auditLevel > 2){
+                                if(!this.form[formIndex].domains[i].auditorThird.id){ auditRule += '第三、' }
+                                audItem.auditorThird = this.form[formIndex].domains[i].auditorThird.id
+                            }
+                            if(this.form[formIndex].domains[i].ccUserid.id){
+                                audItem.ccUserid = this.form[formIndex].domains[i].ccUserid.id
+                            }
+                            if(auditRule){
+                                auditRule = auditRule.substring(0,auditRule.length - 1)
+                                this.$toast.fail('请指定' + this.weekArr[formIndex] + '的[' + auditRule + ']审核人')
+                                return
+                            }
+                            formData.append("auditorSettingArray", JSON.stringify(audItem).replace(/,/g,"@"));
+                        }
+
+
+
+
                         if (this.user.timeType.customDegreeActive == 1) {
                             if(this.form[formIndex].domains[i].degreeId) {
                                 formData.append("degreeId", this.form[formIndex].domains[i].degreeId);
@@ -1775,6 +1905,7 @@
             
             this.getProject();
             this.getReportBasecostList()
+            this.getAllUsersList()
             // this.getReport();
             this.getTimeType();
             //初始化微信js-sdk参数

+ 82 - 17
fhKeeper/formulahousekeeper/timesheet_h5/src/views/review/index.vue

@@ -49,6 +49,11 @@
                 <van-button @click="batchAgree(false)" :disabled="!isCanAgree || report.length == 0" type="danger" size="small" style="margin-left:2vw">批量驳回</van-button>
                 </div>
             </div>
+
+            <van-pull-refresh v-model="downLoading" @refresh="onDownRefresh">
+                <!-- 列表 -->
+                <van-list v-model="upLoading" :finished="upFinished" :immediate-check="false" :offset="100" finished-text="没有更多了" @load="onLoadList">
+
             <van-skeleton  v-for="(item,index) in report" :key="index" title avatar :row="3" :loading="false">
                 <van-panel class="one_report">
                     <template #header>
@@ -152,6 +157,11 @@
                     </van-popup>
                 </van-panel>
             </van-skeleton>
+
+                </van-list>
+            </van-pull-refresh>
+
+            
             <van-popup v-model="denyReasonDialog" position="bottom" closeable >
                 <van-cell>请输入原因</van-cell>
                 <van-field class="form_input"
@@ -188,6 +198,15 @@
                 nowTime: this.format(new Date(new Date()),"yyyy-MM-dd"),
                 showPicker: false,
                 report: [],
+
+                // 懒加载
+                total: 0,               // 列表总数据长度
+                pageIndex: 1,           // 页码,每页数据固定为25
+                upLoading: false,       // 上拉加载
+                upFinished: false,      // 上拉加载完毕
+                downLoading: false,     // 下拉刷新
+                listReLoading: false,   // 是否重新加载列表数据
+
                 flg: false,
                 isCanAgree: false,
                 approveinData: null,
@@ -208,17 +227,42 @@
         created() {
         },
         methods: {
+
+            onDownRefresh() {
+                this.pageIndex = 1
+                this.listReLoading = true
+                this.upLoading = true
+                this.upFinished = false // 不写这句会导致你上拉到底过后在下拉刷新将不能触发下拉加载事件
+                this.getReport()
+            },
+            onLoadList(){
+                if(this.total <= this.report.length) {
+                    this.upFinished = true
+                    this.upLoading = false
+                    return
+                }
+                this.pageIndex += 1
+                this.listReLoading = false
+                this.getReport()
+            },
+
+
+
             selectDateClear(){
                 this.selectDate = []
                 this.selectDateValue = ''
-                this.getReport()
+
+                this.listReLoading = true
+                this.onDownRefresh()
             },
             selectUserClear(){
                 this.userNameValue = ''
                 this.userIdList = []
                 this.userList.forEach(item => {delete item.isChecked})
                 this.showUserList = this.userList
-                this.getReport()
+
+                this.listReLoading = true
+                this.onDownRefresh()
             },
             selectUserClick(){
                 this.selectUserShow = true
@@ -230,7 +274,9 @@
                 this.selectShow = false;
                 this.selectDate = [this.getSelectDateStr(start),this.getSelectDateStr(end)]
                 this.selectDateValue = `${this.selectDate[0]} 至 ${this.selectDate[1]}`;
-                this.getReport()
+                
+                this.listReLoading = true
+                this.onDownRefresh()
             },
             getSelectDateStr(date){
                 return `${date.getFullYear()}-${(date.getMonth() + 1) < 10 ? '0' + (date.getMonth() + 1) : (date.getMonth() + 1)}-${date.getDate() < 10 ? '0' + date.getDate() : date.getDate()}`;
@@ -253,9 +299,12 @@
                     this.userNameValue = this.userNameValue.substring(0, this.userNameValue.length-1);
                     this.userIdList = this.userIdList.substring(0, this.userIdList.length-1);
                 }
-                this.$forceUpdate()
                 this.selectUserShow = false
-                this.getReport()
+
+                this.listReLoading = true
+                this.onDownRefresh()
+
+                this.$forceUpdate()
                 
             },
 
@@ -416,7 +465,9 @@
             getReport() {
                 const toast = this.$toast.loading({
                     forbidClick: true,
-                    duration: 0
+                    duration: 0,
+                    pageIndex: this.pageIndex,
+                    pageSize: 25
                 });
                 let parameter = {
                     state: 0
@@ -432,19 +483,36 @@
                 .then(res => {
                     if(res.code == "ok") {
                         this.$toast.clear();
-                        this.report = res.data;
-                        // this.isAllChecked = this.report.length == 0 ? false : true
-                        if(this.report.length == 0){
-                            this.isAllChecked = false
-                        }
-                        for(let i in this.report){
-                            this.$set(this.report[i],'checked',false)
+                        // this.total = res.data.total
+                        this.downLoading = false
+                        this.upLoading = false
+
+                        this.isAllChecked = false
+                        if(this.listReLoading){
+                            this.report = res.data;
+                            document.documentElement.scrollTop = 0
+                            for(let i in this.report){
+                                this.$set(this.report[i],'checked',false)
+                            }
+                        }else{
+                            for(let i in res.data){
+                                this.report.push(res.data[i])
+                            }
+                            
                         }
+
+                        // this.isAllChecked = this.report.length == 0 ? false : true
+                        
+                        
                     } else {
                         this.$toast.clear();
                         this.$toast.fail('获取失败:'+res.msg);
+                        this.downLoading = false
+                        this.upLoading = false
                     }
-                }).catch(err=> {this.$toast.clear();});
+                }).catch(err=> {this.$toast.clear();
+                    this.downLoading = false
+                    this.upLoading = false});
             },
 
             approve(id, item) {
@@ -548,9 +616,6 @@
 </script>
 
 <style lang="less" scoped>
-.dateSelectCell{
-    display: -webkit-box;
-}
 .userCheckbox {
         padding: 10px;;
     }