Selaa lähdekoodia

Merge remote-tracking branch 'origin/master'

yusm 5 kuukautta sitten
vanhempi
commit
6af6a72e8e
32 muutettua tiedostoa jossa 428 lisäystä ja 249 poistoa
  1. 2 2
      fhKeeper/formulahousekeeper/customerBuler-crm/index.html
  2. 7 0
      fhKeeper/formulahousekeeper/customerBuler-crm/logo.svg
  3. BIN
      fhKeeper/formulahousekeeper/customerBuler-crm/src/assets/login/login_logo.png
  4. BIN
      fhKeeper/formulahousekeeper/customerBuler-crm/src/assets/login/login_logos.png
  5. 3 3
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/contract/api.ts
  6. 1 1
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/contract/index.vue
  7. 1 1
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/header/header.vue
  8. 9 1
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/home.vue
  9. 9 2
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/login.vue
  10. BIN
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/product/客户管家logo@3x.png
  11. 1 1
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/controller/WeiXinCorpController.java
  12. 2 5
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/FeishuInfoController.java
  13. 4 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/ReportController.java
  14. 4 7
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/UserController.java
  15. 4 15
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/WeiXinCorpController.java
  16. 8 5
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/UserFvTime.java
  17. 2 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/mapper/ParticipationMapper.java
  18. 4 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/mapper/UserFvTimeMapper.java
  19. 2 3
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/FeishuInfoService.java
  20. 8 10
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/DingDingServiceImpl.java
  21. 175 63
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/FeishuInfoServiceImpl.java
  22. 11 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ProjectServiceImpl.java
  23. 2 2
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ReportServiceImpl.java
  24. 4 7
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/UserServiceImpl.java
  25. 5 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/WxCorpInfoServiceImpl.java
  26. 10 19
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/task/TimingTask.java
  27. 2 0
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/application.yml
  28. 1 1
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/i18n/messages.properties
  29. 1 1
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/i18n/messages_en_US.properties
  30. 6 0
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/ParticipationMapper.xml
  31. 8 0
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/UserFvTimeMapper.xml
  32. 132 100
      fhKeeper/formulahousekeeper/timesheet/src/views/project/costReportExport.vue

+ 2 - 2
fhKeeper/formulahousekeeper/customerBuler-crm/index.html

@@ -2,9 +2,9 @@
 
 <head>
   <meta charset="UTF-8" />
-  <link rel="icon" type="image/svg+xml" href="/vite.svg" />
+  <link rel="icon" type="image/svg+xml" href="./logo.svg" />
   <meta name="viewport" content="width=device-width, initial-scale=1.0" />
-  <title>客户管家</title>
+  <title>智能客户管家</title>
 </head>
 
 <body>

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 7 - 0
fhKeeper/formulahousekeeper/customerBuler-crm/logo.svg


BIN
fhKeeper/formulahousekeeper/customerBuler-crm/src/assets/login/login_logo.png


BIN
fhKeeper/formulahousekeeper/customerBuler-crm/src/assets/login/login_logos.png


+ 3 - 3
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/contract/api.ts

@@ -13,7 +13,7 @@ export const EXPORT_CONTRACT = "/contract/exportContract"
 export const IMPORITEM = "/contract/importContract"
 
 export const statusArray = [
-  { label: "审核通过", value: "审核通过", color: "color:#67c23a;" },
-  { label: "待审核", value: "待审核", color: "color:#e6a23c;" },
-  { label: "已驳回", value: "已驳回", color: "color:#f56c6c;" },
+  { label: "审核通过", value: "0", color: "color:#67c23a;" },
+  { label: "待审核", value: "1", color: "color:#e6a23c;" },
+  { label: "已驳回", value: "2", color: "color:#f56c6c;" },
 ];

+ 1 - 1
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/contract/index.vue

