Przeglądaj źródła

考勤对接,更新数据,增加星期,请假和外出的时间计算

seyason 3 lat temu
rodzic
commit
2f93ed5ab0
13 zmienionych plików z 397 dodań i 55 usunięć
  1. 26 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/DingDingController.java
  2. 22 3
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/UserCorpwxTimeController.java
  3. 89 11
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/WeiXinCorpController.java
  4. 40 1
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/UserCorpwxTime.java
  5. 4 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/DingDingService.java
  6. 1 1
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/WxCorpInfoService.java
  7. 99 1
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/DingDingServiceImpl.java
  8. 8 7
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ReportServiceImpl.java
  9. 44 10
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/WxCorpInfoServiceImpl.java
  10. 14 1
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/util/DateTimeUtil.java
  11. 11 2
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/UserCorpwxTimeMapper.xml
  12. 10 10
      fhKeeper/formulahousekeeper/timesheet/config/index.js
  13. 29 8
      fhKeeper/formulahousekeeper/timesheet/src/views/workReport/daily.vue

+ 26 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/DingDingController.java

@@ -3,11 +3,20 @@ 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.dingtalk.api.DefaultDingTalkClient;
+import com.dingtalk.api.DingTalkClient;
+import com.dingtalk.api.request.OapiServiceGetSuiteTokenRequest;
+import com.dingtalk.api.request.OapiServiceGetUnactiveCorpRequest;
+import com.dingtalk.api.response.OapiServiceGetSuiteTokenResponse;
+import com.dingtalk.api.response.OapiServiceGetUnactiveCorpResponse;
+import com.management.platform.entity.SysConfig;
 import com.management.platform.service.DingDingService;
 import com.management.platform.util.*;
 import com.taobao.api.ApiException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.springframework.http.*;
 import org.springframework.web.bind.annotation.*;
 
 import javax.annotation.Resource;
@@ -18,6 +27,7 @@ import java.util.concurrent.Executors;
 @RestController
 @RequestMapping("/dingding")
 public class DingDingController {
+
     private final Logger bizLogger = LoggerFactory.getLogger(getClass());
     String token = "cf776d62c5fb3508b5d8c2cbb9f3df0c";
     String aesKey = "ktmbamhymjsf60ndwp6n81mnu92847oynsgj9e0zr9v";
@@ -116,6 +126,8 @@ public class DingDingController {
                             } else if (bizType == 4) {
                                 //企业授权变更,包含授权、解除授权、授权变更。
                                 JSONObject biz_data = JSONObject.parseObject(bizItem.getString("biz_data"));
+                                System.out.println("授权变更数据===@@");
+                                System.out.println(biz_data);
                                 String syncAction = biz_data.getString("syncAction");
                                 if ("org_suite_auth".equals(syncAction) || "org_suite_change".equals(syncAction)) {
                                     //开通授权应用
@@ -148,6 +160,7 @@ public class DingDingController {
                                             dingDingService.corpAuth(corpid, corp_name, authUserId, agentId);
                                         } catch (ApiException e) {
                                             e.printStackTrace();
+                                            System.out.println(e.getMessage());
                                         }
                                     } else {
                                         System.out.println("===未授权启用===");
@@ -178,9 +191,11 @@ public class DingDingController {
 
             // 5. 返回success的加密数据
             Map<String, String> successMap = callbackCrypto.getEncryptedMap("success");
+            System.out.println("给钉钉返回数据了:"+successMap);
             return successMap;
         } catch (DingCallbackCrypto.DingTalkEncryptException e) {
             e.printStackTrace();
+            System.out.println(e.getMessage());
         }
         return null;
     }
@@ -227,4 +242,15 @@ public class DingDingController {
         return dingDingService.syncCorpAgent(corpid);
 
     }
+
+    @RequestMapping("/getUnActiveCorp")
+    public HttpRespMsg getUnActiveCorp() {
+        return dingDingService.getUnActiveCorp();
+    }
+
+    @RequestMapping("/reAuthCorp")
+    public HttpRespMsg reAuthCorp(String corpid) {
+        return dingDingService.reAuthCorp(corpid);
+    }
+
 }

+ 22 - 3
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/UserCorpwxTimeController.java

@@ -84,13 +84,20 @@ public class UserCorpwxTimeController {
             }
             //员工参与的项目
             List<Participation> participationList = participationMapper.selectList(new QueryWrapper<Participation>().in("user_id", userIdList));
+            List<String> names = new ArrayList<>();
             if (participationList.size() > 0) {
                 List<Integer> collect = participationList.stream().map(Participation::getProjectId).collect(Collectors.toList());
                 List<Project> projectList = projectMapper.selectList(new QueryWrapper<Project>().in("id", collect).orderByAsc("id"));
-                List<String> names = projectList.stream().map(Project::getProjectName).collect(Collectors.toList());
-                item.put("projects", names);
-            }
+                names = projectList.stream().map(Project::getProjectName).collect(Collectors.toList());
 
+            }
+            //添加公共项目
+            List<Project> publicProjects = projectMapper.selectList(new QueryWrapper<Project>().eq("company_id", user.getCompanyId()));
+            if (publicProjects.size() > 0) {
+                List<String> collect = publicProjects.stream().map(Project::getProjectName).collect(Collectors.toList());
+                names.addAll(collect);
+            }
+            item.put("projects", names);
         } else {
             item.put("projects", new ArrayList<String>());
         }
