Bladeren bron

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

ggooalice 2 jaren geleden
bovenliggende
commit
cfd6dc3b3a
17 gewijzigde bestanden met toevoegingen van 369 en 153 verwijderingen
  1. 7 2
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/AuthRedirectController.java
  2. 23 10
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/ReportAuditLogController.java
  3. 66 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/UserYearleaveSettingController.java
  4. 65 23
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/WeiXinCorpController.java
  5. 0 4
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/User.java
  6. 19 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/BusinessTripServiceImpl.java
  7. 1 3
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/DingDingServiceImpl.java
  8. 10 4
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/WxCorpInfoServiceImpl.java
  9. 5 0
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/i18n/messages.properties
  10. 6 1
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/i18n/messages_en_US.properties
  11. 0 1
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/ProjectMapper.xml
  12. 2 1
      fhKeeper/formulahousekeeper/timesheet/src/i18n/en.json
  13. 2 1
      fhKeeper/formulahousekeeper/timesheet/src/i18n/zh.json
  14. 40 3
      fhKeeper/formulahousekeeper/timesheet/src/views/leave/list.vue
  15. 3 2
      fhKeeper/formulahousekeeper/timesheet/src/views/project/projectInside.vue
  16. 109 94
      fhKeeper/formulahousekeeper/timesheet_h5/src/views/index/index.vue
  17. 11 4
      fhKeeper/formulahousekeeper/timesheet_h5/src/views/login/index.vue

+ 7 - 2
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/AuthRedirectController.java

@@ -8,6 +8,7 @@ import com.management.platform.mapper.CompanyMapper;
 import com.management.platform.mapper.SysConfigMapper;
 import com.management.platform.mapper.UserMapper;
 import com.management.platform.mapper.WxCorpInfoMapper;
+import com.management.platform.service.UserService;
 import com.management.platform.util.HttpRespMsg;
 import com.management.platform.util.MessageUtils;
 import com.management.platform.util.UserAgentUtils;
