Browse Source

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

cs 2 years ago
parent
commit
56ffbf9639
24 changed files with 968 additions and 199 deletions
  1. 6 0
      fhKeeper/formulahousekeeper/management-platform/pom.xml
  2. 1 1
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/aop/AopLogConfiguration.java
  3. 9 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/CommonUploadController.java
  4. 242 9
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/FeishuInfoController.java
  5. 8 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/ProjectDocumentController.java
  6. 12 3
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/ReportController.java
  7. 7 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/TaskFilesController.java
  8. 15 2
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/mapper/ReportMapper.java
  9. 2 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/FeishuInfoService.java
  10. 1 1
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/ReportService.java
  11. 0 1
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ExcelExportServiceImpl.java
  12. 53 36
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/FeishuInfoServiceImpl.java
  13. 286 131
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ReportServiceImpl.java
  14. 32 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/task/SFTPAsyncUploader.java
  15. 19 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/task/TimingTask.java
  16. 63 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/util/SFTPUploader.java
  17. 39 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/util/TestSample.java
  18. 9 1
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/application-prod.yml
  19. 9 3
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/application.yml
  20. 119 3
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/ReportMapper.xml
  21. 2 1
      fhKeeper/formulahousekeeper/ops-platform/src/main/resources/application-dev.yml
  22. 3 1
      fhKeeper/formulahousekeeper/ops-platform/src/main/resources/application-prod.yml
  23. 25 0
      fhKeeper/formulahousekeeper/restart.sh
  24. 6 6
      fhKeeper/formulahousekeeper/timesheet/src/views/workReport/daily.vue

+ 6 - 0
fhKeeper/formulahousekeeper/management-platform/pom.xml

@@ -179,6 +179,12 @@
             <version>3.3.0</version>
         </dependency>
 
+        <dependency>
+            <groupId>com.jcraft</groupId>
+            <artifactId>jsch</artifactId>
+            <version>0.1.55</version>
+        </dependency>
+
         <dependency>
             <groupId>com.aliyun</groupId>
             <artifactId>dysmsapi20170525</artifactId>

+ 1 - 1
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/aop/AopLogConfiguration.java