@@ -154,15 +161,23 @@ public class UserCorpwxTimeController {
         if (manageDeptId != null && manageDeptId != 0) {
 
         }
+
         HttpRespMsg ret = getMyDeptMembsData(startDate, endDate);
         HashMap map = (HashMap)ret.data;
         List<Map> list = (List<Map>) map.get("list");
         List<String> projects = (List) map.get("projects");
+        if (projects == null) {
+            msg.setError("员工无参与的项目,请先到项目管理中进行设置项目参与人");
+        }
         List<String> titles = new ArrayList<>();
         titles.add("工作日期");
+        titles.add("星期");
         titles.add("员工姓名");
         titles.add("上班时间");
         titles.add("下班时间");
+        titles.add("打卡时长");
+        titles.add("请假时长");
+        titles.add("补卡/外出时长");
         titles.add("工作时长");
         //添加项目名称作为列名
         for (String p : projects) {
@@ -174,9 +189,13 @@ public class UserCorpwxTimeController {
         for (Map dataItem : list) {
             List<String> dataList = new ArrayList<>();
             dataList.add((String)dataItem.get("createDate"));
+            dataList.add((String)dataItem.get("weekDayTxt"));
             dataList.add((String)dataItem.get("username"));
             dataList.add((String)dataItem.get("startTime"));
             dataList.add((String)dataItem.get("endTime"));
+            dataList.add(""+(Double)dataItem.get("cardTime"));
+            dataList.add(""+(Double)dataItem.get("askLeaveTime"));
+            dataList.add(""+(Double)dataItem.get("outdoorTime"));
             dataList.add(""+(Double)dataItem.get("workHours"));
             for (String p : projects) {
                 dataList.add("");

+ 89 - 11
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/WeiXinCorpController.java

@@ -40,7 +40,7 @@ public class WeiXinCorpController {
     //获取成员详情
     public static final String GET_USER_INFO_URL = "https://qyapi.weixin.qq.com/cgi-bin/user/get?access_token=ACCESS_TOKEN&userid=USERID";
     //获取部门列表
-//    public static final String GET_DEPARTMENT_URL = "https://qyapi.weixin.qq.com/cgi-bin/department/list?access_token=ACCESS_TOKEN";
+    public static final String GET_ALL_DEPARTMENT_URL = "https://qyapi.weixin.qq.com/cgi-bin/department/list?access_token=ACCESS_TOKEN";
     public static final String GET_DEPARTMENT_URL = "https://qyapi.weixin.qq.com/cgi-bin/department/list?access_token=ACCESS_TOKEN&id=1";//获取某个部门下的子部门
     //获取部门成员详情
     public static final String GET_DEPARTMENT_USER_DETAIL_URL = "https://qyapi.weixin.qq.com/cgi-bin/user/list?access_token=ACCESS_TOKEN&department_id=DEPARTMENT_ID&fetch_child=0";
@@ -105,9 +105,6 @@ public class WeiXinCorpController {
     @Resource
     UserService userService;
 
-
-
-
     //"获取企业微信jssdk初始化配置参数"
     @RequestMapping("/getCorpWXConfig")
     public HttpRespMsg getCorpWXConfig(String url, String token) {
@@ -349,6 +346,8 @@ public class WeiXinCorpController {
         return msg;
     }
 
+
+
     private void handleCorpAuth(String authCode) {
         String suitAccessToken = getSuiteAccessToken();
         String url = GET_CORP_PERMANENT_CODE_URL.replace("SUITE_ACCESS_TOKEN", suitAccessToken);
@@ -444,8 +443,7 @@ public class WeiXinCorpController {
                         User user = new User()
                                 .setId(id.toString())
                                 .setRole(1)
-                                .setName(data.getAuthUsername())
-                                .setName(userId)//使用wx userid作为姓名
+                                .setName(data.getAuthUsername()==null?userId:data.getAuthUsername())
                                 .setPassword(MD5Util.getPassword("000000"))
                                 .setCorpwxUserid(userId)
                                 .setColor(ColorUtil.randomColor())
@@ -587,7 +585,7 @@ public class WeiXinCorpController {
                         User user = new User()
                                 .setId(id.toString())
                                 .setRole(1)
-                                .setName(data.getAuthUsername())
+                                .setName(data.getAuthUsername()==null?userId:data.getAuthUsername())
                                 .setCorpwxUserid(userId)
                                 .setColor(ColorUtil.randomColor())
                                 .setCompanyId(companyId);
@@ -601,7 +599,7 @@ public class WeiXinCorpController {
     private JSONArray getDeptUserSimple(String accessToken, int deptId) {
         String url = GET_DEPARTMENT_USER_SIMPLE_URL.replace("ACCESS_TOKEN", accessToken).replace("DEPARTMENT_ID", ""+deptId);
         String result = restTemplate.getForObject(url, String.class);
-        log.info("部门人员详情:"+result);
+        System.out.println("部门人员详情:"+result);
         JSONObject obj = JSONObject.parseObject(result);
         JSONArray userlist = obj.getJSONArray("userlist");
 
@@ -616,6 +614,16 @@ public class WeiXinCorpController {
 
         return obj;
     }
+
+    private JSONObject getAllDepartments(String accessToken) {
+        String url = GET_ALL_DEPARTMENT_URL.replace("ACCESS_TOKEN", accessToken);
+        String result = restTemplate.getForObject(url, String.class);
+        System.out.println("部门列表:"+result);
+        JSONObject obj = JSONObject.parseObject(result);
+
+        return obj;
+    }
+
     private JSONObject getUserInfo(String accessToken, String userId) {
         String url = GET_USER_INFO_URL.replace("ACCESS_TOKEN", accessToken).replace("USERID", userId);
         String result = restTemplate.getForObject(url, String.class);
@@ -755,9 +763,10 @@ public class WeiXinCorpController {
 
     //获取企业微信考勤打卡统计数据
     @RequestMapping("/getUserCheckInDayData")
-    public HttpRespMsg getUserCheckInDayData(int companyId, String date) {
-        LocalDateTime localDate = LocalDateTime.parse(date+" 00:00:00", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
-        return wxCorpInfoService.getUserCheckInDayData(companyId, localDate);
+    public HttpRespMsg getUserCheckInDayData(int companyId, String startDate, String endDate) {
+        LocalDateTime start = LocalDateTime.parse(startDate+" 00:00:00", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
+        LocalDateTime end = LocalDateTime.parse(endDate+" 00:00:00", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
+        return wxCorpInfoService.getUserCheckInDayData(companyId, start, end);
     }
 
 
@@ -862,4 +871,73 @@ public class WeiXinCorpController {
 
         return msg;
     }
+
+    @RequestMapping("/getCorpMembs")
+    public HttpRespMsg getCorpMembs(String corpId) {
+
+        WxCorpInfo wxCorpInfo = wxCorpInfoMapper.selectById(corpId);
+
+        Company company = companyMapper.selectById(wxCorpInfo.getCompanyId());
+        String curCorpAccessToken = null;
+        try {
+            curCorpAccessToken = getCorpAccessToken(wxCorpInfo);
+        } catch (Exception exception) {
+            exception.printStackTrace();
+        }
+        int companyId = company.getId();
+        //获取公司根部门人员,也就是没有分配部门的人员
+        int companyRootDeptId = 1;
+        JSONArray unAssignedUserList = getDeptUserSimple(curCorpAccessToken, companyRootDeptId);
+        for (int m=0;m<unAssignedUserList.size(); m++) {
+            JSONObject userJson = unAssignedUserList.getJSONObject(m);
+            String curUserid = userJson.getString("userid");
+            System.out.println("userid="+curUserid+", name=" + userJson.getString("name")+", mobile="+userJson.getString("mobile"));
+            //不存在的人员, 进行插入
+            User user = new User();
+
+            user.setId(SnowFlake.nextId()+"")
+                    .setRole(0)//默认普通员工
+                    .setCompanyId(companyId)
+                    .setName(userJson.getString("name"))
+                    .setCorpwxUserid(curUserid)
+                    .setColor(ColorUtil.randomColor());
+
+            //检查用户是否已经存在
+            if (userMapper.selectCount(new QueryWrapper<User>().eq("corpwx_userid", curUserid)) == 0) {
+                userMapper.insert(user);
+            }
+        }
+
+//获取部门
+        JSONObject deptObj = getAllDepartments(curCorpAccessToken);
+        JSONArray deptObjJSONArray = deptObj.getJSONArray("department");
+
+        for (int i=0;i<deptObjJSONArray.size(); i++) {
+            int deptId = deptObjJSONArray.getJSONObject(i).getIntValue("id");
+
+            JSONArray userList = getDeptUserSimple(curCorpAccessToken, deptId);
+            for (int m=0;m<userList.size(); m++) {
+                JSONObject userJson = userList.getJSONObject(m);
+                String curUserid = userJson.getString("userid");
+                System.out.println("userid="+curUserid+", name=" + userJson.getString("name")+", mobile="+userJson.getString("mobile"));
+                //不存在的人员, 进行插入
+                User user = new User();
+
+                user.setId(SnowFlake.nextId()+"")
+                        .setRole(0)//默认普通员工
+                        .setCompanyId(companyId)
+                        .setDepartmentId(0)
+                        .setName(userJson.getString("name"))
+                        .setCorpwxUserid(curUserid)
+                        .setColor(ColorUtil.randomColor());
+
+                //检查用户是否已经存在
+                if (userMapper.selectCount(new QueryWrapper<User>().eq("corpwx_userid", curUserid)) == 0) {
+                    userMapper.insert(user);
+                }
+            }
+        }
+
+        return new HttpRespMsg();
+    }
 }

+ 40 - 1
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/UserCorpwxTime.java

@@ -16,7 +16,7 @@ import lombok.experimental.Accessors;
  * </p>
  *
  * @author Seyason
- * @since 2022-01-04
+ * @since 2022-01-07
  */
 @Data
 @EqualsAndHashCode(callSuper = false)
@@ -43,6 +43,15 @@ public class UserCorpwxTime extends Model<UserCorpwxTime> {
     @TableField("end_time")
     private String endTime;
 
+    /**
+     * 打卡时长
+     */
+    @TableField("card_time")
+    private Double cardTime;
+
+    /**
+     * 工作时长
+     */
     @TableField("work_hours")
     private Double workHours;
 
@@ -52,6 +61,36 @@ public class UserCorpwxTime extends Model<UserCorpwxTime> {
     @TableField("wx_corpid")
     private String wxCorpid;
 
+    /**
+     * 员工姓名
+     */
+    @TableField("name")
+    private String name;
+
+    /**
+     * 外出时长
+     */
+    @TableField("outdoor_time")
+    private Double outdoorTime;
+
+    /**
+     * 请假时长
+     */
+    @TableField("ask_leave_time")
+    private Double askLeaveTime;
+
+    /**
+     * 周几数字
+     */
+    @TableField("week_day")
+    private Integer weekDay;
+
+    /**
+     * 周几文字
+     */
+    @TableField("week_day_txt")
+    private String weekDayTxt;
+
 
     @Override
     protected Serializable pkVal() {

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

@@ -17,4 +17,8 @@ public interface DingDingService {
     HttpRespMsg syncCorpInfo(String corpid);
 
     HttpRespMsg syncCorpAgent(String corpid);
+
+    HttpRespMsg getUnActiveCorp();
+
+    HttpRespMsg reAuthCorp(String corpid);
 }

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

@@ -23,5 +23,5 @@ public interface WxCorpInfoService extends IService<WxCorpInfo> {
 
     public String testDownloadFile();
 
-    public HttpRespMsg getUserCheckInDayData(int companyId, LocalDateTime localDate);
+    public HttpRespMsg getUserCheckInDayData(int companyId, LocalDateTime startDateTime, LocalDateTime endDateTime);
 }

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

@@ -34,17 +34,27 @@ import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.time.ZoneOffset;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 
 @Service
 @Transactional
 public class DingDingServiceImpl implements DingDingService {
     private final Logger bizLogger = LoggerFactory.getLogger(getClass());
+    long appId = 71020L;
     String token = "cf776d62c5fb3508b5d8c2cbb9f3df0c";
     String aesKey = "ktmbamhymjsf60ndwp6n81mnu92847oynsgj9e0zr9v";
     String suiteKey = "suitejwoq9dw4bxv4stdb";
     String suiteSecret = "o-TWFLkFe8YbJsa_025JOj_JEWydP5GR3eigt1Yn1rtx5dTcryTJiSA6KEih3Bi4";
 
+
+    public static String SUITE_ACCESS_TOKEN = null;
+    public static long suiteTokenExpireTime = 0L;
+
+    public static String PRE_AUTH_CODE = null;
+    public static long expireTime = 0L;
+
+
     @Resource
     private SysConfigMapper sysConfigMapper;
     @Resource
@@ -153,13 +163,13 @@ public class DingDingServiceImpl implements DingDingService {
 
                 //获取授权的部门
                 getAuthedDeptsAndUsers(dingding, accessToken);
-
             } else {
                 System.out.println("AccessToken为空,无法获取部门列表");
             }
         } else {
             companyDingdingMapper.updateById(dingding);
         }
+//        activateSuite(corpid);
     }
 
     @Override
@@ -478,6 +488,7 @@ public class DingDingServiceImpl implements DingDingService {
         return null;
     }
 
+
     private String getValidCorpAccessToken(String corpid) {
         CompanyDingding companyDingding = companyDingdingMapper.selectById(corpid);
         if (companyDingding.getExpireTime().isBefore(LocalDateTime.now())) {
@@ -638,6 +649,7 @@ public class DingDingServiceImpl implements DingDingService {
             if (userMapper.selectCount(new QueryWrapper<User>().eq("dingding_userid", dingdingUserid).eq("company_id", companyId)) == 0) {
                 userMapper.insert(user);
             } else {
+                System.out.println("该人员已存在:dingdingUserid==" + dingdingUserid);
                 //已有人员不做改动
 //                User oldUser = userMapper.selectList(new QueryWrapper<User>().eq("dingding_userid", dingdingUserid).eq("company_id", companyId).orderByDesc("create_time")).get(0);
 //                oldUser.setName(userJson.getString("name"));
@@ -754,4 +766,90 @@ public class DingDingServiceImpl implements DingDingService {
 //
 //        }
 //    }
+
+    @Override
+    public HttpRespMsg getUnActiveCorp() {
+        HttpRespMsg msg = new HttpRespMsg();
+        try {
+            DingTalkClient client = new DefaultDingTalkClient(
+                    "https://oapi.dingtalk.com/service/get_unactive_corp?suite_access_token=" +getDDSuiteAccessToken());
+            OapiServiceGetUnactiveCorpRequest req = new OapiServiceGetUnactiveCorpRequest();
+            req.setAppId(appId);
+            OapiServiceGetUnactiveCorpResponse rsp = null;
+            rsp = client.execute(req);
+            System.out.println(rsp.getBody());
+            msg.data = rsp.getBody();
+        } catch (ApiException e) {
+            e.printStackTrace();
+            msg.setError(e.getMessage());
+        }
+        return msg;
+
+    }
+
+
+    @Override
+    public HttpRespMsg reAuthCorp(String corpid) {
+        HttpRespMsg msg = new HttpRespMsg();
+        try {
+            DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/service/reauth_corp?suite_access_token=" + getDDSuiteAccessToken());
+            OapiServiceReauthCorpRequest req = new OapiServiceReauthCorpRequest();
+            req.setAppId(""+appId);
+            req.setCorpidList(Arrays.asList(corpid));
+            OapiServiceReauthCorpResponse rsp = client.execute(req);
+            System.out.println(rsp.getBody());
+        } catch (ApiException e) {
+            e.printStackTrace();
+            msg.setError(e.getMessage());
+        }
+        return msg;
+
+    }
+
+    public void activateSuite(String authCorpid, String tmpAuthCode) throws ApiException {
+        DingTalkClient client= new DefaultDingTalkClient("https://oapi.dingtalk.com/service/activate_suite?suite_access_token=" + getDDSuiteAccessToken());
+        OapiServiceActivateSuiteRequest req= new OapiServiceActivateSuiteRequest();
+        req.setSuiteKey(suiteKey);
+        req.setAuthCorpid(authCorpid);
+        req.setPermanentCode(getPermanentCode(tmpAuthCode));
+        OapiServiceActivateSuiteResponse rsp= client.execute(req);
+        System.out.println("激活应用返回=="+rsp.getBody());
+    }
+
+
+    public String getPermanentCode(String tmpAuthCode) throws ApiException {
+        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/service/get_permanent_code?suite_access_token=" + getDDSuiteAccessToken());
+        OapiServiceGetPermanentCodeRequest req = new OapiServiceGetPermanentCodeRequest();
+        req.setTmpAuthCode(tmpAuthCode);
+        OapiServiceGetPermanentCodeResponse rsp = client.execute(req);
+        JSONObject resp = JSONObject.parseObject(rsp.getBody());
+        if (resp.getInteger("errcode") == 0) {
+            String permanentCode = resp.getString("permanent_code");
+            return permanentCode;
+        }
+        return null;
+    }
+
+
+    //获取第三方应用临时凭证
+    private String getDDSuiteAccessToken() throws ApiException {
+        if (SUITE_ACCESS_TOKEN == null || suiteTokenExpireTime < System.currentTimeMillis()) {
+            DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/service/get_suite_token");
+            OapiServiceGetSuiteTokenRequest req = new OapiServiceGetSuiteTokenRequest();
+            req.setSuiteKey(suiteKey);
+            req.setSuiteSecret(suiteSecret);
+            SysConfig config = sysConfigMapper.selectOne(new QueryWrapper<SysConfig>().eq("param_key", "dingding_suite_ticket"));
+            String suiteTicket = config.getParamValue();
+            System.out.println("查询到suiteTicket==" + suiteTicket);
+            req.setSuiteTicket(suiteTicket);
+            OapiServiceGetSuiteTokenResponse rsp = client.execute(req);
+            System.out.println(rsp.getBody());
+            JSONObject obj = JSONObject.parseObject(rsp.getBody());
+            if (obj.getIntValue("errcode") == 0) {
+                SUITE_ACCESS_TOKEN = obj.getString("suite_access_token");
+                suiteTokenExpireTime = System.currentTimeMillis() + obj.getIntValue("expires_in")*1000;
+            }
+        }
+        return SUITE_ACCESS_TOKEN;
+    }
 }

+ 8 - 7
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ReportServiceImpl.java

@@ -1603,7 +1603,7 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
             List<String> projectList = new ArrayList<>();
             List<Project> allProjectList = projectMapper.selectList(new QueryWrapper<Project>().eq("company_id", companyId));
             List<Report> reportList = new ArrayList<>();
-            int projectNameStartIndex = (withCheckIn==null?2:5);
+            int projectNameStartIndex = (withCheckIn==null?2:9);
 
             for (int rowIndex = 0; rowIndex <= rowNum; rowIndex++) {
                 Row row = sheet.getRow(rowIndex);
@@ -1642,7 +1642,8 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
 
                     boolean isDateFormat = row.getCell(0).getCellTypeEnum() == CellType.NUMERIC;
                     String reportDate = isDateFormat?sdf.format(row.getCell(0).getDateCellValue()):row.getCell(0).getStringCellValue();
-                    String username = row.getCell(1).getStringCellValue().trim();
+
+                    String username = withCheckIn==null?row.getCell(1).getStringCellValue().trim():row.getCell(2).getStringCellValue().trim();
                     //检查人员是否存在
                     Optional<User> any = allUserList.stream().filter(u -> u.getName().equals(username)).findAny();
                     if (!any.isPresent()) {
@@ -1675,7 +1676,7 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
                                     report.setDepartmentAuditState(1);//部门已审核,到上层领导审核
                                 }
                                 report.setCreateDate(LocalDate.parse(reportDate, dtf));
-                                report.setCost(reportCreator.getCost().multiply(new BigDecimal(time)));
+                                report.setCost(reportCreator.getCost()==null?new BigDecimal(0) : reportCreator.getCost().multiply(new BigDecimal(time)));
                                 reportList.add(report);
                             } else if (time < 0) {
                                 msg.setError(username + "的工时存在负数,请检查修改");
@@ -1683,10 +1684,10 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
                             }
                         }
                         //检查个人总工时不能为0
-                        if (totalTime == 0) {
-                            msg.setError(username + "的工时为0,请检查修改");
-                            return msg;
-                        }
+//                        if (totalTime == 0) {
+//                            msg.setError(username + "的工时为0,请检查修改");
+//                            return msg;
+//                        }
                     }
                 }
             }

+ 44 - 10
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/WxCorpInfoServiceImpl.java

@@ -225,7 +225,7 @@ public class WxCorpInfoServiceImpl extends ServiceImpl<WxCorpInfoMapper, WxCorpI
     }
 
     @Override
-    public HttpRespMsg getUserCheckInDayData(int companyId, LocalDateTime now) {
+    public HttpRespMsg getUserCheckInDayData(int companyId, LocalDateTime startDateTime, LocalDateTime endDateTime) {
         HttpRespMsg msg = new HttpRespMsg();
         WxCorpInfo corpInfo = wxCorpInfoMapper.selectOne(new QueryWrapper<WxCorpInfo>().eq("company_id", companyId));
         if (corpInfo == null) {
@@ -238,14 +238,12 @@ public class WxCorpInfoServiceImpl extends ServiceImpl<WxCorpInfoMapper, WxCorpI
             HttpHeaders headers = new HttpHeaders();
             headers.setContentType(MediaType.APPLICATION_JSON);
             JSONObject reqParam = new JSONObject();
-//            LocalDate now = LocalDate.now();
-//            LocalDateTime now = LocalDateTime.now();
-            now = now.withHour(0).withMinute(0).withSecond(0).withNano(0);
-            System.out.println(now.toString());
-            long startTime = now.toEpochSecond(ZoneOffset.of("+8"));
-            now = now.plusDays(1);
-            System.out.println(now.toString());
-            long endTime = now.toEpochSecond(ZoneOffset.of("+8"));
+            startDateTime = startDateTime.withHour(0).withMinute(0).withSecond(0).withNano(0);
+            System.out.println(startDateTime.toString());
+            long startTime = startDateTime.toEpochSecond(ZoneOffset.of("+8"));
+            endDateTime = endDateTime.withHour(0).withMinute(0).withSecond(0).withNano(0);
+            System.out.println(endDateTime.toString());
+            long endTime = endDateTime.toEpochSecond(ZoneOffset.of("+8"));
             System.out.println("startTime="+startTime+",endTime="+endTime);
             reqParam.put("starttime", startTime);
             reqParam.put("endtime",  endTime);
@@ -268,6 +266,7 @@ public class WxCorpInfoServiceImpl extends ServiceImpl<WxCorpInfoMapper, WxCorpI
                         JSONObject jsonObject = datas.getJSONObject(i);
                         JSONObject base_info = jsonObject.getJSONObject("base_info");
                         String curUserid = base_info.getString("acctid");
+                        String name = base_info.getString("name");
                         Long time = base_info.getLong("date");
                         LocalDate localDate = LocalDateTime.ofInstant(Instant.ofEpochSecond(time), ZoneId.systemDefault()).toLocalDate();
                         UserCorpwxTime ct = new UserCorpwxTime();
@@ -275,14 +274,49 @@ public class WxCorpInfoServiceImpl extends ServiceImpl<WxCorpInfoMapper, WxCorpI
                         ct.setCorpwxUserid(curUserid);
                         ct.setWxCorpid(corpInfo.getCorpid());
                         ct.setCreateDate(localDate);
+                        //计算周几
+                        ct.setWeekDay(localDate.getDayOfWeek().getValue());
+                        ct.setWeekDayTxt(DateTimeUtil.getWeekDayTxt(ct.getWeekDay()));
                         JSONObject summary_info = jsonObject.getJSONObject("summary_info");
                         int sTime = summary_info.getIntValue("earliest_time");//秒
                         int eTime = summary_info.getIntValue("lastest_time");//秒
                         int regular_work_sec = summary_info.getIntValue("regular_work_sec");//秒
+                        Integer standard_work_sec = summary_info.getInteger("standard_work_sec");
 
                         ct.setStartTime(DateTimeUtil.getTimeFromSeconds(sTime));
                         ct.setEndTime(DateTimeUtil.getTimeFromSeconds(eTime));
-                        ct.setWorkHours(DateTimeUtil.getHoursFromSeconds(regular_work_sec));
+                        ct.setCardTime(DateTimeUtil.getHoursFromSeconds(regular_work_sec));
+                        ct.setName(name);
+                        //解析请假和外出的情况
+                        JSONArray sp_items = jsonObject.getJSONArray("sp_items");
+                        for (int j=0;j<sp_items.size(); j++) {
+                            JSONObject spItem = sp_items.getJSONObject(j);
+                            switch (spItem.getInteger("type")) {
+                                case 1://请假
+                                    Double leaveTime = ct.getAskLeaveTime();
+                                    if (leaveTime == null) {
+                                        leaveTime = 0.0;
+                                    }
+                                    ct.setAskLeaveTime(leaveTime + DateTimeUtil.getHoursFromSeconds(spItem.getInteger("duration")));
+                                    break;
+                                case 2://补卡
+                                case 3://出差
+                                case 4://外出
+                                case 100://外勤
+                                    Double outdoorTime = ct.getOutdoorTime();
+                                    if (outdoorTime == null) {
+                                        outdoorTime = 0.0;
+                                    }
+                                    ct.setOutdoorTime(outdoorTime + DateTimeUtil.getHoursFromSeconds(spItem.getInteger("duration")));
+                                    break;
+                            }
+                        }
+                        if (regular_work_sec < standard_work_sec) {
+                            ct.setWorkHours(ct.getCardTime() + ct.getOutdoorTime());
+                        } else {
+                            ct.setWorkHours(ct.getCardTime());
+                        }
+
                         UserCorpwxTime item = userCorpwxTimeMapper.selectOne(new QueryWrapper<UserCorpwxTime>().eq("corpwx_userid", curUserid)
                                             .eq("create_date", localDate));
                         if (item != null) {

+ 14 - 1
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/util/DateTimeUtil.java

@@ -1,12 +1,17 @@
 package com.management.platform.util;
 
+import org.apache.tomcat.jni.Local;
+
 import java.time.Instant;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.time.ZoneId;
 import java.time.format.DateTimeFormatter;
+import java.util.Arrays;
 
 public class DateTimeUtil {
+    public static final String[] WEEK_DAYS = {"周一","周二","周三","周四","周五","周六", "周日"};
+
 
     //把秒转化为时间
     public static String getTimeFromSeconds(int seconds) {
@@ -30,7 +35,15 @@ public class DateTimeUtil {
         return localDate;
     }
 
+    public static String getWeekDayTxt(int day) {
+        return WEEK_DAYS[day-1];
+    }
+
+
     public static void main(String[] args) {
-        System.out.println(getLocalDateFromSeconds(1641225600));
+
+        LocalDate now = LocalDate.now();
+        System.out.println(now.getDayOfWeek().getValue());
+        System.out.println(now.getDayOfWeek().name());
     }
 }

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

@@ -9,18 +9,26 @@
         <result column="corpwx_userid" property="corpwxUserid" />
         <result column="start_time" property="startTime" />
         <result column="end_time" property="endTime" />
+        <result column="card_time" property="cardTime" />
         <result column="work_hours" property="workHours" />
         <result column="company_id" property="companyId" />
         <result column="wx_corpid" property="wxCorpid" />
+        <result column="name" property="name" />
+        <result column="outdoor_time" property="outdoorTime" />
+        <result column="ask_leave_time" property="askLeaveTime" />
+        <result column="week_day" property="weekDay" />
+        <result column="week_day_txt" property="weekDayTxt" />
     </resultMap>
 
     <!-- 通用查询结果列 -->
     <sql id="Base_Column_List">
-        id, create_date, corpwx_userid, start_time, end_time, work_hours, company_id, wx_corpid
+        id, create_date, corpwx_userid, start_time, end_time, card_time, work_hours, company_id, wx_corpid, name, outdoor_time, ask_leave_time, week_day, week_day_txt
     </sql>
 
+
     <select id="getUserDataList" resultType="java.util.HashMap" >
-        SELECT user.id as userId, DATE_FORMAT(a.create_date, '%Y/%m/%d') as createDate,a.start_time as startTime, a.end_time as endTime, a.work_hours as workHours, user.name as username FROM user_corpwx_time a LEFT JOIN user ON user.`corpwx_userid` = a.corpwx_userid
+        SELECT user.id as userId, DATE_FORMAT(a.create_date, '%Y/%m/%d') as createDate,a.start_time as startTime, a.end_time as endTime, a.work_hours as workHours, user.name as username,
+        week_day_txt as weekDayTxt,card_time as cardTime, outdoor_time as outdoorTime, ask_leave_time as askLeaveTime FROM user_corpwx_time a LEFT JOIN user ON user.`corpwx_userid` = a.corpwx_userid
         WHERE a.create_date BETWEEN #{startDate} AND #{endDate}
         AND a.company_id = #{companyId}
         <if test="deptId != null">
@@ -28,4 +36,5 @@
         </if>
         ORDER BY a.create_date ASC
     </select>
+
 </mapper>

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

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

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

@@ -600,7 +600,7 @@
         </el-dialog>
 
         <!--基于企业微信考勤数据的工时导入 -->
-        <el-dialog title="工时批量导入" v-if="importWxDialog" :visible.sync="importWxDialog" customClass="customWidth" width="650px">
+        <el-dialog title="工时批量导入" v-if="importWxDialog" :visible.sync="importWxDialog" customClass="customWidth" width="1100px">
             <el-steps :active="active" finish-status="success">
             <el-step title="选择要导入工时的日期范围">
                 
@@ -612,7 +612,7 @@
             
                 
             <div v-if="active==0" style="padding:30px;height:360px;">
-                <div style="margin-top:50px;margin-left:80px;">
+                <div style="margin-top:50px;margin-left:280px;">
                 <el-date-picker 
                     v-model="importWxParam.date" :editable="false" 
                     format="yyyy-MM-dd" value-format="yyyy-MM-dd" 
@@ -629,10 +629,26 @@
                 <el-table border :data="checkinList" highlight-current-row v-loading="checkinLoading" :height="395" 
                 style="width: 100%;margin-top:5px;" >
                 <el-table-column prop="createDate" label="工作日期"  ></el-table-column>
+                <el-table-column prop="weekDayTxt" label="星期"  ></el-table-column>
                 <el-table-column prop="username" label="员工姓名"  ></el-table-column>
                 <el-table-column prop="startTime" label="上班时间"  ></el-table-column>
                 <el-table-column prop="endTime" label="下班时间" ></el-table-column>
-                <el-table-column prop="workHours" label="工作时长" >
+                <el-table-column prop="cardTime" label="打卡时长" align="right">
+                    <template slot-scope="scope">
+                        {{scope.row.cardTime.toFixed(1)}}h
+                    </template>
+                </el-table-column>
+                <el-table-column prop="askLeaveTime" label="请假时长"  align="right">
+                    <template slot-scope="scope">
+                        {{scope.row.askLeaveTime.toFixed(1)}}h
+                    </template>
+                </el-table-column>
+                <el-table-column prop="outdoorTime" label="补卡/外出时长"  align="right">
+                    <template slot-scope="scope">
+                        {{scope.row.outdoorTime.toFixed(1)}}h
+                    </template>
+                </el-table-column>
+                <el-table-column prop="workHours" label="工作时长"  align="right">
                     <template slot-scope="scope">
                         {{scope.row.workHours.toFixed(1)}}h
                     </template>
@@ -649,7 +665,7 @@
             <el-button style="margin: 0 auto;" @click="pre">上一步</el-button>
             
             <el-button style="float:right;" @click="next" :disabled="importWxParam.date==null" v-if="active<2">下一步</el-button>
-            <el-link v-if="active==1" style="float:right;margin-right:150px;margin-top:10px;" 
+            <el-link v-if="active==1" style="float:right;margin-right:350px;margin-top:10px;" 
                 type="primary" @click="downloadCheckInExcel">下载员工工时统计模板.xlsx</el-link>
             
         </el-dialog>
@@ -829,13 +845,18 @@
                     if (res.code == "ok") {
                         var filePath = res.data;
                         const a = document.createElement('a'); // 创建a标签
-                        var data = filePath.split("\\.");
-
+                        var data = filePath.split("/");
+                        console.log(filePath+',  '+data);
                         a.setAttribute('download', data[data.length-1]);// download属性
                         a.setAttribute('href', filePath);// href链接
                         a.click(); //自执行点击事件
                         a.remove();
-                    } 
+                    } else {
+                        this.$message({
+                            message: res.msg,
+                            type: "error"
+                        });
+                    }
                 },
                 error => {
                     this.checkinLoading = false;
@@ -940,7 +961,7 @@
                         this.listLoading = false;
                         if (res.code == "ok") {
                             this.$message({
-                                message: "成功导入"+res.data+"名人员的工时数据",
+                                message: "成功导入"+res.data+"工时数据",
                                 type: "success"
                             });
                             this.getReportList();