Browse Source

增加企业微信,批量填报,项目导入功能

seyason 3 years ago
parent
commit
a2511b31ad
97 changed files with 4368 additions and 232 deletions
  1. 35 1
      fhKeeper/formulahousekeeper/management-platform/pom.xml
  2. 5 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/aop/AopLogConfiguration.java
  3. 35 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/config/BeanConfig.java
  4. 88 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/config/RefererInterceptor.java
  5. 23 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/config/RefererProperties.java
  6. 28 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/config/WebConfig.java
  7. 21 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/CompanyDingdingController.java
  8. 13 2
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/DepartmentController.java
  9. 21 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/DepartmentDingdingController.java
  10. 96 35
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/DingDingController.java
  11. 36 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/ExpenseTypeController.java
  12. 53 1
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/ProjectController.java
  13. 1 1
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/ProjectTimerController.java
  14. 167 49
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/ReportController.java
  15. 21 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/SysConfigController.java
  16. 1 1
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/SysRoleController.java
  17. 15 6
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/UserController.java
  18. 21 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/UserVcodeController.java
  19. 497 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/WeiXinCorpController.java
  20. 21 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/WxCorpInfoController.java
  21. 5 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/CompanyCustomerContact.java
  22. 63 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/CompanyDingding.java
  23. 57 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/DepartmentDingding.java
  24. 7 1
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/ExpenseItem.java
  25. 48 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/ExpenseType.java
  26. 41 7
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/Project.java
  27. 46 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/SysConfig.java
  28. 25 2
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/User.java
  29. 52 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/UserVcode.java
  30. 4 1
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/VcompanyCustomerContact.java
  31. 84 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/WxCorpInfo.java
  32. 1 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/vo/ProjectVO.java
  33. 16 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/mapper/CompanyDingdingMapper.java
  34. 16 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/mapper/DepartmentDingdingMapper.java
  35. 1 1
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/mapper/DepartmentMapper.java
  36. 16 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/mapper/ExpenseTypeMapper.java
  37. 5 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/mapper/ProjectMapper.java
  38. 3 1
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/mapper/ReportMapper.java
  39. 16 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/mapper/SysConfigMapper.java
  40. 4 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/mapper/TaskMapper.java
  41. 16 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/mapper/UserVcodeMapper.java
  42. 16 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/mapper/WxCorpInfoMapper.java
  43. 16 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/CompanyDingdingService.java
  44. 16 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/DepartmentDingdingService.java
  45. 2 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/DepartmentService.java
  46. 13 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/DingDingService.java
  47. 16 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/ExpenseTypeService.java
  48. 19 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/ProjectService.java
  49. 2 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/ReportService.java
  50. 16 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/SysConfigService.java
  51. 6 2
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/UserService.java
  52. 16 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/UserVcodeService.java
  53. 16 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/WxCorpInfoService.java
  54. 20 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/CompanyDingdingServiceImpl.java
  55. 20 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/DepartmentDingdingServiceImpl.java
  56. 160 39
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/DepartmentServiceImpl.java
  57. 511 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/DingDingServiceImpl.java
  58. 2 2
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ExpenseSheetServiceImpl.java
  59. 20 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ExpenseTypeServiceImpl.java
  60. 39 24
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/FinanceServiceImpl.java
  61. 407 2
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ProjectServiceImpl.java
  62. 19 22
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ReportServiceImpl.java
  63. 20 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/SysConfigServiceImpl.java
  64. 208 11
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/UserServiceImpl.java
  65. 20 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/UserVcodeServiceImpl.java
  66. 20 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/WxCorpInfoServiceImpl.java
  67. 6 3
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/task/TimingTask.java
  68. 10 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/util/Constant.java
  69. 13 4
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/util/ExcelUtil.java
  70. 38 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/util/MD5Util.java
  71. 73 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/util/Sha1Util.java
  72. 53 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/util/SmsUtil.java
  73. 59 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/qq/weixin/mp/aes/AesException.java
  74. 26 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/qq/weixin/mp/aes/ByteGroup.java
  75. 67 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/qq/weixin/mp/aes/PKCS7Encoder.java
  76. 61 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/qq/weixin/mp/aes/SHA1.java
  77. 289 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/qq/weixin/mp/aes/WXBizMsgCrypt.java
  78. 106 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/qq/weixin/mp/aes/XMLParse.java
  79. 20 0
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/application.yml
  80. BIN
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/lib/taobao-sdk-java-auto_1479188381469-20210623.jar
  81. 21 0
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/CompanyDingdingMapper.xml
  82. 20 0
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/DepartmentDingdingMapper.xml
  83. 16 5
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/DepartmentMapper.xml
  84. 2 1
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/ExpenseItemMapper.xml
  85. 17 0
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/ExpenseTypeMapper.xml
  86. 31 2
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/ProjectMapper.xml
  87. 10 3
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/ReportMapper.xml
  88. 18 0
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/SysConfigMapper.xml
  89. 17 0
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/TaskMapper.xml
  90. 7 3
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/UserMapper.xml
  91. 18 0
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/UserVcodeMapper.xml
  92. 26 0
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/WxCorpInfoMapper.xml
  93. BIN
      fhKeeper/formulahousekeeper/management-platform/导入成本6月份(1).xlsx
  94. BIN
      fhKeeper/formulahousekeeper/management-platform/财务人员成本模板 (1)(1).xlsx
  95. BIN
      fhKeeper/formulahousekeeper/management-platform/财务人员成本模板 (1).xlsx
  96. BIN
      fhKeeper/formulahousekeeper/management-platform/项目任务导入模板.xlsx
  97. BIN
      fhKeeper/formulahousekeeper/management-platform/项目导入模板 .xlsx

+ 35 - 1
fhKeeper/formulahousekeeper/management-platform/pom.xml

@@ -84,7 +84,18 @@
             <scope>system</scope>
             <systemPath>${basedir}/src/main/resources/lib/jodconverter-core-3.0.jar</systemPath>
         </dependency>
-
+        <dependency>
+            <groupId>com.dingtalk</groupId>
+            <artifactId>taobao-sdk-java-auto_1479188381469-20210623.jar</artifactId>
+            <version>1.0</version>
+            <scope>system</scope>
+            <systemPath>${basedir}/src/main/resources/lib/taobao-sdk-java-auto_1479188381469-20210623.jar</systemPath>
+        </dependency>
+        <dependency>
+            <groupId>com.aliyun</groupId>
+            <artifactId>dingtalk</artifactId>
+            <version>1.1.50</version>
+        </dependency>
         <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-data-redis</artifactId>
@@ -137,6 +148,17 @@
             <artifactId>weixin-java-mp</artifactId>
             <version>3.3.0</version>
         </dependency>
+
+        <dependency>
+            <groupId>com.aliyun</groupId>
+            <artifactId>dysmsapi20170525</artifactId>
+            <version>2.0.4</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-configuration-processor</artifactId>
+            <optional>true</optional>
+        </dependency>
     </dependencies>
 
     <build>
@@ -164,6 +186,18 @@
                 <enabled>false</enabled>
             </snapshots>
         </repository>
+        <repository>
+            <id>bintray-qcloud-maven-repo</id>
+            <name>qcloud-maven-repo</name>
+            <url>https://dl.bintray.com/qcloud/maven-repo/</url>
+            <layout>default</layout>
+            <releases>
+                <enabled>true</enabled>
+            </releases>
+            <snapshots>
+                <enabled>false</enabled>
+            </snapshots>
+        </repository>
     </repositories>
 
     <pluginRepositories>

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