@@ -54,6 +55,8 @@ public class AuthRedirectController {
     UserMapper userMapper;
     @Resource
     WxCorpInfoMapper wxCorpInfoMapper;
+    @Resource
+    UserService userService;
 
     @RequestMapping("/corpWXAuth")
     public ModelAndView auth(String code, String state) {
@@ -96,6 +99,8 @@ public class AuthRedirectController {
                     reqParam.put("errorMsg", MessageUtils.message("user.accountNoExist"));
                 } else if (curUser.getIsActive() == 1) {
                     reqParam.put("userId", curUser.getId());
+//                    HttpRespMsg httpRespMsg = userService.loginByUserId(curUser.getId(), request);
+//                    reqParam.put("userInfo", httpRespMsg.data);
                 } else {
                     //提示账号已停用
                     //reqParam.put("errorMsg", "您的账号已停用,无法登录");
@@ -106,9 +111,9 @@ public class AuthRedirectController {
         reqParam.put("hasTriedAutoLogin", 1);
         String redirecUrl = null;
         if (isMobile) {
-            redirecUrl = "http://mobworktime.ttkuaiban.com";
+            redirecUrl = "http://mobworktime.ttkuaiban.com/#/index";
         } else {
-            redirecUrl = "http://worktime.ttkuaiban.com";
+            redirecUrl = "http://worktime.ttkuaiban.com/#/index";
         }
         ModelAndView modelAndView = new ModelAndView(
                 new RedirectView(redirecUrl), reqParam);

+ 23 - 10
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/ReportAuditLogController.java

@@ -4,15 +4,12 @@ package com.management.platform.controller;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.management.platform.entity.LocaleInformation;
 import com.management.platform.entity.ReportAlogMembdate;
 import com.management.platform.entity.ReportAuditLog;
-import com.management.platform.entity.ReportImportLog;
 import com.management.platform.entity.User;
 import com.management.platform.entity.vo.SysRichFunction;
-import com.management.platform.mapper.ReportAlogMembdateMapper;
-import com.management.platform.mapper.ReportAuditLogMapper;
-import com.management.platform.mapper.SysFunctionMapper;
-import com.management.platform.mapper.UserMapper;
+import com.management.platform.mapper.*;
 import com.management.platform.util.HttpRespMsg;
 import org.springframework.web.bind.annotation.RequestMapping;
 
@@ -21,10 +18,9 @@ import org.springframework.web.bind.annotation.RestController;
 
 import javax.annotation.Resource;
 import javax.servlet.http.HttpServletRequest;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.*;
 import java.util.stream.Collectors;
 
 /**
@@ -49,6 +45,10 @@ public class ReportAuditLogController {
     UserMapper userMapper;
     @Resource
     SysFunctionMapper sysFunctionMapper;
+    @Resource
+    LocaleInformationMapper localeInformationMapper;
+    @Resource
+    CompanyMapper companyMapper;
 
     @RequestMapping("getImportAuditLog")
     public HttpRespMsg getImportAuditLog(Integer companyId, @RequestParam Integer pageIndex, @RequestParam Integer pageSize) {
@@ -71,7 +71,20 @@ public class ReportAuditLogController {
                     l.setMembdateList(membList.stream().filter(m->m.getRlogId().equals(l.getId())).collect(Collectors.toList()));
                 });
             }
-
+            if (companyMapper.selectById(companyId).getIsInternational() == 1) {
+                //国际化版本
+                LocaleInformation locale = localeInformationMapper.selectById(companyId);
+                TimeZone curZone = TimeZone.getTimeZone(locale.getTimezone());
+                int offsetSeconds = (curZone.getRawOffset() - TimeZone.getTimeZone("GMT+8").getRawOffset())/1000;
+                //时区转换,默认数据库存的是GMT+8
+                DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss", Locale.CHINA);
+                for (ReportAuditLog reportAuditLog : list) {
+                    String inDate = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(reportAuditLog.getIndate());
+                    LocalDateTime time = LocalDateTime.parse(inDate, dtf);
+                    time = time.plusSeconds(offsetSeconds);
+                    reportAuditLog.setIndate(time);
+                }
+            }
             Long total = iPage.getTotal();
             Map<String, Object> map = new HashMap<>();
             map.put("records", list);

+ 66 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/UserYearleaveSettingController.java

@@ -13,9 +13,12 @@ import com.management.platform.entity.vo.SysRichFunction;
 import com.management.platform.mapper.*;
 import com.management.platform.service.CompanyDingdingService;
 import com.management.platform.service.DingDingService;
+import com.management.platform.service.ExcelExportService;
 import com.management.platform.service.UserYearleaveSettingService;
 import com.management.platform.util.HttpRespMsg;
 import com.management.platform.util.ListUtil;
+import com.management.platform.util.MessageUtils;
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.util.StringUtils;
 import org.springframework.web.bind.annotation.RequestMapping;
 
@@ -55,6 +58,8 @@ public class UserYearleaveSettingController {
     private LeaveTypeMapper leaveTypeMapper;
     @Resource
     private DepartmentMapper departmentMapper;
+    @Resource
+    private ExcelExportService excelExportService;
 
     @Resource
     private HttpServletRequest request;
@@ -62,6 +67,11 @@ public class UserYearleaveSettingController {
     private UserMapper userMapper;
     @Resource
     private SysFunctionMapper sysFunctionMapper;
+    @Resource
+    private WxCorpInfoMapper wxCorpInfoMapper;
+
+    @Value(value = "${upload.path}")
+    private String path;
 
     @RequestMapping("/save")
     public HttpRespMsg save(String userId, Integer companyId, Integer yearDays) {
@@ -182,6 +192,62 @@ public class UserYearleaveSettingController {
         return msg;
     }
 
+    //导出剩余假期
+    @RequestMapping("/exportDingDingLeaveQt")
+    public HttpRespMsg exportDingDingLeaveQt(String leaveCode, Integer companyId, Integer departmentId, String userId){
+        HttpRespMsg httpRespMsg = new HttpRespMsg();
+        WxCorpInfo wxCorpInfo = wxCorpInfoMapper.selectOne(new QueryWrapper<WxCorpInfo>().eq("company_id",companyId));
+        List<String> headList = new ArrayList<>();
+        List<List<String>> allList = new ArrayList<>();
+        HttpRespMsg dingDingLeaveQt = getDingDingLeaveQt(leaveCode, companyId, departmentId, userId, 1);
+        HashMap map = (HashMap)dingDingLeaveQt.data;
+        List<LeaveQuotaNum> records = (List<LeaveQuotaNum>)map.get("records");
+        Long total = (Long) map.get("total");
+        Long j = 0L;
+        if (total!=0){
+            j = total / 50;
+            if (total % 50!=0){
+                j += 1;
+            }
+        }
+        //        headList.add("员工姓名");
+        //        headList.add("有效期");
+        //        headList.add("总额度");
+        //        headList.add("已使用");
+        //        headList.add("剩余额度");
+        headList.add(MessageUtils.message("entry.staffName"));
+        headList.add(MessageUtils.message("excel.validity"));
+        headList.add(MessageUtils.message("leave.totalAmount"));
+        headList.add(MessageUtils.message("leave.used"));
+        headList.add(MessageUtils.message("leave.remainingQuota"));
+        allList.add(headList);
+        for (int i = 2; i <= j+1; i++) {
+            if (records.size() == 0){
+                break;
+            }
+            for (LeaveQuotaNum record : records) {
+                ArrayList<String> data = new ArrayList<>();
+                data.add(record.getName());
+                data.add(record.getStartTime()+" - "+record.getEndTime());
+                data.add(record.getQuotaInHours()+"h");
+                data.add(record.getUsedInHours()+"h");
+                data.add(record.getLeftInHours()+"h");
+                allList.add(data);
+            }
+            dingDingLeaveQt = getDingDingLeaveQt(leaveCode, companyId, departmentId, userId, i);
+            map = (HashMap)dingDingLeaveQt.data;
+            records = (List<LeaveQuotaNum>)map.get("records");
+        }
+        //String fileName = "假期剩余表_"+System.currentTimeMillis();
+        String fileName = MessageUtils.message("fileName.leaveRemaining")+System.currentTimeMillis();
+        try {
+            return excelExportService.exportGeneralExcelByTitleAndList(wxCorpInfo,fileName,allList,path);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return httpRespMsg;
+    }
+
 
     //递归获取子部门
     private List<Department> getSubDeptList(List<Department> allDeptList, Department department) {

+ 65 - 23
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/WeiXinCorpController.java

@@ -491,9 +491,49 @@ public class WeiXinCorpController {
             org.json.JSONObject jsonObject = XML.toJSONObject(sMsg);
             log.info("json=="+jsonObject.toString());
             jsonObject = jsonObject.getJSONObject("xml");
-            if(jsonObject.has("Event") && ("open_approval_change".equals(jsonObject.getString("Event")))){
-                //审批状态回调通知
-                System.out.println("审批状态回调通知!");
+            if(jsonObject.has("Event") && ("subscribe".equals(jsonObject.getString("Event")))){
+                //成员关注应用事件,发生在该企业已经开通应用的情况下。
+                System.out.println("成员关注应用事件!");
+                String corpId = jsonObject.getString("ToUserName");
+                String corpWxUserId = jsonObject.getString("FromUserName");
+                WxCorpInfo wxCorpInfo = wxCorpInfoMapper.selectById(corpId);
+                if (wxCorpInfo != null) {
+                    //企业存在,生成对应的用户
+                    Integer companyId = wxCorpInfo.getCompanyId();
+                    JSONObject userObj = getUserInfo(getCorpAccessToken(wxCorpInfo), corpWxUserId);
+                    SysRole defaultRole = sysRoleMapper.selectOne(new QueryWrapper<SysRole>().eq("company_id", companyId).eq("is_default", 1));
+
+                    //成功获取到通讯录的个人详情
+                    Long id = SnowFlake.nextId();
+                    //通过getUserInfo接口获取到的json key是小写的
+                    JSONArray department = userObj.getJSONArray("department");
+                    Integer curUserWXDeptid = getMaxDeptIdFromArray(department);
+                    Department sysDept = departmentMapper.selectOne(new QueryWrapper<Department>().eq("company_id", companyId).eq("corpwx_deptid", curUserWXDeptid));
+                    String userId = userObj.getString("userid");
+                    String openUserId = userObj.getString("open_userid");
+                    int cnt = userMapper.selectCount(new QueryWrapper<User>().eq("corpwx_userid", openUserId));
+                    if (cnt == 0) {
+                        //用户不存在
+                        User user = new User()
+                                .setId(id.toString())
+                                .setRoleId(defaultRole.getId())
+                                .setRoleName(defaultRole.getRolename())
+                                .setName(userObj.getString("name"))
+                                .setPhone(userObj.getString("mobile"))
+                                .setPassword(MD5Util.getPassword("000000"))
+                                .setCorpwxUserid(openUserId)
+                                .setCorpwxRealUserid(corpWxUserId)
+                                .setJobNumber(openUserId.equals(userId)?null:userId)
+                                .setColor(ColorUtil.randomColor())
+                                .setCompanyId(companyId);
+                        if (sysDept != null) {
+                            user.setDepartmentId(sysDept.getDepartmentId());
+                            List<Department> allDeptList = departmentMapper.selectList(new QueryWrapper<Department>().eq("company_id", companyId));
+                            user.setDepartmentCascade(convertDepartmentIdToCascade(user.getDepartmentId(), allDeptList));
+                            userMapper.insert(user);
+                        }
+                    }
+                }
             }
             if (jsonObject.has("AuthCode")) {
                 //企业授权通知
@@ -549,7 +589,7 @@ public class WeiXinCorpController {
                         JSONArray department = userObj.getJSONArray("department");
                         Integer curUserWXDeptid = getMaxDeptIdFromArray(department);
                         Department sysDept = departmentMapper.selectOne(new QueryWrapper<Department>().eq("company_id", companyId).eq("corpwx_deptid", curUserWXDeptid));
-
+                        String userId = userObj.getString("userid");
                         User user = new User()
                                 .setId(id.toString())
                                 .setRoleId(defaultRole.getId())
@@ -559,7 +599,7 @@ public class WeiXinCorpController {
                                 .setPassword(MD5Util.getPassword("000000"))
                                 .setCorpwxUserid(openUserId)
                                 .setCorpwxRealUserid(corpWxUserId)
-                                .setJobNumber(userObj.getString("userid"))
+                                .setJobNumber(openUserId.equals(userId)?null:userId)
                                 .setColor(ColorUtil.randomColor())
                                 .setCompanyId(companyId);
                         if (sysDept != null) {
@@ -590,7 +630,7 @@ public class WeiXinCorpController {
                             JSONArray department = userObj.getJSONArray("department");
                             curUserWXDeptid = getMaxDeptIdFromArray(department);
                             Department sysDept = departmentMapper.selectOne(new QueryWrapper<Department>().eq("company_id", companyId).eq("corpwx_deptid", curUserWXDeptid));
-
+                            String userId = userObj.getString("userid");
                             User user = new User()
                                     .setId(id.toString())
                                     .setRoleId(defaultRole.getId())
@@ -600,7 +640,7 @@ public class WeiXinCorpController {
                                     .setPassword(MD5Util.getPassword("000000"))
                                     .setCorpwxUserid(openUserId)
                                     .setCorpwxRealUserid(corpWxUserId)
-                                    .setJobNumber(userObj.getString("userid"))
+                                    .setJobNumber(openUserId.equals(userId)?null:userId)
                                     .setColor(ColorUtil.randomColor())
                                     .setCorpwxDeptid(curUserWXDeptid)
                                     .setCompanyId(companyId);
@@ -688,14 +728,15 @@ public class WeiXinCorpController {
                                     changeUser.setDepartmentId(sysDept.getDepartmentId());
                                     change = true;
                                 }
-                                if (userObj.containsKey("direct_leader") && userObj.getJSONArray("direct_leader").size() > 0) {
-                                    String directLeader = userObj.getJSONArray("direct_leader").getString(0);
-                                    User leader = userMapper.selectOne(new QueryWrapper<User>().eq("company_id", companyId).eq("corpwx_userid", directLeader));
-                                    if (leader != null && !leader.equals(user.getSuperiorId())) {
-                                        changeUser.setSuperiorId(leader.getId());
-                                        change = true;
-                                    }
-                                }
+                                //暂不处理直属领导
+//                                if (userObj.containsKey("direct_leader") && userObj.getJSONArray("direct_leader").size() > 0) {
+//                                    String directLeader = userObj.getJSONArray("direct_leader").getString(0);
+//                                    User leader = userMapper.selectOne(new QueryWrapper<User>().eq("company_id", companyId).eq("corpwx_userid", directLeader));
+//                                    if (leader != null && !leader.equals(user.getSuperiorId())) {
+//                                        changeUser.setSuperiorId(leader.getId());
+//                                        change = true;
+//                                    }
+//                                }
                                 if (change) {
                                     userMapper.updateById(changeUser);
                                 }
@@ -911,7 +952,7 @@ public class WeiXinCorpController {
                     JSONObject authUserInfo = obj.getJSONObject("auth_user_info");
                     data.setAuthUsername(authUserInfo.getString("name"));
                     String userId = authUserInfo.getString("userid");//授权人的userid
-
+                    String openUserId = authUserInfo.getString("open_userid");
                     //检查公司名称是否存在,按照corpid比对
                     WxCorpInfo findCorp = wxCorpInfoMapper.selectById(corpId);
 
@@ -1035,10 +1076,10 @@ public class WeiXinCorpController {
                                 .setRoleName(managerRole.getRolename())
                                 .setName(name)
                                 .setPassword(MD5Util.getPassword("000000"))
-                                .setCorpwxUserid(userId)
+                                .setCorpwxUserid(openUserId)
                                 .setColor(ColorUtil.randomColor())
                                 .setCompanyId(company.getId())
-                                .setJobNumber(userId);
+                                .setJobNumber(openUserId.equals(userId)?null:userId);
                         userMapper.insert(user);
                         //todo: 生成初始测试项目及任务
                         Project project=new Project();
@@ -1128,6 +1169,7 @@ public class WeiXinCorpController {
                     JSONObject authUserInfo = obj.getJSONObject("auth_user_info");
                     data.setAuthUsername(authUserInfo.getString("name"));
                     String userId = authUserInfo.getString("userid");//授权人的userid
+                    String openUserId = authUserInfo.getString("open_userid");
                     //检查该授权人是否已经存在
                     if (userMapper.selectCount(new QueryWrapper<User>().eq("corpwx_userid", userId)) == 0) {
                         JSONObject userDetail = getUserInfo(curCorpAccessToken, userId);
@@ -1153,7 +1195,7 @@ public class WeiXinCorpController {
                                 .setCorpwxUserid(userId)
                                 .setColor(ColorUtil.randomColor())
                                 .setCompanyId(companyId)
-                                .setJobNumber(userId);//工号就是企业微信的用户ID
+                                .setJobNumber(openUserId.equals(userId)?null:userId);//工号就是企业微信的用户ID
                         userMapper.insert(user);
                     }
                 }
@@ -1673,7 +1715,7 @@ public class WeiXinCorpController {
                     .setCorpwxRealUserid(curUserid)
                     .setColor(ColorUtil.randomColor())
                     .setPassword(MD5Util.getPassword("000000"))
-                    .setJobNumber(curUserid)
+                    .setJobNumber(openUserid.equals(curUserid)?null:curUserid)
                     .setCorpwxDeptid(maxDeptId);
             allCorpWxUserList.add(user);
         }
@@ -1729,7 +1771,7 @@ public class WeiXinCorpController {
                                 .setCorpwxUserid(openUserid)
                                 .setCorpwxRealUserid(curUserid)
                                 .setColor(ColorUtil.randomColor())
-                                .setJobNumber(curUserid)
+                                .setJobNumber(openUserid.equals(curUserid)?null:curUserid)
                                 .setPassword(MD5Util.getPassword("000000"))
                                 .setCorpwxDeptid(curDept.getCorpwxDeptid());
                         allCorpWxUserList.add(user);
@@ -1761,7 +1803,7 @@ public class WeiXinCorpController {
             if (first.isPresent()) {
                 User oldUser = first.get();
                 User changeUser = new User();
-                if (!userItem.getJobNumber().equals(oldUser.getJobNumber())) {
+                if (userItem.getJobNumber() != null && !userItem.getJobNumber().equals(oldUser.getJobNumber())) {
                     changeUser.setId(oldUser.getId());
                     changeUser.setJobNumber(userItem.getJobNumber());
                 }
@@ -2081,7 +2123,7 @@ public class WeiXinCorpController {
             if (first.isPresent()) {
                 User oldUser = first.get();
                 User changeUser = new User();
-                if (!userItem.getJobNumber().equals(oldUser.getJobNumber())) {
+                if (userItem.getJobNumber() != null && !userItem.getJobNumber().equals(oldUser.getJobNumber())) {
                     changeUser.setId(oldUser.getId());
                     changeUser.setJobNumber(userItem.getJobNumber());
                 }

+ 0 - 4
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/User.java

@@ -257,8 +257,4 @@ public class User extends Model<User> {
         return this.id;
     }
 
-//    public LocalDateTime getCreateTime() {
-//        if ()
-//        return createTime;
-//    }
 }

+ 19 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/BusinessTripServiceImpl.java

@@ -18,6 +18,7 @@ import org.springframework.util.StringUtils;
 
 import javax.annotation.Resource;
 import javax.servlet.http.HttpServletRequest;
+import java.time.LocalDateTime;
 import java.time.format.DateTimeFormatter;
 import java.util.*;
 import java.util.stream.Collectors;
@@ -52,6 +53,10 @@ public class BusinessTripServiceImpl extends ServiceImpl<BusinessTripMapper, Bus
     DepartmentMapper departmentMapper;
     @Resource
     DepartmentService departmentService;
+    @Resource
+    LocaleInformationMapper localeInformationMapper;
+    @Resource
+    CompanyMapper companyMapper;
 
     @Override
     public HttpRespMsg modifyProject(BusinessTrip sheet) {
@@ -248,6 +253,20 @@ public class BusinessTripServiceImpl extends ServiceImpl<BusinessTripMapper, Bus
                     queryWrapper);
         }
         List<BusinessTrip> records = listIPager.getRecords();
+        if (companyMapper.selectById(user.getCompanyId()).getIsInternational() == 1) {
+            //国际化版本
+            LocaleInformation locale = localeInformationMapper.selectById(user.getCompanyId());
+            TimeZone curZone = TimeZone.getTimeZone(locale.getTimezone());
+            int offsetSeconds = (curZone.getRawOffset() - TimeZone.getTimeZone("GMT+8").getRawOffset())/1000;
+            //时区转换,默认数据库存的是GMT+8
+            DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss", Locale.CHINA);
+            for (BusinessTrip record : records) {
+                String inDate = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(record.getIndate());
+                LocalDateTime time = LocalDateTime.parse(inDate, dtf);
+                time = time.plusSeconds(offsetSeconds);
+                record.setIndate(time);
+            }
+        }
         //赋值项目名称
         List<Project> projectList = projectMapper.selectList(new QueryWrapper<Project>().eq("company_id", sheet.getCompanyId()));
         if (records.size() > 0) {

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

@@ -768,7 +768,7 @@ public class DingDingServiceImpl implements DingDingService {
             OapiV2DepartmentGetRequest req = new OapiV2DepartmentGetRequest();
             req.setDeptId(deptId);
             OapiV2DepartmentGetResponse rsp = client.execute(req, accessToken);
-//            System.out.println(rsp.getBody());
+//            System.out.println("获取部门返回="+rsp.getBody());
             JSONObject json = JSONObject.parseObject(rsp.getBody());
             if (json.getInteger("errcode") == 0) {
                 JSONObject dept = json.getJSONObject("result");
@@ -955,8 +955,6 @@ public class DingDingServiceImpl implements DingDingService {
                     .setJobNumber(userJson.getString("job_number"))
                     .setColor(ColorUtil.randomColor());
 
-
-
             if (departmentId != null) {
                 user.setDepartmentCascade(convertDepartmentIdToCascade(departmentId));
             }

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

@@ -795,6 +795,9 @@ public class WxCorpInfoServiceImpl extends ServiceImpl<WxCorpInfoMapper, WxCorpI
 
                     ct.setStartTime(DateTimeUtil.getTimeFromSeconds(sTime));
                     ct.setEndTime(DateTimeUtil.getTimeFromSeconds(eTime));
+                    //有一次有效打卡
+                    boolean hitOnce = (ct.getStartTime().equals(ct.getEndTime()) && !"00:00".equals(ct.getStartTime()));
+                    String originHitTime = ct.getStartTime();
                     //直接设置打卡时长,以企业微信的为准,不考虑漏打卡的情况
                     ct.setCardTime(DateTimeUtil.getHoursFromSeconds(regular_work_sec));
                     ct.setAskLeaveTime(0.0);
@@ -1100,18 +1103,21 @@ public class WxCorpInfoServiceImpl extends ServiceImpl<WxCorpInfoMapper, WxCorpI
 //                        } else {
 //                            ct.setWorkHours(DateTimeUtil.getHoursFromDouble(ct.getCardTime()));
 //                        }
-                        //仅有一次打卡,并且没有请假,外出的情况,需要补足下班的打卡时间
-                        if (ct.getStartTime().equals(ct.getEndTime()) && !"00:00".equals(ct.getStartTime())) {
+                        if (showLog) System.out.println("ct.getStartTime()==" + ct.getStartTime()+", ct.getEndTime()="+ct.getEndTime());
+                        //仅有一次打卡,需要补足下班的打卡时间;重新计算工作时长
+                        if (hitOnce) {
                             if (ct.getEndTime().compareTo(baseAfternoonEnd) < 0) {
+                                if (showLog) System.out.println("打卡一次,自动补足下班时间"+baseAfternoonEnd);
                                 ct.setEndTime(baseAfternoonEnd);
                                 //重新计算时长
                                 double workTime = DateTimeUtil.getHoursFromSeconds(DateTimeUtil.getSecondsFromTime(ct.getEndTime()) - DateTimeUtil.getSecondsFromTime(ct.getStartTime()));
-                                if (ct.getStartTime().compareTo(baseMorningEnd) >= 0) {
+                                if (ct.getStartTime().compareTo(baseMorningEnd) <= 0) {
                                     //重新计算打卡工时时,需要减去中间午休时间
                                     workTime -= restTime;
                                 }
                                 ct.setCardTime(workTime);
-                                ct.setWorkHours(DateTimeUtil.getHoursFromDouble(workTime));
+                                ct.setWorkHours(DateTimeUtil.getHoursFromDouble(workTime) - ct.getAskLeaveTime() + ct.getOutdoorTime());
+                                if (showLog) System.out.println("workTime="+workTime+", 二次校正后workHours="+ct.getWorkHours());
                             }
                         }
                     }

+ 5 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/resources/i18n/messages.properties

@@ -298,6 +298,9 @@ leave.compensatory=调休假
 leave.paternity=陪产假
 leave.notFill=未填写
 leave.clockIn=考勤打卡
+leave.totalAmount=总额度
+leave.used=已使用
+leave.remainingQuota=剩余额度
 #报销相关
 Reimbursement.nameNull=报销人名称不能为空
 Reimbursement.costTypeNull=费用类型不能为空
@@ -527,6 +530,7 @@ fileName.perNoFill=未填人员统计_
 fileName.laborHour=工时对比
 fileName.monthWork=月度工时表
 fileName.deptJoinPro=部门参与项目情况表
+fileName.leaveRemaining = 假期剩余表
 #excel
 excel.publicProject=是否为公共项目
 excel.projectName=项目名称必填
@@ -677,6 +681,7 @@ excel.joinProCount = 参与的项目的数量
 excel.deptName = 部门名称
 excel.joinPeopleCount= 参与人次
 excel.tripDays = 出差的天数
+excel.validity = 有效期
 #推送
 push.fillIn=您今天的工时填报还未完成
 push.name=屈跃庭

+ 6 - 1
fhKeeper/formulahousekeeper/management-platform/src/main/resources/i18n/messages_en_US.properties

@@ -298,6 +298,9 @@ leave.compensatory=Compensatory leave
 leave.paternity=Paternity leave
 leave.notFill=Not filled in
 leave.clockIn=Clock in
+leave.totalAmount=Total amount
+leave.used=Used
+leave.remainingQuota=Remaining quota
 #报销相关
 Reimbursement.nameNull=The name of the reimbursement applicant cannot be blank.
 Reimbursement.costTypeNull=Expense type cannot be empty
@@ -525,8 +528,9 @@ fileName.supStat=Supplier statistics_
 fileName.dailyManHour=Daily man hour statistics_ {0} to {1}
 fileName.perNoFill=Personnel statistics not filled_
 fileName.laborHour=Labor hour comparison
-fileName.monthWork=Monthly man hour table
+fileName.monthWork=Monthly man hour Table
 fileName.deptJoinPro=Department Participation in Projects
+fileName.leaveRemaining = Leave Remaining Table
 #excel
 excel.publicProject=Whether it is a public project
 excel.projectName=Project name is required
@@ -677,6 +681,7 @@ excel.joinProCount = Number of projects involved
 excel.deptName = Department name
 excel.joinPeopleCount= Number of participants
 excel.tripDays = Days of business trip
+excel.validity = term of validity
 #推送
 push.fillIn=Your work hour report for today has not been completed.
 push.name=Qu Yue ting

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

@@ -1287,7 +1287,6 @@
         from department
         left JOIN (
         SELECT `user`.department_id AS departmentId,
-        project.create_date,
         COUNT(DISTINCT(project.id)) AS projectCount,
         COUNT(`user`.id) AS peopleCount
         from  `user`

+ 2 - 1
fhKeeper/formulahousekeeper/timesheet/src/i18n/en.json

@@ -1445,5 +1445,6 @@
   "can-yu-de-xiang-mu-de-shu-liang": "number of projects involved",
   "can-yu-ren-ci": "Number of participants",
   "chu-cha-de-tian-shu": "Days of business trip",
-  "xiang-mu-chuang-jian-shi-jian-duan": "Project Creation Period"
+  "xiang-mu-chuang-jian-shi-jian-duan": "Project Creation Period",
+  "dao-chu-jia-qi": "Export holidays"
 }

+ 2 - 1
fhKeeper/formulahousekeeper/timesheet/src/i18n/zh.json

@@ -1445,5 +1445,6 @@
   "can-yu-de-xiang-mu-de-shu-liang": "参与的项目的数量",
   "can-yu-ren-ci": "参与人次",
   "chu-cha-de-tian-shu": "出差的天数",
-  "xiang-mu-chuang-jian-shi-jian-duan": "项目创建时间段"
+  "xiang-mu-chuang-jian-shi-jian-duan": "项目创建时间段",
+  "dao-chu-jia-qi": "导出假期"
 }

+ 40 - 3
fhKeeper/formulahousekeeper/timesheet/src/views/leave/list.vue

@@ -544,7 +544,7 @@
           <div class="flex">
             <div>
               <span>{{ $t('leavetype') }}</span>
-              <el-select v-model="leaveTypeItem" :placeholder="$t('pleaseselectthetypeofleave')" @change="leaveTypeChange()" style="width: 180px" size="small"  filterable="true">
+              <el-select v-model="leaveTypeItem" :placeholder="$t('pleaseselectthetypeofleave')" @change="leaveTypeChange()" style="width: 120px" size="small"  filterable="true">
                   <span v-for="item in leaveTypeList" :key="item.leaveCode">
                   <el-option :label="item.leaveName" :value="item.leaveCode"></el-option>
                   </span> 
@@ -565,14 +565,15 @@
               </div>
               <div>
                 <span>{{ $t('personnelselection') }}</span>
-                <el-select v-model="userSelId" :placeholder="$t('pleaseselectthepersonaskingforleave')" clearable @change="userChg()" style="width: 180px" size="small" v-show="permissions.leaveAll" filterable="true">
+                <el-select v-model="userSelId" :placeholder="$t('pleaseselectthepersonaskingforleave')" clearable @change="userChg()" style="width: 140px" size="small" v-show="permissions.leaveAll" filterable="true">
                     <span v-for="(item, index) in users" :key="index">
                     <el-option :label="item.name" :value="item.id"></el-option>
                     </span> 
                 </el-select>
               </div>
-              <div style="margin:0 10px 0 40px">
+              <div style="margin:0 0px 0 10px">
                 <el-button size="small" type="primary" @click="listSynchronize" :loading="synchronizeLoading">{{ $t('synchronizefromStaple') }}</el-button>
+                <el-button size="small" type="primary" @click="exportLeaveList" :loading="exporLoading">{{ $t('dao-chu-jia-qi') }}</el-button>
               </div>
             </template>
             
@@ -853,6 +854,7 @@ export default {
       hubs: 0,
       vueCasaderItem: [], // 仿数据
       vueIAlDataSItems: undefined, // 仿数据
+      exporLoading: false
     };
   },
   computed: {},
@@ -922,6 +924,41 @@ export default {
         })
       })
     },
+    // 导出假期
+    exportLeaveList() {
+      this.exporLoading = true
+      let param = {
+        leaveCode: this.leaveTypeItem,
+        companyId: this.user.companyId,
+        departmentId: this.departmentSel ? this.departmentSel[this.departmentSel.length - 1] : '',
+      }
+      if(this.userSelId != '') {
+        param.userId = this.userSelId
+      }
+      this.http.post('/user-yearleave-setting/exportDingDingLeaveQt',param,
+      res => {
+        this.exporLoading = false
+        if(res.code == 'ok'){
+          var filePath = res.data;
+          const a = document.createElement('a'); // 创建a标签
+          a.setAttribute('download', '剩余假期');// download属性
+          a.setAttribute('href', filePath);// href链接
+          a.click(); //自执行点击事件
+          a.remove();
+        }else{
+          this.$message({
+            message: res.msg,
+            type: 'error'
+          })
+        }
+      },err => {
+        this.exporLoading = false
+        this.$message({
+          message: err,
+          type: 'error'
+        })
+      })
+    },
 
     // 从钉钉同步假期剩余表
     listSynchronize(){

+ 3 - 2
fhKeeper/formulahousekeeper/timesheet/src/views/project/projectInside.vue

@@ -1041,8 +1041,8 @@
     import 'quill/dist/quill.bubble.css'
     // 导入富文本
     import { quillEditor } from 'vue-quill-editor'
-import { error } from 'dingtalk-jsapi';
-import delete$ from 'dingtalk-jsapi/api/biz/cspace/delete';
+    import { error } from 'dingtalk-jsapi';
+    import delete$ from 'dingtalk-jsapi/api/biz/cspace/delete';
     let id=1;
     export default {
         name: "two-list-headerslots",
@@ -3258,6 +3258,7 @@ import delete$ from 'dingtalk-jsapi/api/biz/cspace/delete';
             };
         },
         mounted() {
+
             this.curProjectId = parseInt(this.$route.params.id);
             this.activeName = this.$route.path.split("/")[1];
             this.getDetail();

+ 109 - 94
fhKeeper/formulahousekeeper/timesheet_h5/src/views/index/index.vue

@@ -41,101 +41,97 @@
         created() {
         },
         mounted() {
+            // 手机上看控制台
             // if(this.user.companyName == '比基尼小镇'){
-            //     let consoleScript = document.createElement("script");
-            //     consoleScript.src = "https://cdn.bootcss.com/vConsole/3.3.4/vconsole.min.js";
-            //     consoleScript.onload = function () {
-            //         new VConsole()
-            //     }
-            //     document.head.appendChild(consoleScript);
+                // let consoleScript = document.createElement("script");
+                // consoleScript.src = "https://cdn.bootcss.com/vConsole/3.3.4/vconsole.min.js";
+                // consoleScript.onload = function () {
+                //     new VConsole()
+                // }
+                // document.head.appendChild(consoleScript);
             // }
-            // console.log('userNameNeedTranslate',window.location.href);
-            if(this.user.userNameNeedTranslate == '1'){
-                this.agentConfig()
-            }
             var ua = navigator.userAgent.toLowerCase();
             if (ua.indexOf("wxwork") > 0) {
                 this.isCorpWX = true;
             } else if (ua.indexOf("micromessenger") > 0) {
                 this.isWX = true;
             }
-
-            if (this.user.company.packageEngineering == 1) {
-                this.routers.push(
-                {
-                    name: '专业审核',
-                    url: '/profession_review',
-                    icon: 'todo-list-o'
-                });
+            let that = this
+            if (localStorage.userInfo != null) {
+                that.getAccountInfo();
+            } else {
+                this.$router.push("/login");
             }
-            var list = this.user.moduleList
-            for (var i in list) {
-                if(list[i].name == '工时报告') {
-                    this.routers.push({name: '查看日报',url: '/calendar',icon: 'description'})
-                    this.routers.push({name: '填写日报',url: '/edit',icon: 'edit'})
-                    // if (this.user.companyId == 817 || this.user.companyId == 7 || this.user.companyId == 10) {
-                        this.routers.push({name: '按周填报',url: '/weekEdit',icon: 'records'})
-                    // }
+           
+        },
+        components: {
+            Footer
+        },
+        methods: {
+            // 模块
+            getModule() {
+                if(this.user.userNameNeedTranslate == '1'){
+                    this.agentConfig()
                 }
-                if(list[i].name == '待办任务') {
-                    this.routers.push({
-                        name: '待办任务',
-                        url: '/task',
-                        icon: 'coupon-o'
+
+                if (this.user.company.packageEngineering == 1) {
+                    this.routers.push(
+                    {
+                        name: '专业审核',
+                        url: '/profession_review',
+                        icon: 'todo-list-o'
                     });
                 }
-                if(list[i].name == '项目报告审核') {
-                    this.routers.push({name: '项目报告审核',url: '/review',icon: 'todo-list-o'})
-                }
-                if(list[i].name == '项目管理') {
-                    this.routers.push({name: '项目管理',url: '/project',icon: 'label-o'})
-                }
-                if(list[i].name == '导入日报审核') {
-                    this.routers.push({name: '导入日报审核',url: '/audit',icon: 'label-o'})
+                var list = this.user.moduleList
+                for (var i in list) {
+                    if(list[i].name == '工时报告') {
+                        this.routers.push({name: '查看日报',url: '/calendar',icon: 'description'})
+                        this.routers.push({name: '填写日报',url: '/edit',icon: 'edit'})
+                        // if (this.user.companyId == 817 || this.user.companyId == 7 || this.user.companyId == 10) {
+                            this.routers.push({name: '按周填报',url: '/weekEdit',icon: 'records'})
+                        // }
+                    }
+                    if(list[i].name == '待办任务') {
+                        this.routers.push({
+                            name: '待办任务',
+                            url: '/task',
+                            icon: 'coupon-o'
+                        });
+                    }
+                    if(list[i].name == '项目报告审核') {
+                        this.routers.push({name: '项目报告审核',url: '/review',icon: 'todo-list-o'})
+                    }
+                    if(list[i].name == '项目管理') {
+                        this.routers.push({name: '项目管理',url: '/project',icon: 'label-o'})
+                    }
+                    if(list[i].name == '导入日报审核') {
+                        this.routers.push({name: '导入日报审核',url: '/audit',icon: 'label-o'})
+                    }
+                    if(list[i].name == '费用报销') {
+                        this.routers.push({
+                            name: '费用报销',
+                            url: '/expense',
+                            icon: 'balance-list-o'
+                        });
+                    }
                 }
-                if(list[i].name == '费用报销') {
-                    this.routers.push({
-                        name: '费用报销',
-                        url: '/expense',
-                        icon: 'balance-list-o'
+                if (this.user.manageDeptId != 0 && this.user.company.packageEngineering == 1) {
+                    this.routers.push(
+                    {
+                        name: '部门审核',
+                        url: '/department_review',
+                        icon: 'todo-list-o'
                     });
                 }
-            }
-            if (this.user.manageDeptId != 0 && this.user.company.packageEngineering == 1) {
-                this.routers.push(
-                {
-                    name: '部门审核',
-                    url: '/department_review',
-                    icon: 'todo-list-o'
-                });
-            }
-            
-            this.routers.push({
-                                name: '消息记录',
-                                url: '/msg',
-                                icon: 'todo-list-o',
-                                info: this.unreadNum
-                            });
+                
+                this.routers.push({
+                                    name: '消息记录',
+                                    url: '/msg',
+                                    icon: 'todo-list-o',
+                                    info: this.unreadNum
+                                });
+            },
 
-            
-            this.getMessage();
-            this.bindIfNessary();
-            if (localStorage.userInfo != null) {
-                this.getAccountInfo();
-            }
-            
-            this.getMessage();
-            this.bindIfNessary();
-            if (localStorage.userInfo != null) {
-                this.getAccountInfo();
-            }
-            
-            
-        },
-        components: {
-            Footer
-        },
-        methods: {
             // 获取企业微信参数
             agentConfig(){
                 let curUrl = window.location.href.split('#')[0]
@@ -196,22 +192,39 @@
 
             //获取账户信息
             getAccountInfo() {
-                this.$axios.get('/user/loginByUserId', {params:{userId: this.user.id}})
-                            .then(res => {
-                                // console.log(res);
-                                if (res.code == 'error') {
-                                    localStorage.errorMsg = res.msg;
-                                    //账号信息有问题,不能使用。
-                                    this.$router.push("/error");
-                                } else {
-                                    
-                                    localStorage.userInfo = JSON.stringify(res.data);
-                                    this.user = res.data;
-                                } 
-                            }).catch(err=> {
-                                alert('err=' + err);
-                            });
+                let userId = this.user.id
+                if(window.location.href.indexOf('userId') != '-1') {
+                    let href = window.location.href;
+                    var loginUserId = href.substring(href.indexOf("userId=")+"userId=".length);
+                    if (loginUserId.includes('#/')) {
+                        loginUserId = loginUserId.substring(0, loginUserId.indexOf('#/'));
+                    }
+                    userId = loginUserId
+                }
+                if(window.location.href.indexOf('errorMsg') != '-1') {
+                    let err = window.location.href.split('errorMsg=')[1]
+                    let str = err.split('#/')[0]
+                    this.$router.push("/login");
+                }
+                this.$axios.get('/user/loginByUserId', {params:{userId: userId}})
+                .then(res => {
+                    // console.log(res);
+                    if (res.code == 'error') {
+                        localStorage.errorMsg = res.msg;
+                        //账号信息有问题,不能使用。
+                        this.$router.push("/error");
+                    } else {
+                        localStorage.userInfo = JSON.stringify(res.data);
+                        this.user = res.data;
+                        this.getModule()
+                        this.getMessage();
+                        this.bindIfNessary();
+                    } 
+                }).catch(err=> {
+                    alert('err=' + err);
+                });
             },
+
             bindIfNessary() {
                 let href = window.location.href;
                 var requestUrl = "";
@@ -267,6 +280,7 @@
                     }
                 }
             },
+
             //获取消息
             getMessage() {
                 this.$axios.post("/information/list", {
@@ -280,6 +294,7 @@
                     } 
                 }).catch(err=> {this.$toast.clear();});
             },
+
         },
         activated(){
             this.getMessage()

+ 11 - 4
fhKeeper/formulahousekeeper/timesheet_h5/src/views/login/index.vue

@@ -144,7 +144,8 @@
                                     //获取openId
                                     if (res.data != null && ((this.isWX && res.data.wxOpenid != undefined)
                                                 || (this.isCorpWX && res.data.corpwxUserid != undefined))) {
-                                        localStorage.userInfo = JSON.stringify(res.data);
+                                        // localStorage.userInfo = JSON.stringify(res.data);
+                                        localStorage.setItem('userInfo', JSON.stringify(res.data))
                                         console.log('绑定成功');
                                         this.user = res.data;
                                         window.location.href = '/#/my/center';
@@ -160,6 +161,7 @@
                 }
             },
             tryAutoLogin() {
+                console.log('第三方回调')
                 var appId = "ww4e237fd6abb635af";//企业微信第三方的SUIT ID
                 var url = "http://worktime.ttkuaiban.com/api/corpWXAuth";//授权回调页面
                 var weixinUrl="https://open.weixin.qq.com/connect/oauth2/authorize?appid="+appId+"&redirect_uri="+encodeURI(url)+"&response_type=code&scope=snsapi_base&state=0#wechat_redirect";
@@ -172,13 +174,17 @@
                         if (res == null) {
 
                         } else if(res.errcode != null) {
-                            
+
                         } else {
                             //获取openId
                             if (res.data != null) {
-                                localStorage.userInfo = JSON.stringify(res.data);
+                                // alert('赋值成功' + JSON.stringify(res.data))
+                                localStorage.setItem('userInfo', JSON.stringify(res.data))
+                                this.$store.commit("updateLogin", true);
                                 this.user = res.data;
-                                window.location.href = '/#/index';
+                                // alert('本地存储的值' + localStorage.getItem('userInfo'))
+                                // window.location.href = '/#/index';
+                                this.$router.push("/index");
                             }
                         }
                     }).catch(err=> {
@@ -211,6 +217,7 @@
                 if (localStorage.userInfo != null && !this.isCorpWX) {
                     this.$router.push("/index").catch(err => { console.log(err, '错误5')});
                 } else {
+                    console.log('判断企业微信是否授权',this.isCorpWX || this.isWX)
                     if (this.isCorpWX || this.isWX) {
                         //判断企业微信,是否存在授权
                         if (href.includes("com/?code")) {