@@ -24,7 +24,7 @@ import java.util.stream.Stream;
 @Aspect
 @Configuration
 public class AopLogConfiguration {
-    public static String[] methods = {"importData", "editReport", "approve", "deny", "cancel", "batchApproveReport", "batchDenyReport"
+    public static String[] methods = {"importData", "exportReport", "editReport", "approve", "deny", "cancel", "batchApproveReport", "batchDenyReport"
             , "loginByUserId", "getUserByCode"};
     public static List<String> printMethods = new ArrayList<String>();
     static {

+ 9 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/CommonUploadController.java

@@ -1,13 +1,16 @@
 package com.management.platform.controller;
 
+import com.management.platform.task.SFTPAsyncUploader;
 import com.management.platform.util.HttpRespMsg;
 import org.apache.log4j.LogManager;
 import org.apache.log4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 import org.springframework.web.multipart.MultipartFile;
 
+import javax.annotation.Resource;
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.InputStream;
@@ -21,6 +24,8 @@ public class CommonUploadController {
     Logger logger = LogManager.getLogger(org.apache.logging.log4j.LogManager.ROOT_LOGGER_NAME);
     @Value(value = "${upload.path}")
     private String path;
+    @Autowired
+    public SFTPAsyncUploader sftpAsyncUploader;
 
     @RequestMapping(value="uploadFile")
     public HttpRespMsg uploadFile(MultipartFile multipartFile) {
@@ -50,6 +55,10 @@ public class CommonUploadController {
             inputStream.close();
             outputStream.close();
             msg.data = serverName;
+
+            // 上传到SFTP服务器
+            sftpAsyncUploader.uploadFileAsync(file);
+
         } catch (Exception exception) {
             exception.printStackTrace();
             logger.error(exception.getMessage());

+ 242 - 9
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/FeishuInfoController.java

@@ -1,29 +1,36 @@
 package com.management.platform.controller;
 
 
+import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.google.gson.JsonObject;
 import com.management.platform.constant.Constant;
 import com.management.platform.entity.*;
 import com.management.platform.entity.vo.UserVO;
 import com.management.platform.mapper.*;
+import com.management.platform.service.DepartmentOtherManagerService;
 import com.management.platform.service.FeishuInfoService;
 import com.management.platform.service.SysRoleService;
 import com.management.platform.service.UserService;
 import com.management.platform.service.impl.FeishuInfoServiceImpl;
 import com.management.platform.util.*;
 import com.taobao.api.ApiException;
+import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.http.*;
 import org.springframework.util.StringUtils;
-import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.*;
 
-import org.springframework.web.bind.annotation.RestController;
 import org.springframework.web.client.RestTemplate;
 
 import javax.annotation.Resource;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.PrintWriter;
 import java.time.LocalDateTime;
 import java.time.ZoneOffset;
 import java.util.*;
@@ -39,6 +46,7 @@ import java.util.stream.Collectors;
  */
 @RestController
 @RequestMapping("/feishu-info")
+@Slf4j
 public class FeishuInfoController {
 
     @Resource
@@ -79,6 +87,8 @@ public class FeishuInfoController {
     private TaskGroupMapper taskGroupMapper;
     @Resource
     private ProjectAuditorMapper projectAuditorMapper;
+    @Resource
+    DepartmentOtherManagerService departmentOtherManagerService;
 
 
     /**
@@ -93,8 +103,7 @@ public class FeishuInfoController {
         //查找公司对应的记录是否已经添加
         FeishuInfo feishuInfo = feishuInfoMapper.selectOne(new QueryWrapper<FeishuInfo>().eq("app_id",appId));
         if (feishuInfo == null) {
-            //msg.setError("请在company_dingding表中增加corpid:" + corpid);
-            msg.setError("请在company_dingding表中增加appid:" + appId);
+            msg.setError("请在feishu_info表中增加appid:" + appId);
         } else if (feishuInfo.getCompanyId() != null) {
             //msg.setError("companyId已存在,如需重新初始化请先重置company_dingding中该条数据的companyId为null");
             msg.setError("companyId已存在,如需重新初始化请先重置feishu_info中该条数据的companyId为null");
@@ -144,7 +153,7 @@ public class FeishuInfoController {
                 if(departmentInfo!=null&&departmentInfo.size()>0){
                     departmentInfoArrays.addAll(departmentInfo);
                 }
-                JSONArray subDepartmentList = feishuInfoService.getSubDepartmentList(feishuInfo, dpId, null);
+                JSONArray subDepartmentList =getSubDepartmentList(feishuInfo,dpId);
                 if(subDepartmentList!=null&&subDepartmentList.size()>0){
                     departmentInfoArrays.addAll(subDepartmentList);
                 }
@@ -181,7 +190,7 @@ public class FeishuInfoController {
             for (DepartmentFeishu departmentFeishu : departmentFeishuList) {
                 Optional<Department> first = departmentList.stream().filter(dl -> dl.getDepartmentId().equals(departmentFeishu.getSysDeptid())).findFirst();
                 //获取到当前部门的上级部门
-                Optional<DepartmentFeishu> wx = departmentFeishuList.stream().filter(dl -> dl.getFeishuDeptid().equals(departmentFeishu.getFeishuParentid())).findFirst();
+                Optional<DepartmentFeishu> wx = departmentFeishuList.stream().filter(dl -> dl.getFeishuOpenDeptid().equals(departmentFeishu.getFeishuParentid())).findFirst();
                 if(first.isPresent()){
                     if(wx.isPresent()){
                         Optional<Department> dp = departmentList.stream().filter(dl -> dl.getDepartmentId().equals(wx.get().getSysDeptid())).findFirst();
@@ -219,9 +228,11 @@ public class FeishuInfoController {
                     Optional<DepartmentFeishu> dpFs = departmentFeishuList.stream().filter(dl -> dl.getFeishuOpenDeptid().equals(max)).findFirst();
                     if(dpFs.isPresent()){
                         Optional<Department> dp = departmentList.stream().filter(dl -> dl.getDepartmentId().equals(dpFs.get().getSysDeptid())).findFirst();
-                        user.setDepartmentName(dp.get().getDepartmentName());
-                        user.setDepartmentId(dp.get().getDepartmentId());
-                        user.setDepartmentCascade(convertDepartmentIdToCascade(dp.get().getDepartmentId(),departmentList));
+                        if(dp.isPresent()){
+                            user.setDepartmentName(dp.get().getDepartmentName());
+                            user.setDepartmentId(dp.get().getDepartmentId());
+                            user.setDepartmentCascade(convertDepartmentIdToCascade(dp.get().getDepartmentId(),departmentList));
+                        }
                     }
                     boolean b = userList.stream().anyMatch(ul ->ul.getFeishuUserid()!=null&&ul.getFeishuUserid().equals(user.getFeishuUserid()));
                     if(!b){
@@ -267,6 +278,22 @@ public class FeishuInfoController {
         return msg;
     }
 
+    private JSONArray getSubDepartmentList(FeishuInfo feishuInfo, String dpId) {
+        JSONArray result=new JSONArray();
+        JSONArray subDepartmentList = feishuInfoService.getSubDepartmentList(feishuInfo, dpId, null);
+        result.addAll(subDepartmentList);
+        if(subDepartmentList!=null&&subDepartmentList.size()>0){
+            for (int i = 0; i < subDepartmentList.size(); i++) {
+                JSONObject ob = subDepartmentList.getJSONObject(i);
+                if(ob.getString("open_department_id")!=null){
+                    JSONArray array = getSubDepartmentList(feishuInfo,ob.getString("open_department_id"));
+                    result.addAll(array);
+                }
+            }
+        }
+        return  result;
+    }
+
     //将部门id转换为部门层级
     private String convertDepartmentIdToCascade(Integer id, List<Department> allDeptList) {
         StringBuilder cascade = new StringBuilder();
@@ -559,5 +586,211 @@ public class FeishuInfoController {
         }
     }
 
+
+    @RequestMapping("/initSuperManager")
+    public HttpRespMsg initSuperManager(String corpid, String name) {
+        return feishuInfoService.initSuperManager(corpid, name);
+    }
+
+    //"企业微信数据回调"
+    @RequestMapping(value = "/dataCallback", method = RequestMethod.POST)
+    @ResponseBody
+    public void dataCallback(@RequestBody JSONObject jsonParam, HttpServletResponse response) throws IOException {
+        //用于验证飞书的部分
+        PrintWriter out = null;
+        JSONObject jsonObject=new JSONObject();
+        if(jsonParam.getString("challenge")!=null){
+            jsonObject.put("challenge",jsonParam.getString("challenge"));
+            //设定类容为json的格式
+            response.setContentType("application/json;charset=UTF-8");
+            out = response.getWriter();
+            //写到客户端
+            out.write(jsonObject.toJSONString());
+            out.flush();
+            return;
+        }
+        log.info("============回调参数==========="+jsonParam.toJSONString());
+        JSONObject headerOb =jsonParam.getJSONObject("header");
+        if(headerOb==null||headerOb.size()<=0){
+            return;
+        }
+        JSONObject eventOb = jsonParam.getJSONObject("event");
+        log.info("=========event======"+eventOb.toJSONString());
+        String appId = headerOb.getString("app_id");
+        log.info("========app_id========"+appId);
+        String tenantKey = headerOb.getString("tenant_key");
+        log.info("========tenant_key========"+tenantKey);
+        String createTime = headerOb.getString("create_time");
+        log.info("========create_time========"+createTime);
+        List<FeishuInfo> feishuInfoList = feishuInfoMapper.selectList(new QueryWrapper<FeishuInfo>().eq("app_id", appId));
+        if(feishuInfoList.size()>0){
+            FeishuInfo feishuInfo = feishuInfoList.get(0);
+            List<User> allUserList = userMapper.selectList(new QueryWrapper<User>().eq("company_id", feishuInfo.getCompanyId()));
+            SysRole role = sysRoleMapper.selectOne(new QueryWrapper<SysRole>().eq("company_id",feishuInfo.getCompanyId()).eq("rolename","普通员工"));
+            //通讯录权限范围变更
+            //todo:新增的
+            if(eventOb!=null&&eventOb.getJSONObject("added").size()>0){
+                JSONObject addedOb = eventOb.getJSONObject("added");
+                //todo:处理部门
+                JSONArray departmentArray = addedOb.getJSONArray("departments");
+                JSONArray allNeedTodo=new JSONArray();
+                allNeedTodo.addAll(departmentArray);
+                for (int i = 0; i < departmentArray.size(); i++) {
+                    JSONObject ob = departmentArray.getJSONObject(i);
+                    JSONArray jsonArray = getSubDepartmentList(feishuInfo, ob.getString("open_department_id"));
+                    if(jsonArray!=null&&jsonArray.size()>0){
+                        allNeedTodo.addAll(jsonArray);
+                    }
+                }
+                List<Department> departmentList=new ArrayList<>();
+                List<DepartmentFeishu> departmentFeishuList=new ArrayList<>();
+                for (int j = 0; j < allNeedTodo.size(); j++) {
+                    JSONObject ob = allNeedTodo.getJSONObject(j);
+                    String departmentName = String.valueOf(ob.get("name"));
+                    System.out.println("synchronizationDP========="+departmentName);
+                    String departmentId = String.valueOf(ob.getString("department_id"));
+                    String openDepartmentId = String.valueOf(ob.getString("open_department_id"));
+                    String departmentParentId =String.valueOf(ob.getString("parent_department_id"));
+                    JSONArray leaders = ob.getJSONArray("leaders");
+                    Integer cut = departmentFeishuMapper.selectCount(new QueryWrapper<DepartmentFeishu>().eq("corpid",feishuInfo.getCorpid()).eq("feishu_deptid",departmentId));
+                    if(cut==0&&!departmentId.equals("0")){
+                        System.out.println("join===========");
+                        DepartmentFeishu departmentFeishu=new DepartmentFeishu();
+                        departmentFeishu.setCorpid(feishuInfo.getCorpid())
+                                .setName(departmentName)
+                                .setFeishuParentid(departmentParentId)
+                                .setFeishuDeptid(departmentId)
+                                .setFeishuOpenDeptid(openDepartmentId);
+                        Department department = new Department();
+                        department.setCompanyId(feishuInfo.getCompanyId());
+                        department.setDepartmentName(departmentName);
+                        department.setFeishuDeptid(openDepartmentId);
+                        departmentMapper.insert(department);
+                        List<DepartmentOtherManager> odList=new ArrayList<>();
+                        if(leaders!=null&&leaders.size()>0){
+                            //todo:处理主要负责人
+                            Optional<Object> first = leaders.stream().filter(l -> ((JSONObject) l).getIntValue("leaderType") == 1).findFirst();
+                            if(first.isPresent()){
+                                JSONObject firstOb = (JSONObject) first.get();
+                                Optional<User> leaderID = allUserList.stream().filter(ul -> ul.getFeishuUserid().equals(firstOb.getString("leaderID"))).findFirst();
+                                if(leaderID.isPresent()){
+                                    department.setManagerId(leaderID.get().getId());
+                                }
+                            }
+                            //todo:处理次要负责人
+                            List<Object> othObs = leaders.stream().filter(l -> ((JSONObject) l).getIntValue("leaderType") == 2).collect(Collectors.toList());
+                            for (Object othOb : othObs) {
+                                JSONObject oth = (JSONObject) othOb;
+                                Optional<User> leaderID = allUserList.stream().filter(ul -> ul.getFeishuUserid().equals(oth.getString("leaderID"))).findFirst();
+                                if(leaderID.isPresent()){
+                                    DepartmentOtherManager departmentOtherManager=new DepartmentOtherManager();
+                                    departmentOtherManager.setCompanyId(feishuInfo.getCompanyId());
+                                    departmentOtherManager.setDepartmentId(department.getDepartmentId());
+                                    departmentOtherManager.setOtherManagerId(leaderID.get().getId());
+                                    odList.add(departmentOtherManager);
+                                }
+                            }
+                        }
+                        departmentMapper.updateById(department);
+                        departmentList.add(department);
+                        departmentFeishu.setSysDeptid(department.getDepartmentId());
+                        departmentFeishuMapper.insert(departmentFeishu);
+                        departmentFeishuList.add(departmentFeishu);
+                        departmentOtherManagerService.saveBatch(odList);
+                    }
+                }
+                List<User> newUserList=new ArrayList<>();
+                for (DepartmentFeishu departmentFeishu : departmentFeishuList) {
+                    Optional<Department> first = departmentList.stream().filter(dl -> dl.getDepartmentId().equals(departmentFeishu.getSysDeptid())).findFirst();
+                    //获取到当前部门的上级部门
+                    Optional<DepartmentFeishu> wx = departmentFeishuList.stream().filter(dl -> dl.getFeishuOpenDeptid().equals(departmentFeishu.getFeishuParentid())).findFirst();
+                    if(first.isPresent()){
+                        if(wx.isPresent()){
+                            Optional<Department> dp = departmentList.stream().filter(dl -> dl.getDepartmentId().equals(wx.get().getSysDeptid())).findFirst();
+                            if(dp.isPresent()){
+                                first.get().setSuperiorId(dp.get().getDepartmentId());
+                                departmentMapper.updateById(first.get());
+                            }
+                        }
+                    }
+                    //处理部门下的人员
+                    JSONArray userInfoWithDepartment=feishuInfoService.getUserInfoWithDepartment(feishuInfo,departmentFeishu.getFeishuOpenDeptid(),null);
+                    for (int m=0;m<userInfoWithDepartment.size(); m++) {
+                        JSONObject userJson = userInfoWithDepartment.getJSONObject(m);
+                        String curUserid = userJson.getString("user_id");
+                        String openUserid = userJson.getString("open_id");
+                        if(!userJson.getJSONObject("status").getBoolean("is_activated")){
+                            continue;
+                        }
+                        List<String> departments = (List<String>) userJson.get("department_ids");
+                        System.out.println("user info======:"+userJson.toString());
+                        boolean b = allUserList.stream().anyMatch(al -> al.getFeishuUserid() != null && al.getFeishuUserid().equals(userJson.getString("open_id")));
+                        if(!b){
+                            //不存在的人员, 进行插入
+                            User user = new User();
+                            //在当前部门下的员工
+                            user.setId(SnowFlake.nextId()+"")
+                                    .setRoleId(role.getId())//默认普通员工
+                                    .setRoleName(role.getRolename())
+                                    .setCompanyId(feishuInfo.getCompanyId())
+                                    .setName(userJson.getString("name"))
+                                    .setFeishuUserid(openUserid)
+                                    .setColor(ColorUtil.randomColor())
+                                    .setJobNumber(curUserid)
+                                    .setPassword(MD5Util.getPassword("000000"))
+                                    .setFeishuDeptid(departmentFeishu.getFeishuDeptid());
+                            String max = departments.get(0);
+                            Optional<DepartmentFeishu> dpFs = departmentFeishuList.stream().filter(dl -> dl.getFeishuOpenDeptid().equals(max)).findFirst();
+                            if(dpFs.isPresent()){
+                                Optional<Department> dp = departmentList.stream().filter(dl -> dl.getDepartmentId().equals(dpFs.get().getSysDeptid())).findFirst();
+                                if(dp.isPresent()){
+                                    user.setDepartmentName(dp.get().getDepartmentName());
+                                    user.setDepartmentId(dp.get().getDepartmentId());
+                                    user.setDepartmentCascade(convertDepartmentIdToCascade(dp.get().getDepartmentId(),departmentList));
+                                }
+                            }
+                            boolean c = newUserList.stream().anyMatch(ul ->ul.getFeishuUserid()!=null&&ul.getFeishuUserid().equals(user.getFeishuUserid()));
+                            if(!c){
+                                newUserList.add(user);
+                            }
+                        }
+                    }
+                }
+                //todo:处理人员
+                JSONArray userArrays = addedOb.getJSONArray("users");
+                if(userArrays!=null&&userArrays.size()>0){
+                    for (int i = 0; i < userArrays.size(); i++) {
+                        JSONObject userOb = userArrays.getJSONObject(i);
+                        boolean b = allUserList.stream().anyMatch(al -> al.getFeishuUserid() != null && al.getFeishuUserid().equals(userOb.getString("open_id")));
+                        if(!b){
+                            //不存在的人员, 进行插入
+                            User user = new User();
+                            user.setId(SnowFlake.nextId()+"")
+                                    .setRoleId(role.getId())//默认普通员工
+                                    .setRoleName(role.getRolename())
+                                    .setCompanyId(feishuInfo.getCompanyId())
+                                    .setName(userOb.getString("name"))
+                                    .setFeishuUserid(userOb.getString("open_id"))
+                                    .setColor(ColorUtil.randomColor())
+                                    .setJobNumber(userOb.getString("user_id"))
+                                    .setPassword(MD5Util.getPassword("000000"));
+                            boolean c = newUserList.stream().anyMatch(ul ->ul.getFeishuUserid()!=null&&ul.getFeishuUserid().equals(user.getFeishuUserid()));
+                            if(!c){
+                                newUserList.add(user);
+                            }
+                        }
+                    }
+                }
+                if(newUserList.size()>0){
+                    userService.saveBatch(newUserList);
+                }
+            }
+            //todo:移除的
+            if(eventOb.getJSONObject("removed")!=null){
+
+            }
+        }
+    }
+
 }
 

+ 8 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/ProjectDocumentController.java

@@ -9,6 +9,7 @@ import com.management.platform.constant.Constant;
 import com.management.platform.entity.*;
 import com.management.platform.mapper.*;
 import com.management.platform.service.ProjectDocumentService;
+import com.management.platform.task.SFTPAsyncUploader;
 import com.management.platform.util.*;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
@@ -63,6 +64,9 @@ public class ProjectDocumentController {
     @Value("${upload.path}")
     private String uploadPath;
 
+    @Autowired
+    public SFTPAsyncUploader sftpAsyncUploader;
+
     /**
      * 上传文件
      * @param projectId 项目id
@@ -114,10 +118,14 @@ public class ProjectDocumentController {
                     try {
                         saveFile.createNewFile();
                         file.transferTo(saveFile);
+                        //异步上传到备份服务器
+                        sftpAsyncUploader.uploadFileAsync(saveFile);
+
                         //计算文件大小
                         long fileSize = saveFile.length();
                         String fileLength = FileUtil.getReadableFileSize(fileSize);
                         record.setServerName(uploadPath + fileName);
+
                         record.setSize(fileLength);
                         String pathPrefix = "/upload/";
                         record.setUrl(pathPrefix + fileName);

+ 12 - 3
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/ReportController.java

@@ -188,6 +188,16 @@ public class ReportController {
      */
     @RequestMapping("/exportReport")
     public HttpRespMsg exportReport(String startDate, String endDate, Integer projectId,@RequestParam(defaultValue = "0") Integer stateKey,Integer departmentId) {
+        //startDate和endDate间隔不得超过1年
+        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+        LocalDate start = LocalDate.parse(startDate, dateTimeFormatter);
+        LocalDate end = LocalDate.parse(endDate, dateTimeFormatter);
+        if (start.until(end, ChronoUnit.DAYS) > 365) {
+            HttpRespMsg httpRespMsg = new HttpRespMsg();
+            httpRespMsg.setError("导出日报时间间隔不得超过1年");
+            return httpRespMsg;
+        }
+
         return reportService.exportReport(startDate, endDate, projectId,stateKey,departmentId, request);
     }
 
@@ -203,12 +213,11 @@ public class ReportController {
 
     /**
      * AI智能填报
-     * @param date
      * @return
      */
     @RequestMapping("/getAIReport")
-    public HttpRespMsg getAIReport(@RequestParam String date) {
-        return reportService.getAIReport(date, request);
+    public HttpRespMsg getAIReport() {
+        return reportService.getAIReport(request);
     }
 
 

+ 7 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/TaskFilesController.java

@@ -5,7 +5,9 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.management.platform.entity.*;
 import com.management.platform.mapper.*;
 import com.management.platform.service.ProjectDocumentService;
+import com.management.platform.task.SFTPAsyncUploader;
 import com.management.platform.util.*;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.util.StringUtils;
 import org.springframework.web.bind.annotation.RequestMapping;
@@ -48,6 +50,9 @@ public class TaskFilesController {
     @Value("${upload.path}")
     private String uploadPath;
 
+    @Autowired
+    private SFTPAsyncUploader sftpAsyncUploader;
+
     /**
      * 获取该项目下的所有有效的文件列表
      * @param keyword
@@ -139,6 +144,8 @@ public class TaskFilesController {
                     try {
                         saveFile.createNewFile();
                         file.transferTo(saveFile);
+                        //异步上传到备份服务器
+                        sftpAsyncUploader.uploadFileAsync(saveFile);
                         //计算文件大小
                         long fileSize = saveFile.length();
                         String fileLength = FileUtil.getReadableFileSize(fileSize);

+ 15 - 2
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/mapper/ReportMapper.java

@@ -28,7 +28,14 @@ public interface ReportMapper extends BaseMapper<Report> {
                                                      @Param("stateKey") Integer stateKey,
                                                      @Param("branchDepartment")List<Integer> branchDepartment
                                                  );
-
+    List<HashMap<String, Object>> getAllReportByDateWithReportLog(@Param("startDate") String startDate,
+                                                     @Param("companyId") Integer companyId,
+                                                     @Param("userId") String userId,
+                                                     @Param("endDate") String endDate,
+                                                     @Param("projectId") Integer projectId,
+                                                     @Param("stateKey") Integer stateKey,
+                                                     @Param("branchDepartment")List<Integer> branchDepartment
+    );
     List<HashMap<String, Object>> getProjectMembReportByDate(@Param("startDate") String startDate,
                                                      @Param("companyId") Integer companyId,
                                                      @Param("leaderId") String leaderId,
@@ -36,7 +43,13 @@ public interface ReportMapper extends BaseMapper<Report> {
                                                      @Param("projectId") Integer projectId,
                                                      @Param("stateKey") Integer stateKey,
                                                      @Param("branchDepartment")List<Integer> branchDepartment);
-
+    List<HashMap<String, Object>> getProjectMembReportByDateWithReportLog(@Param("startDate") String startDate,
+                                                             @Param("companyId") Integer companyId,
+                                                             @Param("leaderId") String leaderId,
+                                                             @Param("endDate") String endDate,
+                                                             @Param("projectId") Integer projectId,
+                                                             @Param("stateKey") Integer stateKey,
+                                                             @Param("branchDepartment")List<Integer> branchDepartment);
     //获取部门下的人员的日报
     List<HashMap<String, Object>> getDeptMembReportByDate(@Param("startDate") String startDate,
                                                              @Param("companyId") Integer companyId,

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

@@ -37,4 +37,6 @@ public interface FeishuInfoService extends IService<FeishuInfo> {
     void batchSendCardTemplateMessage(FeishuInfo feishuInfo, List<String> userIds, String sendTypeName, List<String> templateVariableDetail) throws Exception;
 
     void batchSendCardMessage(FeishuInfo feishuInfo, List<String> userIds, String sendTypeName, Map<String, String> templateVariableDetail, String pushUrl) throws Exception;
+
+    HttpRespMsg initSuperManager(String corpid, String name);
 }

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

@@ -113,5 +113,5 @@ public interface ReportService extends IService<Report> {
 
     HttpRespMsg fillAll(String month, String userId, Integer departmentId, Integer whether,HttpServletRequest request);
 
-    HttpRespMsg getAIReport(String date, HttpServletRequest request);
+    HttpRespMsg getAIReport(HttpServletRequest request);
 }

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

@@ -61,7 +61,6 @@ public class ExcelExportServiceImpl implements ExcelExportService {
 
     public HttpRespMsg exportGeneralExcelByTitleAndList(WxCorpInfo wxCorpInfo, String title, List<List<String>> list, String downloadPath) throws Exception {
         HttpRespMsg httpRespMsg = new HttpRespMsg();
-        System.out.println(File.separator);
         if (title.contains("/")) {
             //文件名不能含有路径,得替换掉
             title = title.replace("/", "@");

+ 53 - 36
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/FeishuInfoServiceImpl.java

@@ -6,14 +6,16 @@ import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.google.gson.JsonObject;
 import com.management.platform.constant.Constant;
-import com.management.platform.entity.FeishuInfo;
-import com.management.platform.entity.FeishuSend;
-import com.management.platform.entity.User;
+import com.management.platform.entity.*;
 import com.management.platform.mapper.FeishuInfoMapper;
 import com.management.platform.mapper.FeishuSendMapper;
+import com.management.platform.mapper.SysRoleMapper;
+import com.management.platform.mapper.UserMapper;
+import com.management.platform.service.DepartmentOtherManagerService;
 import com.management.platform.service.FeishuInfoService;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.management.platform.util.HttpRespMsg;
+import com.management.platform.util.MD5Util;
 import com.management.platform.util.MessageUtils;
 import com.management.platform.util.UserAgentUtils;
 import org.apache.http.client.methods.HttpGet;
@@ -67,6 +69,10 @@ public class FeishuInfoServiceImpl extends ServiceImpl<FeishuInfoMapper, FeishuI
         FeishuInfoMapper feishuInfoMapper;
         @Resource
         FeishuSendMapper feishuSendMapper;
+        @Resource
+        UserMapper userMapper;
+        @Resource
+        SysRoleMapper sysRoleMapper;
 
         @Override
         public String getAppAccessToken(FeishuInfo feishuInfo) {
@@ -96,47 +102,42 @@ public class FeishuInfoServiceImpl extends ServiceImpl<FeishuInfoMapper, FeishuI
                 String result="";
                 FeishuInfo feishuInfo = getOne(new QueryWrapper<FeishuInfo>().eq("app_id", appId));
                 if(feishuInfo!=null){
-                        if(feishuInfo.getExpireTime().isBefore(LocalDateTime.now())){
-                                String url = GET_TENANT_ACCESS_TOKEN;
-                                HttpHeaders headers = new HttpHeaders();
-                                RestTemplate restTemplate = new RestTemplate();
-                                MediaType type = MediaType.parseMediaType("application/json; charset=UTF-8");
-                                headers.setContentType(type);
-                                JSONObject requestMap = new JSONObject();
-                                requestMap.put("app_id",feishuInfo.getAppId());
-                                requestMap.put("app_secret",feishuInfo.getAppSecret());
-                                HttpEntity<JSONObject> entity = new HttpEntity<>(requestMap, headers);
-                                ResponseEntity<String> ResponseEntity = restTemplate.postForEntity(url, entity, String.class);
-                                if (ResponseEntity.getStatusCode() == HttpStatus.OK) {
-                                        String resp = ResponseEntity.getBody();
-                                        JSONObject respJson = JSONObject.parseObject(resp);
-                                        if (respJson.getInteger("code")==0){
-                                                result=respJson.getString("tenant_access_token");
-                                                feishuInfo.setAccessToken(result);
-                                                LocalDateTime now = LocalDateTime.now();
-                                                now = now.plusSeconds(7200);
-                                                feishuInfo.setExpireTime(now);
-                                                feishuInfoMapper.updateById(feishuInfo);
-                                        }
+                        String url = GET_TENANT_ACCESS_TOKEN;
+                        HttpHeaders headers = new HttpHeaders();
+                        RestTemplate restTemplate = new RestTemplate();
+                        MediaType type = MediaType.parseMediaType("application/json; charset=UTF-8");
+                        headers.setContentType(type);
+                        JSONObject requestMap = new JSONObject();
+                        requestMap.put("app_id",feishuInfo.getAppId());
+                        requestMap.put("app_secret",feishuInfo.getAppSecret());
+                        HttpEntity<JSONObject> entity = new HttpEntity<>(requestMap, headers);
+                        ResponseEntity<String> ResponseEntity = restTemplate.postForEntity(url, entity, String.class);
+                        if (ResponseEntity.getStatusCode() == HttpStatus.OK) {
+                                String resp = ResponseEntity.getBody();
+                                JSONObject respJson = JSONObject.parseObject(resp);
+                                if (respJson.getInteger("code")==0){
+                                        result=respJson.getString("tenant_access_token");
+                                        feishuInfo.setAccessToken(result);
+                                        LocalDateTime now = LocalDateTime.now();
+                                        now = now.plusSeconds(7200);
+                                        feishuInfo.setExpireTime(now);
+                                        feishuInfoMapper.updateById(feishuInfo);
                                 }
                         }
+
                 }
                 return result;
         }
 
         @Override
         public JSONObject getCorpInfo(FeishuInfo feishuInfo){
-                if(feishuInfo.getExpireTime().isBefore(LocalDateTime.now())){
-                        String tenantAccessToken = getTenantAccessToken(feishuInfo.getAppId());
-                        feishuInfo.setAccessToken(tenantAccessToken);
-                }
                 JSONObject result=new JSONObject();
                 String url = GET_CORP_INFO;
                 HttpHeaders headers = new HttpHeaders();
                 RestTemplate restTemplate = new RestTemplate();
                 MediaType type = MediaType.parseMediaType("application/json; charset=UTF-8");
                 headers.setContentType(type);
-                headers.add("Authorization","Bearer "+feishuInfo.getAccessToken());
+                headers.add("Authorization","Bearer "+getTenantAccessToken(feishuInfo.getAppId()));
                 HttpEntity<JSONObject> httpEntity = new HttpEntity<>(null, headers);
                 ResponseEntity<String> ResponseEntity = restTemplate.exchange(url,HttpMethod.GET,httpEntity,String.class);
                 if (ResponseEntity.getStatusCode() == HttpStatus.OK) {
@@ -152,17 +153,13 @@ public class FeishuInfoServiceImpl extends ServiceImpl<FeishuInfoMapper, FeishuI
 
         @Override
         public JSONObject getUserInfo(FeishuInfo feishuInfo, String feishuUserId){
-                if(feishuInfo.getExpireTime().isBefore(LocalDateTime.now())){
-                        String tenantAccessToken = getTenantAccessToken(feishuInfo.getAppId());
-                        feishuInfo.setAccessToken(tenantAccessToken);
-                }
                 JSONObject result=new JSONObject();
                 String url = GET_USER_INFO.replace(":user_id",feishuUserId);
                 HttpHeaders headers = new HttpHeaders();
                 RestTemplate restTemplate = new RestTemplate();
                 MediaType type = MediaType.parseMediaType("application/json; charset=UTF-8");
                 headers.setContentType(type);
-                headers.add("Authorization","Bearer "+feishuInfo.getAccessToken());
+                headers.add("Authorization","Bearer "+getTenantAccessToken(feishuInfo.getAppId()));
                 HttpEntity<JSONObject> httpEntity = new HttpEntity<>(null, headers);
                 ResponseEntity<String> ResponseEntity = restTemplate.exchange(url,HttpMethod.GET,httpEntity,String.class);
                 if (ResponseEntity.getStatusCode() == HttpStatus.OK) {
@@ -233,7 +230,7 @@ public class FeishuInfoServiceImpl extends ServiceImpl<FeishuInfoMapper, FeishuI
                 RestTemplate restTemplate = new RestTemplate();
                 MediaType type = MediaType.parseMediaType("application/json; charset=UTF-8");
                 headers.setContentType(type);
-                headers.add("Authorization","Bearer "+feishuInfo.getAccessToken());
+                headers.add("Authorization","Bearer "+getTenantAccessToken(feishuInfo.getAppId()));
                 HttpEntity<JSONObject> httpEntity = new HttpEntity<>(null, headers);
                 Map<String,Object> map=new HashMap<>();
                 map.put("fetch_child",0);
@@ -463,4 +460,24 @@ public class FeishuInfoServiceImpl extends ServiceImpl<FeishuInfoMapper, FeishuI
                 }
         }
 
+        @Override
+        public HttpRespMsg initSuperManager(String corpid, String name) {
+                HttpRespMsg msg = new HttpRespMsg();
+                FeishuInfo feishuInfo = feishuInfoMapper.selectById(corpid);
+                Integer companyId = feishuInfo.getCompanyId();
+                User user = userMapper.selectOne(new QueryWrapper<User>().eq("name", name).eq("company_id", companyId));
+                if (user == null) {
+                        //msg.setError("该用户不存在: " + name);
+                        msg.setError(MessageUtils.message("user.notExistsByParam",name));
+                } else {
+                        SysRole role = sysRoleMapper.selectOne(new QueryWrapper<SysRole>().eq("company_id", companyId).eq("rolename", "超级管理员"));
+                        user.setPhone(user.getName());
+                        user.setPassword(MD5Util.getPassword("000000"));
+                        user.setRoleId(role.getId());
+                        user.setRoleName(role.getRolename());
+                        userMapper.updateById(user);
+                }
+                return msg;
+        }
+
 }

+ 286 - 131
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ReportServiceImpl.java

@@ -1711,13 +1711,13 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
                 List<Report> updateReportList = new ArrayList<>();
                 //人员所属部门负责人审核或者直属领导审核
                 boolean hasAuditAllPri = sysFunctionService.hasPriviledge(user.getRoleId(), "审核全员日报");
-                List<Report> reportList = reportMapper.selectList(new QueryWrapper<Report>().select("id, state, group_audit_state, creator_id, create_date, project_id,audit_dept_managerid,department_audit_state, project_auditor_id").in("id", ids));
+                List<Report> reportList = reportMapper.selectList(new QueryWrapper<Report>().select("id, state, group_audit_state, creator_id, create_date, project_id,audit_dept_managerid,department_audit_state, project_auditor_id, is_dept_audit").in("id", ids));
                 for (Report r : reportList) {
                     //直属领导审核或者部门负责人审核
                     Report newReport = new Report();
                     newReport.setId(r.getId());
-                    if(hasAuditAllPri || ((r.getProjectAuditorId() != null &&  user.getId().equals(r.getProjectAuditorId()))
-                        || (r.getProjectAuditorId() == null && user.getId().equals(r.getAuditDeptManagerid())))){
+                    if(hasAuditAllPri || ((r.getIsDeptAudit() == 0 &&  user.getId().equals(r.getProjectAuditorId()))
+                        || (r.getIsDeptAudit() == 1 && user.getId().equals(r.getAuditDeptManagerid())))){
                         newReport.setState(1);
                         newReport.setDepartmentAuditState(1);
                         newReport.setProjectAuditState(1);
@@ -2781,14 +2781,14 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
                 List<Report> updateReportList = new ArrayList<>();
                 //人员所属部门负责人审核或者直属领导审核
                 boolean hasAuditAllPri = sysFunctionService.hasPriviledge(user.getRoleId(), "审核全员日报");
-                List<Report> reportList = reportMapper.selectList(new QueryWrapper<Report>().select("id, state, group_audit_state, creator_id, create_date, project_id,audit_dept_managerid,department_audit_state, project_auditor_id").in("id", ids));
+                List<Report> reportList = reportMapper.selectList(new QueryWrapper<Report>().select("id, state, group_audit_state, creator_id, create_date, project_id,audit_dept_managerid,department_audit_state, project_auditor_id, is_dept_audit").in("id", ids));
                 allReports = reportList;
                 for (Report r : reportList) {
                     //直属领导审核或者部门负责人审核
                     Report newReport = new Report();
                     newReport.setId(r.getId());
-                    if(hasAuditAllPri || ((r.getProjectAuditorId() != null &&  user.getId().equals(r.getProjectAuditorId()))
-                            || (r.getProjectAuditorId() == null && user.getId().equals(r.getAuditDeptManagerid())))){
+                    if(hasAuditAllPri || ((r.getIsDeptAudit() == 0 &&  user.getId().equals(r.getProjectAuditorId()))
+                            || (r.getIsDeptAudit() == 1 && user.getId().equals(r.getAuditDeptManagerid())))){
                         r.setState(1);
                         r.setDepartmentAuditState(1);
                         r.setProjectAuditState(1);
@@ -4159,10 +4159,10 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
 //            titles.add("项目分类");
             titles.add(MessageUtils.message("entry.serialNo"));
             titles.add(MessageUtils.message("entry.No"));
-            titles.add(MessageUtils.message("excel.staff"));
             for (int i = 0; i < userCustomList.size(); i++) {
                 titles.add(userCustomList.get(i).getName());
             }
+            titles.add(MessageUtils.message("excel.staff"));
             titles.add(MessageUtils.message("entry.department"));
             titles.add(MessageUtils.message("entry.projectId"));
             titles.add(MessageUtils.message("entry.projectName"));
@@ -4209,7 +4209,7 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
                 titles.add(MessageUtils.message("excel.inputStage"));
             }
             //每个日报的审批流程记录
-            List<ReportLogDetail> logDetails = new ArrayList<>();
+//            List<ReportLogDetail> logDetails = new ArrayList<>();
             if (timeType.getShowFillauditTime() == 1) {
 //                titles.add("填写时间");
 //                titles.add("项目审核人");
@@ -4219,7 +4219,7 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
                 titles.add(MessageUtils.message("excel.proReviewer"));
                 titles.add(MessageUtils.message("excel.auditTime"));
                 titles.add(MessageUtils.message("excel.auditProcess"));
-                logDetails = reportLogDetailMapper.selectList(new QueryWrapper<ReportLogDetail>().eq("company_id", company.getId()).between("work_date", startDate, endDate));
+//                logDetails = reportLogDetailMapper.selectList(new QueryWrapper<ReportLogDetail>().select("report_id, msg, operator_id, operate_date").eq("company_id", company.getId()).between("work_date", startDate, endDate));
             }
 
             //titles.add("工作事项");
@@ -4238,6 +4238,8 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
             //新增数据行 并且装填数据
             int rowNum = 1;
             List<HashMap<String, Object>> allReportByDate = null;
+
+            System.out.println("开始查询"+LocalDateTime.now().toString());
             List<SysRichFunction> functionList = sysFunctionMapper.getRoleFunctions(user.getRoleId(), "查看全公司工时");
             //获取部门的所有子部门
             List<Department> departments = departmentMapper.selectList(new QueryWrapper<Department>().eq("company_id",companyId));
@@ -4256,10 +4258,20 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
                 //检查是否是项目负责人
                 int cnt = projectMapper.selectCount(new QueryWrapper<Project>().eq("incharger_id", user.getId()));
                 if (cnt > 0) {
-                    reportsFromProjects = reportMapper.getProjectMembReportByDate(startDate, null, user.getId(), endDate, projectId,stateKey,branchDepartment);
+                    if (timeType.getShowFillauditTime() == 1) {
+                        reportsFromProjects = reportMapper.getProjectMembReportByDateWithReportLog(startDate, null, user.getId(), endDate, projectId,stateKey,branchDepartment);
+                    } else{
+                        reportsFromProjects = reportMapper.getProjectMembReportByDate(startDate, null, user.getId(), endDate, projectId,stateKey,branchDepartment);
+                    }
+
                 } else {
                     //普通员工只能看自己的
-                    reportsFromProjects = reportMapper.getAllReportByDate(startDate, null, user.getId(), endDate, projectId,stateKey,branchDepartment);
+                    if (timeType.getShowFillauditTime() == 1) {
+                        reportsFromProjects = reportMapper.getAllReportByDateWithReportLog(startDate, null, user.getId(), endDate, projectId,stateKey,branchDepartment);
+                    } else {
+                        reportsFromProjects = reportMapper.getAllReportByDate(startDate, null, user.getId(), endDate, projectId,stateKey,branchDepartment);
+                    }
+
                 }
                 if (allReportByDate == null) {
                     allReportByDate = reportsFromProjects;
@@ -4279,10 +4291,20 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
 //            }
             else {
                 //看公司所有人的
-                allReportByDate = reportMapper.getAllReportByDate(startDate, user.getCompanyId(), null, endDate, projectId,stateKey,branchDepartment);
+                allReportByDate = null;
+                if (timeType.getShowFillauditTime() == 1) {
+                    allReportByDate = reportMapper.getAllReportByDateWithReportLog(startDate, user.getCompanyId(), null, endDate, projectId,stateKey,branchDepartment);
+                } else {
+                    allReportByDate = reportMapper.getAllReportByDate(startDate, user.getCompanyId(), null, endDate, projectId,stateKey,branchDepartment);
+                }
             }
+            System.out.println("进度1"+LocalDateTime.now().toString());
             //获取企业微信考勤数据
-            List<UserCorpwxTime> userCorpwxTimeList = userCorpwxTimeMapper.selectList(new QueryWrapper<UserCorpwxTime>().eq("company_id", user.getCompanyId()).between("create_date", startDate, endDate));
+            List<UserCorpwxTime> userCorpwxTimeList = new ArrayList<>();
+            if(timeType.getSyncCorpwxTime()==1) {
+                userCorpwxTimeList = userCorpwxTimeMapper.selectList(new QueryWrapper<UserCorpwxTime>().eq("company_id", user.getCompanyId()).between("create_date", startDate, endDate));
+            }
+            System.out.println("进度2"+LocalDateTime.now().toString());
             if (timeType.getMultiWorktime() == 1) {
                 java.text.DecimalFormat df = new java.text.DecimalFormat("#0.00");
                 //重新处理一下数据,把工作时间和工作事项移出来
@@ -4325,14 +4347,14 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
                 }
                 allReportByDate = dealDataList;
             }
-            //HSSFRow条数范围限制0..65535
-            if (allReportByDate.size() > 60000) {
+            //07Excel HSSFRow条数范围限制0..1048576
+            if (allReportByDate.size() > 1048576) {
                 HttpRespMsg msg = new HttpRespMsg();
                 //msg.setError("数据量过大,请分时间段导出");
                 msg.setError(MessageUtils.message("data.OversizeError"));
                 return msg;
             }
-            DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
+            DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
             DecimalFormat df = new DecimalFormat("#0.0");
             int offsetSeconds = 0;
             if (company.getIsInternational() == 1) {
@@ -4358,6 +4380,9 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
                 }
             }
             List<User> userList = userMapper.selectList(new QueryWrapper<User>().eq("company_id", companyId));
+            System.out.println("进度3"+LocalDateTime.now().toString());
+            long t1 = System.currentTimeMillis();
+            DateTimeFormatter dft = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
             for (Map<String, Object> map : allReportByDate) {
                 List<String> item=new ArrayList<>();
                 item.add(String.valueOf(rowNum));
@@ -4392,6 +4417,7 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
                     item.add((String) map.get("name"));
                     item.add(departmentService.getSupDepartment(dept,departments));
                 }
+
                 item.add((String) map.get("projectCode"));
                 item.add((String) map.get("project"));
                 item.add((String) map.get("categoryName"));
@@ -4449,13 +4475,22 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
                     } else {
                         item.add(sdf.format((Date)map.get("projectAuditTime")));
                     }
-                    //审核流程显示
-                    List<ReportLogDetail> detailList = logDetails.stream().filter(log -> log.getReportId().equals((Integer) map.get("id"))).collect(Collectors.toList());
-                    if (detailList.size() > 0) {
-                        StringBuilder sb = new StringBuilder();
-                        boolean isFirst = true;
-                        for (ReportLogDetail audit:detailList) {
-                            LocalDateTime operateDate = audit.getOperateDate();
+
+                    StringBuilder sb = new StringBuilder();
+                    boolean isFirst = true;
+                    String logMsg = (String)map.get("logMsg");
+                    if (logMsg != null) {
+                        String[] logMsgs = logMsg.split("❤");
+                        for (String msgItem : logMsgs) {
+                            String[] splitItems = msgItem.split("@");
+                            //operator_id@operate_date@msg
+                            String operateDateStr = splitItems[1];
+                            LocalDateTime operateDate = LocalDateTime.parse(operateDateStr, dtf);
+                            ReportLogDetail audit = new ReportLogDetail();
+                            audit.setOperatorId(splitItems[0]);
+                            audit.setOperateDate(operateDate);
+                            audit.setMsg(splitItems[2]);
+
                             if (company.getIsInternational() == 1) {
                                 operateDate = operateDate.plusSeconds(offsetSeconds);
                             }
@@ -4488,10 +4523,90 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
                             }
                             sb.append(msg);
                         }
-                        item.add(sb.toString());
-                    } else {
-                        item.add("");
                     }
+                    //审核流程显示;//stream性能较差,换成for循环
+//                    for (int m=0; m <logDetails.size(); m++) {
+//                        ReportLogDetail audit = logDetails.get(m);
+//                        //仅处理当前日报的审核流程
+//                        if (audit.getReportId().intValue() == ((Integer)map.get("id")).intValue()) {
+//                            LocalDateTime operateDate = audit.getOperateDate();
+//                            if (company.getIsInternational() == 1) {
+//                                operateDate = operateDate.plusSeconds(offsetSeconds);
+//                            }
+//                            String time = dtf.format(operateDate);
+//                            String msg= "";
+//                            if(wxCorpInfo!=null&&wxCorpInfo.getSaasSyncContact()==1){
+//                                Optional<User> first = userList.stream().filter(ul -> ul.getId().equals(audit.getOperatorId())).findFirst();
+//                                if(first.isPresent()){
+//                                    if(audit.getMsg().contains("提交了")){
+//                                        int i = audit.getMsg().indexOf("提");
+//                                        String substring = audit.getMsg().substring(0, i);
+//                                        msg = time+" " + audit.getMsg().replaceAll(substring,"\\$userName="+first.get().getCorpwxUserid()+"\\$");
+//                                    }else if(audit.getMsg().contains("审核通过了")){
+//                                        int i = audit.getMsg().indexOf("审");
+//                                        String substring = audit.getMsg().substring(0, i);
+//                                        msg = time+" " + audit.getMsg().replaceAll(substring,"\\$userName="+first.get().getCorpwxUserid()+"\\$");
+//                                    }else if(audit.getMsg().contains("驳回了")) {
+//                                        int i = audit.getMsg().indexOf("驳");
+//                                        String substring = audit.getMsg().substring(0, i);
+//                                        msg = time+" " + audit.getMsg().replaceAll(substring,"\\$userName="+first.get().getCorpwxUserid()+"\\$");
+//                                    }
+//                                }
+//                            }else {
+//                                msg = time+" " + audit.getMsg();
+//                            }
+//                            if (!isFirst) {
+//                                sb.append("->");
+//                            } else {
+//                                isFirst = false;
+//                            }
+//                            sb.append(msg);
+//                            //去掉这条记录,减少下次循环的次数
+//                            logDetails.remove(m);
+//                            m--;//因为删除了一条记录,所以要减少一次循环
+//                        }
+//                    }
+                    item.add(sb.toString());
+//                    List<ReportLogDetail> detailList = logDetails.parallelStream().filter(log -> log.getReportId().equals((Integer) map.get("id"))).collect(Collectors.toList());
+//                    if (detailList.size() > 0) {
+//                        for (ReportLogDetail audit:detailList) {
+//                            LocalDateTime operateDate = audit.getOperateDate();
+//                            if (company.getIsInternational() == 1) {
+//                                operateDate = operateDate.plusSeconds(offsetSeconds);
+//                            }
+//                            String time = dtf.format(operateDate);
+//                            String msg= "";
+//                            if(wxCorpInfo!=null&&wxCorpInfo.getSaasSyncContact()==1){
+//                                Optional<User> first = userList.stream().filter(ul -> ul.getId().equals(audit.getOperatorId())).findFirst();
+//                                if(first.isPresent()){
+//                                    if(audit.getMsg().contains("提交了")){
+//                                        int i = audit.getMsg().indexOf("提");
+//                                        String substring = audit.getMsg().substring(0, i);
+//                                        msg = time+" " + audit.getMsg().replaceAll(substring,"\\$userName="+first.get().getCorpwxUserid()+"\\$");
+//                                    }else if(audit.getMsg().contains("审核通过了")){
+//                                        int i = audit.getMsg().indexOf("审");
+//                                        String substring = audit.getMsg().substring(0, i);
+//                                        msg = time+" " + audit.getMsg().replaceAll(substring,"\\$userName="+first.get().getCorpwxUserid()+"\\$");
+//                                    }else if(audit.getMsg().contains("驳回了")) {
+//                                        int i = audit.getMsg().indexOf("驳");
+//                                        String substring = audit.getMsg().substring(0, i);
+//                                        msg = time+" " + audit.getMsg().replaceAll(substring,"\\$userName="+first.get().getCorpwxUserid()+"\\$");
+//                                    }
+//                                }
+//                            }else {
+//                                msg = time+" " + audit.getMsg();
+//                            }
+//                            if (!isFirst) {
+//                                sb.append("->");
+//                            } else {
+//                                isFirst = false;
+//                            }
+//                            sb.append(msg);
+//                        }
+//                        item.add(sb.toString());
+//                    } else {
+//                        item.add("");
+//                    }
                 }
                 item.add((String) map.get("content"));
                 if(stateKey==1){
@@ -4580,10 +4695,14 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
                 dataList.add(item);
                 rowNum++;
             }
+            System.out.println("进度4"+LocalDateTime.now().toString());
+            long t2 = System.currentTimeMillis();
+            System.out.println("计算耗时:"+(t2-t1)+", 共"+rowNum+"条数据");
             //生成Excel文件
             //String fileUrlSuffix = (startDate==null?"":(startDate+"至"+endDate))+"工作日报" + System.currentTimeMillis() + ".xls";
-            String fileUrlSuffix = (startDate==null?"":(startDate+MessageUtils.message("leave.to")+endDate))+MessageUtils.message("excel.workReport") + System.currentTimeMillis() + ".xls";
+            String fileUrlSuffix = (startDate==null?"":(startDate+MessageUtils.message("leave.to")+endDate))+MessageUtils.message("excel.workReport") + System.currentTimeMillis();
             httpRespMsg = excelExportService.exportGeneralExcelByTitleAndList(wxCorpInfo,fileUrlSuffix,dataList,path);
+            System.out.println("进度5, 导出结束"+LocalDateTime.now().toString());
         } catch (NullPointerException e) {
             //httpRespMsg.setError("验证失败或缺少数据");
             httpRespMsg.setError(MessageUtils.message("access.verErrorOrDataLack"));
@@ -5874,7 +5993,7 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
     }
 
     @Override
-    public HttpRespMsg getAIReport(String date, HttpServletRequest request) {
+    public HttpRespMsg getAIReport(HttpServletRequest request) {
         HttpRespMsg msg = new HttpRespMsg();
         String userId = request.getHeader("token");
         Integer companyId = userMapper.selectById(userId).getCompanyId();
@@ -5883,134 +6002,170 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
         QueryWrapper<Report> queryWrapper = new QueryWrapper<>();
         queryWrapper.eq("creator_id",userId).orderByDesc("id").last("limit 1");
         Report report = reportMapper.selectOne(queryWrapper);
+        List<Project> allProjectList = projectMapper.selectList(new QueryWrapper<Project>()
+                .eq("company_id", companyId).eq("status", 1));
+        List<Report> reports = new ArrayList<>();
         if (report != null) {
             queryWrapper = new QueryWrapper<>();
             queryWrapper.eq("creator_id", userId).eq("create_date", report.getCreateDate());
             //获取最近填写的那一天的全部日报
-            List<Report> reports = reportMapper.selectList(queryWrapper);
-            List<Project> allProjectList = projectMapper.selectList(new QueryWrapper<Project>()
-                    .eq("company_id", companyId).eq("status", 1));
+            reports = reportMapper.selectList(queryWrapper);
             //仅保留进行中的项目的日报
             reports = reports.stream().filter(r->allProjectList.stream().anyMatch(p->p.getId().equals(r.getProjectId()))).collect(Collectors.toList());
-            try {
-                List<Integer> integerList = reports.stream().map(Report::getProjectId).collect(Collectors.toList());
-                //开启状态的子项目
-                List<SubProject> subProjects = subProjectMapper.selectList(new QueryWrapper<SubProject>().in("project_id", integerList).eq("status", 1));
-                List<SubProject> subProjectList = integerList.size() > 0?subProjects:new ArrayList<>();
-                List<ProjectAuditor> auditorList = integerList.size() > 0?projectAuditorMapper.selectList(new QueryWrapper<ProjectAuditor>().in("project_id", integerList)): new ArrayList<>();
-                List<Profession> professions = professionMapper.selectList(new QueryWrapper<Profession>().eq("company_id", companyId));
-                List<ReportExtraDegree> degreeList = reportExtraDegreeMapper.selectList(new QueryWrapper<ReportExtraDegree>().eq("company_id", companyId));
-                List<TaskGroup> taskGroups = integerList.size() > 0?taskGroupMapper.selectList(new QueryWrapper<TaskGroup>().in("project_id", integerList)):new ArrayList<>();
-                List<Stages> stagesList = integerList.size() > 0?stagesMapper.selectList(new QueryWrapper<Stages>().in("project_id", integerList)) : new ArrayList<>();
-                //获取当前项目的子项目列表,任务分组,任务列表,项目相关维度列表
-                reports.forEach(r->{
-                    r.setContent(null);
-                    r.setSubProjectList(subProjectList.stream().filter(s->s.getProjectId().equals(r.getProjectId())).collect(Collectors.toList()));
-                    r.setTaskList(taskMapper.recentSimpleList(r.getProjectId(), userId));
-                    //获取当前项目的工程专业进度
-                    List<ReportProfessionProgress> progressList = reportProfessionProgressService.list(new QueryWrapper<ReportProfessionProgress>().eq("report_id", r.getId()));
-                    //去掉当前项目上已经不存在的专业
-                    List<ProjectProfession> projectProfessions = projectProfessionMapper.selectList(new QueryWrapper<ProjectProfession>().eq("project_id", r.getProjectId()));
-                    progressList = progressList.stream().filter(p->projectProfessions.stream().anyMatch(pp->pp.getProfessionId().equals(p.getProfessionId()))).collect(Collectors.toList());
-                    progressList.stream().forEach(p->{
-                        p.setProfessionName(professions.stream().filter(m->m.getId().equals(p.getProfessionId())).findFirst().get().getName());
-                    });
-                    r.setProfessionProgressList(progressList);
-                    //获取任务阶段列表
-                    if (company.getPackageProject() == 1 && r.getGroupId() != null && r.getGroupId() != 0) {
-                        r.setStages(stagesList.stream().filter(s->s.getGroupId() !=null && s.getGroupId().equals(r.getGroupId())).collect(Collectors.toList()));
+        } else {
+            //没有填写过日报,获取该员工参与的项目
+            List<Participation> participationList = participationMapper.selectList(new QueryWrapper<Participation>().eq("user_id", userId));
+            List<Integer> projectIds = participationList.stream().map(Participation::getProjectId).collect(Collectors.toList());
+            projectIds = projectIds.stream().filter(pid->allProjectList.stream().anyMatch(p->p.getId().equals(pid))).collect(Collectors.toList());
+            //仅保留进行中的项目的日报
+            if (projectIds.size() == 0) {
+                //无参与的项目的话,则查找公共项目
+                List<Project> pubProjectList = projectMapper.selectList(new QueryWrapper<Project>().eq("company_id", companyId).eq("is_public", 1).eq("status", 1));
+                projectIds = pubProjectList.stream().map(Project::getId).collect(Collectors.toList());
+            }
+            if (projectIds.size() > 0) {
+                Report recentFillReport = reportMapper.selectOne(new QueryWrapper<Report>().in("project_id", projectIds).orderByDesc("id").last("limit 1"));
+                Float allday = timeTypeMapper.selectById(companyId).getAllday();
+                if (recentFillReport != null) {
+                    recentFillReport.setContent(null);
+                    recentFillReport.setWorkingTime(allday.doubleValue());
+                    reports.add(recentFillReport);
+                } else {
+                    recentFillReport = new Report();
+                    recentFillReport.setWorkingTime(allday.doubleValue());
+                    Project recentProject = projectMapper.selectOne(new QueryWrapper<Project>().in("id", projectIds).orderByDesc("id").last("limit 1"));
+                    if (recentProject != null) {
+                        recentFillReport.setProjectId(recentProject.getId());
                     }
+                    reports.add(recentFillReport);
+                }
+            } else {
+                msg.setError("请先设置参与的项目");
+                return msg;
+            }
+        }
+        try {
+            List<Integer> integerList = reports.stream().map(Report::getProjectId).collect(Collectors.toList());
+            //开启状态的子项目
+            List<SubProject> subProjects = subProjectMapper.selectList(new QueryWrapper<SubProject>().in("project_id", integerList).eq("status", 1));
+            List<SubProject> subProjectList = integerList.size() > 0?subProjects:new ArrayList<>();
+            List<ProjectAuditor> auditorList = integerList.size() > 0?projectAuditorMapper.selectList(new QueryWrapper<ProjectAuditor>().in("project_id", integerList)): new ArrayList<>();
+            List<Profession> professions = professionMapper.selectList(new QueryWrapper<Profession>().eq("company_id", companyId));
+            List<ReportExtraDegree> degreeList = reportExtraDegreeMapper.selectList(new QueryWrapper<ReportExtraDegree>().eq("company_id", companyId));
+            List<TaskGroup> taskGroups = integerList.size() > 0?taskGroupMapper.selectList(new QueryWrapper<TaskGroup>().in("project_id", integerList)):new ArrayList<>();
+            List<Stages> stagesList = integerList.size() > 0?stagesMapper.selectList(new QueryWrapper<Stages>().in("project_id", integerList)) : new ArrayList<>();
+            //获取当前项目的子项目列表,任务分组,任务列表,项目相关维度列表
+            reports.forEach(r->{
+                r.setContent(null);
+                r.setSubProjectList(subProjectList.stream().filter(s->s.getProjectId().equals(r.getProjectId())).collect(Collectors.toList()));
+                r.setTaskList(taskMapper.recentSimpleList(r.getProjectId(), userId));
+                //获取当前项目的工程专业进度
+                List<ReportProfessionProgress> progressList = reportProfessionProgressService.list(new QueryWrapper<ReportProfessionProgress>().eq("report_id", r.getId()));
+                //去掉当前项目上已经不存在的专业
+                List<ProjectProfession> projectProfessions = projectProfessionMapper.selectList(new QueryWrapper<ProjectProfession>().eq("project_id", r.getProjectId()));
+                progressList = progressList.stream().filter(p->projectProfessions.stream().anyMatch(pp->pp.getProfessionId().equals(p.getProfessionId()))).collect(Collectors.toList());
+                progressList.stream().forEach(p->{
+                    p.setProfessionName(professions.stream().filter(m->m.getId().equals(p.getProfessionId())).findFirst().get().getName());
+                });
+                r.setProfessionProgressList(progressList);
+                //获取任务阶段列表
+                if (company.getPackageProject() == 1 && r.getGroupId() != null && r.getGroupId() != 0) {
+                    r.setStages(stagesList.stream().filter(s->s.getGroupId() !=null && s.getGroupId().equals(r.getGroupId())).collect(Collectors.toList()));
+                }
 
-                    //处理维度列表数据
-                    if (timeTypeMapper.selectById(companyId).getCustomDegreeActive() == 1) {
-                        Project project = allProjectList.stream().filter(p -> p.getId().equals(r.getProjectId())).findFirst().get();
-                        String associateDegrees = project.getAssociateDegrees();
-                        List<HashMap> degreeMapList = new ArrayList<>();
-                        if (associateDegrees != null) {
-                            String[] split = associateDegrees.split("\\,");
-                            for (int i=0;i<split.length; i++) {
-                                HashMap map = new HashMap();
-                                if (!StringUtils.isEmpty(split[i])) {
-                                    Integer id = Integer.parseInt(split[i]);
-                                    map.put("id", id);
-                                    map.put("name", degreeList.stream().filter(d->d.getId().equals(id)).findFirst().get().getName());
-                                    degreeMapList.add(map);
-                                }
+                //处理维度列表数据
+                if (timeTypeMapper.selectById(companyId).getCustomDegreeActive() == 1) {
+                    Project project = allProjectList.stream().filter(p -> p.getId().equals(r.getProjectId())).findFirst().get();
+                    String associateDegrees = project.getAssociateDegrees();
+                    List<HashMap> degreeMapList = new ArrayList<>();
+                    if (associateDegrees != null) {
+                        String[] split = associateDegrees.split("\\,");
+                        for (int i=0;i<split.length; i++) {
+                            HashMap map = new HashMap();
+                            if (!StringUtils.isEmpty(split[i])) {
+                                Integer id = Integer.parseInt(split[i]);
+                                map.put("id", id);
+                                map.put("name", degreeList.stream().filter(d->d.getId().equals(id)).findFirst().get().getName());
+                                degreeMapList.add(map);
                             }
                         }
-                        r.setDegreeList(degreeMapList);
                     }
-                    int reportAuditType = timeTypeMapper.selectById(companyId).getReportAuditType();
-                    //分组
-                    if (company.getPackageProject() == 1) {
-                        if (reportAuditType == 0) {
-                            r.setTaskGroups(taskGroups.stream().filter(tg->tg.getProjectId().equals(r.getProjectId())).collect(Collectors.toList()));
+                    r.setDegreeList(degreeMapList);
+                }
+                int reportAuditType = timeTypeMapper.selectById(companyId).getReportAuditType();
+                //分组
+                if (company.getPackageProject() == 1) {
+                    //分组负责人审核的情况,按人员所在分组来加载
+                    if (reportAuditType == 1 || reportAuditType == 2){
+                        List<GroupParticipator> groupParticipatorList = groupParticipatorMapper.selectList(new QueryWrapper<GroupParticipator>());
+                        if (groupParticipatorList.size() > 0) {
+                            List<Integer> groupIds = groupParticipatorList.stream().map(GroupParticipator::getGroupId).collect(Collectors.toList());
+                            List<TaskGroup> findGroups = taskGroups.stream().filter(tg->groupIds.contains(tg.getId()) || userId.equals(tg.getInchargerId())).collect(Collectors.toList());
+                            r.setTaskGroups(findGroups);
                             if (r.getGroupId() != null && r.getGroupId() != 0) {
                                 Optional<TaskGroup> optinal = taskGroups.stream().filter(tg->tg.getId().equals(r.getGroupId())).findFirst();
                                 if (optinal.isPresent()) {
                                     r.setGroupName(optinal.get().getName());
                                 }
                             }
-                        } else if (reportAuditType == 1 || reportAuditType == 2){
-                            List<GroupParticipator> groupParticipatorList = groupParticipatorMapper.selectList(new QueryWrapper<GroupParticipator>());
-                            if (groupParticipatorList.size() > 0) {
-                                List<Integer> groupIds = groupParticipatorList.stream().map(GroupParticipator::getGroupId).collect(Collectors.toList());
-                                List<TaskGroup> findGroups = taskGroups.stream().filter(tg->groupIds.contains(tg.getId()) || userId.equals(tg.getInchargerId())).collect(Collectors.toList());
-                                r.setTaskGroups(findGroups);
-                                if (r.getGroupId() != null && r.getGroupId() != 0) {
-                                    Optional<TaskGroup> optinal = taskGroups.stream().filter(tg->tg.getId().equals(r.getGroupId())).findFirst();
-                                    if (optinal.isPresent()) {
-                                        r.setGroupName(optinal.get().getName());
-                                    }
-                                }
+                        }
+                    } else {
+                        //其他情况加载全部任务分组
+                        r.setTaskGroups(taskGroups.stream().filter(tg->tg.getProjectId().equals(r.getProjectId())).collect(Collectors.toList()));
+                        if (r.getGroupId() != null && r.getGroupId() != 0) {
+                            Optional<TaskGroup> optinal = taskGroups.stream().filter(tg->tg.getId().equals(r.getGroupId())).findFirst();
+                            if (optinal.isPresent()) {
+                                r.setGroupName(optinal.get().getName());
                             }
                         }
                     }
-                    //项目的审核人
-                    if (reportAuditType == 0) {
-                        r.setAuditUserList(auditorList.stream().filter(au->au.getProjectId().equals(r.getProjectId())).collect(Collectors.toList()));
-                        if (r.getProjectAuditorId() != null) {
-                            Optional<ProjectAuditor> auItem = auditorList.stream().filter(au->au.getAuditorId().equals(r.getProjectAuditorId())).findFirst();
-                            if (auItem.isPresent()) {
-                                r.setProjectAuditorName(auItem.get().getAuditorName());
-                            }
+                }
+                //项目的审核人
+                if (reportAuditType == 0) {
+                    r.setAuditUserList(auditorList.stream().filter(au->au.getProjectId().equals(r.getProjectId())).collect(Collectors.toList()));
+                    if (r.getProjectAuditorId() != null) {
+                        Optional<ProjectAuditor> auItem = auditorList.stream().filter(au->au.getAuditorId().equals(r.getProjectAuditorId())).findFirst();
+                        if (auItem.isPresent()) {
+                            r.setProjectAuditorName(auItem.get().getAuditorName());
                         }
-                    } else if (reportAuditType == 1 || reportAuditType == 2) {
-                        if (r.getGroupId() != null && r.getGroupId() != 0) {
-                            //直接获取分组的负责人作为审核人
-                            Optional<TaskGroup> tgoup = taskGroups.stream().filter(tg->tg.getId().equals(r.getGroupId())).findFirst();
-                            if (tgoup.isPresent()) {
-                                TaskGroup curGroup = tgoup.get();
-                                if (curGroup.getInchargerId() != null) {
-                                    User user = userMapper.selectById(curGroup.getInchargerId());
-                                    HashMap map = new HashMap();
-                                    map.put("auditorId", user.getId());
-                                    map.put("auditorName", user.getName());
-                                    List list = new ArrayList();
-                                    list.add(map);
-                                    r.setAuditUserList(list);
-                                    if (r.getProjectAuditorId() != null) {
-                                        r.setProjectAuditorName(user.selectById(r.getProjectAuditorId()).getName());
-                                    }
+                    }
+                } else if (reportAuditType == 1 || reportAuditType == 2) {
+                    if (r.getGroupId() != null && r.getGroupId() != 0) {
+                        //直接获取分组的负责人作为审核人
+                        Optional<TaskGroup> tgoup = taskGroups.stream().filter(tg->tg.getId().equals(r.getGroupId())).findFirst();
+                        if (tgoup.isPresent()) {
+                            TaskGroup curGroup = tgoup.get();
+                            if (curGroup.getInchargerId() != null) {
+                                User user = userMapper.selectById(curGroup.getInchargerId());
+                                HashMap map = new HashMap();
+                                map.put("auditorId", user.getId());
+                                map.put("auditorName", user.getName());
+                                List list = new ArrayList();
+                                list.add(map);
+                                r.setAuditUserList(list);
+                                if (r.getProjectAuditorId() != null) {
+                                    r.setProjectAuditorName(user.selectById(r.getProjectAuditorId()).getName());
                                 }
                             }
                         }
-                    } else if (reportAuditType == 3) {
-                        //获取日报对应已经设置好的审核人和抄送人
-                        r.setAuditorSetting(reportAuditorSettingMapper.selectById(r.getId()));
                     }
-                });
-                msg.data = reports;
-            } catch (NullPointerException e) {
-                e.printStackTrace();
-                //httpRespMsg.setError("验证失败");
-                msg.setError(MessageUtils.message("Company.validationError"));
-                return msg;
-            } catch (DateTimeParseException e) {
-                //httpRespMsg.setError("日期格式有误");
-                msg.setError(MessageUtils.message("date.formatError"));
-                return msg;
-            }
+                } else if (reportAuditType == 3) {
+                    //获取日报对应已经设置好的审核人和抄送人
+                    r.setAuditorSetting(reportAuditorSettingMapper.selectById(r.getId()));
+                } else {
+                    //4和5是所属BU负责人审核和部门负责人审核,不需要前端页面显示审核人
+                }
+            });
+            msg.data = reports;
+        } catch (NullPointerException e) {
+            e.printStackTrace();
+            //httpRespMsg.setError("验证失败");
+            msg.setError(MessageUtils.message("Company.validationError"));
+            return msg;
+        } catch (DateTimeParseException e) {
+            //httpRespMsg.setError("日期格式有误");
+            msg.setError(MessageUtils.message("date.formatError"));
+            return msg;
         }
 
         return msg;

+ 32 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/task/SFTPAsyncUploader.java

@@ -0,0 +1,32 @@
+package com.management.platform.task;
+
+import com.management.platform.util.SFTPUploader;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.stereotype.Component;
+import java.io.File;
+import javax.annotation.PostConstruct;
+
+@Component
+public class SFTPAsyncUploader {
+
+    private final SFTPUploader sftpUploader;
+
+    public SFTPAsyncUploader(SFTPUploader sftpUploader) {
+        this.sftpUploader = sftpUploader;
+    }
+
+    @PostConstruct
+    public void init() {
+//        new File("uploads").mkdirs(); // 创建上传目录
+    }
+
+    @Async
+    public void uploadFileAsync(File file) {
+        try {
+            sftpUploader.uploadFile(file);
+            System.out.println("File " + file.getName() + " has been uploaded.");
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+}

+ 19 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/task/TimingTask.java

@@ -30,6 +30,7 @@ import org.springframework.web.client.DefaultResponseErrorHandler;
 import org.springframework.web.client.RestTemplate;
 
 import javax.annotation.Resource;
+import java.io.File;
 import java.io.IOException;
 import java.math.BigDecimal;
 import java.security.SecureRandom;
@@ -141,6 +142,24 @@ public class TimingTask {
         /*IntStream.rangeClosed('!', '*').forEach(VALID_TOKEN_CHARS::add);    // !-**/
     }
 
+    //每天凌晨5点10删除导出的临时文件
+    @Scheduled(cron = "0 10 05 ? * *")
+    private void deleteExportFile() {
+        if (isDev) return;
+        System.out.println("删除导出的临时文件");
+        File pathRoot = new File(path);
+        File[] files = pathRoot.listFiles();
+        //遍历files,删除名称匹配规则为以任意开头以十三位数字加.xls或.xlsx结尾的文件
+        for (File file : files) {
+            if (file.getName().matches("^[\\s\\S]*\\d{13}\\.xls[x]?$")) {
+                //删除一天前的导出文件
+                if (file.lastModified() < System.currentTimeMillis() - 24 * 60 * 60 * 1000) {
+                    file.delete();
+                }
+            }
+        }
+    }
+
     //检查项目到期,距离到期时间3天内的,每天提醒
     @Scheduled(cron = "0 0 10 ? * *")
     private void projectDeadlineAlert() {

+ 63 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/util/SFTPUploader.java

@@ -0,0 +1,63 @@
+package com.management.platform.util;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import com.jcraft.jsch.ChannelSftp;
+import com.jcraft.jsch.JSch;
+import com.jcraft.jsch.Session;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+@Component
+public class SFTPUploader {
+    @Value("${sftp.isEnabled}")
+    private boolean isEnabled;
+    @Value("${sftp.server}")
+    private String server;
+
+    @Value("${sftp.port}")
+    private int port;
+    @Value("${sftp.remoteDir}")
+    private String remoteDir;
+
+    @Value("${sftp.user}")
+    private String user;
+
+    @Value("${sftp.password}")
+    private String password;
+
+    public void uploadFile(File file) throws Exception {
+        if (!isEnabled) {
+            System.out.println("sftp is not enabled, please set sftp.isEnabled=true in application.properties");
+            return;
+        }
+        JSch jsch = new JSch();
+        Session session = null;
+        ChannelSftp sftpChannel = null;
+        FileInputStream inputStream = null;
+        try {
+            session = jsch.getSession(user, server, port);
+            session.setPassword(password);
+            session.setConfig("StrictHostKeyChecking", "no");
+            session.connect();
+
+            sftpChannel = (ChannelSftp) session.openChannel("sftp");
+            sftpChannel.connect();
+
+            String remoteFilePath = (remoteDir.endsWith("/")?remoteDir: (remoteDir + "/")) + file.getName();
+            inputStream = new FileInputStream(file);
+
+            sftpChannel.put(inputStream, remoteFilePath);
+        } finally {
+            if (inputStream != null) {
+                inputStream.close();
+            }
+            if (sftpChannel != null) {
+                sftpChannel.disconnect();
+            }
+            if (session != null) {
+                session.disconnect();
+            }
+        }
+    }
+}

+ 39 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/util/TestSample.java

@@ -0,0 +1,39 @@
+package com.management.platform.util;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ForkJoinPool;
+
+public class TestSample {
+    public static void main(String[] args) {
+        /* 创建数组,用来构建不同大小的List */
+        Integer[] intArr = new Integer[200];
+        List<Integer> intList = Arrays.asList(intArr);
+
+        List<Integer> forList = new ArrayList<>();
+        List<Integer> streamForList = new ArrayList<>();
+        List<Integer> parallelStreamForList = new ArrayList<>();
+
+
+        intList.forEach(l -> forList.add(l));
+        intList.stream().forEach(l -> streamForList.add(l));
+        ForkJoinPool forkJoinPool1 = new ForkJoinPool(Runtime.getRuntime().availableProcessors());
+        CountDownLatch countDownLatch = new CountDownLatch(2);
+        forkJoinPool1.submit(() -> {
+            intList.parallelStream().forEach(l -> parallelStreamForList.add(l));
+            countDownLatch.countDown();
+        });
+//        intList.parallelStream().forEach(l -> parallelStreamForList.add(l));
+//        try {
+//            countDownLatch.await();
+//        } catch (InterruptedException e) {
+//            throw new RuntimeException(e);
+//        }
+
+        System.out.println(forList.size() + "---普通for循环数组");
+        System.out.println(streamForList.size() + "---stream流for循环数组");
+        System.out.println(parallelStreamForList.size() + "---parallelStream流for循环数组");
+    }
+}

+ 9 - 1
fhKeeper/formulahousekeeper/management-platform/src/main/resources/application-prod.yml

@@ -102,4 +102,12 @@ management:
       enabled: false
 
 configEnv:
-  isDev: false
+  isDev: false
+# SFTP上传配置
+sftp:
+  isEnabled: true
+  server: 101.132.166.205
+  port: 22022
+  remoteDir: /bkup/timesheet
+  user: root
+  password: Huoshi@2022

+ 9 - 3
fhKeeper/formulahousekeeper/management-platform/src/main/resources/application.yml

@@ -15,7 +15,7 @@ spring:
       location: C:/upload/
   datasource:
     driver-class-name: com.mysql.cj.jdbc.Driver
-    url: jdbc:mysql://47.101.180.183:3306/man_dev?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&rewriteBatchedStatements=true&useSSL=false
+    url: jdbc:mysql://47.101.180.183:3306/man_hour_manager?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&rewriteBatchedStatements=true&useSSL=false
     username: root
     password: HuoshiDB@2022
     hikari:
@@ -150,6 +150,12 @@ privateDeployURL:
   pcUrl: http://dev.huoshishanxin.com/#/
   mobUrl: http://dev.huoshishanxin.com/#/
 
-
-
+# SFTP上传配置
+sftp:
+  isEnabled: false
+  server: 101.132.166.205
+  port: 22022
+  remoteDir: /bkup/timesheet
+  user: root
+  password: Huoshi@2022
 

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

@@ -108,6 +108,61 @@
         ORDER BY a.creator_id, a.create_date desc
     </select>
 
+    <select id="getAllReportByDateWithReportLog" resultType="java.util.Map">
+        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,a.is_dept_audit as isDeptAudit,a.group_audit_state as groupAuditState,task_group.incharger_id as inchargerId,a.project_audit_state as projectAuditState,a.audit_dept_managerid as deptAuditorName
+        ,c.plate1 as plate1,c.plate2 as plate2,c.plate3 as plate3,c.plate4 as plate4,c.plate5 as plate5
+        , reject_reason as rejectReason, reject_username as rejectUsername, reject_userid as rejectUserid, degree_id as degree_id,report_extra_degree.name as degreeName,task_group.name as groupName,a.group_id as groupId,a.custom_data as customData
+        ,u.name as projectAuditorName,u.corpwx_userid as projectAuditorCorpwxUserId, a.project_auditor_id as projectAuditorId, department.department_name as departmentName,dp2.department_name as buDepartmentName,department.department_id as departmentId, a.overtime_hours as overtimeHours, a.custom_text as customText,a.project_audit_time  as projectAuditTime,project_main.name as projectMainName,
+        GROUP_CONCAT(rlog.operator_id,'@', rlog.operate_date,'@', rlog.msg SEPARATOR '❤') AS logMsg
+        FROM report AS a
+        JOIN project AS b ON a.project_id=b.id
+        LEFT JOIN user AS c ON a.creator_id=c.id
+        left join sub_project as d on d.id = a.sub_project_id
+        left join task on task.id = a.task_id
+        left join report_extra_degree on report_extra_degree.id = a.degree_id
+        left join task_group on task_group.id = a.group_id
+        left join user u on u.id = a.project_auditor_id
+        left join department on department.department_id = c.department_id
+        left join department dp2 on dp2.department_id = b.bu_id
+        left join project_main on b.project_main_id=project_main.id
+        left join report_log_detail rlog on rlog.report_id = a.id
+        WHERE (<if test="stateKey == null or stateKey == 0">
+        a.state = 1
+    </if>
+        <if test="stateKey!=null">
+            <if test="stateKey==1">
+                (a.state = 1 or a.state = 0 or a.state = -1)
+            </if>
+            <if test="stateKey==2">
+                (a.state=0 or a.state = -1)
+            </if>
+        </if>)
+        <if test="startDate != null and startDate != ''">
+            AND a.create_date between #{startDate} and #{endDate}
+        </if>
+        <if test="projectId != null">
+            AND a.project_id = #{projectId}
+        </if>
+        <if test="companyId != null">
+            AND c.company_id = #{companyId}
+        </if>
+        <if test="userId != null">
+            AND a.creator_id = #{userId}
+        </if>
+        <if test="branchDepartment != null">
+            AND department.department_id in
+            <foreach collection="branchDepartment" item="deptId" separator="," close=")" open="(" index="index">
+                #{deptId}
+            </foreach>
+        </if>
+        group by a.id
+        ORDER BY a.creator_id, a.create_date desc
+    </select>
+
+
     <select id="geReportByProject" resultType="java.util.Map">
         SELECT project_main.name as projectMainName,project_main.code as projectMainCode,
         b.project_name as project,b.project_code as projectCode,
@@ -212,7 +267,66 @@
         </if>
         ORDER BY a.creator_id, a.create_date desc
     </select>
-
+    <select id="getProjectMembReportByDateWithReportLog" resultType="java.util.Map">
+        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,
+        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,a.is_dept_audit as isDeptAudit,a.group_audit_state as groupAuditState,task_group.incharger_id as inchargerId,a.project_audit_state as projectAuditState,a.audit_dept_managerid as deptAuditorName
+        , reject_reason as rejectReason, reject_username as rejectUsername, reject_userid as rejectUserid, degree_id as
+        degree_id,report_extra_degree.name as degreeName,task_group.name as groupName,a.group_id as groupId,
+        a.custom_data as customData
+        ,c.plate1 as plate1,c.plate2 as plate2,c.plate3 as plate3,c.plate4 as plate4,c.plate5 as plate5
+        ,u.name as projectAuditorName,u.corpwx_userid as projectAuditorCorpwxUserId, a.project_auditor_id as projectAuditorId, department.department_name as
+        departmentName,dp2.department_name as buDepartmentName,department.department_id as departmentId, a.overtime_hours as overtimeHours, a.custom_text as customText, a.project_audit_time as
+        projectAuditTime,project_main.name as projectMainName,
+        GROUP_CONCAT(rlog.operator_id,'@', rlog.operate_date,'@', rlog.msg SEPARATOR '❤') AS logMsg
+        FROM report AS a
+        JOIN project AS b ON a.project_id=b.id
+        LEFT JOIN user AS c ON a.creator_id=c.id
+        left join sub_project as d on d.id = a.sub_project_id
+        left join task on task.id = a.task_id
+        left join report_extra_degree on report_extra_degree.id = a.degree_id
+        left join task_group on task_group.id = a.group_id
+        left join user u on u.id = a.project_auditor_id
+        left join department on department.department_id = c.department_id
+        left join department dp2 on dp2.department_id = b.bu_id
+        left join project_main on project_main.id=b.project_main_id
+        left join report_log_detail rlog on rlog.report_id = a.id
+        WHERE
+        (<if test="stateKey == null or stateKey == 0">
+        a.state = 1
+    </if>
+        <if test="stateKey!=null">
+            <if test="stateKey==1">
+                (a.state = 1 or a.state=0 or a.state = -1)
+            </if>
+            <if test="stateKey==2">
+                (a.state=0 or a.state = -1)
+            </if>
+        </if>)
+        <if test="startDate != null and startDate != ''">
+            AND a.create_date between #{startDate} and #{endDate}
+        </if>
+        <if test="companyId != null">
+            AND c.company_id = #{companyId}
+        </if>
+        <if test="projectId != null">
+            AND a.project_id = #{projectId}
+        </if>
+        <if test="leaderId != null">
+            AND (b.incharger_id = #{leaderId} or a.creator_id=#{leaderId})
+        </if>
+        <if test="branchDepartment != null">
+            AND department.department_id in
+            <foreach collection="branchDepartment" item="deptId" separator="," close=")" open="(" index="index">
+                #{deptId}
+            </foreach>
+        </if>
+        group by a.id
+        ORDER BY a.creator_id, a.create_date desc
+    </select>
     <select id="getDeptMembReportByDate" resultType="java.util.Map">
         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,
@@ -706,16 +820,18 @@
     </select>
     <select id="getProWaitingApproveCnt" resultType="java.util.HashMap">
         select count(1) as num, user.dingding_userid as auditorDDId ,user.corpwx_userid as corpwxUserid from report
-         left join user on user.id = project_auditor_id
+         left join `user` on `user`.id = project_auditor_id
          where state = 0 and project_audit_state = 0 and is_dept_audit = 0
         and report.company_id = #{companyId}
+        and `user`.is_active=1
         group by project_auditor_id
     </select>
     <select id="getDeptWaitingApproveCnt" resultType="java.util.HashMap">
         select COUNT(1) as num, user.dingding_userid as auditorDDId ,user.corpwx_userid as corpwxUserid from report
-         left join user on user.id = audit_dept_managerid
+         left join `user` on `user`.id = audit_dept_managerid
          where state = 0 and department_audit_state = 0 and is_dept_audit = 1
         and report.company_id =#{companyId}
+        and `user`.is_active=1
         group by audit_dept_managerid
     </select>
     <select id="getProjectCost" resultType="java.util.HashMap">

+ 2 - 1
fhKeeper/formulahousekeeper/ops-platform/src/main/resources/application-dev.yml

@@ -81,7 +81,8 @@ mybatis:
 #####配置图片上传路径####
 upload:
   path: /www/staticproject/timesheet/upload/
-
+logDownLoad:
+  path: /www/webapps/worktime/wt_print.log
 ##actuator健康检查配置
 management:
   security:

+ 3 - 1
fhKeeper/formulahousekeeper/ops-platform/src/main/resources/application-prod.yml

@@ -80,8 +80,10 @@ mybatis:
   mapper-locations: mappers/*Mapper.xml
 #####配置图片上传路径####
 upload:
-  path: /www/staticproject/timesheet/upload/
+  path: /www/staticproject/octopus_vue/upload/
 
+logDownLoad:
+  path: /www/webapps/worktime/wt_print.log
 ##actuator健康检查配置
 management:
   security:

+ 25 - 0
fhKeeper/formulahousekeeper/restart.sh

@@ -0,0 +1,25 @@
+#!/bin/bash
+
+# 进程名
+process="timesheet"
+
+# 获取进程ID
+PID=$(ps -ef | grep $process | grep -v grep | awk '{print $2}')
+
+if [ -n "$PID" ]; then
+    echo "$process is exist"
+    if ps -p $PID >/dev/null; then
+        echo "$process is runnig"
+    else
+        echo " $ process is not running"
+    fi
+else
+    echo "$process is not exist"
+fi
+echo $PID;
+# 暂停1秒
+sleep 1;
+kill -9 $PID;
+echo "$process is killed"
+./startWorkTime.sh
+echo "restart timesheet success"

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

@@ -363,7 +363,7 @@
                         v-if="!isBatch && user.timeType.syncCorpwxTime==1 && (workForm.createDate == today || !workForm.time || workForm.time.workHours <= 0)" icon="el-icon-refresh" 
                                 @click="refreshWXCardTime(workForm.createDate)"></el-button>
                         <!-- AI智能填报 -->
-                        <el-button type="primary" @click="getAIReport(workForm.createDate)" v-if="user.companyId == 7 || user.companyId == 10" size="mini" style="margin-left:5px;" >AI智能填报</el-button>
+                        <el-button type="primary" @click="getAIReport()" v-if="(user.companyId == 7 || user.companyId == 10) && !hasWrittenReport" size="mini" style="margin-left:5px;" >AI智能填报</el-button>
                     </el-form-item>
                     <!-- 000000 -->
                     <div v-for="(domain, index) in workForm.domains" :key="domain.id" :style="index>0?'margin-top:10px;':''">
@@ -630,7 +630,7 @@
                                 </el-select>
                                 <template v-if="user.timeType.mainProjectState != 1">
                                 <span  v-if="domain.subProjectList != null && domain.subProjectList.length> 0 && domain.projectId != ''"
-                                    style="margin-left:45px;"><span v-if="user.timeType.subProMustFill==1" style="color:red;">*</span>{{$t('lable.subproject')}}</span>{{$t('lable.subproject')}}
+                                    style="margin-left:45px;"><span v-if="user.timeType.subProMustFill==1" style="color:red;">*</span>{{$t('lable.subproject')}}</span>
                                 <!--子项目 -->
                                 <el-select v-model="domain.subProjectId" :placeholder="$t('defaultText.PleaseSelectaSub-item')" style="width:200px;margin-left:10px;" clearable="true"
                                 v-if="domain.subProjectList != null && domain.subProjectList.length> 0 && domain.projectId != ''"
@@ -1713,6 +1713,7 @@
         },
         data() {
             return {
+                hasWrittenReport: false,
                 today:null,
                 syncTimeLoading: false,
                 seluserText: '',
@@ -4487,9 +4488,7 @@
                 
             },
             getAIReport(createDate) {
-                this.http.post('/report/getAIReport', {
-                    date: createDate
-                },
+                this.http.post('/report/getAIReport', {},
                 res => {
                     if (res.code == "ok") {
                         var quanbu = 0 
@@ -4594,7 +4593,8 @@
                         //从后端接口的数据设置是否是周末,后端会判断节假日以及中航工业一周6天工作日的情况
                         this.isWeekend = !this.report.isWorkDay;
                         
-                        this.canCancelInDialog = false
+                        this.canCancelInDialog = false;
+                        this.hasWrittenReport = list.report.length != 0;
                         if(list.report.length != 0) {
                             var arr = [];
                             this.canEdit = false;