@@ -32,6 +32,7 @@ public class AopLogConfiguration {
     @Before("logPointcut()")
     public void  methodBefore(JoinPoint joinPoint){
         ServletRequestAttributes requestAttributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
+        if (requestAttributes == null) return;
         HttpServletRequest request = requestAttributes.getRequest();
         if(request.getRequestURL().toString().contains("/imageProcessing")){
             return;
@@ -49,6 +50,7 @@ public class AopLogConfiguration {
     @AfterReturning(returning = "o",pointcut = "logPointcut()")
     public void methodAfterReturning(Object o){
         ServletRequestAttributes requestAttributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
+        if (requestAttributes == null) return;
         HttpServletRequest request = requestAttributes.getRequest();
         if(request.getRequestURL().toString().contains("/imageProcessing")){
             return;
@@ -61,6 +63,9 @@ public class AopLogConfiguration {
     @AfterThrowing(pointcut = "logPointcut()",throwing = "e")
     public void logThrowing(JoinPoint joinPoint,Throwable e){
         ServletRequestAttributes requestAttributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
+        if (requestAttributes == null) {
+            return ;
+        }
         HttpServletRequest request = requestAttributes.getRequest();
         if(request.getRequestURL().toString().contains("/imageProcessing")){
             return;

+ 35 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/config/BeanConfig.java

@@ -0,0 +1,35 @@
+package com.management.platform.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.task.TaskExecutor;
+import org.springframework.scheduling.annotation.EnableAsync;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
+
+import java.util.concurrent.ThreadPoolExecutor;
+
+@Configuration
+@EnableAsync
+public class BeanConfig {
+
+    @Bean
+    public TaskExecutor taskExecutor() {
+        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
+        // 设置核心线程数
+        executor.setCorePoolSize(5);
+        // 设置最大线程数
+        executor.setMaxPoolSize(10);
+        // 设置队列容量
+        executor.setQueueCapacity(20);
+        // 设置线程活跃时间(秒)
+        executor.setKeepAliveSeconds(60);
+        // 设置默认线程名称
+        executor.setThreadNamePrefix("worktime-");
+        // 设置拒绝策略
+        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
+        // 等待所有任务结束后再关闭线程池
+        executor.setWaitForTasksToCompleteOnShutdown(true);
+        System.out.println("初始化TaskExecutor");
+        return executor;
+    }
+}

+ 88 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/config/RefererInterceptor.java

@@ -0,0 +1,88 @@
+package com.management.platform.config;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.util.AntPathMatcher;
+import org.springframework.util.StringUtils;
+import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.net.MalformedURLException;
+
+public class RefererInterceptor extends HandlerInterceptorAdapter {
+    static final Logger LOGGER = LoggerFactory.getLogger(RefererInterceptor.class);
+
+    // URL匹配器
+    private AntPathMatcher matcher = new AntPathMatcher();
+    @Resource
+    private RefererProperties properties;
+
+    @Value(value = "${excludeUrls}")
+    private String excludeUrls;
+
+    @Override
+    public boolean preHandle(HttpServletRequest req, HttpServletResponse resp, Object handler) throws Exception {
+        String referer = req.getHeader("referer");
+        String host = req.getServerName();
+        //对外开放的回调url排除在外
+        String reqUrl = req.getRequestURI();
+        System.out.println(reqUrl);
+        if (!StringUtils.isEmpty(excludeUrls)) {
+            String[] split = excludeUrls.split(",");
+            boolean isPass = false;
+            for (String pattern: split) {
+                System.out.println(""+pattern+", "+reqUrl);
+                if (matcher.match(pattern, reqUrl)) {
+                    isPass = true;
+                    break;
+                }
+            }
+            if (isPass) {
+                System.out.println("开放请求,不检查Referer");
+                return true;
+            }
+        }
+        // 只验证POST请求
+        if ("POST".equals(req.getMethod())) {
+            if (referer == null) {
+                System.out.println("===referer为Null, 返回404,拦截==");
+                // 状态置为404
+                resp.setStatus(HttpServletResponse.SC_NOT_FOUND);
+                return false;
+            }
+            java.net.URL url = null;
+            try {
+                url = new java.net.URL(referer);
+            } catch (MalformedURLException e) {
+                // URL解析异常,也置为404
+                resp.setStatus(HttpServletResponse.SC_NOT_FOUND);
+                return false;
+            }
+            LOGGER.info("host="+host+", refer host="+url.getHost());
+            boolean isSame = false;
+            if (host.equals(url.getHost())) {
+                isSame = true;
+            }
+            // 首先判断请求域名和referer域名是否相同
+            if (!isSame) {
+                // 如果不等,判断是否在白名单中
+                LOGGER.info("properties.getRefererDomain()=="+properties.getRefererDomain());
+                if (properties.getRefererDomain() != null) {
+                    LOGGER.info("request from Host="+url.getHost()+", REF="+url.getRef());
+                    for (String s : properties.getRefererDomain()) {
+                        if (s.equals(url.getHost())) {
+                            return true;
+                        }
+                    }
+                }
+                return false;
+            }
+        }
+        return true;
+    }
+}
+

+ 23 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/config/RefererProperties.java

@@ -0,0 +1,23 @@
+package com.management.platform.config;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+
+@Component
+@ConfigurationProperties(prefix = "referer")
+public class RefererProperties {
+    // 白名单域名
+    private List<String> refererDomain;
+    //setter,getter方法
+
+
+    public List<String> getRefererDomain() {
+        return refererDomain;
+    }
+
+    public void setRefererDomain(List<String> refererDomain) {
+        this.refererDomain = refererDomain;
+    }
+}

+ 28 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/config/WebConfig.java

@@ -0,0 +1,28 @@
+package com.management.platform.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.config.annotation.EnableWebMvc;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+@EnableWebMvc
+@Configuration
+public class WebConfig implements WebMvcConfigurer {
+
+    @Bean
+    public RefererInterceptor refererInterceptor() {
+        return new RefererInterceptor();
+    }
+
+    /**
+     * 注册拦截器
+     */
+    @Override
+    public void addInterceptors(InterceptorRegistry registry) {
+        //referer拦截
+        registry.addInterceptor(refererInterceptor());
+    }
+
+
+}

+ 21 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/CompanyDingdingController.java

@@ -0,0 +1,21 @@
+package com.management.platform.controller;
+
+
+import org.springframework.web.bind.annotation.RequestMapping;
+
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * <p>
+ *  前端控制器
+ * </p>
+ *
+ * @author Seyason
+ * @since 2021-06-27
+ */
+@RestController
+@RequestMapping("/company-dingding")
+public class CompanyDingdingController {
+
+}
+

+ 13 - 2
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/DepartmentController.java

@@ -80,12 +80,23 @@ public class DepartmentController {
     }
 
     /**
-     * 获取某个部门人员的统计
+     * 获取某个部门或者公司全部的人员的统计
      * departmentId 要查询的项目
      */
     @RequestMapping("/userStatistic")
-    public HttpRespMsg getUserStatistics(String startDate, String endDate, @RequestParam Integer departmentId, HttpServletRequest request) {
+    public HttpRespMsg getUserStatistics(String startDate, String endDate, Integer departmentId, HttpServletRequest request) {
         return departmentService.getUserStatistics(startDate, endDate, departmentId, request);
     }
+
+    /**
+     * 按人员导出工时统计,可选人员
+     * departmentId 要查询的项目
+     */
+    @RequestMapping("/exportUserStatistic")
+    public HttpRespMsg exportUserStatistic(String startDate, String endDate, String userIds, HttpServletRequest request) {
+        return departmentService.exportUserStatistic(startDate, endDate, userIds, request);
+    }
+
+
 }
 

+ 21 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/DepartmentDingdingController.java

@@ -0,0 +1,21 @@
+package com.management.platform.controller;
+
+
+import org.springframework.web.bind.annotation.RequestMapping;
+
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * <p>
+ *  前端控制器
+ * </p>
+ *
+ * @author Seyason
+ * @since 2021-06-27
+ */
+@RestController
+@RequestMapping("/department-dingding")
+public class DepartmentDingdingController {
+
+}
+

+ 96 - 35
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/DingDingController.java

@@ -1,60 +1,42 @@
 package com.management.platform.controller;
 
 import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
-import com.management.platform.util.DingCallbackCrypto;
+import com.management.platform.service.DingDingService;
+import com.management.platform.util.*;
+import com.taobao.api.ApiException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.web.bind.annotation.*;
 
+import javax.annotation.Resource;
 import java.util.Map;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
 
 @RestController
-@RequestMapping("/")
+@RequestMapping("/dingding")
 public class DingDingController {
     private final Logger bizLogger = LoggerFactory.getLogger(getClass());
     String token = "cf776d62c5fb3508b5d8c2cbb9f3df0c";
     String aesKey = "ktmbamhymjsf60ndwp6n81mnu92847oynsgj9e0zr9v";
     String suiteKey = "suitejwoq9dw4bxv4stdb";
+    String suiteSecret = "o-TWFLkFe8YbJsa_025JOj_JEWydP5GR3eigt1Yn1rtx5dTcryTJiSA6KEih3Bi4";
 
-    @PostMapping(value = "dingCallback")
+    @Resource
+    private DingDingService dingDingService;
+    static ExecutorService executorService = Executors.newCachedThreadPool();
+
+    @RequestMapping("/callback")
     public Map<String, String> dingCallback(
             @RequestParam(value = "signature") String signature,
             @RequestParam(value = "timestamp") String timestamp,
             @RequestParam(value = "nonce") String nonce,
             @RequestBody(required = false) JSONObject body
     ) {
-//        String[] config = CommonUtil.readConfig();
-//        String params = "signature:" + signature + " timestamp:" + timestamp + " nonce:" + nonce + " body:" + body;
-//        DingTalkEncryptor dingTalkEncryptor = new DingTalkEncryptor(config[CommonUtil.TOKEN], config[CommonUtil.ENCODING_AES_KEY], config[CommonUtil.SUITE_KEY]);
-//
-//        // 从post请求的body中获取回调信息的加密数据进行解密处理,消息加解密参见下文
-//        String encrypt = body.getString("encrypt");
-//        String plainText = dingTalkEncryptor.getDecryptMsg(signature, timestamp.toString(), nonce, encrypt);
-//        JSONObject callBackContent = JSON.parseObject(plainText);
-//
-//        // 根据回调事件类型做不同的业务处理
-//        String eventType = callBackContent.getString("EventType");
-        //TODO 将数据持久化
-//        return plainText;
-//        try {
-//            DingCallbackCrypto encryptor = new DingCallbackCrypto(token, aesKey, suiteKey);
-//            String encrypt = body.getString("encrypt");
-//            String plainText = encryptor.getDecryptMsg(signature, timestamp.toString(), nonce, encrypt);
-//            JSONObject callBackContent = JSON.parseObject(plainText);
-//                    // 根据回调事件类型做不同的业务处理
-//            String eventType = callBackContent.getString("EventType");
-//            log.info("eventType=="+eventType);
-//            System.out.println("eventType=="+eventType);
-//            System.out.println("plainText=="+plainText);
-//
-//
-//            return plainText;
-//        } catch (DingCallbackCrypto.DingTalkEncryptException e) {
-//            e.printStackTrace();
-//            return e.getMessage();
-//        }
-
+        System.out.println("接收到ding call back");
+        bizLogger.info("接收到ding call back=" + body.toJSONString());
         try {
             // 1. 从http请求中获取加解密参数
 
@@ -71,7 +53,8 @@ public class DingDingController {
             // 3. 反序列化回调事件json数据
             JSONObject eventJson = JSON.parseObject(decryptMsg);
             String eventType = eventJson.getString("EventType");
-
+            bizLogger.info("DingDing回调触发了");
+            bizLogger.info(eventJson.toJSONString());
             // 4. 根据EventType分类处理
             if ("check_url".equals(eventType)) {
                 // 测试回调url的正确性
@@ -82,6 +65,71 @@ public class DingDingController {
             } else {
                 // 添加其他已注册的
                 bizLogger.info("发生了:" + eventType + "事件");
+                //推送suit ticket事件
+                /**
+                 * {
+                 *   "SuiteKey": "xxxxxx",
+                 *   "EventType": "suite_ticket ",
+                 *   "TimeStamp": 123456,
+                 *   "SuiteTicket": "xxxxxx"
+                 * }
+                 */
+                if ("suite_ticket".equals(eventType)) {
+                    dingDingService.updateSuiteTicket(eventJson.getString("SuiteTicket"));
+                } else if ("tmp_auth_code".equals(eventType)) {
+                    //企业授权开通应用
+                    /**
+                     * {
+                     *    "TimeStamp":1553709079062,
+                     *    "AuthCode": "xxxxxx",
+                     *    "AuthCorpId":"xxxxxx",
+                     *    "EventType":"tmp_auth_code",
+                     *    "SuiteKey":"xxxxxx"
+                     *  }
+                     */
+
+                } else if ("SYNC_HTTP_PUSH_HIGH".equals(eventType)) {
+                    /**
+                     * {"EventType":"SYNC_HTTP_PUSH_HIGH",
+                     * "bizData":[{"gmt_create":1624757980000,"biz_type":2,"open_cursor":0,
+                     * "subscribe_id":"16822005_0","id":15275,"gmt_modified":1624757980000,
+                     * "biz_id":"16822005",
+                     * "biz_data":"{\"syncAction\":\"suite_ticket\",
+                     * \"suiteTicket\":\"IaIbq7a9S36R2uAbUh02VNlWoMB2LkorhyFCFhdpSWxJPZhIsIEhxIoIS7HQRn0zxMGh57gGd56RRh2Ntmcuzq\",
+                     * \"syncSeq\":\"AE815E12E6908BDEE8CA8D33A9\"}","corp_id":"ding169917db7f1ee5f435c2f4657eb6378f","status":0}]}
+                     */
+                    JSONArray bizData = eventJson.getJSONArray("bizData");
+                    if (bizData.size() > 0) {
+                        for (int i=0;i<bizData.size(); i++) {
+                            JSONObject bizItem = bizData.getJSONObject(i);
+                            int bizType = bizItem.getInteger("biz_type");
+                            if (bizType == 2) {
+                                //SuteTicket推送事件
+                                JSONObject biz_data = JSONObject.parseObject(bizItem.getString("biz_data"));
+                                String syncAction = biz_data.getString("syncAction");
+                                if ("suite_ticket".equals(syncAction)) {
+                                    dingDingService.updateSuiteTicket(biz_data.getString("suiteTicket"));
+                                }
+                            } else if (bizType == 4) {
+                                //企业授权变更,包含授权、解除授权、授权变更。
+                                JSONObject biz_data = JSONObject.parseObject(bizItem.getString("biz_data"));
+                                String syncAction = biz_data.getString("syncAction");
+                                if ("org_suite_auth".equals(syncAction)) {
+                                    //开通授权应用
+                                    JSONObject authCorpInfo = biz_data.getJSONObject("auth_corp_info");
+                                    String corp_name = authCorpInfo.getString("corp_name");
+                                    String corpid = authCorpInfo.getString("corpid");
+                                    String authUserId = biz_data.getJSONObject("auth_user_info").getString("userId");
+                                    try {
+                                        dingDingService.corpAuth(corpid, corp_name, authUserId);
+                                    } catch (ApiException e) {
+                                        e.printStackTrace();
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
             }
 
             // 5. 返回success的加密数据
@@ -93,4 +141,17 @@ public class DingDingController {
         return null;
     }
 
+
+    @RequestMapping("/getUserByCode")
+    public HttpRespMsg getUserByCode(String code, String corpid) {
+        return dingDingService.getUserByCode(code, corpid);
+    }
+
+    @RequestMapping("/testAsync")
+    public HttpRespMsg testAsync() {
+        HttpRespMsg msg = new HttpRespMsg();
+        dingDingService.testAsync();
+        return msg;
+    }
+
 }

+ 36 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/ExpenseTypeController.java

@@ -0,0 +1,36 @@
+package com.management.platform.controller;
+
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.management.platform.entity.ExpenseType;
+import com.management.platform.mapper.ExpenseTypeMapper;
+import com.management.platform.util.HttpRespMsg;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+
+/**
+ * <p>
+ *  前端控制器
+ * </p>
+ *
+ * @author Seyason
+ * @since 2021-06-18
+ */
+@RestController
+@RequestMapping("/expense-type")
+public class ExpenseTypeController {
+    @Resource
+    private ExpenseTypeMapper expenseTypeMapper;
+
+    @RequestMapping("/getList")
+    public HttpRespMsg getList() {
+        HttpRespMsg msg = new HttpRespMsg();
+        msg.data = expenseTypeMapper.selectList(new QueryWrapper<>());
+        return msg;
+    }
+
+}
+

+ 53 - 1
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/ProjectController.java

@@ -8,6 +8,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.multipart.MultipartFile;
 
 import javax.annotation.Resource;
 import javax.servlet.http.HttpServletRequest;
@@ -127,7 +128,7 @@ public class ProjectController {
      * 导出查询者所在公司每个项目的工时成本
      */
     @RequestMapping("/exportTimeCost")
-    public HttpRespMsg exportTimeCost(@RequestParam String startDate, @RequestParam String endDate, Integer projectId) {
+    public HttpRespMsg exportTimeCost(String startDate, String endDate, Integer projectId) {
         return projectService.exportTimeCost(startDate, endDate, projectId, request);
     }
 
@@ -202,5 +203,56 @@ public class ProjectController {
         return projectService.addMemb(id, userId);
     }
 
+    @RequestMapping("/exportProfit")
+    public HttpRespMsg exportProfit() {
+        return projectService.exportProfit(request);
+    }
+
+    //导出项目报表
+    @RequestMapping("/exportProject")
+    public HttpRespMsg exportProject() {
+        return projectService.exportProject(request);
+    }
+
+    //分页查询项目任务报表
+    @RequestMapping("/getProjectTask")
+    public HttpRespMsg getProjectTask(@RequestParam Integer pageIndex, @RequestParam Integer pageSize) {
+        return projectService.getProjectTask(pageIndex, pageSize, request);
+    }
+    //导出项目任务报表
+    @RequestMapping("/exportProjectTask")
+    public HttpRespMsg exportProjectTask() {
+        return projectService.exportProjectTask(request);
+    }
+
+    //分页查询项目成本报表
+    @RequestMapping("/getAllProjectCost")
+    public HttpRespMsg getAllProjectCost(@RequestParam Integer pageIndex, @RequestParam Integer pageSize) {
+        return projectService.getAllProjectCost(pageIndex, pageSize, request);
+    }
+    //导出项目成本报表
+    @RequestMapping("/exportAllProjectCost")
+    public HttpRespMsg exportAllProjectCost() {
+        return projectService.exportAllProjectCost(request);
+    }
+
+
+    //分页查询项目收支平衡表
+    @RequestMapping("/getProjectInAndOut")
+    public HttpRespMsg getProjectInAndOut(@RequestParam Integer pageIndex, @RequestParam Integer pageSize) {
+        return projectService.getProjectInAndOut(pageIndex, pageSize, request);
+    }
+    //导出项目收支平衡表
+    @RequestMapping("/exportProjectInAndOut")
+    public HttpRespMsg exportProjectInAndOut() {
+        return projectService.exportProjectInAndOut(request);
+    }
+
+    @RequestMapping("/importData")
+    public HttpRespMsg importData(String userId, MultipartFile file, HttpServletRequest request) {
+        return projectService.importData(userId, file, request);
+    }
+
+
 }
 

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

@@ -132,7 +132,7 @@ public class ProjectTimerController {
             //计算时长
             long time = timer.getEndTime().toEpochSecond(ZoneOffset.ofHours(8)) - timer.getStartTime().toEpochSecond(ZoneOffset.ofHours(8));
             int minutes = (int)time/60;
-            double hours = minutes*1.0f/60;
+            double hours = (minutes*1.0f/60);
             report.setWorkingTime(hours);
             report.setCost(user.getCost().multiply(new BigDecimal(hours)));
 

+ 167 - 49
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/ReportController.java

@@ -1,10 +1,15 @@
 package com.management.platform.controller;
 
 
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.management.platform.entity.Report;
+import com.management.platform.entity.User;
+import com.management.platform.entity.UserSalary;
 import com.management.platform.service.ReportService;
+import com.management.platform.service.UserSalaryService;
 import com.management.platform.service.UserService;
 import com.management.platform.util.HttpRespMsg;
+import org.apache.log4j.helpers.DateTimeDateFormat;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestParam;
@@ -15,11 +20,13 @@ import javax.servlet.http.HttpServletRequest;
 import java.math.BigDecimal;
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
+import java.time.DayOfWeek;
 import java.time.LocalDate;
 import java.time.format.DateTimeFormatter;
 import java.util.ArrayList;
 import java.util.Date;
 import java.util.List;
+import java.util.stream.Collectors;
 
 /**
  * <p>
@@ -38,11 +45,18 @@ public class ReportController {
     private HttpServletRequest request;
     @Resource
     private UserService userService;
+    @Resource
+    private UserSalaryService userSalaryService;
 
     /**
      * 根据时间 按照人分类 获取报告信息
      * date 日期 格式yyyy-mm-dd
      */
+    @RequestMapping("/getReportFillStatus")
+    public HttpRespMsg getReportFillStatus(String startDate, String endDate, String userId) {
+        return reportService.getReportFillStatus(startDate, endDate, userId, request);
+    }
+
     @RequestMapping("/getReportList")
     public HttpRespMsg getReportList(@RequestParam String date, @RequestParam(required = false) Integer deptId, @RequestParam(required = false) String userId) {
         return reportService.getReportList(date, deptId, userId, request);
@@ -90,63 +104,167 @@ public class ReportController {
                                   Integer[] progress) {
         List<Report> reportList = new ArrayList<>();
         String token = request.getHeader("Token");
-        BigDecimal hourCost = userService.getById(token).getCost();
+        User user = userService.getById(token);
+        LocalDate now = LocalDate.now();
+        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+        BigDecimal hourCost = null;
+        if (user.getCostApplyDate() != null) {
+            //检查有效期
+            if (user.getCostApplyDate().compareTo(dtf.format(now)) > 0) {
+                //取上一个历史成本
+                List<UserSalary> list = userSalaryService.list(new QueryWrapper<UserSalary>().eq("user_id", user.getId()).orderByDesc("indate").last("limit 2"));
+                if (list.size() > 1) {
+                    hourCost = list.get(1).getCost();
+                } else {
+                    //没有记录,又没有达到预设的起效时间,则默认为0
+                    hourCost = new BigDecimal(0);
+                }
+            } else {
+                hourCost = user.getCost();
+            }
+        } else {
+            hourCost = user.getCost();
+        }
+
         if (hourCost == null) {
             hourCost = new BigDecimal(0);
         }
         SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
 
-
         try {
             for (int i = 0; i < id.length; i++) {
-                Report report = new Report()
-                        .setId(id[i] == -1 ? null : id[i])
-                        .setProjectId(projectId[i])
-                        .setSubProjectId(subProjectId[i] == 0?null:subProjectId[i])
-                        .setReportTimeType(reportTimeType[i])
-                        .setContent(content[i])
-                        .setState(0)
-                        .setCreateDate(LocalDate.parse(createDate[i], DateTimeFormatter.ofPattern("yyyy-MM-dd")))
-                        .setCreatorId(token);
-                if (taskId != null && taskId[i] != null && taskId[i] != 0) {
-                    report.setTaskId(taskId[i]);
-                }
-                if (isOvertime != null && isOvertime[i] != null) {
-                    report.setIsOvertime(isOvertime[i]);
-                }
-                if (progress != null && progress[i] != null) {
-                    report.setProgress(progress[i]);
-                }
-                if (report.getReportTimeType() == 0) {
-                    report.setWorkingTime(workingTime[i])
-                            .setCost(hourCost.multiply(new BigDecimal(workingTime[i])))
-                            .setTimeType(timeType[i]);
-                } else if (report.getReportTimeType() == 1) {
-                    report.setWorkingTime(workingTime[i])
-                            .setCost(hourCost.multiply(new BigDecimal(workingTime[i])));
-                } else if (report.getReportTimeType() == 2) {
-                    //时间范围填报, 计算一下时长
-                    try {
-                        report.setStartTime(startTime[i]).setEndTime(endTime[i]);
-                        long time = sdf.parse(report.getEndTime()).getTime() - sdf.parse(report.getStartTime()).getTime();
-                        int minutes = (int)time/1000/60;
-                        double hours = minutes*1.0f/60;
-                        report.setWorkingTime(hours);
-                        report.setCost(hourCost.multiply(new BigDecimal(hours)));
-                    } catch (ParseException e) {
-                        e.printStackTrace();
+                System.out.println("==@@"+createDate[i]+", "+createDate[i].contains("@"));
+                if (createDate[i].contains("@")) {
+                    DateTimeFormatter ddtf = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+                    DateTimeFormatter mdFormatter = DateTimeFormatter.ofPattern("MM-dd");
+                    System.out.println("============这是批量填报=");
+                    //这是批量填报的情况,日期有范围
+                    String[] dateArray = createDate[i].split("@");
+                    String startDate = dateArray[0];
+                    String endDate = dateArray[1];
+                    //检查该时间范围是否已经有填写过的日报了
+                    List<Report> oldReportList = reportService.list(new QueryWrapper<Report>().between("create_date", startDate, endDate).eq("creator_id", token));
+                    if (oldReportList.size() > 0) {
+                        List<LocalDate> collect = oldReportList.stream().map(Report::getCreateDate).collect(Collectors.toList());
+                        StringBuilder sb = new StringBuilder();
+                        collect.forEach(c->{
+                            sb.append(mdFormatter.format(c)).append(",");
+                        });
+                        String s = sb.toString();
+                        s = s.substring(0, s.length() -1);
+                        HttpRespMsg msg = new HttpRespMsg();
+                        msg.setError("已存在填写日报: " + s+", 请重新选择日期范围");
+                        return msg;
+                    }
+
+                    LocalDate localStartDate = LocalDate.parse(startDate, ddtf);
+                    LocalDate localEndDate = LocalDate.parse(endDate, ddtf);
+                    int daysOffset = 0;
+                    while(true) {
+                        localStartDate = localStartDate.plusDays(daysOffset);
+                        //跳过周末
+                        if (localStartDate.getDayOfWeek() != DayOfWeek.SATURDAY && localStartDate.getDayOfWeek() != DayOfWeek.SUNDAY) {
+                            Report report = new Report()
+                                    .setId(id[i] == -1 ? null : id[i])
+                                    .setProjectId(projectId[i])
+                                    .setSubProjectId(subProjectId[i] == 0?null:subProjectId[i])
+                                    .setReportTimeType(reportTimeType[i])
+                                    .setContent(content[i])
+                                    .setState(0)
+                                    .setCreateDate(localStartDate)
+                                    .setCreatorId(token);
+                            if (taskId != null && taskId[i] != null && taskId[i] != 0) {
+                                report.setTaskId(taskId[i]);
+                            }
+                            if (isOvertime != null && isOvertime[i] != null) {
+                                report.setIsOvertime(isOvertime[i]);
+                            }
+                            if (progress != null && progress[i] != null) {
+                                report.setProgress(progress[i]);
+                            }
+                            if (report.getReportTimeType() == 0) {
+                                report.setWorkingTime(workingTime[i])
+                                        .setCost(hourCost.multiply(new BigDecimal(workingTime[i])))
+                                        .setTimeType(timeType[i]);
+                            } else if (report.getReportTimeType() == 1) {
+                                report.setWorkingTime(workingTime[i])
+                                        .setCost(hourCost.multiply(new BigDecimal(workingTime[i])));
+                            } else if (report.getReportTimeType() == 2) {
+                                //时间范围填报, 计算一下时长
+                                try {
+                                    report.setStartTime(startTime[i]).setEndTime(endTime[i]);
+                                    long time = sdf.parse(report.getEndTime()).getTime() - sdf.parse(report.getStartTime()).getTime();
+                                    int minutes = (int)time/1000/60;
+                                    double hours = minutes*1.0f/60;
+                                    report.setWorkingTime(hours);
+                                    report.setCost(hourCost.multiply(new BigDecimal(hours)));
+                                } catch (ParseException e) {
+                                    e.printStackTrace();
+                                }
+                            } else if (report.getReportTimeType() == 3) {
+                                //计算时长
+                                report.setWorkingTime(workingTime[i])
+                                        .setCost(hourCost.multiply(new BigDecimal(workingTime[i])));
+                            }
+                            reportList.add(report);
+                        }
+
+                        //结束条件
+                        if (localStartDate.isEqual(localEndDate)) {
+                            break;
+                        }
+                        daysOffset = 1;
+                    }
+                } else {
+                    Report report = new Report()
+                            .setId(id[i] == -1 ? null : id[i])
+                            .setProjectId(projectId[i])
+                            .setSubProjectId(subProjectId[i] == 0?null:subProjectId[i])
+                            .setReportTimeType(reportTimeType[i])
+                            .setContent(content[i])
+                            .setState(0)
+                            .setCreateDate(LocalDate.parse(createDate[i], DateTimeFormatter.ofPattern("yyyy-MM-dd")))
+                            .setCreatorId(token);
+                    if (taskId != null && taskId[i] != null && taskId[i] != 0) {
+                        report.setTaskId(taskId[i]);
+                    }
+                    if (isOvertime != null && isOvertime[i] != null) {
+                        report.setIsOvertime(isOvertime[i]);
+                    }
+                    if (progress != null && progress[i] != null) {
+                        report.setProgress(progress[i]);
+                    }
+                    if (report.getReportTimeType() == 0) {
+                        report.setWorkingTime(workingTime[i])
+                                .setCost(hourCost.multiply(new BigDecimal(workingTime[i])))
+                                .setTimeType(timeType[i]);
+                    } else if (report.getReportTimeType() == 1) {
+                        report.setWorkingTime(workingTime[i])
+                                .setCost(hourCost.multiply(new BigDecimal(workingTime[i])));
+                    } else if (report.getReportTimeType() == 2) {
+                        //时间范围填报, 计算一下时长
+                        try {
+                            report.setStartTime(startTime[i]).setEndTime(endTime[i]);
+                            long time = sdf.parse(report.getEndTime()).getTime() - sdf.parse(report.getStartTime()).getTime();
+                            int minutes = (int)time/1000/60;
+                            double hours = minutes*1.0f/60;
+                            report.setWorkingTime(hours);
+                            report.setCost(hourCost.multiply(new BigDecimal(hours)));
+                        } catch (ParseException e) {
+                            e.printStackTrace();
+                        }
+                    } else if (report.getReportTimeType() == 3) {
+                        //计算时长
+                        report.setWorkingTime(workingTime[i])
+                                .setCost(hourCost.multiply(new BigDecimal(workingTime[i])));
+                    }
+                    reportList.add(report);
+                    /*后续需要加入状态*/
+                    if (createDate[i] == null || projectId[i] == null) {
+                        HttpRespMsg httpRespMsg = new HttpRespMsg();
+                        httpRespMsg.setError("缺少数据");
+                        return httpRespMsg;
                     }
-                } else if (report.getReportTimeType() == 3) {
-                    //计算时长
-                    report.setWorkingTime(workingTime[i])
-                            .setCost(hourCost.multiply(new BigDecimal(workingTime[i])));
-                }
-                reportList.add(report);
-                /*后续需要加入状态*/
-                if (createDate[i] == null || projectId[i] == null) {
-                    HttpRespMsg httpRespMsg = new HttpRespMsg();
-                    httpRespMsg.setError("缺少数据");
-                    return httpRespMsg;
                 }
             }
         } catch (NullPointerException e) {

+ 21 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/SysConfigController.java

@@ -0,0 +1,21 @@
+package com.management.platform.controller;
+
+
+import org.springframework.web.bind.annotation.RequestMapping;
+
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * <p>
+ *  前端控制器
+ * </p>
+ *
+ * @author Seyason
+ * @since 2021-06-26
+ */
+@RestController
+@RequestMapping("/sys-config")
+public class SysConfigController {
+
+}
+

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

@@ -40,7 +40,7 @@ public class SysRoleController {
     @RequestMapping("/getRoleList")
     public HttpRespMsg getRoleList() {
         HttpRespMsg msg = new HttpRespMsg();
-        String userId = request.getHeader("TOKEN");
+        String userId = request.getHeader("Token");
         Integer companyId = userService.getById(userId).getCompanyId();
         msg.data = sysRoleService.list(new QueryWrapper<SysRole>().eq("company_id", companyId));
         return msg;

+ 15 - 6
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/UserController.java

@@ -94,6 +94,11 @@ public class UserController {
         return userService.resetPwd(userId);
     }
 
+    @RequestMapping("/sendVcode")
+    public HttpRespMsg sendVcode(@RequestParam String mobile) {
+        return userService.sendVcode(mobile);
+    }
+
 
 
     /**
@@ -104,8 +109,9 @@ public class UserController {
      */
     @RequestMapping("/insertCompany")
     public HttpRespMsg insertCompany(
-            @RequestParam String companyName, @RequestParam String name, @RequestParam String phone) {
-        return userService.insertCompany(companyName, name, phone);
+            @RequestParam String companyName, @RequestParam String name, @RequestParam String phone,
+            String vcode, String password) {
+        return userService.insertCompany(companyName, name, phone, vcode, password);
     }
 
     /**
@@ -119,9 +125,9 @@ public class UserController {
      * departmentCascade 部门层叠关系字符串 默认"0"
      */
     @RequestMapping("/insertUser")
-    public HttpRespMsg insertUser(String id, @RequestParam String name, @RequestParam String phone,
-                                  @RequestParam Integer role, Double monthCost, Double cost, Integer departmentId, Integer salaryType) {
-        return userService.insertUser(id, name, phone, role, monthCost, cost, departmentId, salaryType, request);
+    public HttpRespMsg insertUser(String id, @RequestParam String name, String phone,
+                                  @RequestParam Integer role, Double monthCost, Double cost, Integer departmentId, Integer salaryType, String costApplyDate) {
+        return userService.insertUser(id, name, phone, role, monthCost, cost, departmentId, salaryType, costApplyDate, request);
     }
 
     /**
@@ -154,6 +160,9 @@ public class UserController {
         return userService.setActive(id, isActive);
     }
 
-
+    @RequestMapping("/exportUsers")
+    public HttpRespMsg exportUsers(Integer containInvalid) {
+        return userService.exportUsers(containInvalid,request);
+    }
 }
 

+ 21 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/UserVcodeController.java

@@ -0,0 +1,21 @@
+package com.management.platform.controller;
+
+
+import org.springframework.web.bind.annotation.RequestMapping;
+
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * <p>
+ *  前端控制器
+ * </p>
+ *
+ * @author Seyason
+ * @since 2021-06-25
+ */
+@RestController
+@RequestMapping("/user-vcode")
+public class UserVcodeController {
+
+}
+

File diff suppressed because it is too large
+ 497 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/WeiXinCorpController.java


+ 21 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/WxCorpInfoController.java

@@ -0,0 +1,21 @@
+package com.management.platform.controller;
+
+
+import org.springframework.web.bind.annotation.RequestMapping;
+
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * <p>
+ *  前端控制器
+ * </p>
+ *
+ * @author Seyason
+ * @since 2021-07-14
+ */
+@RestController
+@RequestMapping("/wx-corp-info")
+public class WxCorpInfoController {
+
+}
+

+ 5 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/CompanyCustomerContact.java

@@ -5,9 +5,12 @@ import com.baomidou.mybatisplus.annotation.TableId;
 import java.time.LocalDateTime;
 import com.baomidou.mybatisplus.annotation.TableField;
 import java.io.Serializable;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
 import lombok.experimental.Accessors;
+import org.springframework.format.annotation.DateTimeFormat;
 
 /**
  * <p>
@@ -40,6 +43,8 @@ public class CompanyCustomerContact extends Model<CompanyCustomerContact> {
     private String feedback;
 
     @TableField("indate")
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
     private LocalDateTime indate;
 
 

+ 63 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/CompanyDingding.java

@@ -0,0 +1,63 @@
+package com.management.platform.entity;
+
+import com.baomidou.mybatisplus.extension.activerecord.Model;
+import com.baomidou.mybatisplus.annotation.TableId;
+import java.time.LocalDateTime;
+import com.baomidou.mybatisplus.annotation.TableField;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+/**
+ * <p>
+ * 
+ * </p>
+ *
+ * @author Seyason
+ * @since 2021-06-27
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+public class CompanyDingding extends Model<CompanyDingding> {
+
+    private static final long serialVersionUID=1L;
+
+    /**
+     * 钉钉企业id
+     */
+    @TableId("corpid")
+    private String corpid;
+
+    @TableField("corp_name")
+    private String corpName;
+
+    @TableField("auth_user_id")
+    private String authUserId;
+
+    @TableField("indate")
+    private LocalDateTime indate;
+
+    /**
+     * 内部系统公司id
+     */
+    @TableField("company_id")
+    private Integer companyId;
+
+    @TableField("access_token")
+    private String accessToken;
+
+    /**
+     * accessToken过期时间
+     */
+    @TableField("expire_time")
+    private LocalDateTime expireTime;
+
+
+    @Override
+    protected Serializable pkVal() {
+        return this.corpid;
+    }
+
+}

+ 57 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/DepartmentDingding.java

@@ -0,0 +1,57 @@
+package com.management.platform.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.extension.activerecord.Model;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableField;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+/**
+ * <p>
+ * 
+ * </p>
+ *
+ * @author Seyason
+ * @since 2021-06-27
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+public class DepartmentDingding extends Model<DepartmentDingding> {
+
+    private static final long serialVersionUID=1L;
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Integer id;
+
+    @TableField("dd_deptid")
+    private Integer ddDeptid;
+
+    @TableField("dd_parentid")
+    private Integer ddParentid;
+
+    /**
+     * 企业corpid
+     */
+    @TableField("corpid")
+    private String corpid;
+
+    @TableField("name")
+    private String name;
+
+    /**
+     * 内部部门id
+     */
+    @TableField("sys_deptid")
+    private Integer sysDeptid;
+
+
+    @Override
+    protected Serializable pkVal() {
+        return this.id;
+    }
+
+}

+ 7 - 1
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/ExpenseItem.java

@@ -15,7 +15,7 @@ import lombok.experimental.Accessors;
  * </p>
  *
  * @author Seyason
- * @since 2021-05-18
+ * @since 2021-06-18
  */
 @Data
 @EqualsAndHashCode(callSuper = false)
@@ -81,6 +81,12 @@ public class ExpenseItem extends Model<ExpenseItem> {
     @TableField("remark")
     private String remark;
 
+    /**
+     * 费用类型
+     */
+    @TableField("expense_type")
+    private String expenseType;
+
 
     @Override
     protected Serializable pkVal() {

+ 48 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/ExpenseType.java

@@ -0,0 +1,48 @@
+package com.management.platform.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.extension.activerecord.Model;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableField;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+/**
+ * <p>
+ * 
+ * </p>
+ *
+ * @author Seyason
+ * @since 2021-06-18
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+public class ExpenseType extends Model<ExpenseType> {
+
+    private static final long serialVersionUID=1L;
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Integer id;
+
+    /**
+     * 主类型: 0-一般费用,1-差旅费用,2-外包费用
+     */
+    @TableField("main_type")
+    private Integer mainType;
+
+    /**
+     * 费用类型名称
+     */
+    @TableField("type_name")
+    private String typeName;
+
+
+    @Override
+    protected Serializable pkVal() {
+        return this.id;
+    }
+
+}

+ 41 - 7
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/Project.java

@@ -9,9 +9,11 @@ import java.io.Serializable;
 import java.util.List;
 import java.util.Map;
 
+import com.fasterxml.jackson.annotation.JsonFormat;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
 import lombok.experimental.Accessors;
+import org.springframework.format.annotation.DateTimeFormat;
 
 /**
  * <p>
@@ -19,7 +21,7 @@ import lombok.experimental.Accessors;
  * </p>
  *
  * @author Seyason
- * @since 2021-05-15
+ * @since 2021-06-22
  */
 @Data
 @EqualsAndHashCode(callSuper = false)
@@ -62,12 +64,16 @@ public class Project extends Model<Project> {
      * 计划开始日期
      */
     @TableField("plan_start_date")
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
     private LocalDate planStartDate;
 
     /**
      * 计划结束日期
      */
     @TableField("plan_end_date")
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
     private LocalDate planEndDate;
 
     /**
@@ -92,6 +98,8 @@ public class Project extends Model<Project> {
      * 实际完成日期
      */
     @TableField("finish_date")
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
     private LocalDate finishDate;
 
     /**
@@ -110,6 +118,8 @@ public class Project extends Model<Project> {
      * 创建日期
      */
     @TableField("create_date")
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
     private LocalDate createDate;
 
     /**
@@ -122,37 +132,61 @@ public class Project extends Model<Project> {
      * 基线总成本:单位元
      */
     @TableField("budget")
-    private Integer budget = 0;
+    private Integer budget;
 
     /**
      * 人员成本:单位元
      */
     @TableField("base_man")
-    private Integer baseMan = 0;
+    private Integer baseMan;
 
     /**
      * 外包费用
      */
     @TableField("base_outsourcing")
-    private Integer baseOutsourcing = 0;
+    private Integer baseOutsourcing;
 
     /**
      * 风险预留资金1
      */
     @TableField("base_risk1")
-    private Integer baseRisk1 = 0;
+    private Integer baseRisk1;
 
     /**
      * 风险预留资金1
      */
     @TableField("base_risk2")
-    private Integer baseRisk2 = 0;
+    private Integer baseRisk2;
 
     /**
      * 基线费用
      */
     @TableField("base_fee")
-    private Integer baseFee = 0;
+    private Integer baseFee;
+
+    /**
+     * 一般费用
+     */
+    @TableField("fee_normal")
+    private Double feeNormal;
+
+    /**
+     * 差旅费
+     */
+    @TableField("fee_travel")
+    private Double feeTravel;
+
+    /**
+     * 外包费用
+     */
+    @TableField("fee_outsourcing")
+    private Double feeOutsourcing;
+
+    /**
+     * 人工成本
+     */
+    @TableField("fee_man")
+    private Double feeMan;
 
 
     @TableField(exist = false)

+ 46 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/SysConfig.java

@@ -0,0 +1,46 @@
+package com.management.platform.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.extension.activerecord.Model;
+import com.baomidou.mybatisplus.annotation.TableId;
+import java.time.LocalDateTime;
+import com.baomidou.mybatisplus.annotation.TableField;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+/**
+ * <p>
+ * 
+ * </p>
+ *
+ * @author Seyason
+ * @since 2021-06-27
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+public class SysConfig extends Model<SysConfig> {
+
+    private static final long serialVersionUID=1L;
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Integer id;
+
+    @TableField("param_key")
+    private String paramKey;
+
+    @TableField("param_value")
+    private String paramValue;
+
+    @TableField("indate")
+    private LocalDateTime indate;
+
+
+    @Override
+    protected Serializable pkVal() {
+        return this.id;
+    }
+
+}

+ 25 - 2
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/User.java

@@ -16,7 +16,7 @@ import lombok.experimental.Accessors;
  * </p>
  *
  * @author Seyason
- * @since 2021-06-04
+ * @since 2021-07-14
  */
 @Data
 @EqualsAndHashCode(callSuper = false)
@@ -62,7 +62,7 @@ public class User extends Model<User> {
     private LocalDateTime createTime;
 
     /**
-     * 角色权限 0-员工 1-负责人 2-管理员
+     * 角色权限 0-员工 1-负责人 2-管理员,3-公司高层,4-人事管理员,5-项目管理员
      */
     @TableField("role")
     private Integer role;
@@ -139,6 +139,29 @@ public class User extends Model<User> {
     @TableField("role_name")
     private String roleName;
 
+    /**
+     * 成本生效日期
+     */
+    @TableField("cost_apply_date")
+    private String costApplyDate;
+
+    /**
+     * 钉钉userid
+     */
+    @TableField("dingding_userid")
+    private String dingdingUserid;
+
+    /**
+     * 钉钉unionid
+     */
+    @TableField("dingding_unionid")
+    private String dingdingUnionid;
+
+    /**
+     * 企业微信用户id
+     */
+    @TableField("corpwx_userid")
+    private String corpwxUserid;
 
 
     @TableField(exist = false)

+ 52 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/UserVcode.java

@@ -0,0 +1,52 @@
+package com.management.platform.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.extension.activerecord.Model;
+import com.baomidou.mybatisplus.annotation.TableId;
+import java.time.LocalDateTime;
+import com.baomidou.mybatisplus.annotation.TableField;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+/**
+ * <p>
+ * 
+ * </p>
+ *
+ * @author Seyason
+ * @since 2021-06-25
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+public class UserVcode extends Model<UserVcode> {
+
+    private static final long serialVersionUID=1L;
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Integer id;
+
+    /**
+     * 手机号
+     */
+    @TableField("mobile")
+    private String mobile;
+
+    /**
+     * 验证码
+     */
+    @TableField("vcode")
+    private String vcode;
+
+    @TableField("indate")
+    private LocalDateTime indate;
+
+
+    @Override
+    protected Serializable pkVal() {
+        return this.id;
+    }
+
+}

+ 4 - 1
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/VcompanyCustomerContact.java

@@ -4,9 +4,12 @@ import com.baomidou.mybatisplus.extension.activerecord.Model;
 import java.time.LocalDateTime;
 import com.baomidou.mybatisplus.annotation.TableField;
 import java.io.Serializable;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
 import lombok.experimental.Accessors;
+import org.springframework.format.annotation.DateTimeFormat;
 
 /**
  * <p>
@@ -84,9 +87,9 @@ public class VcompanyCustomerContact extends Model<VcompanyCustomerContact> {
      * 创建时间
      */
     @TableField("c_time")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm")
     private LocalDateTime cTime;
 
-
     @Override
     protected Serializable pkVal() {
         return null;

+ 84 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/WxCorpInfo.java

@@ -0,0 +1,84 @@
+package com.management.platform.entity;
+
+import com.baomidou.mybatisplus.extension.activerecord.Model;
+import com.baomidou.mybatisplus.annotation.TableId;
+import java.time.LocalDateTime;
+import com.baomidou.mybatisplus.annotation.TableField;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+/**
+ * <p>
+ * 
+ * </p>
+ *
+ * @author Seyason
+ * @since 2021-07-14
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+public class WxCorpInfo extends Model<WxCorpInfo> {
+
+    private static final long serialVersionUID=1L;
+
+    @TableId("corpid")
+    private String corpid;
+
+    @TableField("corp_name")
+    private String corpName;
+
+    @TableField("corp_full_name")
+    private String corpFullName;
+
+    @TableField("corp_scale")
+    private String corpScale;
+
+    @TableField("corp_industry")
+    private String corpIndustry;
+
+    @TableField("corp_sub_industry")
+    private String corpSubIndustry;
+
+    @TableField("location")
+    private String location;
+
+    /**
+     * 企业token
+     */
+    @TableField("access_token")
+    private String accessToken;
+
+    /**
+     * token有效期
+     */
+    @TableField("expire_time")
+    private LocalDateTime expireTime;
+
+    /**
+     * 企业永久授权码
+     */
+    @TableField("permanent_code")
+    private String permanentCode;
+
+    /**
+     * 授权人姓名
+     */
+    @TableField("auth_username")
+    private String authUsername;
+
+    /**
+     * 系统内部的公司id
+     */
+    @TableField("company_id")
+    private Integer companyId;
+
+
+    @Override
+    protected Serializable pkVal() {
+        return this.corpid;
+    }
+
+}

+ 1 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/vo/ProjectVO.java

@@ -15,4 +15,5 @@ public class ProjectVO extends Project {
     List<Map<String, Object>> participator;
     String inchargerName;
     String inchargerPhone;
+    String statusName;
 }

+ 16 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/mapper/CompanyDingdingMapper.java

@@ -0,0 +1,16 @@
+package com.management.platform.mapper;
+
+import com.management.platform.entity.CompanyDingding;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+ * <p>
+ *  Mapper 接口
+ * </p>
+ *
+ * @author Seyason
+ * @since 2021-06-27
+ */
+public interface CompanyDingdingMapper extends BaseMapper<CompanyDingding> {
+
+}

+ 16 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/mapper/DepartmentDingdingMapper.java

@@ -0,0 +1,16 @@
+package com.management.platform.mapper;
+
+import com.management.platform.entity.DepartmentDingding;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+ * <p>
+ *  Mapper 接口
+ * </p>
+ *
+ * @author Seyason
+ * @since 2021-06-27
+ */
+public interface DepartmentDingdingMapper extends BaseMapper<DepartmentDingding> {
+
+}

+ 1 - 1
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/mapper/DepartmentMapper.java

@@ -18,5 +18,5 @@ import java.util.Map;
 public interface DepartmentMapper extends BaseMapper<Department> {
     Map<String, Object> getCostByDepartment(@Param("departmentIds") List departmentIds, String startDate, String endDate);
 
-    List<Map<String, Object>> getCostByUser(@Param("departmentIds") List departmentIds, String startDate, String endDate);
+    List<Map<String, Object>> getCostByUser(@Param("departmentIds") List departmentIds, String startDate, String endDate, Integer companyId, List<String> userIds);
 }

+ 16 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/mapper/ExpenseTypeMapper.java

@@ -0,0 +1,16 @@
+package com.management.platform.mapper;
+
+import com.management.platform.entity.ExpenseType;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+ * <p>
+ *  Mapper 接口
+ * </p>
+ *
+ * @author Seyason
+ * @since 2021-06-18
+ */
+public interface ExpenseTypeMapper extends BaseMapper<ExpenseType> {
+
+}

+ 5 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/mapper/ProjectMapper.java

@@ -31,4 +31,9 @@ public interface ProjectMapper extends BaseMapper<Project> {
     //获取全部人员成本
     List<Map<String, Object>> getAllMembCost(@Param("startDate") String startDate, @Param("endDate") String endDate, @Param("projectId") Integer projectId,
                                              @Param("companyId") Integer companyId);
+
+    List<Project> getAllProjectCost(Integer companyId, Integer pageStart, Integer pageSize);
+
+    List<Project> getProjectInAndOut(Integer companyId, Integer pageStart, Integer pageSize);
+
 }

+ 3 - 1
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/mapper/ReportMapper.java

@@ -43,5 +43,7 @@ public interface ReportMapper extends BaseMapper<Report> {
                                                @Param("companyId") Integer companyId,
                                                 @Param("leaderId") String leaderId);
 
-    List<Map<String, Object>> getRealProjectTime(@Param("startDate") LocalDateTime startDate, @Param("endDate") LocalDateTime endDate, Integer companyId);
+    List<Map<String, Object>> getRealProjectTime(@Param("startDate") LocalDate startDate, @Param("endDate") LocalDate endDate, Integer companyId);
+
+    List<Map<String, Object>> getReportFillStatus(String startDate, String endDate, String userId);
 }

+ 16 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/mapper/SysConfigMapper.java

@@ -0,0 +1,16 @@
+package com.management.platform.mapper;
+
+import com.management.platform.entity.SysConfig;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+ * <p>
+ *  Mapper 接口
+ * </p>
+ *
+ * @author Seyason
+ * @since 2021-06-26
+ */
+public interface SysConfigMapper extends BaseMapper<SysConfig> {
+
+}

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

@@ -29,4 +29,8 @@ public interface TaskMapper extends BaseMapper<Task> {
     List getTaskTimeCompare(Integer projectId);
 
     List<TimeTask> getTaskWithWorktime(Integer projectId, Integer taskType);
+
+    List getProjectTask(Integer companyId, Integer pageStart, Integer pageSize);
+
+    Integer getProjectTaskCount(Integer companyId);
 }

+ 16 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/mapper/UserVcodeMapper.java

@@ -0,0 +1,16 @@
+package com.management.platform.mapper;
+
+import com.management.platform.entity.UserVcode;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+ * <p>
+ *  Mapper 接口
+ * </p>
+ *
+ * @author Seyason
+ * @since 2021-06-25
+ */
+public interface UserVcodeMapper extends BaseMapper<UserVcode> {
+
+}

+ 16 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/mapper/WxCorpInfoMapper.java

@@ -0,0 +1,16 @@
+package com.management.platform.mapper;
+
+import com.management.platform.entity.WxCorpInfo;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+ * <p>
+ *  Mapper 接口
+ * </p>
+ *
+ * @author Seyason
+ * @since 2021-07-14
+ */
+public interface WxCorpInfoMapper extends BaseMapper<WxCorpInfo> {
+
+}

+ 16 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/CompanyDingdingService.java

@@ -0,0 +1,16 @@
+package com.management.platform.service;
+
+import com.management.platform.entity.CompanyDingding;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * <p>
+ *  服务类
+ * </p>
+ *
+ * @author Seyason
+ * @since 2021-06-27
+ */
+public interface CompanyDingdingService extends IService<CompanyDingding> {
+
+}

+ 16 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/DepartmentDingdingService.java

@@ -0,0 +1,16 @@
+package com.management.platform.service;
+
+import com.management.platform.entity.DepartmentDingding;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * <p>
+ *  服务类
+ * </p>
+ *
+ * @author Seyason
+ * @since 2021-06-27
+ */
+public interface DepartmentDingdingService extends IService<DepartmentDingding> {
+
+}

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

@@ -28,4 +28,6 @@ public interface DepartmentService extends IService<Department> {
     HttpRespMsg getDepartmentStatistics(String startDate, String endDate, HttpServletRequest request);
 
     HttpRespMsg getUserStatistics(String startDate, String endDate, Integer departmentId, HttpServletRequest request);
+
+    HttpRespMsg exportUserStatistic(String startDate, String endDate, String userIds, HttpServletRequest request);
 }

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

@@ -0,0 +1,13 @@
+package com.management.platform.service;
+
+import com.management.platform.util.HttpRespMsg;
+import com.taobao.api.ApiException;
+
+public interface DingDingService {
+    public void corpAuth(String corpid, String corpName, String authUserId) throws ApiException;
+    public void updateSuiteTicket(String suiteTicket);
+
+    HttpRespMsg getUserByCode(String code, String corpid);
+
+    public HttpRespMsg testAsync();
+}

+ 16 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/ExpenseTypeService.java

@@ -0,0 +1,16 @@
+package com.management.platform.service;
+
+import com.management.platform.entity.ExpenseType;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * <p>
+ *  服务类
+ * </p>
+ *
+ * @author Seyason
+ * @since 2021-06-18
+ */
+public interface ExpenseTypeService extends IService<ExpenseType> {
+
+}

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

@@ -3,6 +3,7 @@ package com.management.platform.service;
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.management.platform.entity.Project;
 import com.management.platform.util.HttpRespMsg;
+import org.springframework.web.multipart.MultipartFile;
 
 import javax.servlet.http.HttpServletRequest;
 import java.time.LocalDate;
@@ -56,4 +57,22 @@ public interface ProjectService extends IService<Project> {
     HttpRespMsg addMemb(Integer id, String[] userId);
 
     HttpRespMsg adjustBase(Project project, HttpServletRequest request);
+
+    HttpRespMsg exportProfit(HttpServletRequest request);
+
+    HttpRespMsg exportProject(HttpServletRequest request);
+
+    HttpRespMsg getProjectTask(Integer pageIndex, Integer pageSize, HttpServletRequest request);
+
+    HttpRespMsg exportProjectTask(HttpServletRequest request);
+
+    HttpRespMsg getAllProjectCost(Integer pageIndex, Integer pageSize, HttpServletRequest request);
+
+    HttpRespMsg exportAllProjectCost(HttpServletRequest request);
+
+    HttpRespMsg getProjectInAndOut(Integer pageIndex, Integer pageSize, HttpServletRequest request);
+
+    HttpRespMsg exportProjectInAndOut(HttpServletRequest request);
+
+    HttpRespMsg importData(String userId, MultipartFile file, HttpServletRequest request);
 }

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

@@ -45,4 +45,6 @@ public interface ReportService extends IService<Report> {
     HttpRespMsg batchDenyReport(String ids, HttpServletRequest request);
 
     HttpRespMsg cancelReport(String userId, String reportIds, HttpServletRequest request);
+
+    HttpRespMsg getReportFillStatus(String startDate, String endDate, String userId, HttpServletRequest request);
 }

+ 16 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/SysConfigService.java

@@ -0,0 +1,16 @@
+package com.management.platform.service;
+
+import com.management.platform.entity.SysConfig;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * <p>
+ *  服务类
+ * </p>
+ *
+ * @author Seyason
+ * @since 2021-06-26
+ */
+public interface SysConfigService extends IService<SysConfig> {
+
+}

+ 6 - 2
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/UserService.java

@@ -28,10 +28,10 @@ public interface UserService extends IService<User> {
 
     HttpRespMsg editPassword(String originPassword, String newPassword, HttpServletRequest request);
 
-    HttpRespMsg insertCompany(String companyName, String name, String phone);
+    HttpRespMsg insertCompany(String companyName, String name, String phone, String vcode, String pwd);
 
     HttpRespMsg insertUser(String id, String name, String phone, Integer role, Double monthCost, Double cost, Integer departmentId,
-                           Integer salaryType,
+                           Integer salaryType, String costApplyDate,
                            HttpServletRequest request);
 
     HttpRespMsg importUser(Integer departmentId, MultipartFile multipartFile, HttpServletRequest request);
@@ -45,4 +45,8 @@ public interface UserService extends IService<User> {
     HttpRespMsg setActive(String id, int isActive);
 
     HttpRespMsg bindWeiXin(String code, String userId);
+
+    HttpRespMsg exportUsers(Integer containInvalid, HttpServletRequest request);
+
+    HttpRespMsg sendVcode(String mobile);
 }

+ 16 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/UserVcodeService.java

@@ -0,0 +1,16 @@
+package com.management.platform.service;
+
+import com.management.platform.entity.UserVcode;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * <p>
+ *  服务类
+ * </p>
+ *
+ * @author Seyason
+ * @since 2021-06-25
+ */
+public interface UserVcodeService extends IService<UserVcode> {
+
+}

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

@@ -0,0 +1,16 @@
+package com.management.platform.service;
+
+import com.management.platform.entity.WxCorpInfo;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * <p>
+ *  服务类
+ * </p>
+ *
+ * @author Seyason
+ * @since 2021-07-14
+ */
+public interface WxCorpInfoService extends IService<WxCorpInfo> {
+
+}

+ 20 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/CompanyDingdingServiceImpl.java

@@ -0,0 +1,20 @@
+package com.management.platform.service.impl;
+
+import com.management.platform.entity.CompanyDingding;
+import com.management.platform.mapper.CompanyDingdingMapper;
+import com.management.platform.service.CompanyDingdingService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ *  服务实现类
+ * </p>
+ *
+ * @author Seyason
+ * @since 2021-06-27
+ */
+@Service
+public class CompanyDingdingServiceImpl extends ServiceImpl<CompanyDingdingMapper, CompanyDingding> implements CompanyDingdingService {
+
+}

+ 20 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/DepartmentDingdingServiceImpl.java

@@ -0,0 +1,20 @@
+package com.management.platform.service.impl;
+
+import com.management.platform.entity.DepartmentDingding;
+import com.management.platform.mapper.DepartmentDingdingMapper;
+import com.management.platform.service.DepartmentDingdingService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ *  服务实现类
+ * </p>
+ *
+ * @author Seyason
+ * @since 2021-06-27
+ */
+@Service
+public class DepartmentDingdingServiceImpl extends ServiceImpl<DepartmentDingdingMapper, DepartmentDingding> implements DepartmentDingdingService {
+
+}

+ 160 - 39
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/DepartmentServiceImpl.java

@@ -9,13 +9,17 @@ import com.management.platform.entity.vo.DepartmentVO;
 import com.management.platform.mapper.DepartmentMapper;
 import com.management.platform.mapper.UserMapper;
 import com.management.platform.service.DepartmentService;
+import com.management.platform.util.ExcelUtil;
 import com.management.platform.util.HttpRespMsg;
+import com.management.platform.util.ListUtil;
 import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
 
 import javax.annotation.Resource;
 import javax.servlet.http.HttpServletRequest;
 import java.math.BigDecimal;
+import java.text.DecimalFormat;
 import java.util.*;
 
 /**
@@ -28,7 +32,8 @@ import java.util.*;
  */
 @Service
 public class DepartmentServiceImpl extends ServiceImpl<DepartmentMapper, Department> implements DepartmentService {
-
+    @Value(value = "${upload.path}")
+    private String path;
     @Resource
     private UserMapper userMapper;
     @Resource
@@ -318,25 +323,51 @@ public class DepartmentServiceImpl extends ServiceImpl<DepartmentMapper, Departm
         return httpRespMsg;
     }
 
-    //获取某个部门下人员的统计
+    //获取某个人员的统计, departmentId为null时获取全部公司人员
     @SuppressWarnings("SuspiciousMethodCalls")
     @Override
     public HttpRespMsg getUserStatistics(String startDate, String endDate, Integer departmentId, HttpServletRequest request) {
         HttpRespMsg httpRespMsg = new HttpRespMsg();
         try {
             Integer companyId = userMapper.selectById(request.getHeader("Token")).getCompanyId();
+
+            List<Integer> deptIds = null;
             //首先校验有无权限
-            if (departmentMapper.selectCount(new QueryWrapper<Department>()
-                    .eq("department_id", departmentId)
-                    .eq("company_id", companyId)) == 1) {
-                List<Map<String, Object>> list = departmentMapper
-                        .getCostByUser(getBranchDepartment(departmentId, companyId), startDate, endDate);
-                Map<String, List<Map<String, Object>>> tempMap = new HashMap<>();
-                BigDecimal totalCostMoney = new BigDecimal(0);
-                for (Map<String, Object> map : list) {
-                    if (tempMap.containsKey(map.get("user"))) {
-                        //这个名字已经装进数组中了
-                        List<Map<String, Object>> tempList = tempMap.get(map.get("user"));
+            if (departmentId != null) {
+                if (departmentMapper.selectCount(new QueryWrapper<Department>()
+                        .eq("department_id", departmentId)
+                        .eq("company_id", companyId)) == 1) {
+                    deptIds = getBranchDepartment(departmentId, companyId);
+                } else {
+                    httpRespMsg.setError("部门不存在或无查看权限");
+                    return httpRespMsg;
+                }
+            }
+            List<Map<String, Object>> list = departmentMapper
+                    .getCostByUser(deptIds, startDate, endDate, companyId, null);
+            Map<String, List<Map<String, Object>>> tempMap = new HashMap<>();
+            BigDecimal totalCostMoney = new BigDecimal(0);
+            List<User> userList = new ArrayList<>();
+            for (Map<String, Object> map : list) {
+                if (tempMap.containsKey(map.get("user"))) {
+                    //这个名字已经装进数组中了
+                    List<Map<String, Object>> tempList = tempMap.get(map.get("user"));
+                    Map<String, Object> dataMap = new HashMap<>();
+                    dataMap.put("project", map.get("project"));
+                    BigDecimal money = (BigDecimal) map.getOrDefault("money", 0);
+                    Double time = (Double) map.getOrDefault("time", 0);
+                    totalCostMoney = totalCostMoney.add(money);
+                    dataMap.put("money", money);
+                    dataMap.put("time", time);
+                    tempList.add(dataMap);
+                } else {
+                    User user = new User();
+                    user.setId((String)map.get(("id")));
+                    user.setName((String)map.get("user"));
+                    userList.add(user);
+                    //这个名字尚未装进数组中
+                    List<Map<String, Object>> tempList = new ArrayList<>();
+                    if (map.containsKey("project")) {
                         Map<String, Object> dataMap = new HashMap<>();
                         dataMap.put("project", map.get("project"));
                         BigDecimal money = (BigDecimal) map.getOrDefault("money", 0);
@@ -345,36 +376,126 @@ public class DepartmentServiceImpl extends ServiceImpl<DepartmentMapper, Departm
                         dataMap.put("money", money);
                         dataMap.put("time", time);
                         tempList.add(dataMap);
-                    } else {
-                        //这个名字尚未装进数组中
-                        List<Map<String, Object>> tempList = new ArrayList<>();
-                        if (map.containsKey("project")) {
-                            Map<String, Object> dataMap = new HashMap<>();
-                            dataMap.put("project", map.get("project"));
-                            BigDecimal money = (BigDecimal) map.getOrDefault("money", 0);
-                            Double time = (Double) map.getOrDefault("time", 0);
-                            totalCostMoney = totalCostMoney.add(money);
-                            dataMap.put("money", money);
-                            dataMap.put("time", time);
-                            tempList.add(dataMap);
-                        }
-                        tempMap.put((String) map.get("user"), tempList);
                     }
+                    tempMap.put((String) map.get("user"), tempList);
                 }
-                Map<String, Object> finalMap = new HashMap<>();
-                List<Map<String, Object>> finalList = new ArrayList<>();
-                for (String key : tempMap.keySet()) {
-                    Map<String, Object> map = new HashMap<>();
-                    map.put("name", key);
-                    map.put("project", tempMap.get(key));
-                    finalList.add(map);
+            }
+            Map<String, Object> finalMap = new HashMap<>();
+            List<Map<String, Object>> finalList = new ArrayList<>();
+            for (String key : tempMap.keySet()) {
+                Map<String, Object> map = new HashMap<>();
+                map.put("name", key);
+                map.put("project", tempMap.get(key));
+                finalList.add(map);
+            }
+            finalMap.put("totalCostMoney", totalCostMoney);
+            finalMap.put("list", finalList);
+            finalMap.put("userList", userList);
+            httpRespMsg.data = finalMap;
+
+        } catch (NullPointerException e) {
+            httpRespMsg.setError("验证失败");
+            return httpRespMsg;
+        }
+        return httpRespMsg;
+    }
+
+    @Override
+    public HttpRespMsg exportUserStatistic(String startDate, String endDate, String userIds, HttpServletRequest request) {
+        HttpRespMsg httpRespMsg = new HttpRespMsg();
+        try {
+            Integer companyId = userMapper.selectById(request.getHeader("Token")).getCompanyId();
+            List<String> allUserIds = null;
+            if (userIds != null) {
+                allUserIds = ListUtil.convertLongIdsArrayToList(userIds);
+            }
+            //按选择的人员来查询数据
+            List<Map<String, Object>> list = departmentMapper
+                    .getCostByUser(null, startDate, endDate, companyId, allUserIds);
+            Map<String, List<Map<String, Object>>> tempMap = new HashMap<>();
+            BigDecimal totalCostMoney = new BigDecimal(0);
+            for (Map<String, Object> map : list) {
+                if (tempMap.containsKey(map.get("user"))) {
+                    //这个名字已经装进数组中了
+                    List<Map<String, Object>> tempList = tempMap.get(map.get("user"));
+                    Map<String, Object> dataMap = new HashMap<>();
+                    dataMap.put("project", map.get("project"));
+                    BigDecimal money = (BigDecimal) map.getOrDefault("money", 0);
+                    Double time = (Double) map.getOrDefault("time", 0);
+                    totalCostMoney = totalCostMoney.add(money);
+                    dataMap.put("money", money);
+                    dataMap.put("time", time);
+                    tempList.add(dataMap);
+                } else {
+                    //这个名字尚未装进数组中
+                    List<Map<String, Object>> tempList = new ArrayList<>();
+                    if (map.containsKey("project")) {
+                        Map<String, Object> dataMap = new HashMap<>();
+                        dataMap.put("project", map.get("project"));
+                        BigDecimal money = (BigDecimal) map.getOrDefault("money", 0);
+                        Double time = (Double) map.getOrDefault("time", 0);
+                        totalCostMoney = totalCostMoney.add(money);
+                        dataMap.put("money", money);
+                        dataMap.put("time", time);
+                        tempList.add(dataMap);
+                    }
+                    tempMap.put((String) map.get("user"), tempList);
                 }
-                finalMap.put("totalCostMoney", totalCostMoney);
-                finalMap.put("list", finalList);
-                httpRespMsg.data = finalMap;
-            } else {
-                httpRespMsg.setError("部门不存在或无查看权限");
             }
+//            Map<String, Object> finalMap = new HashMap<>();
+//            List<Map<String, Object>> finalList = new ArrayList<>();
+            DecimalFormat df = new DecimalFormat("#.0");
+            List<List<String>> dataList = new ArrayList<List<String>>();
+            String[] titles = {"人员", "项目", "工时(h)", "成本(元)"};
+            List<String> titleList = Arrays.asList(titles.clone());
+            dataList.add(titleList);
+            BigDecimal totalMoneyCost = BigDecimal.valueOf(0);
+            double totalCostTime = 0;
+            for (String key : tempMap.keySet()) {
+                Map<String, Object> map = new HashMap<>();
+                map.put("name", key);
+                map.put("project", tempMap.get(key));
+                List<String> nameList = new ArrayList<String>();
+                nameList.add(key);//姓名
+                nameList.add("");//空着
+                List<Map<String, Object>> tempList = tempMap.get(key);
+                //统计个人的时间和成本
+                double tTime = 0;
+                BigDecimal tCost = new BigDecimal(0);
+                for (Map<String, Object> membData : tempList) {
+                    tTime += (double)membData.get("time");
+                    tCost = tCost.add((BigDecimal)membData.get("money"));
+                }
+                totalMoneyCost = totalMoneyCost.add(tCost);
+                totalCostTime += tTime;
+                nameList.add(df.format(tTime));
+                nameList.add(tCost.setScale(2, BigDecimal.ROUND_UP).toString());
+                dataList.add(nameList);
+                //装载该人员下的项目的工时数据
+                for (Map<String, Object> membData : tempList) {
+                    tTime += (double)membData.get("time");
+                    tCost.add((BigDecimal)membData.get("money"));
+                    List<String> projectDataList = new ArrayList<>();
+                    projectDataList.add("");
+                    projectDataList.add(membData.get("project")+"");
+                    projectDataList.add(df.format((double)membData.get("time"))+"");
+                    projectDataList.add(((BigDecimal)membData.get("money")).setScale(2, BigDecimal.ROUND_UP).toString());
+                    dataList.add(projectDataList);
+                }
+            }
+            String total = totalMoneyCost.setScale(2, BigDecimal.ROUND_UP).toString();
+            //合计
+            List<String> sumRow = new ArrayList<String>();
+            sumRow.add("合计");
+            sumRow.add("");
+            sumRow.add(""+df.format(totalCostTime));
+            sumRow.add(total);
+            dataList.add(sumRow);
+            //生成excel文件导出
+            String fileName = "人员成本统计_"+System.currentTimeMillis();
+            String resp = ExcelUtil.exportGeneralExcelByTitleAndList(fileName , dataList, path);
+
+            httpRespMsg.data = resp;
         } catch (NullPointerException e) {
             httpRespMsg.setError("验证失败");
             return httpRespMsg;

+ 511 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/DingDingServiceImpl.java

@@ -0,0 +1,511 @@
+package com.management.platform.service.impl;
+
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.aliyun.dingtalkcontact_1_0.models.GetUserHeaders;
+import com.aliyun.tea.TeaException;
+import com.aliyun.teaopenapi.models.Config;
+import com.aliyun.teautil.models.RuntimeOptions;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.dingtalk.api.DefaultDingTalkClient;
+import com.dingtalk.api.DingTalkClient;
+import com.dingtalk.api.request.*;
+import com.dingtalk.api.response.*;
+import com.management.platform.entity.*;
+import com.management.platform.entity.vo.UserVO;
+import com.management.platform.mapper.*;
+import com.management.platform.service.DepartmentService;
+import com.management.platform.service.DingDingService;
+import com.management.platform.service.UserService;
+import com.management.platform.util.ColorUtil;
+import com.management.platform.util.Constant;
+import com.management.platform.util.HttpRespMsg;
+import com.management.platform.util.SnowFlake;
+import com.taobao.api.ApiException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.BeanUtils;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import javax.annotation.Resource;
+import java.time.LocalDateTime;
+import java.time.ZoneOffset;
+import java.util.ArrayList;
+import java.util.List;
+
+@Service
+@Transactional
+public class DingDingServiceImpl implements DingDingService {
+    private final Logger bizLogger = LoggerFactory.getLogger(getClass());
+    String token = "cf776d62c5fb3508b5d8c2cbb9f3df0c";
+    String aesKey = "ktmbamhymjsf60ndwp6n81mnu92847oynsgj9e0zr9v";
+    String suiteKey = "suitejwoq9dw4bxv4stdb";
+    String suiteSecret = "o-TWFLkFe8YbJsa_025JOj_JEWydP5GR3eigt1Yn1rtx5dTcryTJiSA6KEih3Bi4";
+
+    @Resource
+    private SysConfigMapper sysConfigMapper;
+    @Resource
+    private CompanyMapper companyMapper;
+    @Resource
+    private TimeTypeMapper timeTypeMapper;
+    @Resource
+    private UserMapper userMapper;
+    @Resource
+    private CompanyDingdingMapper companyDingdingMapper;
+    @Resource
+    private DepartmentMapper departmentMapper;
+    @Resource
+    private DepartmentDingdingMapper departmentDingdingMapper;
+    @Resource
+    private DepartmentService departmentService;
+    @Resource
+    private UserService userService;
+    @Resource
+    private ProjectMapper projectMapper;
+
+    @Override
+    @Async
+    public void corpAuth(String corpid, String corpName, String authUserId) throws ApiException {
+        System.out.println("@@@@@@@@@@@@@@@@@进行企业授权@@@@@@@@@@@@@@@@@"+corpid);
+        //检查是否已经存在
+        CompanyDingding oldD = companyDingdingMapper.selectById(corpid);
+        Company company = null;
+        if (oldD != null) {
+            company = companyMapper.selectById(oldD.getCompanyId());
+            if (!company.getExpirationDate().isAfter(LocalDateTime.now())) {
+                //超期了,不处理
+                return;
+            }
+        }
+        if (company != null) {
+            if (!company.getCompanyName().equals(corpName)) {
+                company.setCompanyName(corpName);
+                companyMapper.updateById(company);
+            }
+        } else {
+            //首先生成一个新公司,增加会员的试用一个月
+            company = new Company().setCompanyName(corpName)
+                    .setExpirationDate(LocalDateTime.now().plusMonths(1));
+            companyMapper.insert(company);
+
+            //生成工作时长
+            TimeType timeType = new TimeType();
+            timeType.setCompanyId(company.getId());
+            timeTypeMapper.insert(timeType);
+        }
+
+
+        //钉钉企业外部关系表
+        CompanyDingding dingding = new CompanyDingding();
+        dingding.setCompanyId(company.getId());
+        dingding.setCorpid(corpid);
+        dingding.setCorpName(corpName);
+        dingding.setAuthUserId(authUserId);
+
+        if (oldD == null) {
+            //第一次,查询对方企业的accessToken
+            SysConfig config = sysConfigMapper.selectOne(new QueryWrapper<SysConfig>().eq("param_key", "dingding_suite_ticket"));
+            OapiServiceGetCorpTokenResponse result = getAuthCorpAccessToken(corpid, config.getParamValue());
+            if (result != null) {
+                dingding.setAccessToken(result.getAccessToken());
+                LocalDateTime time = LocalDateTime.now();
+                time = time.plusSeconds(result.getExpiresIn());//设置token过期时间
+                dingding.setExpireTime(time);
+            }
+            companyDingdingMapper.insert(dingding);
+
+            //然后生成一个负责人
+            Long id = SnowFlake.nextId();
+            User user = new User()
+                    .setId(id.toString())
+                    .setRole(1)
+                    .setDingdingUserid(authUserId)
+                    .setColor(ColorUtil.randomColor())
+                    .setCompanyId(company.getId());
+
+            userMapper.insert(user);
+            //获取部门
+            if (dingding.getAccessToken() != null) {
+                String accessToken = dingding.getAccessToken();
+                getDepartmentList(company.getId(), corpid, accessToken, 1L, null);
+            }
+        } else {
+            companyDingdingMapper.updateById(dingding);
+        }
+    }
+
+    private void getUserDetailInfo(User user, String accessToken) throws ApiException {
+        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/v2/user/get");
+        OapiV2UserGetRequest req = new OapiV2UserGetRequest();
+        req.setUserid(user.getDingdingUserid());
+        req.setLanguage("zh_CN");
+        OapiV2UserGetResponse rsp = null;
+        rsp = client.execute(req, accessToken);
+        String body = rsp.getBody();
+        JSONObject json = JSONObject.parseObject(body);
+        JSONObject result = json.getJSONObject("result");
+        String name = result.getString("name");
+        String unionId = result.getString("unionid");
+        user.setDingdingUnionid(unionId);
+        user.setName(name);
+        userMapper.updateById(user);
+    }
+
+
+    //获取授权企业的accessToken
+    private OapiServiceGetCorpTokenResponse getAuthCorpAccessToken(String corpid, String suiteTicket) throws ApiException {
+        DefaultDingTalkClient client= new DefaultDingTalkClient("https://oapi.dingtalk.com/service/get_corp_token");
+        OapiServiceGetCorpTokenRequest req= new OapiServiceGetCorpTokenRequest();
+        req.setAuthCorpid(corpid);
+        OapiServiceGetCorpTokenResponse execute= client.execute(req,suiteKey,suiteSecret,suiteTicket);
+        return execute;
+    }
+
+
+    public void getCorpAccessToken(String authCorpId) {
+        DefaultDingTalkClient client= new DefaultDingTalkClient("https://oapi.dingtalk.com/service/get_corp_token");
+        OapiServiceGetCorpTokenRequest req= new OapiServiceGetCorpTokenRequest();
+        req.setAuthCorpid(authCorpId);
+        try {
+            OapiServiceGetCorpTokenResponse execute= client.execute(req,suiteKey,suiteSecret,"suiteTicket");
+        } catch (ApiException e) {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * 使用 Token 初始化账号Client
+     * @return Client
+     * @throws Exception
+     */
+    public com.aliyun.dingtalkcontact_1_0.Client createClient() throws Exception {
+        Config config = new Config();
+        config.protocol = "https";
+        config.regionId = "central";
+        return new com.aliyun.dingtalkcontact_1_0.Client(config);
+    }
+
+
+    //更新suiteTicket
+    public void updateSuiteTicket(String suiteTicket) {
+        List<SysConfig> sysConfigs = sysConfigMapper.selectList(new QueryWrapper<SysConfig>().eq("param_key", "dingding_suite_ticket"));
+        if (sysConfigs.size() > 0) {
+            SysConfig sysConfig = sysConfigs.get(0);
+            sysConfig.setParamValue(suiteTicket);
+            sysConfig.setIndate(LocalDateTime.now());
+            sysConfigMapper.updateById(sysConfig);
+        } else {
+            SysConfig sysConfig = new SysConfig();
+            sysConfig.setParamKey("dingding_suite_ticket");
+            sysConfig.setParamValue(suiteTicket);
+            sysConfigMapper.insert(sysConfig);
+        }
+    }
+
+    @Override
+    public HttpRespMsg getUserByCode(String code, String corpid) {
+        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/v2/user/getuserinfo");
+        OapiV2UserGetuserinfoRequest req = new OapiV2UserGetuserinfoRequest();
+        req.setCode(code);
+        //获取有效的accessToken
+        String accessToken = getValidCorpAccessToken(corpid);
+        HttpRespMsg httpRespMsg = new HttpRespMsg();
+        OapiV2UserGetuserinfoResponse rsp = null;
+        try {
+            rsp = client.execute(req, accessToken);
+            System.out.println(rsp.getBody());
+            JSONObject json = JSONObject.parseObject(rsp.getBody());
+
+            if (json.getInteger("errcode") == 0) {
+                JSONObject result = json.getJSONObject("result");
+                String dduid = result.getString("userid");
+                List<User> userList = userMapper.selectList(new QueryWrapper<User>().eq("dingding_userid", dduid).orderByDesc("create_time"));
+                User user = userList.get(0);
+                if (user.getIsActive() == 0) {
+                    httpRespMsg.setError("该账户已停用,无法登陆。请联系管理员");
+                } else {
+                    //查看该公司非会员公司,只能允许试用三天,超时不可登录
+                    Company company = companyMapper.selectOne(new QueryWrapper<Company>().eq("id", user.getCompanyId()));
+                    //公司未办理会员
+                    if (null != company.getExpirationDate()) {
+                        if (0 == company.getSetMeal()) {
+                            //未办理会员
+                            if (company.getExpirationDate().isBefore(LocalDateTime.now())) {
+                                httpRespMsg.setError("账号试用已到期,请联系客服。");
+                                return httpRespMsg;
+                            }
+                        } else {
+                            if (company.getExpirationDate().isBefore(LocalDateTime.now())) {
+                                httpRespMsg.setError("账号会员已到期,请联系客服。");
+                                return httpRespMsg;
+                            }
+                        }
+                    }
+                    //检测密码正确时
+                    UserVO userVO = new UserVO().setCompanyName(company.getCompanyName());
+                    userVO.setCompany(company);
+                    BeanUtils.copyProperties(user, userVO);
+                    //还要多返回一个公司名字
+                    userVO.setPassword("");
+                    LocalDateTime remainingTime = company.getExpirationDate() == null ? LocalDateTime.now() : company.getExpirationDate();
+                    userVO.setRemainingTime(remainingTime.toInstant(ZoneOffset.of("+8")).toEpochMilli() -
+                            LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli());
+                    //检测是否是项目经理,项目经理有审核功能权限
+                    int cnt = projectMapper.selectCount(new QueryWrapper<Project>().eq("incharger_id", userVO.getId()));
+                    if (cnt > 0) {
+                        userVO.setLeader(true);
+                    }
+                    httpRespMsg.data = userVO;
+                }
+            }
+        } catch (ApiException e) {
+            e.printStackTrace();
+        }
+        return httpRespMsg;
+    }
+
+    @Override
+    @Async
+    public HttpRespMsg testAsync() {
+        try {
+            System.out.println("==========开始执行====");
+            Thread.sleep(3000);
+            System.out.println("=========结束执行=====");
+        } catch (InterruptedException e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    private String getValidCorpAccessToken(String corpid) {
+        CompanyDingding companyDingding = companyDingdingMapper.selectById(corpid);
+        if (companyDingding.getExpireTime().isBefore(LocalDateTime.now())) {
+            String suiteTicket = sysConfigMapper.selectOne(new QueryWrapper<SysConfig>().eq("param_key", "dingding_suite_ticket")).getParamValue();
+            try {
+                OapiServiceGetCorpTokenResponse authCorpAccessToken = getAuthCorpAccessToken(corpid, suiteTicket);
+                String token = authCorpAccessToken.getAccessToken();
+                companyDingding.setAccessToken(token);
+                companyDingding.setExpireTime(LocalDateTime.now().plusSeconds(authCorpAccessToken.getExpiresIn()));
+                companyDingdingMapper.updateById(companyDingding);
+                return token;
+            } catch (ApiException e) {
+                e.printStackTrace();
+            }
+        } else {
+            return companyDingding.getAccessToken();
+        }
+        return null;
+    }
+
+    //获取该部门下的人员和子部门列表,递归下一级子部门
+    public void getDepartmentList(Integer companyId, String corpid, String access_token, long parentDeptId, Integer parentSysDeptId) throws ApiException {
+        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/v2/department/listsub");
+        OapiV2DepartmentListsubRequest req = new OapiV2DepartmentListsubRequest();
+        req.setDeptId(parentDeptId);
+        req.setLanguage("zh_CN");
+        OapiV2DepartmentListsubResponse rsp = client.execute(req, access_token);
+        System.out.println(rsp.getBody());
+        JSONObject json = JSONObject.parseObject(rsp.getBody());
+        if (json.getInteger("errcode") == 0) {
+            //正确返回的情况
+            JSONArray depts = json.getJSONArray("result");
+            List<Department> innerDeptList = new ArrayList<>();
+            List<DepartmentDingding> dingdingDeptList = new ArrayList<>();
+            for (int i=0;i<depts.size(); i++) {
+                JSONObject dept = depts.getJSONObject(i);
+                DepartmentDingding departmentDingding = new DepartmentDingding();
+                departmentDingding.setCorpid(corpid);
+                departmentDingding.setDdDeptid(dept.getInteger("dept_id"));
+                departmentDingding.setName(dept.getString("name"));
+                departmentDingding.setDdParentid(dept.getInteger("parent_id"));
+                Department department = new Department();
+                department.setDepartmentName(dept.getString("name"));
+                department.setCompanyId(companyId);
+                department.setSuperiorId(parentSysDeptId);
+                departmentMapper.insert(department);
+                departmentDingding.setSysDeptid(department.getDepartmentId());
+                departmentDingdingMapper.insert(departmentDingding);
+                innerDeptList.add(department);
+                dingdingDeptList.add(departmentDingding);
+
+                //获取该部门下的人员
+//                getDeptUserList(companyId, departmentDingding.getDdDeptid(), department.getDepartmentId(), access_token, 0L);
+                //获取子部门的数据
+                getDepartmentList(companyId, corpid, access_token, departmentDingding.getDdDeptid(), department.getDepartmentId());
+            }
+            //获取部门下的人员列表
+            getDeptUserIdList(companyId, parentDeptId, parentSysDeptId, access_token);
+        }
+    }
+
+    //获取部门下的人员ids
+    public void getDeptUserIdList(int companyId, long ddDeptId,Integer sysDeptId, String access_token) throws ApiException {
+        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/user/listid");
+        OapiUserListidRequest req = new OapiUserListidRequest();
+        req.setDeptId(ddDeptId);
+        OapiUserListidResponse rsp = client.execute(req, access_token);
+        System.out.println(rsp.getBody());
+        JSONObject resp = JSONObject.parseObject(rsp.getBody());
+        if (resp.getInteger("errcode") == 0) {
+            JSONArray jsonArray = resp.getJSONObject("result").getJSONArray("userid_list");
+            for (int i=0;i<jsonArray.size(); i++) {
+                String dduid = jsonArray.getString(i);
+                getUserDetail(companyId, sysDeptId, dduid, access_token);
+            }
+        }
+    }
+
+    //获取人员详情
+    private void getUserDetail(Integer companyId, Integer departmentId, String dingdingUserid, String access_token) throws ApiException {
+        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/v2/user/get");
+        OapiV2UserGetRequest req = new OapiV2UserGetRequest();
+        req.setUserid(dingdingUserid);
+        req.setLanguage("zh_CN");
+        OapiV2UserGetResponse rsp = client.execute(req, access_token);
+        System.out.println(rsp.getBody());
+        JSONObject resp = JSONObject.parseObject(rsp.getBody());
+        if (resp.getInteger("errcode") == 0) {
+            JSONObject userJson = resp.getJSONObject("result");
+            User user = new User();
+            int role = 0;
+            if (userJson.getBooleanValue("boss")) {
+                role = Constant.ROLE_MASTER;
+            } else if (userJson.getBooleanValue("admin")) {
+                role = Constant.ROLE_MANAGER;
+            } else if (userJson.getBooleanValue("senior")) {
+                role = Constant.ROLE_SENIOR;
+            }
+            user.setId(SnowFlake.nextId()+"")
+                    .setRole(role)
+                    .setCompanyId(companyId)
+                    .setDepartmentId(departmentId)
+                    .setName(userJson.getString("name"))
+                    .setDingdingUserid(dingdingUserid)
+                    .setDingdingUnionid(userJson.getString("unionid"))
+                    .setColor(ColorUtil.randomColor());
+
+            if (departmentId != null) {
+                user.setDepartmentCascade(convertDepartmentIdToCascade(departmentId));
+            }
+            //检查用户是否已经存在
+            if (userMapper.selectCount(new QueryWrapper<User>().eq("dingding_userid", dingdingUserid)) == 0) {
+                userMapper.insert(user);
+            } else {
+                //更新信息
+                User oldUser = userMapper.selectList(new QueryWrapper<User>().eq("dingding_userid", dingdingUserid).orderByDesc("create_time")).get(0);
+                oldUser.setName(userJson.getString("name"));
+                oldUser.setDepartmentId(departmentId);
+                if (oldUser.getRole() != Constant.ROLE_MASTER) {
+                    oldUser.setRole(user.getRole());
+                }
+                if (departmentId != null) {
+                    oldUser.setDepartmentCascade(convertDepartmentIdToCascade(departmentId));
+                }
+                userMapper.updateById(oldUser);
+            }
+
+        }
+    }
+
+    //通过unionid获取个人手机号
+    private void getUserMobile() throws Exception {
+        com.aliyun.dingtalkcontact_1_0.Client client = createClient();
+        GetUserHeaders getUserHeaders = new GetUserHeaders();
+        getUserHeaders.xAcsDingtalkAccessToken = "<your access token>";
+        try {
+            client.getUserWithOptions("z21HjQliSzpw0Yxxxx", getUserHeaders, new RuntimeOptions());
+        } catch (TeaException err) {
+            if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) {
+                // err 中含有 code 和 message 属性,可帮助开发定位问题
+                bizLogger.error(err.code+":"+err.message);
+            }
+        } catch (Exception _err) {
+            TeaException err = new TeaException(_err.getMessage(), _err);
+            if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) {
+                // err 中含有 code 和 message 属性,可帮助开发定位问题
+                bizLogger.error(err.code+":"+err.message);
+            }
+        }
+    }
+
+    //获取部门下的人员信息
+    private void getDeptUserList(int companyId, long ddDeptId,Integer sysDeptId, String access_token, long startCursor) throws ApiException {
+        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/user/listsimple");
+        OapiUserListsimpleRequest req = new OapiUserListsimpleRequest();
+        req.setDeptId(ddDeptId);
+        req.setCursor(startCursor);
+        req.setSize(100L);
+        req.setOrderField("modify_desc");
+        req.setContainAccessLimit(false);
+        req.setLanguage("zh_CN");
+        OapiUserListsimpleResponse rsp = client.execute(req, access_token);
+        System.out.println(rsp.getBody());
+        JSONObject resp = JSONObject.parseObject(rsp.getBody());
+        if (resp.getInteger("errcode") == 0) {
+            JSONObject result = resp.getJSONObject("result");
+            JSONArray list = result.getJSONArray("list");
+            List<User> userList = new ArrayList<>();
+            for (int i=0;i<list.size(); i++) {
+                JSONObject userObj = list.getJSONObject(i);
+                User user = new User();
+                Long id = SnowFlake.nextId();
+                user.setId(id+"");
+                user.setName(userObj.getString("name"));
+                user.setDingdingUserid(userObj.getString("userid"));
+                user.setDepartmentId(sysDeptId);
+                user.setRole(0);
+                user.setCompanyId(companyId);
+                user.setColor(ColorUtil.randomColor());
+                user.setDepartmentCascade(convertDepartmentIdToCascade(sysDeptId));
+                userList.add(user);
+            }
+            userService.saveBatch(userList);
+
+            //检查是否有更多
+            if (result.getBooleanValue("has_more")) {
+                getDeptUserList(companyId, ddDeptId, sysDeptId, access_token, result.getLong("next_cursor"));
+            }
+        }
+    }
+
+
+    //将部门id转换为部门层级
+    private String convertDepartmentIdToCascade(Integer id) {
+        StringBuilder cascade = new StringBuilder();
+        if (id == 0) {
+            cascade.append("0");
+        } else {
+            cascade.append(id);
+            id = departmentMapper.selectById(id).getSuperiorId();
+            while (id != null) {
+                cascade.append(",").append(id);
+                id = departmentMapper.selectById(id).getSuperiorId();
+            }
+        }
+        return cascade.toString();
+    }
+
+//
+//    //获取通讯录个人信息(带手机号)
+//    private void getUserMobile() throws Exception {
+//        com.aliyun.dingtalkcontact_1_0.Client client = createClient();
+//        GetUserHeaders getUserHeaders = new GetUserHeaders();
+//        getUserHeaders.xAcsDingtalkAccessToken = "<your access token>";
+//        try {
+//            client.getUserWithOptions("z21HjQliSzpw0Yxxxx", getUserHeaders, new RuntimeOptions());
+//        } catch (TeaException err) {
+//            if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) {
+//                // err 中含有 code 和 message 属性,可帮助开发定位问题
+//            }
+//
+//        } catch (Exception _err) {
+//            TeaException err = new TeaException(_err.getMessage(), _err);
+//            if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) {
+//                // err 中含有 code 和 message 属性,可帮助开发定位问题
+//            }
+//
+//        }
+//    }
+}

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

@@ -65,9 +65,9 @@ public class ExpenseSheetServiceImpl extends ServiceImpl<ExpenseSheetMapper, Exp
             }
         }
         JSONArray array = JSONArray.parseArray(items);
-        sheet.setOwnerId(userId);
+//        sheet.setOwnerId(userId);
         User user = userMapper.selectById(userId);
-        sheet.setOwnerName(user.getName());
+        sheet.setOwnerName(userMapper.selectById(sheet.getOwnerId()).getName());
         sheet.setCompanyId(user.getCompanyId());
         if (isNew) {
             expenseSheetMapper.insert(sheet);

+ 20 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ExpenseTypeServiceImpl.java

@@ -0,0 +1,20 @@
+package com.management.platform.service.impl;
+
+import com.management.platform.entity.ExpenseType;
+import com.management.platform.mapper.ExpenseTypeMapper;
+import com.management.platform.service.ExpenseTypeService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ *  服务实现类
+ * </p>
+ *
+ * @author Seyason
+ * @since 2021-06-18
+ */
+@Service
+public class ExpenseTypeServiceImpl extends ServiceImpl<ExpenseTypeMapper, ExpenseType> implements ExpenseTypeService {
+
+}

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

@@ -106,11 +106,15 @@ public class FinanceServiceImpl extends ServiceImpl<FinanceMapper, Finance> impl
 
             //由于第一行需要指明列对应的标题
             int rowNum = sheet.getLastRowNum();
-            for (int rowIndex = 0; rowIndex < sheet.getLastRowNum(); rowIndex++) {
+            for (int rowIndex = 0; rowIndex <= sheet.getLastRowNum(); rowIndex++) {
+
                 XSSFRow row = sheet.getRow(rowIndex);
                 if (row == null) {
                     continue;
                 }
+                if (ExcelUtil.isRowEmpty(row)) {
+                    continue;
+                }
                 //姓名	工资	奖金	津贴	养老保险	医疗保险	失业保险	住房公积金	其他
                 XSSFCell nameCell = row.getCell(0);
                 XSSFCell salaryCell = row.getCell(1);
@@ -131,9 +135,9 @@ public class FinanceServiceImpl extends ServiceImpl<FinanceMapper, Finance> impl
                 inMedicalCell.setCellType(CellType.STRING);
                 inJobCell.setCellType(CellType.STRING);
                 houseFundCell.setCellType(CellType.STRING);
-                otherCell.setCellType(CellType.STRING);
+                if (otherCell != null)otherCell.setCellType(CellType.STRING);
 
-                String name = nameCell.getStringCellValue();
+                String name = nameCell.getStringCellValue().trim().replaceAll("\\u00a0", "");
                 Finance finance = new Finance();
                 if (name.equals("姓名") && rowIndex == 0) {
                     //跳过第一行标题
@@ -150,7 +154,7 @@ public class FinanceServiceImpl extends ServiceImpl<FinanceMapper, Finance> impl
                     if (salaryCell != null) {
                         salaryCell.setCellType(CellType.STRING);
                         String item = salaryCell.getStringCellValue();
-                        BigDecimal value = item != null ? new BigDecimal(item) : BigDecimal.valueOf(0);
+                        BigDecimal value = item != null ? new BigDecimal(item.trim().replaceAll("\\u00a0", "")) : BigDecimal.valueOf(0);
                         finance.setMonthCost(value);
                         total = total.add(value);
                     }
@@ -164,49 +168,49 @@ public class FinanceServiceImpl extends ServiceImpl<FinanceMapper, Finance> impl
                     if (bonusCell != null) {
                         bonusCell.setCellType(CellType.STRING);
                         String bonusString = bonusCell.getStringCellValue();
-                        BigDecimal bonus = bonusString != null ? new BigDecimal(bonusString) : BigDecimal.valueOf(0);
+                        BigDecimal bonus = bonusString != null ? new BigDecimal(bonusString.trim().replaceAll("\\u00a0", "")) : BigDecimal.valueOf(0);
                         finance.setBonus(bonus);
                         total = total.add(bonus);
                     }
                     if (allowanceCell != null) {
                         allowanceCell.setCellType(CellType.STRING);
                         String item = allowanceCell.getStringCellValue();
-                        BigDecimal value = item != null ? new BigDecimal(item) : BigDecimal.valueOf(0);
+                        BigDecimal value = item != null ? new BigDecimal(item.trim().replaceAll("\\u00a0", "")) : BigDecimal.valueOf(0);
                         finance.setAllowance(value);
                         total = total.add(value);
                     }
                     if (inJobCell != null) {
                         inJobCell.setCellType(CellType.STRING);
                         String item = inJobCell.getStringCellValue();
-                        BigDecimal value = item != null ? new BigDecimal(item) : BigDecimal.valueOf(0);
+                        BigDecimal value = item != null ? new BigDecimal(item.trim().replaceAll("\\u00a0", "")) : BigDecimal.valueOf(0);
                         finance.setInsuranceLosejob(value);
                         total = total.add(value);
                     }
                     if (inMedicalCell != null) {
                         inMedicalCell.setCellType(CellType.STRING);
                         String item = inMedicalCell.getStringCellValue();
-                        BigDecimal value = item != null ? new BigDecimal(item) : BigDecimal.valueOf(0);
+                        BigDecimal value = item != null ? new BigDecimal(item.trim().replaceAll("\\u00a0", "")) : BigDecimal.valueOf(0);
                         finance.setInsuranceMedical(value);
                         total = total.add(value);
                     }
                     if (inOldCell != null) {
                         inOldCell.setCellType(CellType.STRING);
                         String item = inOldCell.getStringCellValue();
-                        BigDecimal value = item != null ? new BigDecimal(item) : BigDecimal.valueOf(0);
+                        BigDecimal value = item != null ? new BigDecimal(item.trim().replaceAll("\\u00a0", "")) : BigDecimal.valueOf(0);
                         finance.setInsuranceOld(value);
                         total = total.add(value);
                     }
                     if (houseFundCell != null) {
                         houseFundCell.setCellType(CellType.STRING);
                         String item = houseFundCell.getStringCellValue();
-                        BigDecimal value = item != null ? new BigDecimal(item) : BigDecimal.valueOf(0);
+                        BigDecimal value = item != null ? new BigDecimal(item.trim().replaceAll("\\u00a0", "")) : BigDecimal.valueOf(0);
                         finance.setHouseFund(value);
                         total = total.add(value);
                     }
                     if (otherCell != null) {
                         otherCell.setCellType(CellType.STRING);
                         String item = otherCell.getStringCellValue();
-                        BigDecimal value = item != null ? new BigDecimal(item) : BigDecimal.valueOf(0);
+                        BigDecimal value = item != null ? new BigDecimal(item.trim().replaceAll("\\u00a0", "")) : BigDecimal.valueOf(0);
                         finance.setOthers(value);
                         total = total.add(value);
                     }
@@ -219,13 +223,24 @@ public class FinanceServiceImpl extends ServiceImpl<FinanceMapper, Finance> impl
                 financeList.add(finance);
 
             }
-            //最后删掉这个文件
-//            if (!file.delete()) {
-//                System.out.println("临时文件" + file.getName() + "删除失败");
-//            }
-            System.out.println("size=="+financeList.size());
+
             //批量插入
             financeService.saveOrUpdateBatch(financeList);
+
+            //检查是否有删除的,需要删除掉
+            List<Integer> readyForDelete = new ArrayList<>();
+            oldFinanceList.forEach(old->{
+                boolean exists = false;
+                if (financeList.stream().filter(f->f.getName().equals(old.getName())).findAny().isPresent()) {
+                    exists = true;
+                }
+                if (!exists) {
+                    readyForDelete.add(old.getId());
+                }
+            });
+            if (readyForDelete.size() > 0) {
+                financeService.removeByIds(readyForDelete);
+            }
         } catch (IOException e) {
             e.printStackTrace();
             msg.setError("文件处理出错");
@@ -290,10 +305,10 @@ public class FinanceServiceImpl extends ServiceImpl<FinanceMapper, Finance> impl
 
 
             //获取月成本列表
-            DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
-            String dateStr = yearMonth+"-01 00:00:00";
-            LocalDateTime startDate = LocalDateTime.parse(dateStr,df);
-            LocalDateTime endDate = LocalDateTime.parse(dateStr,df);
+            DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+            String dateStr = yearMonth+"-01";
+            LocalDate startDate = LocalDate.parse(dateStr,df);
+            LocalDate endDate = LocalDate.parse(dateStr,df);
             endDate = endDate.plusMonths(1);
 
             List<Map<String, Object>> projectTimeList = reportMapper.getRealProjectTime(startDate, endDate, companyId);
@@ -502,10 +517,10 @@ public class FinanceServiceImpl extends ServiceImpl<FinanceMapper, Finance> impl
             Integer companyId = userMapper.selectById(request.getHeader("Token")).getCompanyId();
             Map<String, Object> resultMap = new HashMap<>();
             //获取月成本列表
-            DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
-            String dateStr = yearMonth+"-01 00:00:00";
-            LocalDateTime startDate = LocalDateTime.parse(dateStr,df);
-            LocalDateTime endDate = LocalDateTime.parse(dateStr,df);
+            DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+            String dateStr = yearMonth+"-01";
+            LocalDate startDate = LocalDate.parse(dateStr,df);
+            LocalDate endDate = LocalDate.parse(dateStr,df);
             endDate = endDate.plusMonths(1);
 
             List<Map<String, Object>> projectTimeList = reportMapper.getRealProjectTime(startDate, endDate, companyId);

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

@@ -12,18 +12,27 @@ import com.management.platform.service.ProjectService;
 import com.management.platform.util.HttpRespMsg;
 import com.management.platform.util.ExcelUtil;
 import com.management.platform.util.ListUtil;
+import org.apache.poi.ss.usermodel.CellType;
+import org.apache.poi.xssf.usermodel.XSSFCell;
+import org.apache.poi.xssf.usermodel.XSSFRow;
+import org.apache.poi.xssf.usermodel.XSSFSheet;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+import org.assertj.core.util.Lists;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.util.StringUtils;
+import org.springframework.web.multipart.MultipartFile;
 
 import javax.annotation.Resource;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import javax.servlet.http.Part;
+import java.io.*;
 import java.math.BigDecimal;
+import java.text.SimpleDateFormat;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.time.format.DateTimeFormatter;
@@ -43,6 +52,9 @@ import java.util.stream.Collectors;
 @Service
 @Transactional
 public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> implements ProjectService {
+    String pathPrefix = "/upload/";
+    @Resource
+    private ProjectService projectService;
     @Resource
     private ProjectMapper projectMapper;
     @Resource
@@ -58,6 +70,8 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
     @Resource
     private EarningSnapshotMapper earningSnapshotMapper;
     @Resource
+    private ExpenseItemMapper expenseItemMapper;
+    @Resource
     private TimeTypeMapper timeTypeMapper;
     @Resource
     private HttpServletResponse response;
@@ -172,7 +186,10 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
                 httpRespMsg.setError("请填写项目名称");
             } else {
                 //检查项目编号不能重复
-                Integer count = projectMapper.selectCount(new QueryWrapper<Project>().eq("company_id", companyId).eq("project_code", code));
+                Integer count = 0;
+                if (!StringUtils.isEmpty(code)) {
+                    count = projectMapper.selectCount(new QueryWrapper<Project>().eq("company_id", companyId).eq("project_code", code));
+                }
                 if (count > 0) {
                     httpRespMsg.setError("提交失败:项目编号已存在");
                 } else {
@@ -349,7 +366,7 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
             List<String> headList = new ArrayList<String>();
             headList.add("项目");
             headList.add("人员");
-            headList.add("时(h)");
+            headList.add("时(h)");
             headList.add("成本(元)");
             List<List<String>> allList = new ArrayList<List<String>>();
             allList.add(headList);
@@ -533,6 +550,7 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
         return new HttpRespMsg();
     }
 
+
     //获取某个项目每个人分别需要的工时
     @Override
     public HttpRespMsg getProjectCost(String startDate, String endDate, Integer projectId, HttpServletRequest request) {
@@ -595,4 +613,391 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
         }
         return httpRespMsg;
     }
+
+
+    @Override
+    public HttpRespMsg exportProfit(HttpServletRequest request) {
+        String userId = request.getHeader("TOKEN");
+        Integer companyId = userMapper.selectById(userId).getCompanyId();
+        List<Project> projectList = projectMapper.selectList(new QueryWrapper<Project>().eq("company_id", companyId));
+        
+        return null;
+    }
+
+    @Override
+    public HttpRespMsg exportProject(HttpServletRequest request) {
+        HttpRespMsg httpRespMsg = new HttpRespMsg();
+        //通过公司id获取该公司所有的项目列表
+        User user = userMapper.selectById(request.getHeader("Token"));
+        Integer companyId = user.getCompanyId();
+        //判断用户的角色,如果是管理员和负责人,查看全部的。如果是普通员工,只能是看到参与的项目
+        QueryWrapper<Project> queryWrapper = new QueryWrapper<Project>().eq("company_id", companyId);
+        DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+        List<Project> projectList = projectMapper.selectList(queryWrapper);
+        List<User> userList = userMapper.selectList(new QueryWrapper<User>().eq("company_id", companyId));
+        List<ProjectVO> list = new ArrayList<>();
+        String[] statusNames = {"-","进行中","已完成","已撤销"};
+        List<List<String>> exportList = new ArrayList<>();
+        String[] titles = {"项目编号", "项目名称", "负责人", "项目金额(元)", "状态","计划开始时间", "计划结束时间", "完成度"};
+        exportList.add(Lists.list(titles));
+        for (Project project : projectList) {
+            List<String> data = new ArrayList<>();
+            data.add(project.getProjectCode() == null?"":project.getProjectCode());
+            data.add(project.getProjectName() == null?"":project.getProjectName());
+            Optional<User> first = userList.stream().filter(u -> u.getId().equals(project.getInchargerId())).findFirst();
+            if (first.isPresent()) {
+                User incharger = first.get();
+                data.add(incharger.getName());
+            } else {
+                data.add("");
+            }
+            if (project.getContractAmount() != null) {
+                data.add(project.getContractAmount().doubleValue()+"");
+            }
+            data.add(project.getStatus()==null?"":statusNames[project.getStatus()]);
+            data.add(project.getPlanStartDate() != null?df.format(project.getPlanStartDate()):"");
+            data.add(project.getPlanEndDate() != null?df.format(project.getPlanEndDate()):"");
+            data.add(project.getProgress() != null?project.getProgress()+"%" :"");
+            exportList.add(data);
+        }
+        String fileName = "项目报表_"+System.currentTimeMillis();
+        ExcelUtil.exportGeneralExcelByTitleAndList(fileName, exportList, path);
+        httpRespMsg.data =  pathPrefix + fileName+".xls";
+        return httpRespMsg;
+    }
+
+    @Override
+    public HttpRespMsg getProjectTask(Integer pageIndex, Integer pageSize, HttpServletRequest request) {
+        User user = userMapper.selectById(request.getHeader("Token"));
+        Integer companyId = user.getCompanyId();
+        int total = taskMapper.getProjectTaskCount(companyId);
+        int pageStart = (pageIndex -1) * pageSize;
+        System.out.println("companyId="+companyId+", pageStart="+pageStart+", pageSize="+pageSize);
+        List projectTask = taskMapper.getProjectTask(companyId, pageStart, pageSize);
+        HttpRespMsg httpRespMsg = new HttpRespMsg();
+        Map<String, Object> map = new HashMap<>();
+        map.put("records", projectTask);
+        map.put("total", total);
+        httpRespMsg.data = map;
+        return httpRespMsg;
+    }
+
+    @Override
+    public HttpRespMsg exportProjectTask(HttpServletRequest request) {
+        HttpRespMsg httpRespMsg = new HttpRespMsg();
+
+        User user = userMapper.selectById(request.getHeader("Token"));
+        Integer companyId = user.getCompanyId();
+
+        QueryWrapper<Project> queryWrapper = new QueryWrapper<Project>().eq("company_id", companyId);
+        DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+        List<Map> projectList = taskMapper.getProjectTask(companyId, null, null);
+        List<ProjectVO> list = new ArrayList<>();
+        String[] statusNames = {"进行中","已完成","已撤销"};
+        String[] typeList = {"任务","里程碑","风险"};
+        List<List<String>> exportList = new ArrayList<>();
+        String[] titles = {"项目编号", "项目名称", "任务名称", "计划工时(h)", "实际工时(h)","状态", "类型", "截止日期"};
+        exportList.add(Lists.list(titles));
+        for (Map task : projectList) {
+            List<String> data = new ArrayList<>();
+            data.add(task.get("project_code") == null?"":task.get("project_code").toString());
+            data.add(task.get("project_name") == null?"":task.get("project_name").toString());
+            data.add(task.get("name") != null?task.get("name").toString():"");
+            data.add(task.get("plan_hours") != null?task.get("plan_hours").toString():"");
+            data.add(task.get("real_hours").toString());
+            data.add(task.get("task_status")==null?"":statusNames[Integer.parseInt(task.get("task_status").toString())]);
+            data.add(typeList[Integer.parseInt(task.get("task_type").toString())]);
+            data.add(task.get("end_date") != null? task.get("end_date").toString():"");
+            exportList.add(data);
+        }
+        String fileName = "项目任务报表_"+System.currentTimeMillis();
+        ExcelUtil.exportGeneralExcelByTitleAndList(fileName, exportList, path);
+        httpRespMsg.data =  pathPrefix + fileName+".xls";
+        return httpRespMsg;
+    }
+
+    @Override
+    public HttpRespMsg getAllProjectCost(Integer pageIndex, Integer pageSize, HttpServletRequest request) {
+        User user = userMapper.selectById(request.getHeader("Token"));
+        Integer companyId = user.getCompanyId();
+        //撤销的项目不算
+        QueryWrapper<Project> queryWrapper = new QueryWrapper<Project>().eq("company_id", companyId);
+        queryWrapper.and(wrapper->wrapper.isNull("status").or().ne("status", 3));
+        int total = projectMapper.selectCount(queryWrapper);
+        int pageStart = (pageIndex -1) * pageSize;
+        System.out.println("companyId="+companyId+", pageStart="+pageStart+", pageSize="+pageSize);
+        List projectTask = projectMapper.getAllProjectCost(companyId, pageStart, pageSize);
+        HttpRespMsg httpRespMsg = new HttpRespMsg();
+        Map<String, Object> map = new HashMap<>();
+        map.put("records", projectTask);
+        map.put("total", total);
+        httpRespMsg.data = map;
+        return httpRespMsg;
+    }
+
+    @Override
+    public HttpRespMsg exportAllProjectCost(HttpServletRequest request) {
+        HttpRespMsg httpRespMsg = new HttpRespMsg();
+        //通过公司id获取该公司所有的项目列表
+        User user = userMapper.selectById(request.getHeader("Token"));
+        Integer companyId = user.getCompanyId();
+
+        QueryWrapper<Project> queryWrapper = new QueryWrapper<Project>().eq("company_id", companyId);
+        List<Project> projectList = projectMapper.getAllProjectCost(companyId, null, null);
+        List<List<String>> exportList = new ArrayList<>();
+        String[] titles = {"项目编号", "项目名称", "人工成本", "一般费用", "差旅费用","外包费用", "总费用"};
+        exportList.add(Lists.list(titles));
+        for (Project project : projectList) {
+            List<String> data = new ArrayList<>();
+            data.add(project.getProjectCode());
+            data.add(project.getProjectName());
+            data.add(project.getFeeMan().toString());
+            data.add(project.getFeeNormal().toString());
+            data.add(project.getFeeTravel().toString());
+            data.add(project.getFeeOutsourcing().toString());
+            double totalFee = project.getFeeMan() + project.getFeeNormal()+ project.getFeeTravel()+ project.getFeeOutsourcing();
+            data.add(totalFee+"");
+            exportList.add(data);
+        }
+        String fileName = "项目成本报表_"+System.currentTimeMillis();
+        ExcelUtil.exportGeneralExcelByTitleAndList(fileName, exportList, path);
+        httpRespMsg.data =  pathPrefix + fileName+".xls";
+        return httpRespMsg;
+    }
+
+    @Override
+    public HttpRespMsg getProjectInAndOut(Integer pageIndex, Integer pageSize, HttpServletRequest request) {
+        User user = userMapper.selectById(request.getHeader("Token"));
+        Integer companyId = user.getCompanyId();
+        //撤销的项目不算
+        //撤销的项目不算
+        QueryWrapper<Project> queryWrapper = new QueryWrapper<Project>().eq("company_id", companyId);
+        queryWrapper.and(wrapper->wrapper.isNull("status").or().ne("status", 3));
+        int total = projectMapper.selectCount(queryWrapper);
+        int pageStart = (pageIndex -1) * pageSize;
+        System.out.println("companyId="+companyId+", pageStart="+pageStart+", pageSize="+pageSize);
+        List projectTask = projectMapper.getProjectInAndOut(companyId, pageStart, pageSize);
+        HttpRespMsg httpRespMsg = new HttpRespMsg();
+        Map<String, Object> map = new HashMap<>();
+        map.put("records", projectTask);
+        map.put("total", total);
+        httpRespMsg.data = map;
+        return httpRespMsg;
+    }
+
+    @Override
+    public HttpRespMsg exportProjectInAndOut(HttpServletRequest request) {
+        HttpRespMsg httpRespMsg = new HttpRespMsg();
+        //通过公司id获取该公司所有的项目列表
+        User user = userMapper.selectById(request.getHeader("Token"));
+        Integer companyId = user.getCompanyId();
+
+        QueryWrapper<Project> queryWrapper = new QueryWrapper<Project>().eq("company_id", companyId);
+        List<Project> projectList = projectMapper.getProjectInAndOut(companyId, null, null);
+        List<List<String>> exportList = new ArrayList<>();
+        String[] titles = {"项目编号", "项目名称", "合同金额", "人工成本", "一般费用", "差旅费用","外包费用", "总费用", "利润", "利润率"};
+        exportList.add(Lists.list(titles));
+        for (Project project : projectList) {
+            List<String> data = new ArrayList<>();
+            data.add(project.getProjectCode());
+            data.add(project.getProjectName());
+            data.add(project.getContractAmount() != null?project.getContractAmount().toString():"");
+            data.add(project.getFeeMan().toString());
+            data.add(project.getFeeNormal().toString());
+            data.add(project.getFeeTravel().toString());
+            data.add(project.getFeeOutsourcing().toString());
+            double totalFee = project.getFeeMan() + project.getFeeNormal()+ project.getFeeTravel()+ project.getFeeOutsourcing();
+            data.add(totalFee+"");
+            if (project.getContractAmount() != null && project.getContractAmount() > 0) {
+                double profitAmt = project.getContractAmount() - totalFee;
+                data.add(profitAmt+"");
+                data.add(new java.text.DecimalFormat("#.0").format((100*profitAmt/project.getContractAmount()))+"%");
+            } else {
+                double profitAmt = -totalFee;
+                data.add(profitAmt+"");
+                data.add("");
+            }
+            exportList.add(data);
+        }
+        String fileName = "项目收支平衡报表(利润表)_"+System.currentTimeMillis();
+        ExcelUtil.exportGeneralExcelByTitleAndList(fileName, exportList, path);
+        httpRespMsg.data =  pathPrefix + fileName+".xls";
+        return httpRespMsg;
+    }
+
+    @Override
+    public HttpRespMsg importData(String userId, MultipartFile multipartFile, HttpServletRequest request) {
+        HttpRespMsg msg = new HttpRespMsg();
+        User user = userMapper.selectById(userId);
+        //然后处理文件
+        String fileName = multipartFile.getOriginalFilename();
+        File file = new File(fileName == null ? "file" : fileName);
+        InputStream inputStream = null;
+        OutputStream outputStream = null;
+        try {
+            inputStream = multipartFile.getInputStream();
+            outputStream = new FileOutputStream(file);
+            byte[] buffer = new byte[4096];
+            int temp = 0;
+            while ((temp = inputStream.read(buffer, 0, 4096)) != -1) {
+                outputStream.write(buffer, 0, temp);
+            }
+            inputStream.close();
+            outputStream.close();
+            //然后解析表格
+            XSSFWorkbook workbook = new XSSFWorkbook(file);
+            //我们只需要第一个sheet
+            XSSFSheet sheet = workbook.getSheetAt(0);
+            //获取全部人员
+            List<User> userList = userMapper.selectList(new QueryWrapper<User>().eq("company_id", user.getCompanyId()));
+            List<Project> projectList = new ArrayList<Project>();
+            //由于第一行需要指明列对应的标题
+            int rowNum = sheet.getLastRowNum();
+
+            HashMap<String, Integer> projectLevelMap = new HashMap<>();
+            projectLevelMap.put("正常", 1);
+            projectLevelMap.put("紧急", 2);
+            projectLevelMap.put("重要", 3);
+            projectLevelMap.put("重要且紧急", 4);
+            for (int rowIndex = 0; rowIndex <= rowNum; rowIndex++) {
+                XSSFRow row = sheet.getRow(rowIndex);
+                if (row == null) {
+                    continue;
+                }
+                //跳过空行
+                if (ExcelUtil.isRowEmpty(row)) {
+                    continue;
+                }
+                System.out.println("当前行="+rowIndex);
+                //项目编号	项目名称 参与人 负责人 级别 开始日期 截止日期 合同金额
+                XSSFCell codeCell = row.getCell(0);
+                XSSFCell nameCell = row.getCell(1);
+                XSSFCell participatorCell = row.getCell(2);
+                XSSFCell inchargerCell = row.getCell(3);
+                XSSFCell levelCell = row.getCell(4);
+                XSSFCell startDateCell = row.getCell(5);
+                XSSFCell endDateCell = row.getCell(6);
+                XSSFCell amountCell = row.getCell(7);
+
+
+                if (codeCell != null)codeCell.setCellType(CellType.STRING);
+                if (nameCell != null)nameCell.setCellType(CellType.STRING);
+                if (participatorCell != null)participatorCell.setCellType(CellType.STRING);
+                if (inchargerCell != null)inchargerCell.setCellType(CellType.STRING);
+                if (levelCell != null)levelCell.setCellType(CellType.STRING);
+                if (startDateCell != null)startDateCell.setCellType(CellType.NUMERIC);
+                if (endDateCell != null)endDateCell.setCellType(CellType.NUMERIC);
+                if (amountCell != null)amountCell.setCellType(CellType.STRING);
+                if (nameCell == null) {//项目名称为空的直接跳过
+                    throw new Exception("项目名称不能为空");
+                }
+
+                Project project = new Project();
+                if (codeCell != null) {
+                    String code = codeCell.getStringCellValue().trim().replaceAll("\\u00a0", "");
+                    if (code.equals("项目编号") && rowIndex == 0) {
+                        //跳过第一行标题
+                        continue;
+                    }
+                    //检查编号是否已经存在
+                    if (!StringUtils.isEmpty(code)) {
+                        int cnt = projectMapper.selectCount(new QueryWrapper<Project>().eq("project_code", code).eq("company_id", user.getCompanyId()));
+                        if (cnt > 0) {
+                            throw new Exception("项目编码存在重复: " + code);
+                        }
+                    } else {
+                        project.setProjectCode(code);
+                    }
+                }
+
+                String name = nameCell.getStringCellValue().trim().replaceAll("\\u00a0", "");
+                project.setCompanyId(user.getCompanyId());
+                project.setCreatorId(userId);
+                project.setCreatorName(user.getName());
+                project.setProjectName(name);
+                //处理人员
+                if (inchargerCell != null) {
+                    String inchargerName = inchargerCell.getStringCellValue();
+                    if (!StringUtils.isEmpty(inchargerName)) {
+                        Optional<User> first = userList.stream().filter(u -> u.getName().equals(inchargerName)).findFirst();
+                        if (first.isPresent()) {
+                            project.setInchargerId(first.get().getId());
+                            project.setInchargerName(inchargerName);
+                        } else {
+                            throw new Exception("项目负责人["+inchargerName+"]不存在");
+                        }
+                    }
+                }
+
+
+                if (levelCell != null) {
+                    String levelStr = levelCell.getStringCellValue();
+                    if (!StringUtils.isEmpty(levelStr)) {
+                        project.setLevel(projectLevelMap.get(levelStr));
+                    }
+                }
+
+                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
+                if (startDateCell !=null && !StringUtils.isEmpty(startDateCell.getDateCellValue())) {
+                    project.setPlanStartDate(LocalDate.parse(sdf.format(startDateCell.getDateCellValue()), DateTimeFormatter.ofPattern("yyyy-MM-dd")));
+                }
+                if (endDateCell !=null && !StringUtils.isEmpty(endDateCell.getDateCellValue())) {
+                    project.setPlanEndDate(LocalDate.parse(sdf.format(endDateCell.getDateCellValue()), DateTimeFormatter.ofPattern("yyyy-MM-dd")));
+                }
+                if (amountCell !=null && !StringUtils.isEmpty(amountCell.getStringCellValue())) {
+                    project.setContractAmount(Integer.parseInt(amountCell.getStringCellValue()));
+                }
+
+                projectMapper.insert(project);
+                //参与人
+                if (participatorCell != null) {
+                    String part = participatorCell.getStringCellValue();
+                    if (!StringUtils.isEmpty(part)) {
+                        String[] split = part.split(",");
+                        for (String str : split) {
+                            Participation p = new Participation();
+                            Optional<User> first = userList.stream().filter(u -> u.getName().equals(str)).findFirst();
+                            if (first.isPresent()) {
+                                p.setUserId(first.get().getId());
+                                p.setProjectId(project.getId());
+                                participationMapper.insert(p);
+                            } else {
+                                projectMapper.deleteById(project.getId());
+                                throw new Exception("参与人["+str+"]不存在");
+                            }
+                        }
+                    }
+                }
+
+            }
+            //批量插入
+            //projectService.saveOrUpdateBatch(projectList);
+        } catch (IOException e) {
+            e.printStackTrace();
+            msg.setError("文件处理出错");
+            return msg;
+        } catch (NullPointerException e) {
+            e.printStackTrace();
+            msg.setError("数据格式有误或存在空数据 导入失败");
+            return msg;
+        } catch (Exception e) {
+            e.printStackTrace();
+            msg.setError("上传失败:"+e.getMessage());
+            return msg;
+        } finally {
+            //关闭流
+            try {
+                if (outputStream != null && inputStream != null) {
+                    outputStream.close();
+                    inputStream.close();
+                    System.out.println("流已关闭");
+                }
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+//            file.deleteOnExit();//程序退出时删除临时文件
+            System.out.println(file.delete());
+        }
+        return msg;
+    }
 }

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

@@ -179,6 +179,7 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
                             List<Map<String, Object>> list2 =
                                     inchargeReportList.stream().filter(i->i.get("creatorId").equals(map2.get("id"))).collect(Collectors.toList());
                             map2.put("data", list2);
+
                             double reportTime = 0;
                             BigDecimal total = new BigDecimal(0);
                             for (Map<String, Object> m : list2) {
@@ -370,7 +371,7 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
             }
             idList.add(report.getId());
         }
-        if (idList.size() > 0 && date != null) {
+        if (idList.size() > 0 && date != null && !date.contains("@")) {
             reportMapper.delete(new QueryWrapper<Report>()
                     .eq("create_date", date)
                     .eq("creator_id", reportList.get(0).getCreatorId())
@@ -417,6 +418,9 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
                     return (sdf.format((java.sql.Date)map.get("date"))).equals(date);
                 }).collect(Collectors.toList());
             }
+            nameList.forEach(n->{
+                n.put("dateStr",sdf.format((java.sql.Date)n.get("date")));
+            });
 
             List<User> userList = userMapper.selectList(new QueryWrapper<User>().eq("company_id", companyId));
 
@@ -456,27 +460,6 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
                     map2.put("state", list2.get(0).get("state"));
                 }
             }
-//            for (Map<String, Object> map : nameList) {
-//                //再根据人分别获取当天的报告
-//                List<Map<String, Object>> list = reportMapper.getReportByDate(
-//                        map.get("date").toString(),
-//                        (String) map.get("id"));
-//                map.put("data", list);
-//                double reportTime = 0;
-//                if (list.size() > 0) {
-//                    for (Map<String, Object> m : list) {
-//                        double t = (double) m.get("time");
-//                        reportTime += t;
-//                    }
-//                    map.put("state", list.get(0).get("state"));
-//                }
-//                DecimalFormat df = new DecimalFormat("0.00");
-//                map.put("reportTime", df.format(reportTime));
-//                //计算成本
-//                BigDecimal multiply = userList.stream().filter(u -> u.getId().equals((String) map.get("id"))).findFirst().get().getCost().multiply(new BigDecimal(reportTime));
-//                map.put("cost", multiply);
-//
-//            }
             httpRespMsg.data = nameList;
         } catch (NullPointerException e) {
             httpRespMsg.setError("验证失败");
@@ -587,6 +570,12 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
         if (manageDeptId != null && manageDeptId > 0) {
             //指定查看某个部门下的
             list = getSpecifiedDept(list, manageDeptId);
+        } else {
+            //加上未分配的部门
+            DepartmentVO unAssignedDept = new DepartmentVO();
+            unAssignedDept.setId(0);
+            unAssignedDept.setLabel("未分配");
+            list.add(unAssignedDept);
         }
         //获取公司全部人员
         List<User> userList = userMapper.selectList(new QueryWrapper<User>().eq("company_id", companyId));
@@ -660,6 +649,14 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
         return msg;
     }
 
+    @Override
+    public HttpRespMsg getReportFillStatus(String startDate, String endDate, String userId, HttpServletRequest request) {
+        HttpRespMsg msg = new HttpRespMsg();
+        msg.data = reportMapper.getReportFillStatus(startDate, endDate, userId);
+
+        return msg;
+    }
+
     private void fillDeptUser(List<DepartmentVO> list, List<HashMap> userList) {
         list.forEach(l->{
             List<HashMap> collect = userList.stream().filter(u -> u.get("departmentId").equals(l.getId())).collect(Collectors.toList());

+ 20 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/SysConfigServiceImpl.java

@@ -0,0 +1,20 @@
+package com.management.platform.service.impl;
+
+import com.management.platform.entity.SysConfig;
+import com.management.platform.mapper.SysConfigMapper;
+import com.management.platform.service.SysConfigService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ *  服务实现类
+ * </p>
+ *
+ * @author Seyason
+ * @since 2021-06-26
+ */
+@Service
+public class SysConfigServiceImpl extends ServiceImpl<SysConfigMapper, SysConfig> implements SysConfigService {
+
+}

+ 208 - 11
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/UserServiceImpl.java

@@ -1,6 +1,7 @@
 package com.management.platform.service.impl;
 
 import com.alibaba.fastjson.JSONObject;
+import com.aliyun.dysmsapi20170525.models.SendSmsResponse;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
@@ -8,8 +9,10 @@ import com.management.platform.constant.Constant;
 import com.management.platform.entity.*;
 import com.management.platform.entity.vo.UserVO;
 import com.management.platform.mapper.*;
+import com.management.platform.service.ReportService;
 import com.management.platform.service.UserService;
 import com.management.platform.util.*;
+import org.apache.poi.hssf.usermodel.*;
 import org.apache.poi.ss.usermodel.CellType;
 import org.apache.poi.xssf.usermodel.XSSFCell;
 import org.apache.poi.xssf.usermodel.XSSFRow;
@@ -23,20 +26,22 @@ import org.springframework.http.HttpStatus;
 import org.springframework.http.ResponseEntity;
 import org.springframework.stereotype.Service;
 import org.springframework.util.NumberUtils;
+import org.springframework.util.StringUtils;
 import org.springframework.web.client.RestTemplate;
 import org.springframework.web.multipart.MultipartFile;
+import sun.util.calendar.ZoneInfoFile;
 
 import javax.annotation.Resource;
 import javax.servlet.http.HttpServletRequest;
 import java.io.*;
 import java.math.BigDecimal;
 import java.math.RoundingMode;
+import java.text.SimpleDateFormat;
+import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.time.ZoneOffset;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.time.format.DateTimeFormatter;
+import java.util.*;
 
 /**
  * <p>
@@ -49,6 +54,8 @@ import java.util.Map;
 @Service
 public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
 
+    @Value(value = "${upload.path}")
+    private String path;
     @Value("${wx.template_report_fill}")
     public String TEMPLATE_REPORT_FILL;
     @Value("${wx.app_id}")
@@ -63,11 +70,15 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
     @Autowired
     private RestTemplate restTemplate;
 
+    @Resource
+    private ReportService reportService;
     @Resource
     private HttpServletRequest request;
     @Resource
     private UserMapper userMapper;
     @Resource
+    private ReportMapper reportMapper;
+    @Resource
     private CompanyMapper companyMapper;
     @Resource
     private DepartmentMapper departmentMapper;
@@ -77,6 +88,8 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
     private ProjectMapper projectMapper;
     @Resource
     private UserSalaryMapper userSalaryMapper;
+    @Resource
+    private UserVcodeMapper userVcodeMapper;
     //登录网页端
     @Override
     public HttpRespMsg loginAdmin(String username, String password) {
@@ -297,11 +310,20 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
 
     //新增公司和负责人
     @Override
-    public HttpRespMsg insertCompany(String companyName, String name, String phone) {
+    public HttpRespMsg insertCompany(String companyName, String name, String phone, String vcode, String password) {
         HttpRespMsg httpRespMsg = new HttpRespMsg();
+        //检查验证码是否正确
+        LocalDateTime now = LocalDateTime.now();
+        now = now.minusMinutes(5);//5分钟内有效
+
+        Integer exists = userVcodeMapper.selectCount(new QueryWrapper<UserVcode>().eq("mobile", phone).gt("indate", now).eq("vcode", vcode));
+        if (exists == 0) {
+            httpRespMsg.setError("验证码不正确");
+            return httpRespMsg;
+        }
         //首先检测用户名是否重复
         if (userMapper.selectList(new QueryWrapper<User>().eq("phone", phone)).size() > 0) {
-            httpRespMsg.setError("电话号码重复");
+            httpRespMsg.setError("该电话号码已注册");
         } else {
             //首先生成一个新公司,增加会员的试用一个月
             Company company = new Company().setCompanyName(companyName)
@@ -321,7 +343,7 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
             User user = new User()
                     .setId(id.toString())
                     .setName(name)
-                    .setPassword(MD5Util.getPassword("000000"))
+                    .setPassword(MD5Util.getPassword(password))
                     .setPhone(phone)
                     .setRole(1)
                     .setColor(ColorUtil.randomColor())
@@ -339,13 +361,13 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
     //新增或修改用户
     @Override
     public HttpRespMsg insertUser(String targetId, String name, String phone, Integer role, Double monthCost, Double cost,
-                                  Integer departmentId, Integer salaryType, HttpServletRequest request) {
+                                  Integer departmentId, Integer salaryType, String costApplyDate, HttpServletRequest request) {
         HttpRespMsg httpRespMsg = new HttpRespMsg();
         try {
             User creator = userMapper.selectById(request.getHeader("Token"));
             //处理时薪
             BigDecimal costValue = cost == null ? BigDecimal.valueOf(0) : BigDecimal.valueOf(cost);
-            BigDecimal monthCostValue = monthCost == null ? BigDecimal.valueOf(0) : BigDecimal.valueOf(monthCost);
+            BigDecimal monthCostValue = (monthCost == null ? BigDecimal.valueOf(0) : BigDecimal.valueOf(monthCost));
             if (targetId == null) {
                 //新增
                 if (creator.getRole() == 2 && role != 0) {
@@ -354,7 +376,7 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
                     httpRespMsg.setError("不可新增负责人");
                 } else {
                     //电话号码列 检测重名
-                    if (userMapper.selectList(new QueryWrapper<User>().eq("phone", phone)).size() > 0) {
+                    if (!StringUtils.isEmpty(phone) && userMapper.selectList(new QueryWrapper<User>().eq("phone", phone)).size() > 0) {
                         httpRespMsg.setError("电话号码重复");
                     } else {
                         //只计算活跃的用户
@@ -375,6 +397,7 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
                                     .setCost(costValue)
                                     .setColor(ColorUtil.randomColor())
                                     .setSalaryType(salaryType)
+                                    .setCostApplyDate(costApplyDate)
                                     .setDepartmentId(departmentId == null ? 0 : departmentId)
                                     .setDepartmentCascade(departmentId == null ?
                                             convertDepartmentIdToCascade(0) :
@@ -393,15 +416,18 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
                 //修改
                 User oldUser = userMapper.selectById(targetId);
                 boolean salaryChange = false;
-                if (oldUser.getMonthCost().compareTo(monthCostValue) != 0 || oldUser.getCost().compareTo(costValue) != 0) {
+
+                if ((oldUser.getMonthCost() == null && monthCostValue.intValue() != 0) || oldUser.getMonthCost().compareTo(monthCostValue) != 0 || oldUser.getCost().compareTo(costValue) != 0) {
                     salaryChange = true;
                 }
+                String oldCostApplyDate = oldUser.getCostApplyDate();
                 userMapper.updateById(oldUser
                         .setName(name)
                         .setPhone(phone)
                         .setRole(role)
                         .setMonthCost(monthCostValue)
                         .setCost(costValue)
+                        .setCostApplyDate(costApplyDate)
                         .setSalaryType(salaryType)
                         .setDepartmentId(departmentId == null ? 0 : departmentId)
                         .setDepartmentCascade(departmentId == null ?
@@ -411,8 +437,50 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
                     UserSalary userSalary = UserSalary.copyFromUser(oldUser);
                     userSalaryMapper.insert(userSalary);
                 }
+                //薪资或者
+                DateTimeFormatter sdf = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+                String now = sdf.format(LocalDateTime.now());
+                boolean shouldChangeOldReport = false;
+                QueryWrapper<Report> reportQueryWrapper = new QueryWrapper<Report>().ge("create_date", costApplyDate).eq("creator_id", targetId);
+                //日期发生改变
+                if (costApplyDate != null && !costApplyDate.equals(oldCostApplyDate)) {
+                    int cnt = reportMapper.selectCount(reportQueryWrapper);
+                    if (cnt > 0) {
+                        shouldChangeOldReport = true;
+                    }
+                }  else if (salaryChange && costApplyDate != null) {
+                    //成本发生改变
+                    int cnt = reportMapper.selectCount(reportQueryWrapper);
+                    if (cnt > 0) {
+                        shouldChangeOldReport = true;
+                    }
+                }
+                if (shouldChangeOldReport) {
+                    //更新已填写的日报
+                    List<Report> reports = reportMapper.selectList(reportQueryWrapper);
+                    List<Report> collection = new ArrayList<>();
+                    reports.forEach(r->{
+                        Report item = new Report();
+                        item.setId(r.getId());
+                        BigDecimal newCost = costValue.multiply(new BigDecimal(r.getWorkingTime()));
+                        //成本发生变化的需要更新
+                        if (newCost.compareTo(r.getCost()) != 0) {
+                            item.setCost(newCost);
+                            collection.add(item);
+                        }
+                    });
+                    if (collection.size() > 0) {
+                        boolean n = reportService.updateBatchById(collection);
+                        System.out.println("更新"+(n?"成功":"失败"));
+                    } else {
+                        System.out.println("没有更新");
+                    }
+                } else {
+                    System.out.println("没有日报的成本需要更新");
+                }
             }
         } catch (NullPointerException e) {
+            e.printStackTrace();
             httpRespMsg.setError("数据有误 验证失败");
             return httpRespMsg;
         }
@@ -761,4 +829,133 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
         }
         return respMsg;
     }
+
+    @Override
+    public HttpRespMsg exportUsers(Integer containInvalid, HttpServletRequest request) {
+        HttpRespMsg httpRespMsg = new HttpRespMsg();
+        try {
+            String userId = request.getHeader("Token");
+            User user = userMapper.selectById(userId);
+
+            //准备导出
+            HSSFWorkbook workbook = new HSSFWorkbook();
+            HSSFSheet sheet = workbook.createSheet("全部员工列表");
+            //创建表头
+            HSSFRow headRow = sheet.createRow(0);
+            //设置列宽 setColumnWidth的第二个参数要乘以256 这个参数的单位是1/256个字符宽度
+            sheet.setColumnWidth(0, 5 * 256);
+            sheet.setColumnWidth(1, 10 * 256);
+            sheet.setColumnWidth(2, 20 * 256);
+            sheet.setColumnWidth(3, 20 * 256);
+            sheet.setColumnWidth(4, 10 * 256);
+
+            sheet.setColumnWidth(5, 10 * 256);
+            sheet.setColumnWidth(6, 10 * 256);
+            sheet.setColumnWidth(7, 10 * 256);
+            //设置为居中加粗
+            HSSFCellStyle headStyle = workbook.createCellStyle();
+            HSSFFont font = workbook.createFont();
+            font.setBold(true);
+            headStyle.setFont(font);
+            //表头
+            HSSFCell headCell;
+            headCell = headRow.createCell(0);
+            headCell.setCellValue("序号");
+            headCell.setCellStyle(headStyle);
+            headCell = headRow.createCell(1);
+            headCell.setCellValue("姓名");
+            headCell.setCellStyle(headStyle);
+            headCell = headRow.createCell(2);
+            headCell.setCellValue("手机号");
+            headCell.setCellStyle(headStyle);
+            headCell = headRow.createCell(3);
+            headCell.setCellValue("部门");
+            headCell.setCellStyle(headStyle);
+            headCell = headRow.createCell(4);
+            headCell.setCellValue("月薪");
+            headCell.setCellStyle(headStyle);
+            headCell = headRow.createCell(5);
+            headCell.setCellValue("时薪");
+            headCell.setCellStyle(headStyle);
+            headCell = headRow.createCell(6);
+            headCell.setCellValue("状态");
+            headCell.setCellStyle(headStyle);
+
+            //设置日期格式
+            HSSFCellStyle style = workbook.createCellStyle();
+            style.setDataFormat(HSSFDataFormat.getBuiltinFormat("yy/mm/dd hh:mm"));
+            //新增数据行 并且装填数据
+            int rowNum = 1;
+            QueryWrapper<User> queryWrapper = new QueryWrapper<>();
+            queryWrapper.eq("company_id", user.getCompanyId());
+            if (containInvalid == 0) {
+                queryWrapper.eq("is_active", 1);
+            }
+            List<User> data = userMapper.selectList(queryWrapper);
+            List<Department> deptList = departmentMapper.selectList(new QueryWrapper<Department>().eq("company_id", user.getCompanyId()));
+            for (User item : data) {
+                if (item.getDepartmentId() != 0) {
+                    Department department = deptList.stream().filter(d->d.getDepartmentId().equals(item.getDepartmentId())).findFirst().get();
+                    item.setDepartmentName(department.getDepartmentName());
+                }
+                HSSFRow row = sheet.createRow(rowNum);
+                row.createCell(0).setCellValue(rowNum);
+                row.createCell(1).setCellValue(item.getName());
+                row.createCell(2).setCellValue(item.getPhone());
+                row.createCell(3).setCellValue(item.getDepartmentName());
+                row.createCell(4).setCellValue(item.getMonthCost()==null? 0 : item.getMonthCost().intValue());
+                row.createCell(5).setCellValue(item.getCost() == null?0.0 : item.getCost().doubleValue());
+                row.createCell(6).setCellValue(item.getIsActive()==1?"正常":"已停用");
+
+                rowNum++;
+            }
+            //生成Excel文件
+            String fileUrlSuffix = "全部员工列表" + System.currentTimeMillis() + ".xls";
+            FileOutputStream fos = new FileOutputStream(path + fileUrlSuffix);
+            workbook.write(fos);
+            fos.flush();
+            fos.close();
+            //返回生成的文件地址/upload文件夹下
+            httpRespMsg.data = "/upload/" + fileUrlSuffix;
+        } catch (NullPointerException e) {
+            httpRespMsg.setError("验证失败或缺少数据");
+            return httpRespMsg;
+        } catch (IOException e) {
+            httpRespMsg.setError("文件生成错误");
+            return httpRespMsg;
+        }
+        return httpRespMsg;
+    }
+
+    @Override
+    public HttpRespMsg sendVcode(String mobile) {
+        //检查最近一条记录时间
+        HttpRespMsg msg = new HttpRespMsg();
+        List<UserVcode> list = userVcodeMapper.selectList(
+                new QueryWrapper<UserVcode>().eq("mobile", mobile).orderByDesc("id").last("limit 1"));
+        LocalDateTime now = LocalDateTime.now();
+        if (list.size() > 0) {
+            long lastTimeSec = list.get(0).getIndate().toEpochSecond(ZoneOffset.of("+8"));
+            if (now.toEpochSecond(ZoneOffset.of("+8")) - lastTimeSec < 60) {
+                msg.setError("请求过于频繁,请稍后再试");
+                return msg;
+            }
+        }
+        Random random = new Random();
+        int vcode = random.nextInt(10000);
+        if (vcode < 1000) {
+            vcode = 1000 + vcode;
+        }
+        UserVcode item = new UserVcode();
+        item.setMobile(mobile);
+        item.setVcode(""+vcode);
+        SendSmsResponse sendSmsResponse = SmsUtil.sendSms(mobile, "" + vcode);
+        if (!sendSmsResponse.getBody().getCode().equals("OK")) {
+            msg.setError(sendSmsResponse.getBody().getMessage());
+        } else {
+            userVcodeMapper.insert(item);
+        }
+//        userVcodeMapper.insert(item);
+        return msg;
+    }
 }

+ 20 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/UserVcodeServiceImpl.java

@@ -0,0 +1,20 @@
+package com.management.platform.service.impl;
+
+import com.management.platform.entity.UserVcode;
+import com.management.platform.mapper.UserVcodeMapper;
+import com.management.platform.service.UserVcodeService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ *  服务实现类
+ * </p>
+ *
+ * @author Seyason
+ * @since 2021-06-25
+ */
+@Service
+public class UserVcodeServiceImpl extends ServiceImpl<UserVcodeMapper, UserVcode> implements UserVcodeService {
+
+}

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

@@ -0,0 +1,20 @@
+package com.management.platform.service.impl;
+
+import com.management.platform.entity.WxCorpInfo;
+import com.management.platform.mapper.WxCorpInfoMapper;
+import com.management.platform.service.WxCorpInfoService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ *  服务实现类
+ * </p>
+ *
+ * @author Seyason
+ * @since 2021-07-14
+ */
+@Service
+public class WxCorpInfoServiceImpl extends ServiceImpl<WxCorpInfoMapper, WxCorpInfo> implements WxCorpInfoService {
+
+}

+ 6 - 3
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/task/TimingTask.java

@@ -30,9 +30,7 @@ import javax.annotation.Resource;
 import java.time.LocalDateTime;
 import java.time.format.DateTimeFormatter;
 import java.time.temporal.TemporalAccessor;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+import java.util.*;
 
 /**
  * Author: 吴涛涛
@@ -105,6 +103,11 @@ public class TimingTask {
     @Scheduled(fixedRate = 60 * 1000)
     private void process() {
         LocalDateTime now = LocalDateTime.now();
+        int day = now.getDayOfWeek().getValue();
+        //周末休息
+        if (day == 7||day==6) {
+            return;
+        }
         DateTimeFormatter dt = DateTimeFormatter.ofPattern("HH:mm");
         String str = dt.format(now);
         List<TimeType> typeList = timeTypeMapper.selectList(new QueryWrapper<TimeType>().isNotNull("alert_time")

+ 10 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/util/Constant.java

@@ -0,0 +1,10 @@
+package com.management.platform.util;
+
+public class Constant {
+    public static final int ROLE_EMPLOYEE = 0;
+    public static final int ROLE_MASTER = 1;
+    public static final int ROLE_MANAGER = 2;
+    public static final int ROLE_SENIOR = 3;
+    public static final int ROLE_HR = 4;
+    public static final int ROLE_PMP = 5;
+}

+ 13 - 4
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/util/ExcelUtil.java

@@ -1,10 +1,8 @@
 package com.management.platform.util;
 
 import org.apache.poi.hssf.usermodel.*;
-import org.apache.poi.ss.usermodel.BorderStyle;
-import org.apache.poi.ss.usermodel.CellStyle;
-import org.apache.poi.ss.usermodel.FillPatternType;
-import org.apache.poi.ss.usermodel.HorizontalAlignment;
+import org.apache.poi.ss.usermodel.*;
+import org.springframework.util.StringUtils;
 
 import javax.servlet.http.HttpServletResponse;
 import java.io.File;
@@ -152,4 +150,15 @@ public class ExcelUtil {
         return "/upload/"+fileName;
 //        return "";
     }
+
+    public static boolean isRowEmpty(Row row){
+        for (int i = row.getFirstCellNum(); i < row.getLastCellNum(); i++) {
+            Cell cell = row.getCell(i);
+            if (cell != null && !StringUtils.isEmpty(cell.getStringCellValue())){
+                System.out.println(i+":"+cell.getStringCellValue());
+                return false;
+            }
+        }
+        return true;
+    }
 }

+ 38 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/util/MD5Util.java

@@ -3,6 +3,7 @@ package com.management.platform.util;
 import org.springframework.util.DigestUtils;
 import sun.security.rsa.RSASignature;
 
+import java.security.MessageDigest;
 import java.text.ParseException;
 
 /**
@@ -13,6 +14,9 @@ import java.text.ParseException;
  */
 public class MD5Util {
 
+    private static final String hexDigits[] = { "0", "1", "2", "3", "4", "5",
+            "6", "7", "8", "9", "a", "b", "c", "d", "e", "f" };
+
     public static String getPassword(String password) {
         return DigestUtils.md5DigestAsHex(password.getBytes());
     }
@@ -93,4 +97,38 @@ public class MD5Util {
 //            e.printStackTrace();
 //        }
 //    }
+
+
+    private static String byteArrayToHexString(byte b[]) {
+        StringBuffer resultSb = new StringBuffer();
+        for (int i = 0; i < b.length; i++)
+            resultSb.append(byteToHexString(b[i]));
+
+        return resultSb.toString();
+    }
+
+    private static String byteToHexString(byte b) {
+        int n = b;
+        if (n < 0)
+            n += 256;
+        int d1 = n / 16;
+        int d2 = n % 16;
+        return hexDigits[d1] + hexDigits[d2];
+    }
+
+    public static String MD5Encode(String origin, String charsetname) {
+        String resultString = null;
+        try {
+            resultString = new String(origin);
+            MessageDigest md = MessageDigest.getInstance("MD5");
+            if (charsetname == null || "".equals(charsetname))
+                resultString = byteArrayToHexString(md.digest(resultString
+                        .getBytes()));
+            else
+                resultString = byteArrayToHexString(md.digest(resultString
+                        .getBytes(charsetname)));
+        } catch (Exception exception) {
+        }
+        return resultString;
+    }
 }

+ 73 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/util/Sha1Util.java

@@ -0,0 +1,73 @@
+package com.management.platform.util;
+
+
+import java.security.MessageDigest;
+import java.util.*;
+
+/*
+'============================================================================
+'api说明:
+'createSHA1Sign创建签名SHA1
+'getSha1()Sha1签名
+'============================================================================
+'*/
+public class Sha1Util {
+
+    public static void main(String[] args) {
+        String str = "jsapi_ticket=kgt8ON7yVITDhtdwci0qecaNzS34qhbQACy88uRm_S0XvT3hcWiBONbLzKnA5o5uPukt2sA3a8bBfETg4TyaQg&noncestr=10907813b97e249163587e6246612e21&timestamp=1516590573&url=http://www.dzjy.com/payHtml.html?num=1&code=001EjC0a2q6qoO0fn2Z92E6D0a2EjC0D&state=1";
+        String sign = getSha1(str);
+        System.out.println(sign);
+    }
+
+    public static String getNonceStr() {
+        Random random = new Random();
+        return MD5Util.MD5Encode(String.valueOf(random.nextInt(10000)), "UTF-8");
+    }
+    public static String getTimeStamp() {
+        return String.valueOf(System.currentTimeMillis() / 1000);
+    }
+
+    //创建签名SHA1
+    public static String createSHA1Sign(SortedMap<String, String> signParams) throws Exception {
+        StringBuffer sb = new StringBuffer();
+        Set es = signParams.entrySet();
+        Iterator it = es.iterator();
+        while (it.hasNext()) {
+            Map.Entry entry = (Map.Entry) it.next();
+            String k = (String) entry.getKey();
+            String v = (String) entry.getValue();
+            sb.append(k + "=" + v + "&");
+            //要采用URLENCODER的原始值!
+        }
+        String params = sb.substring(0, sb.lastIndexOf("&"));
+        System.out.println("sha1之前:" + params);
+        System.out.println("SHA1签名为:"+getSha1(params));
+        return getSha1(params);
+    }
+    //Sha1签名
+    public static String getSha1(String str) {
+        if (str == null || str.length() == 0) {
+            return null;
+        }
+        char hexDigits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+                'a', 'b', 'c', 'd', 'e', 'f' };
+
+        try {
+            MessageDigest mdTemp = MessageDigest.getInstance("SHA1");
+            mdTemp.update(str.getBytes("UTF-8"));
+
+            byte[] md = mdTemp.digest();
+            int j = md.length;
+            char buf[] = new char[j * 2];
+            int k = 0;
+            for (int i = 0; i < j; i++) {
+                byte byte0 = md[i];
+                buf[k++] = hexDigits[byte0 >>> 4 & 0xf];
+                buf[k++] = hexDigits[byte0 & 0xf];
+            }
+            return new String(buf);
+        } catch (Exception e) {
+            return null;
+        }
+    }
+}

+ 53 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/util/SmsUtil.java

@@ -0,0 +1,53 @@
+package com.management.platform.util;
+
+import com.aliyun.tea.*;
+import com.aliyun.dysmsapi20170525.*;
+import com.aliyun.dysmsapi20170525.models.*;
+import com.aliyun.teaopenapi.*;
+import com.aliyun.teaopenapi.models.*;
+
+public class SmsUtil {
+    private static String accessKeyId = "LTAI5tQ2uwLE9T6Zrq1Jh3mr";
+    private static String accessKeySecret = "eGUxd8ipnLLCF6XqurKrGiMoyqC69u";
+    /**
+     * 使用AK&SK初始化账号Client
+     * @param accessKeyId
+     * @param accessKeySecret
+     * @return Client
+     * @throws Exception
+     */
+    public static com.aliyun.dysmsapi20170525.Client createClient(String accessKeyId, String accessKeySecret) throws Exception {
+        Config config = new Config()
+                // 您的AccessKey ID
+                .setAccessKeyId(accessKeyId)
+                // 您的AccessKey Secret
+                .setAccessKeySecret(accessKeySecret);
+        // 访问的域名
+        config.endpoint = "dysmsapi.aliyuncs.com";
+        return new com.aliyun.dysmsapi20170525.Client(config);
+    }
+
+    public static SendSmsResponse sendSms(String mobile, String code) {
+        com.aliyun.dysmsapi20170525.Client client = null;
+        try {
+            client = SmsUtil.createClient(accessKeyId, accessKeySecret);
+            System.out.println("发送短信");
+            SendSmsRequest sendSmsRequest = new SendSmsRequest()
+                    .setPhoneNumbers(mobile)
+                    .setSignName("火石闪信")
+                    .setTemplateCode("SMS_218575084")
+                    .setTemplateParam("{\"code\":\""+code+"\"}");
+            // 复制代码运行请自行打印 API 的返回值
+            SendSmsResponse sendSmsResponse = client.sendSms(sendSmsRequest);
+            System.out.println(sendSmsResponse.getBody().getCode()+":"+sendSmsResponse.getBody().message);
+            return sendSmsResponse;
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    public static void main(String[] args_) throws Exception {
+        SmsUtil.sendSms("15895914665", "1234");
+    }
+}

+ 59 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/qq/weixin/mp/aes/AesException.java

@@ -0,0 +1,59 @@
+package com.qq.weixin.mp.aes;
+
+@SuppressWarnings("serial")
+public class AesException extends Exception {
+
+	public final static int OK = 0;
+	public final static int ValidateSignatureError = -40001;
+	public final static int ParseXmlError = -40002;
+	public final static int ComputeSignatureError = -40003;
+	public final static int IllegalAesKey = -40004;
+	public final static int ValidateCorpidError = -40005;
+	public final static int EncryptAESError = -40006;
+	public final static int DecryptAESError = -40007;
+	public final static int IllegalBuffer = -40008;
+	//public final static int EncodeBase64Error = -40009;
+	//public final static int DecodeBase64Error = -40010;
+	//public final static int GenReturnXmlError = -40011;
+
+	private int code;
+
+	private static String getMessage(int code) {
+		switch (code) {
+			case ValidateSignatureError:
+				return "签名验证错误";
+			case ParseXmlError:
+				return "xml解析失败";
+			case ComputeSignatureError:
+				return "sha加密生成签名失败";
+			case IllegalAesKey:
+				return "SymmetricKey非法";
+			case ValidateCorpidError:
+				return "corpid校验失败";
+			case EncryptAESError:
+				return "aes加密失败";
+			case DecryptAESError:
+				return "aes解密失败";
+			case IllegalBuffer:
+				return "解密后得到的buffer非法";
+//		case EncodeBase64Error:
+//			return "base64加密错误";
+//		case DecodeBase64Error:
+//			return "base64解密错误";
+//		case GenReturnXmlError:
+//			return "xml生成失败";
+			default:
+				return null; // cannot be
+		}
+	}
+
+	public int getCode() {
+		return code;
+	}
+
+	AesException(int code) {
+		super(getMessage(code));
+		this.code = code;
+	}
+
+}

+ 26 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/qq/weixin/mp/aes/ByteGroup.java

@@ -0,0 +1,26 @@
+package com.qq.weixin.mp.aes;
+
+import java.util.ArrayList;
+
+class ByteGroup {
+	ArrayList<Byte> byteContainer = new ArrayList<Byte>();
+
+	public byte[] toBytes() {
+		byte[] bytes = new byte[byteContainer.size()];
+		for (int i = 0; i < byteContainer.size(); i++) {
+			bytes[i] = byteContainer.get(i);
+		}
+		return bytes;
+	}
+
+	public ByteGroup addBytes(byte[] bytes) {
+		for (byte b : bytes) {
+			byteContainer.add(b);
+		}
+		return this;
+	}
+
+	public int size() {
+		return byteContainer.size();
+	}
+}

+ 67 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/qq/weixin/mp/aes/PKCS7Encoder.java

@@ -0,0 +1,67 @@
+/**
+ * 对企业微信发送给企业后台的消息加解密示例代码.
+ * 
+ * @copyright Copyright (c) 1998-2014 Tencent Inc.
+ */
+
+// ------------------------------------------------------------------------
+
+package com.qq.weixin.mp.aes;
+
+import java.nio.charset.Charset;
+import java.util.Arrays;
+
+/**
+ * 提供基于PKCS7算法的加解密接口.
+ */
+class PKCS7Encoder {
+	static Charset CHARSET = Charset.forName("utf-8");
+	static int BLOCK_SIZE = 32;
+
+	/**
+	 * 获得对明文进行补位填充的字节.
+	 * 
+	 * @param count 需要进行填充补位操作的明文字节个数
+	 * @return 补齐用的字节数组
+	 */
+	static byte[] encode(int count) {
+		// 计算需要填充的位数
+		int amountToPad = BLOCK_SIZE - (count % BLOCK_SIZE);
+		if (amountToPad == 0) {
+			amountToPad = BLOCK_SIZE;
+		}
+		// 获得补位所用的字符
+		char padChr = chr(amountToPad);
+		String tmp = new String();
+		for (int index = 0; index < amountToPad; index++) {
+			tmp += padChr;
+		}
+		return tmp.getBytes(CHARSET);
+	}
+
+	/**
+	 * 删除解密后明文的补位字符
+	 * 
+	 * @param decrypted 解密后的明文
+	 * @return 删除补位字符后的明文
+	 */
+	static byte[] decode(byte[] decrypted) {
+		int pad = (int) decrypted[decrypted.length - 1];
+		if (pad < 1 || pad > 32) {
+			pad = 0;
+		}
+		return Arrays.copyOfRange(decrypted, 0, decrypted.length - pad);
+	}
+
+	/**
+	 * 将数字转化成ASCII码对应的字符,用于对明文进行补码
+	 * 
+	 * @param a 需要转化的数字
+	 * @return 转化得到的字符
+	 */
+	static char chr(int a) {
+		byte target = (byte) (a & 0xFF);
+		return (char) target;
+	}
+
+}

+ 61 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/qq/weixin/mp/aes/SHA1.java

@@ -0,0 +1,61 @@
+/**
+ * 对企业微信发送给企业后台的消息加解密示例代码.
+ * 
+ * @copyright Copyright (c) 1998-2014 Tencent Inc.
+ */
+
+// ------------------------------------------------------------------------
+
+package com.qq.weixin.mp.aes;
+
+import java.security.MessageDigest;
+import java.util.Arrays;
+
+/**
+ * SHA1 class
+ *
+ * 计算消息签名接口.
+ */
+class SHA1 {
+
+	/**
+	 * 用SHA1算法生成安全签名
+	 * @param token 票据
+	 * @param timestamp 时间戳
+	 * @param nonce 随机字符串
+	 * @param encrypt 密文
+	 * @return 安全签名
+	 * @throws AesException 
+	 */
+	public static String getSHA1(String token, String timestamp, String nonce, String encrypt) throws AesException
+			  {
+		try {
+			String[] array = new String[] { token, timestamp, nonce, encrypt };
+			StringBuffer sb = new StringBuffer();
+			// 字符串排序
+			Arrays.sort(array);
+			for (int i = 0; i < 4; i++) {
+				sb.append(array[i]);
+			}
+			String str = sb.toString();
+			// SHA1签名生成
+			MessageDigest md = MessageDigest.getInstance("SHA-1");
+			md.update(str.getBytes());
+			byte[] digest = md.digest();
+
+			StringBuffer hexstr = new StringBuffer();
+			String shaHex = "";
+			for (int i = 0; i < digest.length; i++) {
+				shaHex = Integer.toHexString(digest[i] & 0xFF);
+				if (shaHex.length() < 2) {
+					hexstr.append(0);
+				}
+				hexstr.append(shaHex);
+			}
+			return hexstr.toString();
+		} catch (Exception e) {
+			e.printStackTrace();
+			throw new AesException(AesException.ComputeSignatureError);
+		}
+	}
+}

+ 289 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/qq/weixin/mp/aes/WXBizMsgCrypt.java

@@ -0,0 +1,289 @@
+/**
+ * 对企业微信发送给企业后台的消息加解密示例代码.
+ * 
+ * @copyright Copyright (c) 1998-2014 Tencent Inc.
+ */
+
+// ------------------------------------------------------------------------
+
+/**
+ * 针对org.apache.commons.codec.binary.Base64,
+ * 需要导入架包commons-codec-1.9(或commons-codec-1.8等其他版本)
+ * 官方下载地址:http://commons.apache.org/proper/commons-codec/download_codec.cgi
+ */
+package com.qq.weixin.mp.aes;
+
+import java.nio.charset.Charset;
+import java.util.Arrays;
+import java.util.Random;
+
+import javax.crypto.Cipher;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+
+import org.apache.commons.codec.binary.Base64;
+
+/**
+ * 提供接收和推送给企业微信消息的加解密接口(UTF8编码的字符串).
+ * <ol>
+ * 	<li>第三方回复加密消息给企业微信</li>
+ * 	<li>第三方收到企业微信发送的消息,验证消息的安全性,并对消息进行解密。</li>
+ * </ol>
+ * 说明:异常java.security.InvalidKeyException:illegal Key Size的解决方案
+ * <ol>
+ * 	<li>在官方网站下载JCE无限制权限策略文件(JDK7的下载地址:
+ *      http://www.oracle.com/technetwork/java/javase/downloads/jce-7-download-432124.html</li>
+ * 	<li>下载后解压,可以看到local_policy.jar和US_export_policy.jar以及readme.txt</li>
+ * 	<li>如果安装了JRE,将两个jar文件放到%JRE_HOME%\lib\security目录下覆盖原来的文件</li>
+ * 	<li>如果安装了JDK,将两个jar文件放到%JDK_HOME%\jre\lib\security目录下覆盖原来文件</li>
+ * </ol>
+ */
+public class WXBizMsgCrypt {
+	static Charset CHARSET = Charset.forName("utf-8");
+	Base64 base64 = new Base64();
+	byte[] aesKey;
+	String token;
+	String receiveid;
+
+	/**
+	 * 构造函数
+	 * @param token 企业微信后台,开发者设置的token
+	 * @param encodingAesKey 企业微信后台,开发者设置的EncodingAESKey
+	 * @param receiveid, 不同场景含义不同,详见文档
+	 * 
+	 * @throws AesException 执行失败,请查看该异常的错误码和具体的错误信息
+	 */
+	public WXBizMsgCrypt(String token, String encodingAesKey, String receiveid) throws AesException {
+		if (encodingAesKey.length() != 43) {
+			throw new AesException(AesException.IllegalAesKey);
+		}
+
+		this.token = token;
+		this.receiveid = receiveid;
+		aesKey = Base64.decodeBase64(encodingAesKey + "=");
+	}
+
+	// 生成4个字节的网络字节序
+	byte[] getNetworkBytesOrder(int sourceNumber) {
+		byte[] orderBytes = new byte[4];
+		orderBytes[3] = (byte) (sourceNumber & 0xFF);
+		orderBytes[2] = (byte) (sourceNumber >> 8 & 0xFF);
+		orderBytes[1] = (byte) (sourceNumber >> 16 & 0xFF);
+		orderBytes[0] = (byte) (sourceNumber >> 24 & 0xFF);
+		return orderBytes;
+	}
+
+	// 还原4个字节的网络字节序
+	int recoverNetworkBytesOrder(byte[] orderBytes) {
+		int sourceNumber = 0;
+		for (int i = 0; i < 4; i++) {
+			sourceNumber <<= 8;
+			sourceNumber |= orderBytes[i] & 0xff;
+		}
+		return sourceNumber;
+	}
+
+	// 随机生成16位字符串
+	String getRandomStr() {
+		String base = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
+		Random random = new Random();
+		StringBuffer sb = new StringBuffer();
+		for (int i = 0; i < 16; i++) {
+			int number = random.nextInt(base.length());
+			sb.append(base.charAt(number));
+		}
+		return sb.toString();
+	}
+
+	/**
+	 * 对明文进行加密.
+	 * 
+	 * @param text 需要加密的明文
+	 * @return 加密后base64编码的字符串
+	 * @throws AesException aes加密失败
+	 */
+	String encrypt(String randomStr, String text) throws AesException {
+		ByteGroup byteCollector = new ByteGroup();
+		byte[] randomStrBytes = randomStr.getBytes(CHARSET);
+		byte[] textBytes = text.getBytes(CHARSET);
+		byte[] networkBytesOrder = getNetworkBytesOrder(textBytes.length);
+		byte[] receiveidBytes = receiveid.getBytes(CHARSET);
+
+		// randomStr + networkBytesOrder + text + receiveid
+		byteCollector.addBytes(randomStrBytes);
+		byteCollector.addBytes(networkBytesOrder);
+		byteCollector.addBytes(textBytes);
+		byteCollector.addBytes(receiveidBytes);
+
+		// ... + pad: 使用自定义的填充方式对明文进行补位填充
+		byte[] padBytes = PKCS7Encoder.encode(byteCollector.size());
+		byteCollector.addBytes(padBytes);
+
+		// 获得最终的字节流, 未加密
+		byte[] unencrypted = byteCollector.toBytes();
+
+		try {
+			// 设置加密模式为AES的CBC模式
+			Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
+			SecretKeySpec keySpec = new SecretKeySpec(aesKey, "AES");
+			IvParameterSpec iv = new IvParameterSpec(aesKey, 0, 16);
+			cipher.init(Cipher.ENCRYPT_MODE, keySpec, iv);
+
+			// 加密
+			byte[] encrypted = cipher.doFinal(unencrypted);
+
+			// 使用BASE64对加密后的字符串进行编码
+			String base64Encrypted = base64.encodeToString(encrypted);
+
+			return base64Encrypted;
+		} catch (Exception e) {
+			e.printStackTrace();
+			throw new AesException(AesException.EncryptAESError);
+		}
+	}
+
+	/**
+	 * 对密文进行解密.
+	 * 
+	 * @param text 需要解密的密文
+	 * @return 解密得到的明文
+	 * @throws AesException aes解密失败
+	 */
+	String decrypt(String text) throws AesException {
+		byte[] original;
+		try {
+			// 设置解密模式为AES的CBC模式
+			Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
+			SecretKeySpec key_spec = new SecretKeySpec(aesKey, "AES");
+			IvParameterSpec iv = new IvParameterSpec(Arrays.copyOfRange(aesKey, 0, 16));
+			cipher.init(Cipher.DECRYPT_MODE, key_spec, iv);
+
+			// 使用BASE64对密文进行解码
+			byte[] encrypted = Base64.decodeBase64(text);
+
+			// 解密
+			original = cipher.doFinal(encrypted);
+		} catch (Exception e) {
+			e.printStackTrace();
+			throw new AesException(AesException.DecryptAESError);
+		}
+
+		String xmlContent, from_receiveid;
+		try {
+			// 去除补位字符
+			byte[] bytes = PKCS7Encoder.decode(original);
+
+			// 分离16位随机字符串,网络字节序和receiveid
+			byte[] networkOrder = Arrays.copyOfRange(bytes, 16, 20);
+
+			int xmlLength = recoverNetworkBytesOrder(networkOrder);
+
+			xmlContent = new String(Arrays.copyOfRange(bytes, 20, 20 + xmlLength), CHARSET);
+			from_receiveid = new String(Arrays.copyOfRange(bytes, 20 + xmlLength, bytes.length),
+					CHARSET);
+		} catch (Exception e) {
+			e.printStackTrace();
+			throw new AesException(AesException.IllegalBuffer);
+		}
+
+		// receiveid不相同的情况
+		if (!from_receiveid.equals(receiveid)) {
+			throw new AesException(AesException.ValidateCorpidError);
+		}
+		return xmlContent;
+
+	}
+
+	/**
+	 * 将企业微信回复用户的消息加密打包.
+	 * <ol>
+	 * 	<li>对要发送的消息进行AES-CBC加密</li>
+	 * 	<li>生成安全签名</li>
+	 * 	<li>将消息密文和安全签名打包成xml格式</li>
+	 * </ol>
+	 * 
+	 * @param replyMsg 企业微信待回复用户的消息,xml格式的字符串
+	 * @param timeStamp 时间戳,可以自己生成,也可以用URL参数的timestamp
+	 * @param nonce 随机串,可以自己生成,也可以用URL参数的nonce
+	 * 
+	 * @return 加密后的可以直接回复用户的密文,包括msg_signature, timestamp, nonce, encrypt的xml格式的字符串
+	 * @throws AesException 执行失败,请查看该异常的错误码和具体的错误信息
+	 */
+	public String EncryptMsg(String replyMsg, String timeStamp, String nonce) throws AesException {
+		// 加密
+		String encrypt = encrypt(getRandomStr(), replyMsg);
+
+		// 生成安全签名
+		if (timeStamp == "") {
+			timeStamp = Long.toString(System.currentTimeMillis());
+		}
+
+		String signature = SHA1.getSHA1(token, timeStamp, nonce, encrypt);
+
+		// System.out.println("发送给平台的签名是: " + signature[1].toString());
+		// 生成发送的xml
+		String result = XMLParse.generate(encrypt, signature, timeStamp, nonce);
+		return result;
+	}
+
+	/**
+	 * 检验消息的真实性,并且获取解密后的明文.
+	 * <ol>
+	 * 	<li>利用收到的密文生成安全签名,进行签名验证</li>
+	 * 	<li>若验证通过,则提取xml中的加密消息</li>
+	 * 	<li>对消息进行解密</li>
+	 * </ol>
+	 * 
+	 * @param msgSignature 签名串,对应URL参数的msg_signature
+	 * @param timeStamp 时间戳,对应URL参数的timestamp
+	 * @param nonce 随机串,对应URL参数的nonce
+	 * @param postData 密文,对应POST请求的数据
+	 * 
+	 * @return 解密后的原文
+	 * @throws AesException 执行失败,请查看该异常的错误码和具体的错误信息
+	 */
+	public String DecryptMsg(String msgSignature, String timeStamp, String nonce, String postData)
+			throws AesException {
+
+		// 密钥,公众账号的app secret
+		// 提取密文
+		Object[] encrypt = XMLParse.extract(postData);
+
+		// 验证安全签名
+		String signature = SHA1.getSHA1(token, timeStamp, nonce, encrypt[1].toString());
+
+		// 和URL中的签名比较是否相等
+		 System.out.println("第三方收到URL中的签名:" + msgSignature);
+		 System.out.println("第三方校验签名:" + signature);
+		if (!signature.equals(msgSignature)) {
+			throw new AesException(AesException.ValidateSignatureError);
+		}
+
+		// 解密
+		String result = decrypt(encrypt[1].toString());
+		return result;
+	}
+
+	/**
+	 * 验证URL
+	 * @param msgSignature 签名串,对应URL参数的msg_signature
+	 * @param timeStamp 时间戳,对应URL参数的timestamp
+	 * @param nonce 随机串,对应URL参数的nonce
+	 * @param echoStr 随机串,对应URL参数的echostr
+	 * 
+	 * @return 解密之后的echostr
+	 * @throws AesException 执行失败,请查看该异常的错误码和具体的错误信息
+	 */
+	public String VerifyURL(String msgSignature, String timeStamp, String nonce, String echoStr)
+			throws AesException {
+		String signature = SHA1.getSHA1(token, timeStamp, nonce, echoStr);
+
+		if (!signature.equals(msgSignature)) {
+			throw new AesException(AesException.ValidateSignatureError);
+		}
+
+		String result = decrypt(echoStr);
+		return result;
+	}
+
+}

+ 106 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/qq/weixin/mp/aes/XMLParse.java

@@ -0,0 +1,106 @@
+/**
+ * 对企业微信发送给企业后台的消息加解密示例代码.
+ * 
+ * @copyright Copyright (c) 1998-2014 Tencent Inc.
+ */
+
+// ------------------------------------------------------------------------
+
+package com.qq.weixin.mp.aes;
+
+import java.io.StringReader;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+import org.xml.sax.InputSource;
+
+/**
+ * XMLParse class
+ *
+ * 提供提取消息格式中的密文及生成回复消息格式的接口.
+ */
+class XMLParse {
+
+	/**
+	 * 提取出xml数据包中的加密消息
+	 * @param xmltext 待提取的xml字符串
+	 * @return 提取出的加密消息字符串
+	 * @throws AesException 
+	 */
+	public static Object[] extract(String xmltext) throws AesException     {
+		Object[] result = new Object[3];
+		try {
+			DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+			
+			String FEATURE = null;
+			// This is the PRIMARY defense. If DTDs (doctypes) are disallowed, almost all XML entity attacks are prevented
+			// Xerces 2 only - http://xerces.apache.org/xerces2-j/features.html#disallow-doctype-decl
+			FEATURE = "http://apache.org/xml/features/disallow-doctype-decl";
+			dbf.setFeature(FEATURE, true);
+			
+			// If you can't completely disable DTDs, then at least do the following:
+			// Xerces 1 - http://xerces.apache.org/xerces-j/features.html#external-general-entities
+			// Xerces 2 - http://xerces.apache.org/xerces2-j/features.html#external-general-entities
+			// JDK7+ - http://xml.org/sax/features/external-general-entities 
+			FEATURE = "http://xml.org/sax/features/external-general-entities";
+			dbf.setFeature(FEATURE, false);
+			
+			// Xerces 1 - http://xerces.apache.org/xerces-j/features.html#external-parameter-entities
+			// Xerces 2 - http://xerces.apache.org/xerces2-j/features.html#external-parameter-entities
+			// JDK7+ - http://xml.org/sax/features/external-parameter-entities 
+			FEATURE = "http://xml.org/sax/features/external-parameter-entities";
+			dbf.setFeature(FEATURE, false);
+			
+			// Disable external DTDs as well
+			FEATURE = "http://apache.org/xml/features/nonvalidating/load-external-dtd";
+			dbf.setFeature(FEATURE, false);
+			
+			// and these as well, per Timothy Morgan's 2014 paper: "XML Schema, DTD, and Entity Attacks"
+			dbf.setXIncludeAware(false);
+			dbf.setExpandEntityReferences(false);
+			
+			// And, per Timothy Morgan: "If for some reason support for inline DOCTYPEs are a requirement, then 
+			// ensure the entity settings are disabled (as shown above) and beware that SSRF attacks
+			// (http://cwe.mitre.org/data/definitions/918.html) and denial 
+			// of service attacks (such as billion laughs or decompression bombs via "jar:") are a risk."
+			
+			// remaining parser logic
+			DocumentBuilder db = dbf.newDocumentBuilder();
+			StringReader sr = new StringReader(xmltext);
+			InputSource is = new InputSource(sr);
+			Document document = db.parse(is);
+
+			Element root = document.getDocumentElement();
+			NodeList nodelist1 = root.getElementsByTagName("Encrypt");
+			NodeList nodelist2 = root.getElementsByTagName("ToUserName");
+			result[0] = 0;
+			result[1] = nodelist1.item(0).getTextContent();
+			result[2] = nodelist2.item(0).getTextContent();
+			return result;
+		} catch (Exception e) {
+			e.printStackTrace();
+			throw new AesException(AesException.ParseXmlError);
+		}
+	}
+
+	/**
+	 * 生成xml消息
+	 * @param encrypt 加密后的消息密文
+	 * @param signature 安全签名
+	 * @param timestamp 时间戳
+	 * @param nonce 随机字符串
+	 * @return 生成的xml字符串
+	 */
+	public static String generate(String encrypt, String signature, String timestamp, String nonce) {
+
+		String format = "<xml>\n" + "<Encrypt><![CDATA[%1$s]]></Encrypt>\n"
+				+ "<MsgSignature><![CDATA[%2$s]]></MsgSignature>\n"
+				+ "<TimeStamp>%3$s</TimeStamp>\n" + "<Nonce><![CDATA[%4$s]]></Nonce>\n" + "</xml>";
+		return String.format(format, encrypt, signature, timestamp, nonce);
+
+	}
+}

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

@@ -106,4 +106,24 @@ management:
     redis:
       enabled: false
 
+referer:
+  refererDomain:
+    - localhost
+    - ttkuaiban.com
+    - www.ttkuaiban.com
+    - mobworktime.ttkuaiban.com
+    - worktime.ttkuaiban.com
+excludeUrls: /wxcorp/*,/dingding/*,/error
+
+#企业微信相关参数
+suitId: ww4e237fd6abb635af
+suitSecret: 1ApL6LIB4Z0v7wBrKTUNmJrerRWV3gEQWBlYOm8Kijw
+#平台作为服务商的参数
+corpId: wwf11426cf618e1703
+token: Mhi7ehNX61UN4MB7PHnC
+encodingAesKey: PHVMkME1XMrImmGJZ4OZJxSysI7hFEhtDDUQrlHAfIS
+
+
+
+
 

BIN
fhKeeper/formulahousekeeper/management-platform/src/main/resources/lib/taobao-sdk-java-auto_1479188381469-20210623.jar


+ 21 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/CompanyDingdingMapper.xml

@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.management.platform.mapper.CompanyDingdingMapper">
+
+    <!-- 通用查询映射结果 -->
+    <resultMap id="BaseResultMap" type="com.management.platform.entity.CompanyDingding">
+        <id column="corpid" property="corpid" />
+        <result column="corp_name" property="corpName" />
+        <result column="auth_user_id" property="authUserId" />
+        <result column="indate" property="indate" />
+        <result column="company_id" property="companyId" />
+        <result column="access_token" property="accessToken" />
+        <result column="expire_time" property="expireTime" />
+    </resultMap>
+
+    <!-- 通用查询结果列 -->
+    <sql id="Base_Column_List">
+        corpid, corp_name, auth_user_id, indate, company_id, access_token, expire_time
+    </sql>
+
+</mapper>

+ 20 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/DepartmentDingdingMapper.xml

@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.management.platform.mapper.DepartmentDingdingMapper">
+
+    <!-- 通用查询映射结果 -->
+    <resultMap id="BaseResultMap" type="com.management.platform.entity.DepartmentDingding">
+        <id column="id" property="id" />
+        <result column="dd_deptid" property="ddDeptid" />
+        <result column="dd_parentid" property="ddParentid" />
+        <result column="corpid" property="corpid" />
+        <result column="name" property="name" />
+        <result column="sys_deptid" property="sysDeptid" />
+    </resultMap>
+
+    <!-- 通用查询结果列 -->
+    <sql id="Base_Column_List">
+        id, dd_deptid, dd_parentid, corpid, name, sys_deptid
+    </sql>
+
+</mapper>

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

@@ -33,16 +33,27 @@
 
     <!--根据人员获取成本-->
     <select id="getCostByUser" resultType="java.util.Map">
-        SELECT a.name AS user, c.project_name AS project, SUM(b.working_time) AS time, SUM(b.cost) AS
+        SELECT a.id as id, a.name AS user, c.project_name AS project, SUM(b.working_time) AS time, SUM(b.cost) AS
         money
         FROM user AS a
         LEFT JOIN report AS b ON a.id = b.creator_id
         LEFT JOIN project AS c ON b.project_id = c.id
         WHERE b.state = 1
-        AND a.department_id IN
-        <foreach collection="departmentIds" item="departmentId" index="index" open="(" close=")" separator=",">
-            #{departmentId}
-        </foreach>
+        <if test="departmentIds != null">
+            AND a.department_id IN
+            <foreach collection="departmentIds" item="departmentId" index="index" open="(" close=")" separator=",">
+                #{departmentId}
+            </foreach>
+        </if>
+        <if test="userIds != null">
+            AND a.id IN
+            <foreach collection="userIds" item="userId" index="index" open="(" close=")" separator=",">
+                #{userId}
+            </foreach>
+        </if>
+        <if test="companyId != null">
+            AND a.company_id = #{companyId}
+        </if>
         <if test="startDate != null and endDate != null">
             AND b.create_date between #{startDate} and #{endDate}
         </if>

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

@@ -14,11 +14,12 @@
         <result column="tax_value" property="taxValue" />
         <result column="amount" property="amount" />
         <result column="remark" property="remark" />
+        <result column="expense_type" property="expenseType" />
     </resultMap>
 
     <!-- 通用查询结果列 -->
     <sql id="Base_Column_List">
-        id, expense_id, project_id, happen_date, invoice_type, invoice_no, tax_percent, tax_value, amount, remark
+        id, expense_id, project_id, happen_date, invoice_type, invoice_no, tax_percent, tax_value, amount, remark, expense_type
     </sql>
 
 </mapper>

+ 17 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/ExpenseTypeMapper.xml

@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.management.platform.mapper.ExpenseTypeMapper">
+
+    <!-- 通用查询映射结果 -->
+    <resultMap id="BaseResultMap" type="com.management.platform.entity.ExpenseType">
+        <id column="id" property="id" />
+        <result column="main_type" property="mainType" />
+        <result column="type_name" property="typeName" />
+    </resultMap>
+
+    <!-- 通用查询结果列 -->
+    <sql id="Base_Column_List">
+        id, main_type, type_name
+    </sql>
+
+</mapper>

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

@@ -25,14 +25,17 @@
         <result column="base_risk1" property="baseRisk1" />
         <result column="base_risk2" property="baseRisk2" />
         <result column="base_fee" property="baseFee" />
+        <result column="fee_normal" property="feeNormal" />
+        <result column="fee_travel" property="feeTravel" />
+        <result column="fee_outsourcing" property="feeOutsourcing" />
+        <result column="fee_man" property="feeMan" />
     </resultMap>
 
     <!-- 通用查询结果列 -->
     <sql id="Base_Column_List">
-        id, project_name, company_id, project_code, incharger_id, plan_start_date, plan_end_date, progress, level, status, finish_date, creator_id, creator_name, create_date, contract_amount, budget, base_man, base_outsourcing, base_risk1, base_risk2, base_fee
+        id, project_name, company_id, project_code, incharger_id, plan_start_date, plan_end_date, progress, level, status, finish_date, creator_id, creator_name, create_date, contract_amount, budget, base_man, base_outsourcing, base_risk1, base_risk2, base_fee, fee_normal, fee_travel, fee_outsourcing, fee_man
     </sql>
 
-
     <!--获取查询者所在公司每个项目的工时成本-->
     <select id="getParticipatedProject" resultType="java.util.Map">
         SELECT id, project_name AS projectName
@@ -95,4 +98,30 @@
         GROUP BY b.id
         ORDER BY b.id ASC
     </select>
+    <!--分页获取项目成本 -->
+    <select id="getAllProjectCost" resultMap="BaseResultMap">
+        SELECT project_code, project_name,
+        (SELECT IFNULL(SUM(cost),0) FROM report WHERE state = 1 AND project_id = project.id) AS fee_man,
+        (SELECT IFNULL(SUM(amount),0) FROM expense_item , expense_sheet WHERE project_id = project.id AND  expense_sheet.id = expense_item.`expense_id` AND expense_sheet.type = 0) AS fee_normal,
+        (SELECT IFNULL(SUM(amount),0) FROM expense_item , expense_sheet WHERE project_id = project.id AND  expense_sheet.id = expense_item.`expense_id` AND expense_sheet.type = 1) AS fee_travel,
+        (SELECT IFNULL(SUM(amount),0) FROM expense_item , expense_sheet WHERE project_id = project.id AND  expense_sheet.id = expense_item.`expense_id` AND expense_sheet.type = 2) AS fee_outsourcing
+        FROM project WHERE project.`company_id` = #{companyId}
+        and (project.status &lt;&gt; 3 or project.status is null)
+        <if test="pageStart != null and pageSize != null">
+            LIMIT #{pageStart},#{pageSize}
+        </if>
+    </select>
+    <!--分页获取项目收支平衡 -->
+    <select id="getProjectInAndOut" resultMap="BaseResultMap">
+        SELECT project_code, project_name,contract_amount,
+        (SELECT IFNULL(SUM(cost),0) FROM report WHERE state = 1 AND project_id = project.id) AS fee_man,
+        (SELECT IFNULL(SUM(amount),0) FROM expense_item , expense_sheet WHERE project_id = project.id AND  expense_sheet.id = expense_item.`expense_id` AND expense_sheet.type = 0) AS fee_normal,
+        (SELECT IFNULL(SUM(amount),0) FROM expense_item , expense_sheet WHERE project_id = project.id AND  expense_sheet.id = expense_item.`expense_id` AND expense_sheet.type = 1) AS fee_travel,
+        (SELECT IFNULL(SUM(amount),0) FROM expense_item , expense_sheet WHERE project_id = project.id AND  expense_sheet.id = expense_item.`expense_id` AND expense_sheet.type = 2) AS fee_outsourcing
+        FROM project WHERE project.`company_id` = #{companyId}
+        and (project.status &lt;&gt; 3 or project.status is null)
+        <if test="pageStart != null and pageSize != null">
+            LIMIT #{pageStart},#{pageSize}
+        </if>
+    </select>
 </mapper>

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

@@ -94,7 +94,9 @@
     <!-- 批量获取员工某天的报告 -->
     <select id="getUserReportByDate" resultType="java.util.Map">
         SELECT a.id, b.project_name AS project, a.working_time AS time, a.content, a.state, a.time_type as timeType, a.creator_id as creatorId, a.cost, a.report_time_type as reportTimeType, a.start_time as startTime,
-        a.end_time as endTime, d.name as subProjectName,a.task_id as taskId, task.name as taskName, a.is_overtime as isOvertime,a.progress as progress
+        a.end_time as endTime, d.name as subProjectName,a.task_id as taskId, task.name as taskName,
+        b.incharger_id as inchargerId,
+        a.is_overtime as isOvertime,a.progress as progress
         FROM report AS a
         JOIN project AS b ON a.project_id=b.id
         left join sub_project as d on d.id = a.sub_project_id
@@ -170,11 +172,16 @@
         (select id from user where company_id = #{companyId})
         and state = 1
         <if test="startDate != null">
-            AND create_time &gt; #{startDate}
+            AND report.create_date &gt;= #{startDate}
         </if>
         <if test="endDate != null">
-            AND create_time &lt; #{endDate}
+            AND report.create_date &lt; #{endDate}
         </if>
         GROUP BY project_id, report.creator_id;
     </select>
+    <select id="getReportFillStatus" resultType="java.util.Map">
+        SELECT DATE_FORMAT(create_date,'%Y-%m-%d') as createDate, MAX(state) AS state FROM report
+        WHERE create_date BETWEEN #{startDate} AND #{endDate} AND creator_id = #{userId} GROUP BY create_date
+    </select>
+
 </mapper>

+ 18 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/SysConfigMapper.xml

@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.management.platform.mapper.SysConfigMapper">
+
+    <!-- 通用查询映射结果 -->
+    <resultMap id="BaseResultMap" type="com.management.platform.entity.SysConfig">
+        <id column="id" property="id" />
+        <result column="param_key" property="paramKey" />
+        <result column="param_value" property="paramValue" />
+        <result column="indate" property="indate" />
+    </resultMap>
+
+    <!-- 通用查询结果列 -->
+    <sql id="Base_Column_List">
+        id, param_key, param_value, indate
+    </sql>
+
+</mapper>

+ 17 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/TaskMapper.xml

@@ -111,4 +111,21 @@
         </if>
         GROUP BY task.id
     </select>
+
+    <select id="getProjectTask" resultType="java.util.Map">
+        SELECT task.id, task.`name`, task.`end_date`, task.`plan_hours`,
+        (SELECT IFNULL(SUM(working_time),0) FROM report WHERE report.`task_id` = task.id AND report.`state` = 1) AS real_hours,
+        task.`task_status`, task.`task_type`,
+        project.`project_code`, project.`project_name` FROM task LEFT JOIN project ON project.id = task.`project_id`
+        WHERE project.`company_id` = #{companyId}
+        ORDER BY project_name ASC
+        <if test="pageStart != null and pageSize != null">
+            limit #{pageStart}, #{pageSize}
+        </if>
+    </select>
+    <select id="getProjectTaskCount" resultType="java.lang.Integer">
+        SELECT count(1) as total FROM task LEFT JOIN project ON project.id = task.`project_id`
+        WHERE project.`company_id` = #{companyId}
+    </select>
+
 </mapper>

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

@@ -23,17 +23,21 @@
         <result column="wx_openid" property="wxOpenid" />
         <result column="role_id" property="roleId" />
         <result column="role_name" property="roleName" />
+        <result column="cost_apply_date" property="costApplyDate" />
+        <result column="dingding_userid" property="dingdingUserid" />
+        <result column="dingding_unionid" property="dingdingUnionid" />
+        <result column="corpwx_userid" property="corpwxUserid" />
     </resultMap>
 
     <!-- 通用查询结果列 -->
     <sql id="Base_Column_List">
-        id, name, phone, password, portrait_url, create_time, role, company_id, department_id, department_cascade, cost, month_cost, salary_type, manage_dept_id, color, is_active, wx_openid, role_id, role_name
+        id, name, phone, password, portrait_url, create_time, role, company_id, department_id, department_cascade, cost, month_cost, salary_type, manage_dept_id, color, is_active, wx_openid, role_id, role_name, cost_apply_date, dingding_userid, dingding_unionid, corpwx_userid
     </sql>
     <!--单独分页获取人员-->
     <select id="getUserByDepartment" resultType="java.util.Map">
         SELECT a.id, a.name, a.phone, a.portrait_url AS portraitUrl, a.role, a.company_id AS companyId, a.cost,
         a.department_id AS departmentId, b.department_name AS departmentName, a.department_cascade AS departmentCascade,
-        a.month_cost as monthCost, a.salary_type as salaryType, a.is_active as isActive
+        a.month_cost as monthCost, a.salary_type as salaryType, a.is_active as isActive, a.cost_apply_date as costApplyDate
         FROM user AS a
         LEFT JOIN department AS b ON a.department_id = b.department_id
         WHERE a.company_id = #{companyId}
@@ -56,7 +60,7 @@
     <select id="getUserByDepartmentList" resultType="java.util.Map">
         SELECT a.id, a.name, a.phone, a.portrait_url AS portraitUrl, a.role, a.company_id AS companyId, a.cost,
         a.department_id AS departmentId, b.department_name AS departmentName, a.department_cascade AS departmentCascade,
-        a.month_cost as monthCost, a.salary_type as salaryType, a.is_active as isActive
+        a.month_cost as monthCost, a.salary_type as salaryType, a.is_active as isActive, a.cost_apply_date as costApplyDate
         FROM user AS a
         LEFT JOIN department AS b ON a.department_id = b.department_id
         WHERE a.company_id = #{companyId} AND a.department_id IN

+ 18 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/UserVcodeMapper.xml

@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.management.platform.mapper.UserVcodeMapper">
+
+    <!-- 通用查询映射结果 -->
+    <resultMap id="BaseResultMap" type="com.management.platform.entity.UserVcode">
+        <id column="id" property="id" />
+        <result column="mobile" property="mobile" />
+        <result column="vcode" property="vcode" />
+        <result column="indate" property="indate" />
+    </resultMap>
+
+    <!-- 通用查询结果列 -->
+    <sql id="Base_Column_List">
+        id, mobile, vcode, indate
+    </sql>
+
+</mapper>

+ 26 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/WxCorpInfoMapper.xml

@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.management.platform.mapper.WxCorpInfoMapper">
+
+    <!-- 通用查询映射结果 -->
+    <resultMap id="BaseResultMap" type="com.management.platform.entity.WxCorpInfo">
+        <id column="corpid" property="corpid" />
+        <result column="corp_name" property="corpName" />
+        <result column="corp_full_name" property="corpFullName" />
+        <result column="corp_scale" property="corpScale" />
+        <result column="corp_industry" property="corpIndustry" />
+        <result column="corp_sub_industry" property="corpSubIndustry" />
+        <result column="location" property="location" />
+        <result column="access_token" property="accessToken" />
+        <result column="expire_time" property="expireTime" />
+        <result column="permanent_code" property="permanentCode" />
+        <result column="auth_username" property="authUsername" />
+        <result column="company_id" property="companyId" />
+    </resultMap>
+
+    <!-- 通用查询结果列 -->
+    <sql id="Base_Column_List">
+        corpid, corp_name, corp_full_name, corp_scale, corp_industry, corp_sub_industry, location, access_token, expire_time, permanent_code, auth_username, company_id
+    </sql>
+
+</mapper>

BIN
fhKeeper/formulahousekeeper/management-platform/导入成本6月份(1).xlsx


BIN
fhKeeper/formulahousekeeper/management-platform/财务人员成本模板 (1)(1).xlsx


BIN
fhKeeper/formulahousekeeper/management-platform/财务人员成本模板 (1).xlsx


BIN
fhKeeper/formulahousekeeper/management-platform/项目任务导入模板.xlsx


BIN
fhKeeper/formulahousekeeper/management-platform/项目导入模板 .xlsx