@@ -122,7 +122,7 @@ async function importBusiness(param: UploadRequestOptions) {
 function exportContract() {
   allLoading.exportLoading = true
   post(EXPORT_CONTRACT, {}).then((res) => {
-    downloadFile('合同导出.xlsx', res.data)
+    downloadFile(res.data, '合同导出.xlsx')
   }).finally(() => {
     allLoading.exportLoading = false
   })

+ 1 - 1
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/header/header.vue

@@ -1,7 +1,7 @@
 <template>
   <div class="trademark mr-8 flex items-center text-white">
     <img :src="loginLogin" class="w-10 h-10 mr-4" />
-    <div class="text-nowrap">客户管家</div>
+    <div class="text-nowrap">智能客户管家</div>
   </div>
   <div class=" flex flex-row justify-start items-center text-white flex-1 parentDiv" ref="parentDiv">
     <div v-for="(routerItem, routerItemIdex) in routerList" @click="setCurrentRouter(routerItem)"

+ 9 - 1
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/home.vue

@@ -6,7 +6,7 @@
       </el-header>
       <el-main>
         <router-view v-slot="{ Component }">
-          <transition name="router_animate">
+          <transition name="ranimate">
             <component :is="Component" />
           </transition>
         </router-view>
@@ -95,4 +95,12 @@ onMounted(async () => {
   overflow: auto;
   background: $backColor;
 }
+
+.ranimate-enter-active {
+  animation: fadeIn .6s;
+}
+
+.ranimate-leave-active {
+  animation: fadeOut .3s;
+}
 </style>

+ 9 - 2
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/login.vue

@@ -4,7 +4,7 @@
       <div class="m-auto pt-4">
         <img class="w-1/5 m-auto" :src="loginLogo" alt="">
       </div>
-      <h2 class="text-xl text-center pt-4 font-bold">客户管家</h2>
+      <h2 class="text-xl text-center pt-4 font-bold">智能客户管家</h2>
       <el-form class="pt-4" ref="ruleFormRef" :model="ruleForm" :rules="rules">
         <el-form-item prop="username">
           <el-input clearable :prefix-icon="UserFilled" size="large" class="mt-2" v-model.trim="ruleForm.username"
@@ -20,7 +20,7 @@
         </div>
       </el-form>
       <el-divider content-position="center">或</el-divider>
-      <div class="m-auto mb-5">
+      <div class="m-auto mb-5" @click="wxworkCli()">
         <img class="w-9 m-auto p-1 rounded-full border-blue-300 border-2 cursor-pointer" :src="qiyeweixin" alt="">
       </div>
       <div class="flex justify-between pb-5">
@@ -197,6 +197,13 @@ const tryAutoLogin = () => {
   var weixinUrl = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + appId + "&redirect_uri=" + encodeURI(url) + "&response_type=code&scope=snsapi_base&state=1#wechat_redirect";
   window.location.href = weixinUrl;
 }
+const wxworkCli = () => {
+    var appId = "wwdd1137a65ce0fc87";//企业微信第三方的SUIT ID
+    var url = "https://crm.ttkuaiban.com/api/corpWXScanningAuth";//授权回调页面
+    // var weixinUrl=`https://open.work.weixin.qq.com/wwopen/sso/3rd_qrConnect?appid=${appId}&redirect_uri=${url}&state=0&usertype=member`;
+    var weixinUrl=`https://login.work.weixin.qq.com/wwlogin/sso/login?login_type=ServiceApp&appid=${appId}&redirect_uri=${url}&state=0`;
+    window.location.href = weixinUrl;
+}
 
 onMounted(() => {
   checkLogin()

BIN
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/product/客户管家logo@3x.png


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

@@ -3620,7 +3620,7 @@ public class WeiXinCorpController {
         mainTitle.put("desc", "欢迎使用客户管家,点击查看客户管家使用指南");
         data.put("main_title", mainTitle);
         JSONObject cardImg = new JSONObject();
-        cardImg.put("url", "https://crm.ttkuaiban.com/card_img.png");
+        cardImg.put("url", "https://crm.ttkuaiban.com/welcome_card.jpg");
         cardImg.put("aspect_ratio", 2.35);
         data.put("card_image", cardImg);
         JSONArray array = new JSONArray();

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

@@ -29,10 +29,7 @@ import java.io.IOException;
 import java.io.PrintWriter;
 import java.time.LocalDateTime;
 import java.time.ZoneOffset;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
+import java.util.*;
 import java.util.stream.Collectors;
 
 /**
@@ -97,7 +94,7 @@ public class FeishuInfoController {
     public HttpRespMsg loadTaskResult(@RequestBody @Validated LoadTaskResultBO queryBO,HttpServletRequest request){
         HttpRespMsg msg = new HttpRespMsg();
         try {
-            msg = feishuInfoService.loadTaskResult(queryBO,request);
+            msg = feishuInfoService.loadTaskResult(queryBO);
         } catch (Exception e) {
             e.printStackTrace();
             msg.setError(MessageUtils.message("other.error"));

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

@@ -111,6 +111,9 @@ public class ReportController {
     @Resource
     private FinancialAuditMapper financialAuditMapper;
 
+    @Resource
+    private ParticipationMapper participationMapper;
+
     //获取任务相关的日报列表
     @RequestMapping("/getTaskReportList")
     public HttpRespMsg getTaskReportList(Integer taskId) {
@@ -2941,6 +2944,7 @@ public class ReportController {
         User user = userMapper.selectById(userId);
         user.setIsActive(0);
         userMapper.updateById(user);
+        participationMapper.delete(new LambdaQueryWrapper<Participation>().eq(Participation::getUserId,user.getId()));
         return msg;
     }
 

+ 4 - 7
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/UserController.java

@@ -1,17 +1,12 @@
 package com.management.platform.controller;
 
 
-import com.alibaba.fastjson.JSONArray;
-import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
-import com.management.platform.constant.Constant;
 import com.management.platform.entity.*;
 import com.management.platform.mapper.*;
 import com.management.platform.service.*;
-import com.management.platform.util.ColorUtil;
 import com.management.platform.util.HttpRespMsg;
-
 import com.management.platform.util.ListUtil;
 import com.management.platform.util.MessageUtils;
 import org.apache.poi.hssf.usermodel.*;
@@ -35,8 +30,6 @@ import javax.naming.ldap.SortControl;
 import javax.servlet.http.HttpServletRequest;
 import java.io.FileOutputStream;
 import java.io.IOException;
-import java.time.LocalDate;
-import java.time.LocalDateTime;
 import java.util.*;
 import java.util.stream.Collectors;
 
@@ -116,6 +109,9 @@ public class UserController {
     @Resource
     private UserGroupMapper userGroupMapper;
 
+    @Resource
+    private ParticipationMapper participationMapper;
+
     public static HashMap<String, Integer> corpddJobCenter = new HashMap();
     //用于控制线程锁
     public static HashMap<String, CorpwxJobResult> corpwxJobCenter = new HashMap();
@@ -769,6 +765,7 @@ public class UserController {
         }
         user.setIsActive(0);
         userService.updateById(user);
+        participationMapper.delete(new LambdaQueryWrapper<Participation>().eq(Participation::getUserId,user.getId()));
         return msg;
     }
 

+ 4 - 15
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/WeiXinCorpController.java

@@ -4,11 +4,6 @@ import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
-import com.dingtalk.api.DefaultDingTalkClient;
-import com.dingtalk.api.DingTalkClient;
-import com.dingtalk.api.request.OapiV2DepartmentListsubRequest;
-import com.dingtalk.api.response.OapiV2DepartmentListsubResponse;
-import com.google.gson.JsonObject;
 import com.management.platform.constant.Constant;
 import com.management.platform.entity.*;
 import com.management.platform.entity.vo.UserVO;
@@ -16,16 +11,12 @@ import com.management.platform.mapper.*;
 import com.management.platform.service.*;
 import com.management.platform.service.impl.ExcelExportServiceImpl;
 import com.management.platform.service.impl.ReportServiceImpl;
-import com.management.platform.service.impl.TaskServiceImpl;
-import com.management.platform.service.impl.UserServiceImpl;
 import com.management.platform.util.*;
 import com.qq.weixin.mp.aes.AesException;
 import com.qq.weixin.mp.aes.WXBizMsgCrypt;
 import com.taobao.api.ApiException;
 import lombok.extern.slf4j.Slf4j;
-import org.apache.ibatis.annotations.Select;
 import org.json.XML;
-import org.junit.Test;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
@@ -39,15 +30,12 @@ import org.springframework.web.servlet.view.RedirectView;
 import javax.annotation.Resource;
 import javax.servlet.http.HttpServletRequest;
 import java.net.URLEncoder;
-import java.sql.Timestamp;
-import java.time.*;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.ZoneOffset;
 import java.time.format.DateTimeFormatter;
 import java.util.*;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.function.Function;
-import java.util.function.Predicate;
 import java.util.stream.Collectors;
-import java.util.stream.Stream;
 
 @RestController
 @RequestMapping("/wxcorp")
@@ -2567,6 +2555,7 @@ public class WeiXinCorpController {
             //批量设置为停用
             if (setInactiveList.size() > 0) {
                 userService.updateBatchById(setInactiveList);
+                participationMapper.deleteBatchByUserId(setInactiveList.stream().map(User::getId).collect(Collectors.toList()));
             }
             List<User> newUserList = allCorpWxUserList.stream().filter(newItem -> !existingUsers.stream().anyMatch(existingItem -> newItem.getCorpwxUserid().equals(existingItem.getCorpwxUserid()))).collect(Collectors.toList());
             newUserList.forEach(newItem->{

+ 8 - 5
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/UserFvTime.java

@@ -1,18 +1,18 @@
 package com.management.platform.entity;
 
 import com.baomidou.mybatisplus.annotation.IdType;
-import com.baomidou.mybatisplus.extension.activerecord.Model;
-import java.time.LocalDate;
-import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableField;
-import java.io.Serializable;
-
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.extension.activerecord.Model;
 import com.fasterxml.jackson.annotation.JsonFormat;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
 import lombok.experimental.Accessors;
 import org.springframework.format.annotation.DateTimeFormat;
 
+import java.io.Serializable;
+import java.time.LocalDate;
+
 /**
  * <p>
  * 
@@ -51,6 +51,9 @@ public class UserFvTime extends Model<UserFvTime> {
     @TableField("work_hours")
     private Float workHours;
 
+//    @TableField("overtime_hours")
+//    private Float overTimeHours;
+
     /**
      * 是否被标记排除异常范围
      */

+ 2 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/mapper/ParticipationMapper.java

@@ -20,4 +20,6 @@ public interface ParticipationMapper extends BaseMapper<Participation> {
     List<Map<String, Object>> getParticipator(@Param("projectId") Integer projectId);
 
     List<ParticipationUser> getAllParticipator(@Param("projectIdList") List<Integer> projectIdList, Integer companyId);
+
+    void deleteBatchByUserId(@Param("userIds") List<String> userIds);
 }

+ 4 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/mapper/UserFvTimeMapper.java

@@ -2,6 +2,9 @@ package com.management.platform.mapper;
 
 import com.management.platform.entity.UserFvTime;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
 
 /**
  * <p>
@@ -13,4 +16,5 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
  */
 public interface UserFvTimeMapper extends BaseMapper<UserFvTime> {
 
+    void batchInsert(@Param("toAddList") List<UserFvTime> toAddList);
 }

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

@@ -2,12 +2,11 @@ package com.management.platform.service;
 
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
-import com.management.platform.entity.FeishuInfo;
 import com.baomidou.mybatisplus.extension.service.IService;
+import com.management.platform.entity.FeishuInfo;
 import com.management.platform.entity.bo.LoadTaskResultBO;
 import com.management.platform.util.HttpRespMsg;
 
-import javax.servlet.http.HttpServletRequest;
 import java.util.List;
 import java.util.Map;
 
@@ -42,5 +41,5 @@ public interface FeishuInfoService extends IService<FeishuInfo> {
 
     HttpRespMsg initSuperManager(String corpid, String name);
 
-    HttpRespMsg loadTaskResult(LoadTaskResultBO queryBO, HttpServletRequest request);
+    HttpRespMsg loadTaskResult(LoadTaskResultBO queryBO);
 }

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

@@ -3,8 +3,7 @@ package com.management.platform.service.impl;
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
-import com.aliyun.dingtalkcontact_1_0.Client;
-import com.aliyun.dingtalkcontact_1_0.models.GetUserHeaders;
+import com.aliyun.dingtalkcontact_1_0.models.*;
 import com.aliyun.dingtalkoauth2_1_0.models.GetAuthInfoHeaders;
 import com.aliyun.dingtalkoauth2_1_0.models.GetAuthInfoRequest;
 import com.aliyun.dingtalkoauth2_1_0.models.GetAuthInfoResponse;
@@ -14,6 +13,7 @@ import com.aliyun.tea.TeaException;
 import com.aliyun.tea.TeaPair;
 import com.aliyun.teaopenapi.models.Config;
 import com.aliyun.teautil.models.RuntimeOptions;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.dingtalk.api.DefaultDingTalkClient;
 import com.dingtalk.api.DingTalkClient;
@@ -41,7 +41,6 @@ import org.springframework.transaction.annotation.Transactional;
 
 import javax.annotation.Resource;
 import javax.servlet.http.HttpServletRequest;
-import java.math.BigInteger;
 import java.math.RoundingMode;
 import java.text.DecimalFormat;
 import java.text.SimpleDateFormat;
@@ -49,13 +48,6 @@ import java.time.*;
 import java.time.format.DateTimeFormatter;
 import java.util.*;
 import java.util.stream.Collectors;
-import com.aliyun.tea.*;
-import com.aliyun.teautil.*;
-import com.aliyun.teautil.models.*;
-import com.aliyun.dingtalkcontact_1_0.*;
-import com.aliyun.dingtalkcontact_1_0.models.*;
-import com.aliyun.teaopenapi.*;
-import com.aliyun.teaopenapi.models.*;
 
 //import com.management.platform.entity.vo.LeaveQuotaNum;
 
@@ -161,6 +153,9 @@ public class DingDingServiceImpl implements DingDingService {
     @Resource
     private TaskExecutorMapper taskExecutorMapper;
 
+    @Resource
+    private ParticipationMapper participationMapper;
+
 
     @Value("${configEnv.isPrivateDeploy}")
     private boolean isPrivateDeploy;//企业内部应用,私有化部署的情况
@@ -748,6 +743,7 @@ public class DingDingServiceImpl implements DingDingService {
                         u.setIsActive(0);
                         u.setInductionDate(LocalDate.now());
                         updateUser.add(u);
+                        participationMapper.delete(new LambdaQueryWrapper<Participation>().eq(Participation::getUserId,err.getId()));
                     });
                     if (updateUser.size() > 0) {
                         userService.updateBatchById(updateUser);
@@ -1368,6 +1364,7 @@ public class DingDingServiceImpl implements DingDingService {
                                             user.setIsActive(0);
                                             user.setInactiveDate(LocalDate.now());
                                             userMapper.updateById(user);
+                                            participationMapper.delete(new LambdaQueryWrapper<Participation>().eq(Participation::getUserId,user.getId()));
                                         }
                                     }
                                 }
@@ -2426,6 +2423,7 @@ public class DingDingServiceImpl implements DingDingService {
                 user.setIsActive(0);
                 user.setInactiveDate(leaveDate);
                 userMapper.updateById(user);
+                participationMapper.delete(new LambdaQueryWrapper<Participation>().eq(Participation::getUserId,user.getId()));
             }
         }
     }

+ 175 - 63
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/FeishuInfoServiceImpl.java

@@ -8,10 +8,7 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.management.platform.constant.Constant;
 import com.management.platform.entity.*;
 import com.management.platform.entity.bo.*;
-import com.management.platform.mapper.FeishuInfoMapper;
-import com.management.platform.mapper.FeishuSendMapper;
-import com.management.platform.mapper.SysRoleMapper;
-import com.management.platform.mapper.UserMapper;
+import com.management.platform.mapper.*;
 import com.management.platform.service.FeishuInfoService;
 import com.management.platform.util.HttpRespMsg;
 import com.management.platform.util.MD5Util;
@@ -23,14 +20,10 @@ import org.springframework.stereotype.Service;
 import org.springframework.web.client.RestTemplate;
 
 import javax.annotation.Resource;
-import javax.servlet.http.HttpServletRequest;
 import java.math.BigDecimal;
 import java.math.RoundingMode;
 import java.text.SimpleDateFormat;
-import java.time.Instant;
-import java.time.LocalDate;
-import java.time.LocalDateTime;
-import java.time.ZoneId;
+import java.time.*;
 import java.time.format.DateTimeFormatter;
 import java.util.*;
 import java.util.stream.Collectors;
@@ -82,9 +75,13 @@ public class FeishuInfoServiceImpl extends ServiceImpl<FeishuInfoMapper, FeishuI
         @Resource
         SysRoleMapper sysRoleMapper;
 
+        @Resource
+        UserFvTimeMapper userFvTimeMapper;
+
         @Autowired
         private RestTemplate restTemplate;
 
+
         @Override
         public String getAppAccessToken(FeishuInfo feishuInfo) {
                 String result="";
@@ -494,24 +491,18 @@ public class FeishuInfoServiceImpl extends ServiceImpl<FeishuInfoMapper, FeishuI
         }
 
         @Override
-        public HttpRespMsg loadTaskResult(LoadTaskResultBO queryBO, HttpServletRequest request) {
+        public HttpRespMsg loadTaskResult(LoadTaskResultBO queryBO) {
                 HttpRespMsg msg = new HttpRespMsg();
-//                User user = userMapper.selectById(request.getHeader("TOKEN"));
-//                if(null == user){
-//                        msg.setError("token有误,用户不存在");
-//                        return msg;
-//                }
-//                Integer companyId = user.getCompanyId();
 
                 LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<>();
-                lqw.select(User::getId,User::getJobNumber).isNotNull(User::getJobNumber)
+                lqw.select(User::getId,User::getJobNumber,User::getCompanyId).isNotNull(User::getJobNumber)
                         .in(User::getId,Arrays.asList(queryBO.getWtUserIds()));
                 List<User> users = userMapper.selectList(lqw);
                 if(CollectionUtils.isEmpty(users)){
                         msg.setError("未查询到飞书工号");
                         return msg;
                 }
-                Map<String, String> jobNumIdMap = users.stream().collect(Collectors.toMap(User::getJobNumber, User::getId));
+                Map<String, User> jobNumUserMap = users.stream().collect(Collectors.toMap(User::getJobNumber, t->t));
                 String[] feishuUserIdArr = users.stream().map(User::getJobNumber).toArray(String[]::new);
                 queryBO.setUserIds(feishuUserIdArr);
 
@@ -520,11 +511,11 @@ public class FeishuInfoServiceImpl extends ServiceImpl<FeishuInfoMapper, FeishuI
                         msg.setError("飞书获取用户考勤数据失败,请联系管理员");
                         return msg;
                 }
-                for (FeishuClockUserTaskResult userTaskResult : feishuClockData.getUser_task_results()) {
-                        for (FeishuClockTaskRecord record : userTaskResult.getRecords()) {
-                                record.setDateTime();
-                        }
-                }
+//                for (FeishuClockUserTaskResult userTaskResult : feishuClockData.getUser_task_results()) {
+//                        for (FeishuClockTaskRecord record : userTaskResult.getRecords()) {
+//                                record.setDateTime();
+//                        }
+//                }
 //                                msg.setData(userTaskResults);
 
                 //用户id、day、考勤组、班次、打卡记录list
@@ -545,81 +536,202 @@ public class FeishuInfoServiceImpl extends ServiceImpl<FeishuInfoMapper, FeishuI
                 List<Map<String,Object>> res = new ArrayList();
                 SimpleDateFormat HMFormat = new SimpleDateFormat("HH:mm");
                 SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+                List<UserFvTime> toAddFvTimeList = new ArrayList<>();
                 for (FeishuClockUserTaskResult userTaskResult : feishuClockData.getUser_task_results()) {
                         int day = userTaskResult.getDay();//日期 yyyyMMdd
-                        String dayStr = String.valueOf(day).substring(0,4)+"-"+String.valueOf(day).substring(4,6)+"-"+String.valueOf(day).substring(6,7);
+                        String dayStr = String.valueOf(day).substring(0,4)+"-"+String.valueOf(day).substring(4,6)+"-"+String.valueOf(day).substring(6,8);
+                        Map<String,Object> map = new HashMap<>();
+                        UserFvTime userFvTime = new UserFvTime();
+                        userFvTime.setUserId(jobNumUserMap.get(userTaskResult.getUser_id()).getId());
                         //获取正常上班时间段
                         Optional<FeishuClockTaskRecord> first = userTaskResult.getRecords().stream()
                                 .filter(t -> 0 == t.getTask_shift_type())
                                 .findFirst();
                         if(first.isPresent()){
-                                Map<String,Object> map = new HashMap<>();
                                 FeishuClockTaskRecord record = first.get();
-                                UserFvTime userFvTime = new UserFvTime();
                                 //计算时长 需考虑考勤--待处理
-
                                 FeishuShiftResult shiftResult = shiftResultMap.get(userTaskResult.getShift_id());
                                 //判断弹性上下班
-                                Integer flexibleMinutes = null;
+                                Integer earlyFlexibleMinutes = null; //下班最多可早走
+                                Integer lateFlexibleMinutes = null; //上班最多可晚到
                                 if(shiftResult.is_flexible()){
                                         //可以弹性上下班
-                                        flexibleMinutes = shiftResult.getFlexible_minutes();
-                                        if(null == flexibleMinutes || 0 == flexibleMinutes){
+                                        earlyFlexibleMinutes = shiftResult.getFlexible_minutes();
+                                        lateFlexibleMinutes = shiftResult.getFlexible_minutes();
+                                        if(null == shiftResult.getFlexible_minutes() || 0 == shiftResult.getFlexible_minutes()){
                                                 //从规则中获取
                                                 if(CollectionUtils.isNotEmpty(shiftResult.getFlexible_rule())){
                                                         //此处仅获取第一个作为规则
-                                                        flexibleMinutes = shiftResult.getFlexible_rule().get(0).getFlexible_early_minutes();
+                                                        earlyFlexibleMinutes = shiftResult.getFlexible_rule().get(0).getFlexible_early_minutes();
+                                                        lateFlexibleMinutes = shiftResult.getFlexible_rule().get(0).getFlexible_late_minutes();
                                                 }
                                         }
 
                                 }
-                                flexibleMinutes = null==flexibleMinutes?0:flexibleMinutes;
+                                earlyFlexibleMinutes = null==earlyFlexibleMinutes?0:earlyFlexibleMinutes;
+                                lateFlexibleMinutes = null==lateFlexibleMinutes?0:lateFlexibleMinutes;
                                 //获取打卡规则
                                 FeishuPunchTimeRule feishuPunchTimeRule = null;
                                 if(CollectionUtils.isNotEmpty(shiftResult.getPunch_time_rule())){
                                         //仅获取第一个
                                         feishuPunchTimeRule  = shiftResult.getPunch_time_rule().get(0);
                                 }
-                                /**
-                                 * 弹性时间 0 非0
-                                 * 0 仅判断是否缺卡
-                                 * 非0 先判断弹性,再判断是否缺卡
-                                 * */
-                                if(null != feishuPunchTimeRule){
-                                        LocalDateTime.parse(feishuPunchTimeRule.getOn_time(),DateTimeFormatter.ofPattern("HH:mm"));
-                                }
 
+                                map.put("feishuPunchTimeRule",feishuPunchTimeRule);
 
-                                Instant checkInInstant = Instant.ofEpochSecond(Long.parseLong(record.getCheck_in_record().getCheck_time()));
-                                LocalDateTime checkInLocalTime = LocalDateTime.ofInstant(checkInInstant, ZoneId.of("GMT+8"));
-                                Instant checkOutInstant = Instant.ofEpochSecond(Long.parseLong(record.getCheck_out_record().getCheck_time()));
-                                LocalDateTime checkOutLocalTime = LocalDateTime.ofInstant(checkOutInstant, ZoneId.of("GMT+8"));
+                                if(null != feishuPunchTimeRule){
+                                        //转换上下班规则时间
+                                        LocalDateTime onLocalDateTime = LocalDateTime.parse(dayStr + " " + feishuPunchTimeRule.getOn_time(), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"));
+                                        LocalDateTime offLocalDateTime = LocalDateTime.parse(dayStr + " " + feishuPunchTimeRule.getOff_time(), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"));
+                                        /**
+                                         * 弹性时间 0 非0
+                                         * 0 仅判断是否缺卡
+                                         * 非0 先判断弹性,再判断是否缺卡
+                                         * */
+//                                        if("Lack".equals(record.getCheck_in_result()) || "Todo".equals(record.getCheck_in_result())){
+//
+//                                        } else if ("Normal".equals(record.getCheck_in_result()) || "Early".equals(record.getCheck_in_result())) {
+//
+//                                        }
+                                        //上下班打卡时间
+                                        LocalDateTime checkInLocalTime = null;
+                                        LocalDateTime checkOutLocalTime = null;
+                                        if(null != record.getCheck_in_record()){
+                                                Instant checkInInstant = Instant.ofEpochSecond(Long.parseLong(record.getCheck_in_record().getCheck_time()));
+                                                checkInLocalTime = LocalDateTime.ofInstant(checkInInstant, ZoneId.of("GMT+8"));
+                                        }
+                                        if(null != record.getCheck_out_record()){
+                                                Instant checkOutInstant = Instant.ofEpochSecond(Long.parseLong(record.getCheck_out_record().getCheck_time()));
+                                                checkOutLocalTime = LocalDateTime.ofInstant(checkOutInstant, ZoneId.of("GMT+8"));
+                                        }
 
-                                System.out.println("checkInInstant=== "+checkInLocalTime+",checkOutLocalTime=== "+checkOutLocalTime);
+                                        String startTime = null;
+                                        String endTime = null;
+                                        long workSeconds = 0l;
+                                        if(null == checkInLocalTime || null==checkOutLocalTime){
+                                                //记录为缺卡,工时为0
+                                                startTime = null == record.getCheck_in_record()?null:
+                                                        checkInLocalTime.format(DateTimeFormatter.ofPattern("HH:mm"));
+                                                endTime = null == record.getCheck_out_record()?null:
+                                                        checkOutLocalTime.format(DateTimeFormatter.ofPattern("HH:mm"));
+                                        }else{
+                                                startTime = checkInLocalTime.format(DateTimeFormatter.ofPattern("HH:mm"));
+                                                endTime = checkOutLocalTime.format(DateTimeFormatter.ofPattern("HH:mm"));
+
+                                                if((checkInLocalTime.isBefore(onLocalDateTime) || checkInLocalTime.isEqual(onLocalDateTime))
+                                                        && (checkOutLocalTime.isAfter(offLocalDateTime) || checkOutLocalTime.isEqual(offLocalDateTime))){
+                                                        //正常上下班
+                                                        long offStamp = offLocalDateTime.toEpochSecond(ZoneOffset.of("+8"));
+                                                        long onStamp = onLocalDateTime.toEpochSecond(ZoneOffset.of("+8"));
+                                                        workSeconds = offStamp-onStamp;
+                                                }else{
+
+                                                        //判断上班是否满足缺卡条件
+                                                        if(checkInLocalTime.isAfter(onLocalDateTime.plusMinutes(feishuPunchTimeRule.getLate_minutes_as_lack()))){
+                                                                workSeconds = 0;
+                                                        } else if (checkOutLocalTime.isBefore(offLocalDateTime.plusMinutes(feishuPunchTimeRule.getEarly_minutes_as_lack()))) {
+                                                                workSeconds = 0;
+                                                        }else {
+                                                                //判断弹性时间
+                                                                if(checkInLocalTime.isAfter(onLocalDateTime)){ //上班时间 在规定时间之后,查看上班是否在弹性,下班是否在弹性
+                                                                        long offStamp = checkOutLocalTime.toEpochSecond(ZoneOffset.of("+8"));
+                                                                        long onStamp = checkInLocalTime.toEpochSecond(ZoneOffset.of("+8"));
+                                                                        workSeconds = offStamp-onStamp;
+                                                                        //判断上班是否在弹性
+                                                                        boolean checkInFlag = checkInLocalTime.isBefore(onLocalDateTime.plusMinutes(lateFlexibleMinutes))
+                                                                                || checkInLocalTime.isEqual(onLocalDateTime.plusMinutes(lateFlexibleMinutes));
+                                                                        if(checkInFlag){
+                                                                                //在弹性上班范围内,判断下班
+                                                                                if(checkOutLocalTime.isAfter(offLocalDateTime.plusMinutes(lateFlexibleMinutes))
+                                                                                        ||checkOutLocalTime.isEqual(offLocalDateTime.plusMinutes(lateFlexibleMinutes))){
+                                                                                        offStamp = offLocalDateTime.toEpochSecond(ZoneOffset.of("+8"));
+                                                                                        onStamp = onLocalDateTime.toEpochSecond(ZoneOffset.of("+8"));
+                                                                                        workSeconds = offStamp-onStamp;
+                                                                                }
+                                                                        }
+                                                                }
+
+                                                                if(checkOutLocalTime.isBefore(offLocalDateTime)){ //下班时间 在规定时间之前,查看下班是否在弹性,上班是否在弹性
+                                                                        long offStamp = checkOutLocalTime.toEpochSecond(ZoneOffset.of("+8"));
+                                                                        long onStamp = checkInLocalTime.toEpochSecond(ZoneOffset.of("+8"));
+                                                                        workSeconds = offStamp-onStamp;
+                                                                        //判断下班是否在弹性
+                                                                        boolean checkOutFlag = checkOutLocalTime.isAfter(offLocalDateTime.minusMinutes(earlyFlexibleMinutes))
+                                                                                || checkOutLocalTime.isEqual(offLocalDateTime.minusMinutes(earlyFlexibleMinutes));
+                                                                        if(checkOutFlag){
+                                                                                //在弹性下班范围内,判断上班
+                                                                                if(checkInLocalTime.isBefore(onLocalDateTime.minusMinutes(earlyFlexibleMinutes))
+                                                                                        ||checkInLocalTime.isEqual(onLocalDateTime.minusMinutes(earlyFlexibleMinutes))){
+                                                                                        offStamp = offLocalDateTime.toEpochSecond(ZoneOffset.of("+8"));
+                                                                                        onStamp = onLocalDateTime.toEpochSecond(ZoneOffset.of("+8"));
+                                                                                        workSeconds = offStamp-onStamp;
+                                                                                }
+                                                                        }
+                                                                }
+                                                        }
 
+                                                }
+                                        }
 
+                                        userFvTime.setStartTime(startTime);
+                                        userFvTime.setEndTime(endTime);
+                                        userFvTime.setWorkDate(LocalDate.parse(String.valueOf(day),DateTimeFormatter.ofPattern("yyyyMMdd")));
+                                        userFvTime.setCompanyId(jobNumUserMap.get(userTaskResult.getUser_id()).getCompanyId());
+//                                        userFvTime.setWorkHours(workHours);
+
+                                        //计算休息时长
+                                        int sumRestSecond = 0;
+                                        List<FeishuRestTimeRule> restTimeRule = null == shiftResult.getRest_time_rule()?new ArrayList<>():shiftResult.getRest_time_rule();
+                                        for (FeishuRestTimeRule feishuRestTimeRule : restTimeRule) {
+                                                LocalTime tmpBeginTime = LocalTime.parse(feishuRestTimeRule.getRest_begin_time(), DateTimeFormatter.ofPattern("HH:mm"));
+                                                LocalTime tmpEndTime = LocalTime.parse(feishuRestTimeRule.getRest_end_time(), DateTimeFormatter.ofPattern("HH:mm"));
+                                                sumRestSecond += tmpEndTime.toSecondOfDay() - tmpBeginTime.toSecondOfDay();
+                                        }
 
+                                        //获取加班时间段
+                                        //TODO 先不从班次规则里获取,直接类型为加班的记录相减
+                                        List<FeishuClockTaskRecord> overTimeList = userTaskResult.getRecords().stream().filter(t -> 1 == t.getTask_shift_type())
+                                                .collect(Collectors.toList());
+                                        long sumOverTimeSeconds = 0;
+                                        long offRuleSeconds = offLocalDateTime.toEpochSecond(ZoneOffset.of("+8"));
+                                        if(CollectionUtils.isNotEmpty(overTimeList)){
+                                                for (FeishuClockTaskRecord feishuClockTaskRecord : overTimeList) {
+                                                        long startOver = Long.parseLong(feishuClockTaskRecord.getCheck_in_record().getCheck_time());
+                                                        long endOver = Long.parseLong(feishuClockTaskRecord.getCheck_in_record().getCheck_time());
+                                                        startOver = Math.max(startOver, offRuleSeconds);
+                                                        sumOverTimeSeconds += endOver-startOver;
+                                                }
+                                        }
+//                                        float overTimeHours = BigDecimal.valueOf(sumOverTimeSeconds/ (60 * 60f)).setScale(2, RoundingMode.HALF_UP).floatValue();
+//                                        userFvTime.setOverTimeHours(overTimeHours);
+
+                                        float workHours = BigDecimal.valueOf((workSeconds - sumRestSecond + sumOverTimeSeconds) / (60 * 60f))
+                                                .setScale(2, RoundingMode.HALF_UP).floatValue();
+
+                                        userFvTime.setWorkHours(workHours);
+                                        userFvTime.setWorkDate(LocalDate.parse(String.valueOf(userTaskResult.getDay()), DateTimeFormatter.ofPattern("yyyyMMdd")));
+                                        //需要关联user表job_number
+                                        userFvTime.setUserId(jobNumUserMap.get(userTaskResult.getUser_id()).getId());
+                                        Date checkInTime = new Date(Long.parseLong(record.getCheck_in_record().getCheck_time()) * 1000);
+                                        Date checkOutTime = new Date(Long.parseLong(record.getCheck_out_record().getCheck_time()) * 1000);
+//                                        userFvTime.setStartTime(HMFormat.format(checkInTime));
+//                                        userFvTime.setEndTime(HMFormat.format(checkOutTime));
+
+                                        map.put("data",userFvTime);
+                                        map.put("startDateTime",format.format(checkInTime));
+                                        map.put("endDateTime",format.format(checkOutTime));
+                                        res.add(map);
+                                }
+                        }
 
-                                long secondCost = Long.parseLong(record.getCheck_out_record().getCheck_time())
-                                        -Long.parseLong(record.getCheck_in_record().getCheck_time());
-//                                                long hourCost = BigDecimal.valueOf(secondCost / (60 * 60))
-//                                                        .setScale(0, RoundingMode.UP).longValue();
-                                float hourCost = BigDecimal.valueOf(secondCost / (60 * 60f)).setScale(2, RoundingMode.HALF_UP).floatValue();
-                                userFvTime.setWorkHours(hourCost);
-                                userFvTime.setWorkDate(LocalDate.parse(String.valueOf(userTaskResult.getDay()), DateTimeFormatter.ofPattern("yyyyMMdd")));
-                                //需要关联user表job_number
-                                userFvTime.setUserId(jobNumIdMap.get(userTaskResult.getUser_id()));
-                                Date checkInTime = new Date(Long.parseLong(record.getCheck_in_record().getCheck_time()) * 1000);
-                                Date checkOutTime = new Date(Long.parseLong(record.getCheck_out_record().getCheck_time()) * 1000);
-                                userFvTime.setStartTime(HMFormat.format(checkInTime));
-                                userFvTime.setStartTime(HMFormat.format(checkOutTime));
+                        toAddFvTimeList.add(userFvTime);
+                }
 
-                                map.put("data",userFvTime);
-                                map.put("startDateTime",format.format(checkInTime));
-                                map.put("endDateTime",format.format(checkOutTime));
-                                res.add(map);
-                        }
+                if(CollectionUtils.isNotEmpty(toAddFvTimeList)){
+                        userFvTimeMapper.batchInsert(toAddFvTimeList);
                 }
+
+
                 msg.setData(res);
                 return msg;
         }

+ 11 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ProjectServiceImpl.java

@@ -2050,6 +2050,17 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
                                 .eq("group_audit_state", 1)//任务分组已审核,当前是项目经理审核
                                 .eq("project_id", id));
                     }
+                } else if (timeType.getReportAuditType() == 10) {
+                    if (inchargerChanged) {
+                        //项目经理变更,待审核的转移到新的项目经理身上
+                        Report updateItem = new Report();
+                        updateItem.setProjectAuditorId(inchargerId);
+                        reportMapper.update(updateItem, new QueryWrapper<Report>()
+                                .eq("company_id", companyId)
+                                .eq("project_auditor_id", oldInchargerId)
+                                .eq("state", 0)
+                                .eq("project_id", id));
+                    }
                 } else {
                     //其他审核情况,提取变化的部分
                     List<ProjectAuditor> oldAuditorList = projectAuditorMapper.selectList(new QueryWrapper<ProjectAuditor>().eq("project_id", id));

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

@@ -5957,7 +5957,7 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
                 //titles.add("工作事项");
                 titles.add(MessageUtils.message("excel.workItems"));
             }
-            if(stateKey==1){
+            if(stateKey==1 || stateKey==0 || stateKey==2){
                 //titles.add("审核状态");
                 titles.add(MessageUtils.message("excel.auditStatus"));
             }
@@ -6443,7 +6443,7 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
                 if (exportType==0) {
                     item.add((String) map.get("content"));
                 }
-                if(stateKey==1){
+                if(stateKey==1 || stateKey ==0 || stateKey==2){
                     Integer state = (Integer) map.get("state");
                     switch (state){
                         //case 0:row.createCell(index).setCellValue("待审核");

+ 4 - 7
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/UserServiceImpl.java

@@ -10,22 +10,17 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.management.platform.constant.Constant;
-import com.management.platform.controller.WeiXinCorpController;
 import com.management.platform.entity.*;
 import com.management.platform.entity.vo.SysRichFunction;
 import com.management.platform.entity.vo.UserVO;
 import com.management.platform.mapper.*;
 import com.management.platform.service.*;
 import com.management.platform.util.*;
-import jdk.nashorn.api.scripting.ScriptObjectMirror;
 import me.chanjar.weixin.mp.api.WxMpInMemoryConfigStorage;
 import me.chanjar.weixin.mp.api.WxMpService;
 import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl;
 import me.chanjar.weixin.mp.bean.template.WxMpTemplateData;
 import me.chanjar.weixin.mp.bean.template.WxMpTemplateMessage;
-import org.apache.commons.collections4.Put;
-import org.apache.commons.io.FileUtils;
-import org.apache.poi.hssf.usermodel.*;
 import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
 import org.apache.poi.ss.usermodel.*;
 import org.apache.poi.xssf.usermodel.XSSFCell;
@@ -35,12 +30,13 @@ import org.apache.poi.xssf.usermodel.XSSFWorkbook;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
-import org.springframework.http.*;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
 import org.springframework.ldap.core.LdapTemplate;
 import org.springframework.ldap.filter.EqualsFilter;
 import org.springframework.stereotype.Service;
 import org.springframework.util.StringUtils;
-import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.client.RestTemplate;
 import org.springframework.web.multipart.MultipartFile;
 import org.springframework.web.servlet.ModelAndView;
@@ -3193,6 +3189,7 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
                 if(optional.isPresent()){
                     optional.get().setIsActive(0);
                     userMapper.updateById(optional.get());
+                    participationMapper.delete(new LambdaQueryWrapper<Participation>().eq(Participation::getUserId,optional.get().getId()));
                 }
                 continue;
             }

+ 5 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/WxCorpInfoServiceImpl.java

@@ -2,6 +2,7 @@ package com.management.platform.service.impl;
 
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.fasterxml.jackson.databind.ObjectMapper;
@@ -170,6 +171,9 @@ public class WxCorpInfoServiceImpl extends ServiceImpl<WxCorpInfoMapper, WxCorpI
     @Resource
     WxCorpTemplateService wxCorpTemplateService;
 
+    @Resource
+    private ParticipationMapper participationMapper;
+
 
     //获取服务商provider_access_token
     @Override
@@ -964,6 +968,7 @@ public class WxCorpInfoServiceImpl extends ServiceImpl<WxCorpInfoMapper, WxCorpI
                 contactSyncLogMapper.insert(contactSyncLog);
                 user.setIsActive(0);//先同步过来,但是停用
                 userMapper.insert(user);
+                participationMapper.delete(new LambdaQueryWrapper<Participation>().eq(Participation::getUserId,user.getId()));
             }else {
                 userMapper.insert(user);
                 contactSyncLog.setResult(1);

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

@@ -1,21 +1,17 @@
 package com.management.platform.task;
 
-import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
-import com.baomidou.mybatisplus.core.injector.methods.SelectById;
-import com.management.platform.controller.WeiXinCorpController;
 import com.management.platform.entity.*;
-import com.management.platform.entity.Task;
-import com.management.platform.entity.vo.TokenVo;
 import com.management.platform.mapper.*;
 import com.management.platform.service.*;
-import com.management.platform.service.impl.WxCorpInfoServiceImpl;
 import com.management.platform.util.*;
-import com.management.platform.webservice.po.*;
-import jdk.nashorn.internal.ir.ContinueNode;
+import com.management.platform.webservice.po.ProjectQueryResponse;
+import com.management.platform.webservice.po.ProjectTask;
+import com.management.platform.webservice.po.ServiceProduct;
+import com.management.platform.webservice.po.XmlResponseData;
 import lombok.extern.slf4j.Slf4j;
 import me.chanjar.weixin.mp.api.WxMpInMemoryConfigStorage;
 import me.chanjar.weixin.mp.api.WxMpService;
@@ -29,7 +25,6 @@ import org.springframework.http.client.ClientHttpResponse;
 import org.springframework.scheduling.annotation.EnableScheduling;
 import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.stereotype.Component;
-import org.springframework.transaction.annotation.Transactional;
 import org.springframework.util.StringUtils;
 import org.springframework.web.client.DefaultResponseErrorHandler;
 import org.springframework.web.client.RestTemplate;
@@ -38,24 +33,17 @@ import javax.annotation.Resource;
 import java.io.File;
 import java.io.IOException;
 import java.math.BigDecimal;
-import java.math.RoundingMode;
 import java.security.SecureRandom;
-import java.sql.Time;
-import java.sql.Timestamp;
 import java.text.DecimalFormat;
 import java.time.*;
-import java.time.Period;
 import java.time.format.DateTimeFormatter;
-import java.time.temporal.TemporalAccessor;
 import java.time.temporal.TemporalAdjusters;
-import java.time.temporal.WeekFields;
 import java.util.*;
-import java.util.concurrent.*;
+import java.util.concurrent.Executor;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
 import java.util.stream.Collectors;
 import java.util.stream.IntStream;
-import java.util.stream.Stream;
-
-import static org.apache.logging.log4j.message.ParameterizedMessage.format;
 
 /**
  * Author: 吴涛涛
@@ -182,6 +170,8 @@ public class TimingTask {
     private BeisenConfigMapper beisenConfigMapper;
     @Resource
     private HolidaySettingService holidaySettingService;
+    @Resource
+    private ParticipationMapper participationMapper;
 
 
     private static final List<Integer> VALID_TOKEN_CHARS = new ArrayList<>();
@@ -827,6 +817,7 @@ public class TimingTask {
                         User u = optional.get();
                         u.setIsActive(0);
                         userMapper.updateById(optional.get());
+                        participationMapper.delete(new LambdaQueryWrapper<Participation>().eq(Participation::getUserId,u.getId()));
                     }
                     continue;
                 }

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

@@ -66,6 +66,8 @@ spring:
     base:
       dcFirst: yurk
       dcSecond: cn
+#  profiles:
+#    active: dev
 ##########日志配置
 logging:
   level:

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

@@ -158,7 +158,7 @@ finance.skipData=跳过以下已审核数据:{0}。
 finance.importErrorByAllAdopt=本次数据全部已审核通过,无法导入。
 finance.review=专业审核
 finance.dept=部门审核
-finance.hasApprovedReport=已存在审核人审核通过,无法撤回。请联系管理员操作
+finance.hasApprovedReport=请联系审核人撤销审核后修改
 # pdf相关
 pdf.previewError=该格式不支持在线预览
 # 日报相关

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

@@ -158,7 +158,7 @@ finance.skipData=Skipping the following audited data: '{0}'.
 finance.importErrorByAllAdopt=This data has been approved and cannot be imported.
 finance.review=Professional review
 finance.dept=Department review
-finance.hasApprovedReport=Some daily reports have been approved, unable to operate. Please contact your system manager.
+finance.hasApprovedReport=Please contact the auditor to reject your report.
 # pdf相关
 pdf.previewError=This format does not support online preview.
 # 日报相关

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

@@ -13,6 +13,12 @@
     <sql id="Base_Column_List">
         id, user_id, project_id
     </sql>
+    <delete id="deleteBatchByUserId">
+        delete from participation where user_id in
+        <foreach collection="userIds" item="userId" separator="," open="(" close=")">
+            #{userId}
+        </foreach>
+    </delete>
 
     <!--根据项目id获取所有参与者id和name-->
     <select id="getParticipator" resultType="java.util.Map">

+ 8 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/UserFvTimeMapper.xml

@@ -19,4 +19,12 @@
         id, work_date, user_id, company_id, start_time, end_time, work_hours, cancel_normal
     </sql>
 
+    <insert id="batchInsert">
+        insert into user_fv_time(work_date, user_id, company_id, start_time, end_time, work_hours, overtime_hours)
+        values
+            <foreach collection="toAddList" item="toAdd" separator=",">
+            (#{toAdd.workDate},#{toAdd.userId},#{toAdd.companyId},#{toAdd.startTime},#{toAdd.endTime},#{toAdd.workHours},#{toAdd.overTimeHours})
+            </foreach>
+    </insert>
+
 </mapper>

+ 132 - 100
fhKeeper/formulahousekeeper/timesheet/src/views/project/costReportExport.vue

@@ -3,129 +3,144 @@
     :before-close="handleClose">
     <el-form ref="exportFormRef" :model="exportParam">
       <!-- 头部 -->
-      <div style="text-align: center;margin-bottom: 20px">
+      <div style="text-align: center;margin-bottom: 20px" v-if="singleChoiceType != '设备'">
         <el-radio-group size="medium" v-model="exportParam.reportType">
           <el-radio-button :label="0">常规报表</el-radio-button>
           <el-radio-button :label="1">月度报表</el-radio-button>
         </el-radio-group>
       </div>
-      <!-- 常规报表 -->
-      <template v-if="exportParam.reportType == 0">
 
-        <el-form-item prop="projectCategoryId" :label="$t('projectclassification')"
-          v-if="singleChoiceType == $t('projectclassification') || singleChoiceType == $t('other.project')">
-          <el-select v-model="exportParam.projectCategoryId" :placeholder="$t('classificationitems')" clearable
-            style="width:350px;" filterable="true" @change="filterCategory">
-            <el-option v-for="item in categoryList" :key="item.id" :label="item.name" :value="item.id">
-            </el-option>
-          </el-select>
-        </el-form-item>
+      <template v-if="singleChoiceType != '设备'">
+        <!-- 常规报表 -->
+        <template v-if="exportParam.reportType == 0">
 
-        <el-form-item prop="projectId" :label="'选择项目'" v-if="!['人员', '项目分类', '部门', '主项目'].includes(singleChoiceType)">
-          <select-project v-model="exportParam.projectId" :size="'medium'" :placeholder="'全部项目'" width="350px"
-            clearable></select-project>
-        </el-form-item>
+          <el-form-item prop="projectCategoryId" :label="$t('projectclassification')"
+            v-if="singleChoiceType == $t('projectclassification') || singleChoiceType == $t('other.project')">
+            <el-select v-model="exportParam.projectCategoryId" :placeholder="$t('classificationitems')" clearable
+              style="width:350px;" filterable="true" @change="filterCategory">
+              <el-option v-for="item in categoryList" :key="item.id" :label="item.name" :value="item.id">
+              </el-option>
+            </el-select>
+          </el-form-item>
 
-        <el-form-item prop="exportContent" :label="$t('daoChuNeiRon')"
-          v-if="permissions.countCost && permissions.countHours && (['项目', '项目分类'].includes(singleChoiceType))">
-          <el-select v-model="exportParam.exportContent" style="width:350px;" filterable="true"
-            popper-class="projectSelectPopperClass">
-            <el-option :label="$t('gongShiHeChengBen')" value="hoursAndCost"></el-option>
-            <el-option :label="$t('jingGongShi')" value="hours"></el-option>
-            <el-option :label="$t('jingChenBen')" value="cost"></el-option>
-          </el-select>
-        </el-form-item>
+          <el-form-item prop="projectId" :label="'选择项目'" v-if="!['人员', '项目分类', '部门', '主项目'].includes(singleChoiceType)">
+            <select-project v-model="exportParam.projectId" :size="'medium'" :placeholder="'全部项目'" width="350px"
+              clearable></select-project>
+          </el-form-item>
 
-        <el-form-item :label="$t('departmentchoice')" v-if="singleChoiceType == $t('other.project')">
-          <el-cascader v-if="user.userNameNeedTranslate != 1" v-model="exportParam.deptId" :options="departmentList"
-            :placeholder="$t('defaultText.pleaseChoose')" :props="{ checkStrictly: true, expandTrigger: 'hover' }"
-            clearable filterable style="width:350px;"></el-cascader>
+          <el-form-item prop="exportContent" :label="$t('daoChuNeiRon')"
+            v-if="permissions.countCost && permissions.countHours && (['项目', '项目分类'].includes(singleChoiceType))">
+            <el-select v-model="exportParam.exportContent" style="width:350px;" filterable="true"
+              popper-class="projectSelectPopperClass">
+              <el-option :label="$t('gongShiHeChengBen')" value="hoursAndCost"></el-option>
+              <el-option :label="$t('jingGongShi')" value="hours"></el-option>
+              <el-option :label="$t('jingChenBen')" value="cost"></el-option>
+            </el-select>
+          </el-form-item>
 
-          <vueCascader :size="'medium'" :widthStr="'350'" :clearable="true" :subject="departmentList" :radios="true"
-            :distinction="'1'" @vueCasader="vueCasader" v-if="user.userNameNeedTranslate == 1"></vueCascader>
-        </el-form-item>
+          <el-form-item :label="$t('departmentchoice')" v-if="singleChoiceType == $t('other.project')">
+            <el-cascader v-if="user.userNameNeedTranslate != 1" v-model="exportParam.deptId" :options="departmentList"
+              :placeholder="$t('defaultText.pleaseChoose')" :props="{ checkStrictly: true, expandTrigger: 'hover' }"
+              clearable filterable style="width:350px;"></el-cascader>
 
-        <el-form-item prop="userIds" :label="$t('screening.selectPeople')" v-if="singleChoiceType == $t('ren-yuan')">
-          <el-select v-if="user.userNameNeedTranslate != '1'" v-model="exportParam.userIds"
-            :placeholder="$t('lable.allStaff')" multiple="true" clearable style="width:350px;" filterable="true">
-            <el-option v-for="item in hasReportUserList" :key="item.id" :label="item.name" :value="item.id"></el-option>
-          </el-select>
+            <vueCascader :size="'medium'" :widthStr="'350'" :clearable="true" :subject="departmentList" :radios="true"
+              :distinction="'1'" @vueCasader="vueCasader" v-if="user.userNameNeedTranslate == 1"></vueCascader>
+          </el-form-item>
 
-          <selectCat v-if="user.userNameNeedTranslate == '1'" :size="'medium'" :widthStr="'350'" :filterable="true"
-            :subject="hasReportUserList" :clearable="true" :multiSelect="true" @selectCal="selectCal"
-            :distinction="'1'"></selectCat>
-        </el-form-item>
+          <el-form-item prop="userIds" :label="$t('screening.selectPeople')" v-if="singleChoiceType == $t('ren-yuan')">
+            <el-select v-if="user.userNameNeedTranslate != '1'" v-model="exportParam.userIds"
+              :placeholder="$t('lable.allStaff')" multiple="true" clearable style="width:350px;" filterable="true">
+              <el-option v-for="item in hasReportUserList" :key="item.id" :label="item.name" :value="item.id"></el-option>
+            </el-select>
 
-        <el-form-item prop="userIds" :label="$t('screening.selectPeople')"
-          v-if="['项目', '项目分类'].includes(singleChoiceType)">
-          <el-select v-if="user.userNameNeedTranslate != '1'" v-model="exportParam.userIds"
-            :placeholder="$t('lable.allStaff')" multiple="true" clearable style="width:350px;" filterable="true">
-            <el-option v-for="item in users" :key="item.id" :label="item.name" :value="item.id"></el-option>
-          </el-select>
+            <selectCat v-if="user.userNameNeedTranslate == '1'" :size="'medium'" :widthStr="'350'" :filterable="true"
+              :subject="hasReportUserList" :clearable="true" :multiSelect="true" @selectCal="selectCal"
+              :distinction="'1'"></selectCat>
+          </el-form-item>
 
-          <selectCat v-if="user.userNameNeedTranslate == '1'" :size="'medium'" :widthStr="'350'" :filterable="true"
-            :subject="users" :clearable="true" :multiSelect="true" @selectCal="selectCal" :distinction="'1'">
-          </selectCat>
-        </el-form-item>
+          <el-form-item prop="userIds" :label="$t('screening.selectPeople')"
+            v-if="['项目', '项目分类'].includes(singleChoiceType)">
+            <el-select v-if="user.userNameNeedTranslate != '1'" v-model="exportParam.userIds"
+              :placeholder="$t('lable.allStaff')" multiple="true" clearable style="width:350px;" filterable="true">
+              <el-option v-for="item in users" :key="item.id" :label="item.name" :value="item.id"></el-option>
+            </el-select>
 
-        <el-form-item prop="projectId"
-          :label="user.timeType.fixMonthcost == 0 ? $t('time.dateRange') : $t('Selectmonth')">
-          <el-date-picker v-show="user.timeType.fixMonthcost == 0" v-model="exportParam.dateRange" :editable="false"
-            format="yyyy-MM-dd" value-format="yyyy-MM-dd" :clearable="false" :range-separator="$t('other.to')"
-            type="daterange" :start-placeholder="$t('time.startDate')"
-            :end-placeholder="$t('time.endDate')"></el-date-picker>
+            <selectCat v-if="user.userNameNeedTranslate == '1'" :size="'medium'" :widthStr="'350'" :filterable="true"
+              :subject="users" :clearable="true" :multiSelect="true" @selectCal="selectCal" :distinction="'1'">
+            </selectCat>
+          </el-form-item>
 
+          <el-form-item prop="projectId"
+            :label="user.timeType.fixMonthcost == 0 ? $t('time.dateRange') : $t('Selectmonth')">
+            <el-date-picker v-show="user.timeType.fixMonthcost == 0" v-model="exportParam.dateRange" :editable="false"
+              format="yyyy-MM-dd" value-format="yyyy-MM-dd" :clearable="false" :range-separator="$t('other.to')"
+              type="daterange" :start-placeholder="$t('time.startDate')"
+              :end-placeholder="$t('time.endDate')"></el-date-picker>
 
-          <el-date-picker v-show="user.timeType.fixMonthcost == 1" v-model="dateRange" :editable="false"
-            format="yyyy-MM" value-format="yyyy-MM" @change="getEchart" :clearable="true" type="month"></el-date-picker>
-        </el-form-item>
 
-        <el-form-item :label="$t('screening.selectPeople')" v-if="false">
-          <el-select v-if="user.userNameNeedTranslate != '1'" v-model="exportParam.userId"
-            :placeholder="$t('lable.allStaff')" style="width: 350px" filterable="true" clearable="true">
-            <span v-for="(item, index) in users" :key="index">
-              <el-option :label="item.name" :value="item.id"></el-option>
-            </span>
-          </el-select>
+            <el-date-picker v-show="user.timeType.fixMonthcost == 1" v-model="dateRange" :editable="false"
+              format="yyyy-MM" value-format="yyyy-MM" @change="getEchart" :clearable="true" type="month"></el-date-picker>
+          </el-form-item>
 
-          <selectCat v-if="user.userNameNeedTranslate == '1'" :size="'medium'" :distinction="'4'" :widthStr="'350'"
-            :subject="users" :clearable="true" @selectCal="selectCal"></selectCat>
-        </el-form-item>
+          <el-form-item :label="$t('screening.selectPeople')" v-if="false">
+            <el-select v-if="user.userNameNeedTranslate != '1'" v-model="exportParam.userId"
+              :placeholder="$t('lable.allStaff')" style="width: 350px" filterable="true" clearable="true">
+              <span v-for="(item, index) in users" :key="index">
+                <el-option :label="item.name" :value="item.id"></el-option>
+              </span>
+            </el-select>
 
-        <el-form-item prop="type" :label="$t('choosethestyle')" v-if="['项目', '项目分类'].includes(singleChoiceType)">
-          <el-select v-model="exportParam.type" :placeholder="$t('choosethestyle')" style="width:350px;">
-            <el-option
-              :label="singleChoiceType == $t('projectclassification') ? $t('classifiedontheline') : $t('Itemontheline')"
-              value="0"></el-option>
-            <el-option
-              :label="singleChoiceType == $t('projectclassification') ? $t('classifiedcolumns') : $t('itemisonthecolumn')"
-              value="1"></el-option>
-          </el-select>
-          <div class="prompt">
-            <el-popover placement="top" width="1200" trigger="hover">
-              <img src="../../assets/image/hanglie.png" alt="" width="100%"
-                v-if="this.singleChoiceType != $t('projectclassification')">
-              <img src="../../assets/image/hanglie_corp.png" alt="" width="100%" v-else>
-              <i class="el-icon-question" slot="reference" />
-            </el-popover>
-          </div>
-        </el-form-item>
+            <selectCat v-if="user.userNameNeedTranslate == '1'" :size="'medium'" :distinction="'4'" :widthStr="'350'"
+              :subject="users" :clearable="true" @selectCal="selectCal"></selectCat>
+          </el-form-item>
 
-        <el-form-item
-          v-if="exportParam.type == 1 && permissions.countHours && (singleChoiceType == $t('other.project'))">
-          <el-checkbox v-model="exportParam.withPercent">{{ $t('gongHhiZhanbiXmu') }}</el-checkbox>
-        </el-form-item>
+          <el-form-item prop="type" :label="$t('choosethestyle')" v-if="['项目', '项目分类'].includes(singleChoiceType)">
+            <el-select v-model="exportParam.type" :placeholder="$t('choosethestyle')" style="width:350px;">
+              <el-option
+                :label="singleChoiceType == $t('projectclassification') ? $t('classifiedontheline') : $t('Itemontheline')"
+                value="0"></el-option>
+              <el-option
+                :label="singleChoiceType == $t('projectclassification') ? $t('classifiedcolumns') : $t('itemisonthecolumn')"
+                value="1"></el-option>
+            </el-select>
+            <div class="prompt">
+              <el-popover placement="top" width="1200" trigger="hover">
+                <img src="../../assets/image/hanglie.png" alt="" width="100%"
+                  v-if="this.singleChoiceType != $t('projectclassification')">
+                <img src="../../assets/image/hanglie_corp.png" alt="" width="100%" v-else>
+                <i class="el-icon-question" slot="reference" />
+              </el-popover>
+            </div>
+          </el-form-item>
 
-        <el-form-item v-if="['项目', '项目分类', '主项目'].includes(singleChoiceType) && exportParam.type == '0'">
-          <el-checkbox v-model="exportParam.projectSum">{{ $t('individualprojectdata') }}</el-checkbox>
-        </el-form-item>
+          <el-form-item
+            v-if="exportParam.type == 1 && permissions.countHours && (singleChoiceType == $t('other.project'))">
+            <el-checkbox v-model="exportParam.withPercent">{{ $t('gongHhiZhanbiXmu') }}</el-checkbox>
+          </el-form-item>
 
-        <el-form-item v-if="singleChoiceType == $t('ren-yuan') && user.timeType.mainProjectState == 1">
-          <el-checkbox v-model="exportParam.mainProjectColumn">{{ $t('hanZhuXiangMu') }}</el-checkbox>
-        </el-form-item>
+          <el-form-item v-if="['项目', '项目分类', '主项目'].includes(singleChoiceType) && exportParam.type == '0'">
+            <el-checkbox v-model="exportParam.projectSum">{{ $t('individualprojectdata') }}</el-checkbox>
+          </el-form-item>
+
+          <el-form-item v-if="singleChoiceType == $t('ren-yuan') && user.timeType.mainProjectState == 1">
+            <el-checkbox v-model="exportParam.mainProjectColumn">{{ $t('hanZhuXiangMu') }}</el-checkbox>
+          </el-form-item>
+        </template>
+        <!-- 月度报表 -->
+        <template v-if="exportParam.reportType == 1">
+          <el-form-item prop="date" :label="this.$t('Selectmonth')">
+            <el-date-picker size="small" v-model="exportParam.date" :editable="false" format="yyyy-MM"
+              value-format="yyyy-MM" :clearable="false" type="month" :placeholder="$t('Selectmonth')"
+              style="margin-right: 20px"></el-date-picker>
+          </el-form-item>
+        </template>
       </template>
-      <!-- 月度报表 -->
-      <template v-if="exportParam.reportType == 1">
+      
+      <template v-if="singleChoiceType == '设备'">
+        <el-form-item prop="projectId" :label="'选择项目'">
+          <select-project v-model="exportParam.projectId" :size="'medium'" :placeholder="'全部项目'" width="350px"
+            clearable></select-project>
+        </el-form-item>
         <el-form-item prop="date" :label="this.$t('Selectmonth')">
           <el-date-picker size="small" v-model="exportParam.date" :editable="false" format="yyyy-MM"
             value-format="yyyy-MM" :clearable="false" type="month" :placeholder="$t('Selectmonth')"
@@ -137,7 +152,9 @@
     <!-- 导出按钮 -->
     <div slot="footer" class="dialog-footer">
       <el-button type="primary" @click="exportParam.reportType == 0 ? exportProjectData() : exportMonthlyProjectData()"
-        style="width:100%;" :loading="exporting">{{ $t('export.export') }}</el-button>
+        style="width:100%;" :loading="exporting" v-if="singleChoiceType != '设备'">{{ $t('export.export') }}</el-button>
+      <el-button type="primary" @click="deviceExport()"
+        style="width:100%;" :loading="exporting" v-if="singleChoiceType == '设备'">{{ $t('export.export') }}</el-button>
     </div>
   </el-dialog>
 </template>
@@ -200,6 +217,21 @@ export default {
     }
   },
   methods: {
+    deviceExport() {
+      var url = '/device-log/exportDeviceTimeCostByMonth';
+      var fileName = this.exportParam.date + '设备月度统计表.xlsx';
+      const { projectId, date } = this.exportParam
+      this.exporting = true;
+      this.postData(url, { projectId, date }).then((res) => {
+        const aTag = document.createElement('a');
+        aTag.download = fileName;
+        aTag.href = res.data;
+        aTag.click()
+      }).finally(() => {
+        this.exporting = false
+        this.updateValue()
+      })
+    },
     exportMonthlyProjectData() {
       var url = '/project/exportTimeByProjectAndEmployee';
       var fileName = this.exportParam.date + '月度工时统计表.xlsx';