Browse Source

fix: directory refactor

Blizzard 11 months ago
parent
commit
4f3c08895b
100 changed files with 5704 additions and 0 deletions
  1. 150 0
      blade-service/wutong-okr/pom.xml
  2. 20 0
      blade-service/wutong-okr/src/main/java/com/wtkj/OKRServiceApplication.java
  3. 47 0
      blade-service/wutong-okr/src/main/java/com/wtkj/config/AsyncConfig.java
  4. 18 0
      blade-service/wutong-okr/src/main/java/com/wtkj/config/FeignConfig.java
  5. 83 0
      blade-service/wutong-okr/src/main/java/com/wtkj/config/KafkaConfig.java
  6. 16 0
      blade-service/wutong-okr/src/main/java/com/wtkj/config/KafkaConstant.java
  7. 39 0
      blade-service/wutong-okr/src/main/java/com/wtkj/config/MagicValue.java
  8. 62 0
      blade-service/wutong-okr/src/main/java/com/wtkj/config/NacosConfigValue.java
  9. 67 0
      blade-service/wutong-okr/src/main/java/com/wtkj/config/es/EsConfig.java
  10. 156 0
      blade-service/wutong-okr/src/main/java/com/wtkj/controller/AnnouncementController.java
  11. 62 0
      blade-service/wutong-okr/src/main/java/com/wtkj/controller/CommonController.java
  12. 83 0
      blade-service/wutong-okr/src/main/java/com/wtkj/controller/ContactController.java
  13. 231 0
      blade-service/wutong-okr/src/main/java/com/wtkj/controller/FileAndFolderController.java
  14. 140 0
      blade-service/wutong-okr/src/main/java/com/wtkj/controller/IndexController.java
  15. 184 0
      blade-service/wutong-okr/src/main/java/com/wtkj/controller/ProjectController.java
  16. 147 0
      blade-service/wutong-okr/src/main/java/com/wtkj/controller/QrCodeController.java
  17. 139 0
      blade-service/wutong-okr/src/main/java/com/wtkj/controller/ResourceController.java
  18. 307 0
      blade-service/wutong-okr/src/main/java/com/wtkj/controller/TaskController.java
  19. 81 0
      blade-service/wutong-okr/src/main/java/com/wtkj/controller/TypeAndStageController.java
  20. 124 0
      blade-service/wutong-okr/src/main/java/com/wtkj/handler/EsFileHandler.java
  21. 95 0
      blade-service/wutong-okr/src/main/java/com/wtkj/handler/Schedule.java
  22. 33 0
      blade-service/wutong-okr/src/main/java/com/wtkj/handler/es/Document.java
  23. 12 0
      blade-service/wutong-okr/src/main/java/com/wtkj/mapper/AnnouncementMapper.java
  24. 6 0
      blade-service/wutong-okr/src/main/java/com/wtkj/mapper/AnnouncementMapper.xml
  25. 20 0
      blade-service/wutong-okr/src/main/java/com/wtkj/mapper/AnnouncementSendMapper.java
  26. 18 0
      blade-service/wutong-okr/src/main/java/com/wtkj/mapper/AnnouncementSendMapper.xml
  27. 12 0
      blade-service/wutong-okr/src/main/java/com/wtkj/mapper/ApplyJoinMapper.java
  28. 6 0
      blade-service/wutong-okr/src/main/java/com/wtkj/mapper/ApplyJoinMapper.xml
  29. 22 0
      blade-service/wutong-okr/src/main/java/com/wtkj/mapper/ContactOuterMapper.java
  30. 22 0
      blade-service/wutong-okr/src/main/java/com/wtkj/mapper/ContactOuterMapper.xml
  31. 19 0
      blade-service/wutong-okr/src/main/java/com/wtkj/mapper/FileAndFolderHistoryMapper.java
  32. 15 0
      blade-service/wutong-okr/src/main/java/com/wtkj/mapper/FileAndFolderHistoryMapper.xml
  33. 30 0
      blade-service/wutong-okr/src/main/java/com/wtkj/mapper/FileAndFolderMapper.java
  34. 69 0
      blade-service/wutong-okr/src/main/java/com/wtkj/mapper/FileAndFolderMapper.xml
  35. 17 0
      blade-service/wutong-okr/src/main/java/com/wtkj/mapper/FileReadMapper.java
  36. 12 0
      blade-service/wutong-okr/src/main/java/com/wtkj/mapper/FileReadMapper.xml
  37. 12 0
      blade-service/wutong-okr/src/main/java/com/wtkj/mapper/FileShareMapper.java
  38. 6 0
      blade-service/wutong-okr/src/main/java/com/wtkj/mapper/FileShareMapper.xml
  39. 12 0
      blade-service/wutong-okr/src/main/java/com/wtkj/mapper/IndexMessageMapper.java
  40. 6 0
      blade-service/wutong-okr/src/main/java/com/wtkj/mapper/IndexMessageMapper.xml
  41. 24 0
      blade-service/wutong-okr/src/main/java/com/wtkj/mapper/InnerFileAndFolderMapper.java
  42. 53 0
      blade-service/wutong-okr/src/main/java/com/wtkj/mapper/InnerFileAndFolderMapper.xml
  43. 18 0
      blade-service/wutong-okr/src/main/java/com/wtkj/mapper/ProjectAuthMapper.java
  44. 25 0
      blade-service/wutong-okr/src/main/java/com/wtkj/mapper/ProjectAuthMapper.xml
  45. 17 0
      blade-service/wutong-okr/src/main/java/com/wtkj/mapper/ProjectGroupMapper.java
  46. 14 0
      blade-service/wutong-okr/src/main/java/com/wtkj/mapper/ProjectGroupMapper.xml
  47. 12 0
      blade-service/wutong-okr/src/main/java/com/wtkj/mapper/ProjectMapper.java
  48. 6 0
      blade-service/wutong-okr/src/main/java/com/wtkj/mapper/ProjectMapper.xml
  49. 16 0
      blade-service/wutong-okr/src/main/java/com/wtkj/mapper/ProjectStageMapper.java
  50. 9 0
      blade-service/wutong-okr/src/main/java/com/wtkj/mapper/ProjectStageMapper.xml
  51. 21 0
      blade-service/wutong-okr/src/main/java/com/wtkj/mapper/TaskContractMapper.java
  52. 32 0
      blade-service/wutong-okr/src/main/java/com/wtkj/mapper/TaskContractMapper.xml
  53. 18 0
      blade-service/wutong-okr/src/main/java/com/wtkj/mapper/TaskCostMapper.java
  54. 12 0
      blade-service/wutong-okr/src/main/java/com/wtkj/mapper/TaskCostMapper.xml
  55. 14 0
      blade-service/wutong-okr/src/main/java/com/wtkj/mapper/TaskFileMapper.java
  56. 9 0
      blade-service/wutong-okr/src/main/java/com/wtkj/mapper/TaskFileMapper.xml
  57. 15 0
      blade-service/wutong-okr/src/main/java/com/wtkj/mapper/TaskLogMapper.java
  58. 8 0
      blade-service/wutong-okr/src/main/java/com/wtkj/mapper/TaskLogMapper.xml
  59. 44 0
      blade-service/wutong-okr/src/main/java/com/wtkj/mapper/TaskMapper.java
  60. 112 0
      blade-service/wutong-okr/src/main/java/com/wtkj/mapper/TaskMapper.xml
  61. 16 0
      blade-service/wutong-okr/src/main/java/com/wtkj/mapper/TypeStageMapper.java
  62. 12 0
      blade-service/wutong-okr/src/main/java/com/wtkj/mapper/TypeStageMapper.xml
  63. 12 0
      blade-service/wutong-okr/src/main/java/com/wtkj/mapper/WorkStatusMapper.java
  64. 5 0
      blade-service/wutong-okr/src/main/java/com/wtkj/mapper/WorkStatusMapper.xml
  65. 38 0
      blade-service/wutong-okr/src/main/java/com/wtkj/service/IAnnouncementSendService.java
  66. 12 0
      blade-service/wutong-okr/src/main/java/com/wtkj/service/IAnnouncementService.java
  67. 13 0
      blade-service/wutong-okr/src/main/java/com/wtkj/service/IApplyJoinService.java
  68. 40 0
      blade-service/wutong-okr/src/main/java/com/wtkj/service/IAsyncService.java
  69. 38 0
      blade-service/wutong-okr/src/main/java/com/wtkj/service/ICommonService.java
  70. 21 0
      blade-service/wutong-okr/src/main/java/com/wtkj/service/IContactOuterService.java
  71. 19 0
      blade-service/wutong-okr/src/main/java/com/wtkj/service/IFileAndFolderHistoryService.java
  72. 39 0
      blade-service/wutong-okr/src/main/java/com/wtkj/service/IFileAndFolderService.java
  73. 22 0
      blade-service/wutong-okr/src/main/java/com/wtkj/service/IFileReadService.java
  74. 12 0
      blade-service/wutong-okr/src/main/java/com/wtkj/service/IFileShareService.java
  75. 12 0
      blade-service/wutong-okr/src/main/java/com/wtkj/service/IIndexMessageService.java
  76. 35 0
      blade-service/wutong-okr/src/main/java/com/wtkj/service/IIndexService.java
  77. 30 0
      blade-service/wutong-okr/src/main/java/com/wtkj/service/IInnerFileAndFolderService.java
  78. 17 0
      blade-service/wutong-okr/src/main/java/com/wtkj/service/IProjectAuthService.java
  79. 17 0
      blade-service/wutong-okr/src/main/java/com/wtkj/service/IProjectGroupService.java
  80. 26 0
      blade-service/wutong-okr/src/main/java/com/wtkj/service/IProjectService.java
  81. 17 0
      blade-service/wutong-okr/src/main/java/com/wtkj/service/IProjectStageService.java
  82. 33 0
      blade-service/wutong-okr/src/main/java/com/wtkj/service/IQrcodeService.java
  83. 22 0
      blade-service/wutong-okr/src/main/java/com/wtkj/service/ITaskContractService.java
  84. 21 0
      blade-service/wutong-okr/src/main/java/com/wtkj/service/ITaskCostService.java
  85. 17 0
      blade-service/wutong-okr/src/main/java/com/wtkj/service/ITaskFileService.java
  86. 18 0
      blade-service/wutong-okr/src/main/java/com/wtkj/service/ITaskLogService.java
  87. 104 0
      blade-service/wutong-okr/src/main/java/com/wtkj/service/ITaskService.java
  88. 19 0
      blade-service/wutong-okr/src/main/java/com/wtkj/service/ITypeAndStageService.java
  89. 14 0
      blade-service/wutong-okr/src/main/java/com/wtkj/service/IWorkStatusService.java
  90. 60 0
      blade-service/wutong-okr/src/main/java/com/wtkj/service/impl/AnnouncementSendServiceImpl.java
  91. 18 0
      blade-service/wutong-okr/src/main/java/com/wtkj/service/impl/AnnouncementServiceImpl.java
  92. 37 0
      blade-service/wutong-okr/src/main/java/com/wtkj/service/impl/ApplyJoinServiceImpl.java
  93. 978 0
      blade-service/wutong-okr/src/main/java/com/wtkj/service/impl/AsyncServiceImpl.java
  94. 423 0
      blade-service/wutong-okr/src/main/java/com/wtkj/service/impl/CommonServiceImpl.java
  95. 79 0
      blade-service/wutong-okr/src/main/java/com/wtkj/service/impl/ContactOuterServiceImpl.java
  96. 31 0
      blade-service/wutong-okr/src/main/java/com/wtkj/service/impl/FileAndFolderHistoryServiceImpl.java
  97. 177 0
      blade-service/wutong-okr/src/main/java/com/wtkj/service/impl/FileAndFolderServiceImpl.java
  98. 66 0
      blade-service/wutong-okr/src/main/java/com/wtkj/service/impl/FileReadServiceImpl.java
  99. 18 0
      blade-service/wutong-okr/src/main/java/com/wtkj/service/impl/FileShareServiceImpl.java
  100. 37 0
      blade-service/wutong-okr/src/main/java/com/wtkj/service/impl/ITaskContractServiceImpl.java

+ 150 - 0
blade-service/wutong-okr/pom.xml

@@ -0,0 +1,150 @@
+<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <artifactId>blade-service</artifactId>
+        <groupId>org.springblade</groupId>
+        <version>2.9.1.RELEASE</version>
+    </parent>
+
+    <groupId>com.wtkj</groupId>
+    <artifactId>wutong-okr</artifactId>
+    <name>${project.artifactId}</name>
+    <version>${bladex.project.version}</version>
+    <packaging>jar</packaging>
+
+
+    <dependencies>
+        <dependency>
+            <groupId>org.springblade</groupId>
+            <artifactId>blade-core-boot</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springblade</groupId>
+            <artifactId>blade-starter-swagger</artifactId>
+        </dependency>
+
+
+        <!--数据导出-->
+        <!--        <dependency>-->
+        <!--            <groupId>org.springblade</groupId>-->
+        <!--            <artifactId>blade-starter-excel</artifactId>-->
+        <!--        </dependency>-->
+
+        <dependency>
+            <groupId>cn.afterturn</groupId>
+            <artifactId>easypoi-base</artifactId>
+            <version>4.1.2</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>easyexcel</artifactId>
+        </dependency>
+
+        <!--        分布式事务-->
+        <dependency>
+            <groupId>org.springblade</groupId>
+            <artifactId>blade-starter-transaction</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>fastjson</artifactId>
+        </dependency>
+
+        <!--        es-->
+        <dependency>
+            <groupId>co.elastic.clients</groupId>
+            <artifactId>elasticsearch-java</artifactId>
+            <version>8.6.1</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.elasticsearch.client</groupId>
+            <artifactId>elasticsearch-rest-client</artifactId>
+            <version>8.6.1</version>
+        </dependency>
+
+        <!--        <dependency>-->
+        <!--            <groupId>com.fasterxml.jackson.core</groupId>-->
+        <!--            <artifactId>jackson-databind</artifactId>-->
+        <!--            <version>2.12.3</version>-->
+        <!--        </dependency>-->
+
+        <dependency>
+            <groupId>jakarta.json</groupId>
+            <artifactId>jakarta.json-api</artifactId>
+            <version>2.0.1</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.kafka</groupId>
+            <artifactId>spring-kafka</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>cn.hutool</groupId>
+            <artifactId>hutool-all</artifactId>
+            <version>5.5.7</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.tencentcloudapi</groupId>
+            <artifactId>tencentcloud-sdk-java</artifactId>
+            <!-- go to https://search.maven.org/search?q=tencentcloud-sdk-java and get the latest version. -->
+            <!-- 请到https://search.maven.org/search?q=tencentcloud-sdk-java查询所有版本,最新版本如下 -->
+            <version>3.1.875</version>
+        </dependency>
+
+
+        <dependency>
+            <groupId>com.wtkj</groupId>
+            <artifactId>wt-okr-api</artifactId>
+            <version>2.9.1.RELEASE</version>
+        </dependency>
+
+    </dependencies>
+
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>com.spotify</groupId>
+                <artifactId>dockerfile-maven-plugin</artifactId>
+                <configuration>
+                    <username>${docker.username}</username>
+                    <password>${docker.password}</password>
+                    <repository>${docker.registry.url}/${docker.namespace}/${project.artifactId}</repository>
+                    <tag>${project.version}</tag>
+                    <useMavenSettingsForAuth>true</useMavenSettingsForAuth>
+                    <buildArgs>
+                        <JAR_FILE>target/${project.build.finalName}.jar</JAR_FILE>
+                    </buildArgs>
+                    <skip>false</skip>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-antrun-plugin</artifactId>
+            </plugin>
+
+            <!--不打包test-->
+            <!--<plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <version>2.12.4</version>
+                <configuration>
+                    <skipTests>true</skipTests>
+                </configuration>
+            </plugin>-->
+            <!--不打包tes-->
+        </plugins>
+    </build>
+
+</project>

+ 20 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/OKRServiceApplication.java

@@ -0,0 +1,20 @@
+package com.wtkj;
+
+import org.springblade.common.constant.LauncherConstant;
+import org.springblade.core.cloud.feign.EnableBladeFeign;
+import org.springblade.core.launch.BladeApplication;
+import org.springblade.core.transaction.annotation.SeataCloudApplication;
+
+/**
+ * @author Blizzard
+ * @create at 2023-09-13 11:12
+ * @describe
+ */
+
+@EnableBladeFeign
+@SeataCloudApplication
+public class OKRServiceApplication {
+	public static void main(String[] args) {
+		BladeApplication.run(LauncherConstant.APPLICATION_SERVICE_NAME, OKRServiceApplication.class);
+	}
+}

+ 47 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/config/AsyncConfig.java

@@ -0,0 +1,47 @@
+package com.wtkj.config;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.annotation.EnableAsync;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
+
+import java.util.concurrent.ThreadPoolExecutor;
+
+/**
+ * @author Blizzard
+ * @create at 2023-09-13 15:04
+ * @describe
+ */
+@Configuration
+@EnableAsync
+@Slf4j
+public class AsyncConfig {
+
+	@Bean(name = "asyncPoolTaskExecutor")
+	public ThreadPoolTaskExecutor executor() {
+		ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
+		//核心线程数
+		taskExecutor.setCorePoolSize(10);
+		//线程池维护线程的最大数量,只有在缓冲队列满了之后才会申请超过核心线程数的线程
+		taskExecutor.setMaxPoolSize(100);
+		//缓冲队列
+		taskExecutor.setQueueCapacity(50);
+		//设置线程的空闲时间,当超过了核心线程出之外的线程在空闲时间到达之后会被销毁
+		taskExecutor.setKeepAliveSeconds(200);
+		//异步方法内部线程名称
+		taskExecutor.setThreadNamePrefix("async-");
+		/**
+		 * 当线程池的任务缓存队列已满并且线程池中的线程数目达到maximumPoolSize,如果还有任务到来就会采取任务拒绝策略
+		 * 通常有以下四种策略:
+		 * ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常。
+		 * ThreadPoolExecutor.DiscardPolicy:也是丢弃任务,但是不抛出异常。
+		 * ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程)
+		 * ThreadPoolExecutor.CallerRunsPolicy:重试添加当前的任务,自动重复调用 execute() 方法,直到成功
+		 */
+		taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
+		taskExecutor.initialize();
+		return taskExecutor;
+	}
+
+}

+ 18 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/config/FeignConfig.java

@@ -0,0 +1,18 @@
+package com.wtkj.config;
+
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.cloud.openfeign.EnableFeignClients;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * @author Blizzard
+ * @create at 2023-09-15 09:20
+ * @describe
+ */
+@Configuration
+@ComponentScan({"org.springblade", "com.wutong"})
+@EnableFeignClients({"org.springblade", "com.wutong"})
+@MapperScan({"org.springblade.**.mapper.**", "com.wtkj.**.mapper.**"})
+public class FeignConfig {
+}

+ 83 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/config/KafkaConfig.java

@@ -0,0 +1,83 @@
+package com.wtkj.config;
+
+import lombok.AllArgsConstructor;
+import org.apache.kafka.clients.admin.NewTopic;
+import org.springframework.boot.autoconfigure.kafka.KafkaProperties;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.kafka.annotation.EnableKafka;
+import org.springframework.kafka.config.ConcurrentKafkaListenerContainerFactory;
+import org.springframework.kafka.core.*;
+import org.springframework.kafka.listener.ContainerProperties;
+
+/**
+ * @author Blizzard
+ * @create at 2023-09-27 11:27
+ * @describe
+ */
+@Configuration(proxyBeanMethods = false)
+@EnableConfigurationProperties({KafkaProperties.class})
+@EnableKafka
+@AllArgsConstructor
+public class KafkaConfig {
+
+	private final KafkaProperties kafkaProperties;
+
+
+	/**
+	 * topic 配置 启动自动创建 已经存在不会创建
+	 */
+	@Bean
+	public NewTopic kafkaTopic() {
+		return new NewTopic(KafkaConstant.PARSE_SUCCESS_MESSAGE, KafkaConstant.DEFAULT_PARTITION_NUM, (short) 1);
+	}
+
+	@Bean
+	public KafkaTemplate<String, String> kafkaTemplate() {
+		return new KafkaTemplate<>(producerFactory());
+	}
+
+	/**
+	 * 生产者配置
+	 */
+	@Bean
+	public ProducerFactory<String, String> producerFactory() {
+		return new DefaultKafkaProducerFactory<>(kafkaProperties.buildProducerProperties());
+	}
+
+	/**
+	 * 消费者配置
+	 */
+	@Bean
+	public ConsumerFactory<String, String> consumerFactory() {
+		return new DefaultKafkaConsumerFactory<>(kafkaProperties.buildConsumerProperties());
+	}
+
+	/**
+	 * 监听器配置1
+	 */
+	@Bean
+	public ConcurrentKafkaListenerContainerFactory<String, String> kafkaListenerContainerFactory() {
+		ConcurrentKafkaListenerContainerFactory<String, String> factory = new ConcurrentKafkaListenerContainerFactory<>();
+		factory.setConsumerFactory(consumerFactory());
+		//分区大小
+		factory.setConcurrency(KafkaConstant.DEFAULT_PARTITION_NUM);
+		factory.setBatchListener(true);
+		factory.getContainerProperties().setPollTimeout(3000);
+		return factory;
+	}
+
+
+	@Bean("ackContainerFactory")
+	public ConcurrentKafkaListenerContainerFactory<String, String> ackContainerFactory() {
+		ConcurrentKafkaListenerContainerFactory<String, String> factory = new ConcurrentKafkaListenerContainerFactory<>();
+		factory.setConsumerFactory(consumerFactory());
+		factory.getContainerProperties().setAckMode(ContainerProperties.AckMode.MANUAL_IMMEDIATE);
+		//3个分区
+		factory.setConcurrency(KafkaConstant.DEFAULT_PARTITION_NUM);
+		return factory;
+	}
+
+
+}

+ 16 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/config/KafkaConstant.java

@@ -0,0 +1,16 @@
+package com.wtkj.config;
+
+/**
+ * @author Blizzard
+ * @create at 2023-09-27 11:22
+ * @describe
+ */
+public interface KafkaConstant {
+
+	//分区数量
+	Integer DEFAULT_PARTITION_NUM = 3;
+
+	//项目文件解析成功消息处理topic
+	String PARSE_SUCCESS_MESSAGE = "parse-success-message-topic";
+
+}

+ 39 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/config/MagicValue.java

@@ -0,0 +1,39 @@
+package com.wtkj.config;
+
+/**
+ * @author Blizzard
+ * @create at 2023-09-14 09:17
+ * @describe
+ */
+public interface MagicValue {
+
+	/**
+	 * 业主机构管理员
+	 */
+	String DEPT_ADMIN = "deptAdmin";
+
+	/**
+	 * 服务机构管理员
+	 */
+	String STAFF_ADMIN = "staff_admin";
+
+	/**
+	 * 服务机构次级管理员
+	 */
+	String STAFF_SECOND_ADMIN = "staff_second_admin";
+
+	/**
+	 * 服务机构
+	 */
+	String STAFF_PROJECT_MANAGER = "staff_project_manager";
+
+	String STAFF_USER = "staff_user";
+
+	Integer ZERO = 0;
+
+	Integer ONE = 1;
+
+	Integer TWO = 2;
+
+	String PROJECT_RESOURCE_INDEX = "project_resource_index";
+}

+ 62 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/config/NacosConfigValue.java

@@ -0,0 +1,62 @@
+package com.wtkj.config;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * @author Blizzard
+ * @create at 2023-09-19 11:08
+ * @describe nacos配置中心读取 配置
+ */
+@Configuration
+public class NacosConfigValue {
+
+
+	public static long expireIn;
+
+	public static long scanCount;
+
+	public static String corpId;
+	public static String qyAgentId;
+
+	public static String qySecret;
+
+	public static String txSecretId;
+
+	public static String txSecretKey;
+
+	@Value("${qrcode.expireIn}")
+	public void setExpireIn(Long expireIn) {
+		NacosConfigValue.expireIn = expireIn;
+	}
+
+	@Value("${qrcode.scanCount}")
+	public void setScanCount(Long scanCount) {
+		NacosConfigValue.scanCount = scanCount;
+	}
+
+	@Value("${qy.corpId}")
+	public void setCorpId(String corpId) {
+		NacosConfigValue.corpId = corpId;
+	}
+
+	@Value("${qy.agentId}")
+	public void setCpAgentId(String qyAgentId) {
+		NacosConfigValue.qyAgentId = qyAgentId;
+	}
+
+	@Value("${qy.secret}")
+	public void setCpSecret(String qySecret) {
+		NacosConfigValue.qySecret = qySecret;
+	}
+
+	@Value("${txCloud.secretId}")
+	public void setTxSecretId(String secretId) {
+		NacosConfigValue.txSecretId = secretId;
+	}
+
+	@Value("${txCloud.secretKey}")
+	public void setTxSecretKey(String secretKey) {
+		NacosConfigValue.txSecretKey = secretKey;
+	}
+}

+ 67 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/config/es/EsConfig.java

@@ -0,0 +1,67 @@
+package com.wtkj.config.es;
+
+import co.elastic.clients.elasticsearch.ElasticsearchClient;
+import co.elastic.clients.json.jackson.JacksonJsonpMapper;
+import co.elastic.clients.transport.ElasticsearchTransport;
+import co.elastic.clients.transport.rest_client.RestClientTransport;
+import org.apache.http.HttpHost;
+import org.elasticsearch.client.RestClient;
+import org.elasticsearch.client.RestClientBuilder;
+import org.elasticsearch.client.RestHighLevelClient;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.util.StringUtils;
+
+/**
+ * @author Blizzard
+ * @create at 2023-09-27 10:03
+ * @describe
+ */
+@Configuration
+public class EsConfig {
+
+	@Value("${spring.elasticsearch.rest.uris}")
+	private String hosts;
+
+
+	private HttpHost[] toHttpHost() {
+		if (!StringUtils.hasLength(hosts)) {
+			throw new RuntimeException("invalid elasticsearch configuration. elasticsearch.hosts不能为空!");
+		}
+
+		// 多个IP逗号隔开
+		String[] hostArray = hosts.split(",");
+		HttpHost[] httpHosts = new HttpHost[hostArray.length];
+		HttpHost httpHost;
+		for (int i = 0; i < hostArray.length; i++) {
+			String[] strings = hostArray[i].split(":");
+			httpHost = new HttpHost(strings[0], Integer.parseInt(strings[1]), "http");
+			httpHosts[i] = httpHost;
+		}
+
+		return httpHosts;
+	}
+
+
+	@Bean
+	public ElasticsearchClient elasticsearchClient() {
+		HttpHost[] httpHost = toHttpHost();
+		RestClient restClient = RestClient.builder(httpHost).build();
+		// Create the transport with a Jackson mapper
+		ElasticsearchTransport transport = new RestClientTransport(
+			restClient, new JacksonJsonpMapper());
+
+		// And create the API client
+		return new ElasticsearchClient(transport);
+	}
+
+	@Bean
+	public RestHighLevelClient esRestClient() {
+		RestClientBuilder builder;
+		builder = RestClient.builder(toHttpHost());
+		return new RestHighLevelClient(builder);
+	}
+
+
+}

+ 156 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/controller/AnnouncementController.java

@@ -0,0 +1,156 @@
+package com.wtkj.controller;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
+import com.wtkj.entity.Announcement;
+import com.wtkj.entity.AnnouncementSend;
+import com.wtkj.service.IAnnouncementSendService;
+import com.wtkj.service.IAnnouncementService;
+import com.wtkj.vo.AnnouncementSendVO;
+import com.wtkj.wrapper.AnnouncementSendWrapper;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
+import lombok.AllArgsConstructor;
+import org.springblade.core.mp.support.Condition;
+import org.springblade.core.mp.support.Query;
+import org.springblade.core.secure.utils.AuthUtil;
+import org.springblade.core.tool.api.R;
+import org.springblade.core.tool.utils.Func;
+import org.springframework.web.bind.annotation.*;
+
+import javax.validation.Valid;
+
+/**
+ * @author Blizzard
+ * @create at 2023-09-23 11:24
+ * @describe
+ */
+@RestController
+@AllArgsConstructor
+@RequestMapping("/announcement")
+@Api(value = "通知公告模块", tags = "通知公告模块")
+public class AnnouncementController {
+
+	private final IAnnouncementService announcementService;
+	private final IAnnouncementSendService announcementSendService;
+
+	/**
+	 * 详情
+	 */
+	@GetMapping("/detail")
+	@ApiOperationSupport(order = 1)
+	@ApiOperation(value = "详情", notes = "传入announcement")
+	public R<Announcement> detail(Announcement announcement) {
+		Announcement detail = announcementService.getOne(Condition.getQueryWrapper(announcement));
+		return R.data(detail);
+	}
+
+	/**
+	 * 分页 系统通告表
+	 */
+	@GetMapping("/page")
+	@ApiOperationSupport(order = 2)
+	@ApiOperation(value = "分页", notes = "传入announcement")
+	public R<IPage<Announcement>> list(Announcement announcement, Query query) {
+		IPage<Announcement> pages = announcementService.page(Condition.getPage(query), Condition.getQueryWrapper(announcement));
+		return R.data(pages);
+	}
+
+
+	/**
+	 * 新增或修改 系统通告表
+	 */
+	@PostMapping("/submit")
+	@ApiOperationSupport(order = 3)
+	@ApiOperation(value = "新增或修改", notes = "传入announcement")
+	public R submit(@Valid @RequestBody Announcement announcement) {
+		return R.status(announcementService.saveOrUpdate(announcement));
+	}
+
+
+	/**
+	 * 删除 系统通告表
+	 */
+	@PostMapping("/remove")
+	@ApiOperationSupport(order = 4)
+	@ApiOperation(value = "逻辑删除", notes = "传入ids")
+	public R remove(@ApiParam(value = "主键集合", required = true) @RequestParam String ids) {
+		return R.status(announcementService.deleteLogic(Func.toLongList(ids)));
+	}
+
+
+	@GetMapping("/send-detail")
+	@ApiOperationSupport(order = 5)
+	@ApiOperation(value = "发送详情", notes = "传入announcementSend")
+	public R<AnnouncementSendVO> detail(AnnouncementSend announcementSend) {
+		AnnouncementSend detail = announcementSendService.getOne(Condition.getQueryWrapper(announcementSend));
+		return R.data(AnnouncementSendWrapper.build().entityVO(detail));
+	}
+
+
+	/**
+	 * 自定义分页 获取用户消息列表
+	 */
+	@GetMapping("/send-page")
+	@ApiOperationSupport(order = 6)
+	@ApiOperation(value = "发送分页", notes = "")
+	public R<IPage<AnnouncementSendVO>> page(Query query) {
+		Long userId = AuthUtil.getUserId();
+		if (userId == -1L) {
+			return R.fail("获取用户信息失败!");
+		}
+		IPage<AnnouncementSend> pages = announcementSendService.selectAnnouncementSendPage(Condition.getPage(query), userId);
+		return R.data(AnnouncementSendWrapper.build().pageVO(pages));
+	}
+
+	/**
+	 * 获取用户未读消息数量
+	 */
+	@GetMapping("/send-notReadCount")
+	@ApiOperationSupport(order = 7)
+	@ApiOperation(value = "获取用户未读消息数量", notes = "")
+	public R notReadCount() {
+		Long userId = AuthUtil.getUserId();
+		if (userId == -1L) {
+			return R.fail("获取用户信息失败!");
+		}
+		return R.data(announcementSendService.notReadCount(userId));
+	}
+
+
+	/**
+	 * 用户阅读状态修改
+	 */
+	@PostMapping("/send-read")
+	@ApiOperationSupport(order = 8)
+	@ApiOperation(value = "用户阅读状态修改", notes = "传入id")
+	public R read(@ApiParam(value = "主键ID", required = true) @RequestParam Long id) {
+		return R.status(announcementSendService.updateReadFlag(id));
+	}
+
+	/**
+	 * 用户阅读状态修改
+	 */
+	@PostMapping("/send-allRead")
+	@ApiOperationSupport(order = 9)
+	@ApiOperation(value = "一键全部已读", notes = "")
+	public R allRead() {
+		Long userId = AuthUtil.getUserId();
+		if (userId == -1L) {
+			return R.fail("获取用户信息失败!");
+		}
+		return R.status(announcementSendService.allRead(userId));
+	}
+
+
+	/**
+	 * 删除 用户通告阅读标记表
+	 */
+	@PostMapping("/send-remove")
+	@ApiOperationSupport(order = 10)
+	@ApiOperation(value = "发送逻辑删除", notes = "传入ids")
+	public R removeSend(@ApiParam(value = "主键集合", required = true) @RequestParam String ids) {
+		return R.status(announcementSendService.deleteLogic(Func.toLongList(ids)));
+	}
+}

+ 62 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/controller/CommonController.java

@@ -0,0 +1,62 @@
+package com.wtkj.controller;
+
+import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
+import com.wtkj.service.ICommonService;
+import com.wtkj.service.ITaskService;
+import com.wtkj.util.Workload;
+import com.wtkj.vo.AuthUserInfo;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.AllArgsConstructor;
+import org.springblade.core.secure.annotation.PreAuth;
+import org.springblade.core.tool.api.R;
+import org.springblade.core.tool.constant.RoleConstant;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.List;
+
+/**
+ * @author Blizzard
+ * @create at 2023-09-14 11:13
+ * @describe
+ */
+@RestController
+@AllArgsConstructor
+@RequestMapping("/common")
+@Api(value = "公共模块", tags = "公共模块")
+public class CommonController {
+
+	private final ITaskService taskService;
+	private final ICommonService commonService;
+
+	/**
+	 * 当前登录用户信息
+	 */
+	@GetMapping("/user-info")
+	@ApiOperation(value = "当前登录用户信息", notes = "")
+	@ApiOperationSupport(order = 1)
+	public R<AuthUserInfo> userInfo() {
+		return R.data(commonService.userInfo());
+	}
+
+
+	/**
+	 * 导出工作量
+	 */
+	@GetMapping("/export-task")
+	@ApiOperation(value = "工作量导出", notes = "")
+	@ApiOperationSupport(order = 2)
+	@PreAuth(RoleConstant.HAS_ROLE_ADMIN)
+	public void export(@RequestParam String startDate, @RequestParam String endDate, HttpServletResponse response) throws IOException {
+		List<Workload> list = taskService.exportList(startDate, endDate);
+		taskService.export(list, response);
+
+	}
+
+
+}

+ 83 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/controller/ContactController.java

@@ -0,0 +1,83 @@
+package com.wtkj.controller;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
+import com.wtkj.dto.UpdateUserDTO;
+import com.wtkj.entity.ContactOuter;
+import com.wtkj.service.IContactOuterService;
+import com.wtkj.service.IWorkStatusService;
+import com.wtkj.vo.WorkStatusVO;
+import com.wtkj.wrapper.ContactOuterUserWrapper;
+import com.wtkj.wrapper.ContactOuterWrapper;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.AllArgsConstructor;
+import org.springblade.core.mp.support.Condition;
+import org.springblade.core.mp.support.Query;
+import org.springblade.core.secure.utils.AuthUtil;
+import org.springblade.core.tool.api.R;
+import org.springframework.web.bind.annotation.*;
+
+import javax.validation.Valid;
+
+/**
+ * @author Blizzard
+ * @create at 2023-09-20 11:58
+ * @describe
+ */
+@RestController
+@AllArgsConstructor
+@RequestMapping("/contact")
+@Api(value = "联系人模块", tags = "联系人模块")
+public class ContactController {
+
+	private final IContactOuterService contactOuterService;
+	private final IWorkStatusService workStatusService;
+
+
+	/**
+	 * 外部联系人
+	 */
+	@GetMapping("/outer-dept")
+	@ApiOperation(value = "外部联系人机构分页", notes = "传入分页参数")
+	@ApiOperationSupport(order = 1)
+	public R address(Query query) {
+		IPage<ContactOuter> page = contactOuterService.selectPage(AuthUtil.getUserId(), Condition.getPage(query));
+		return R.data(ContactOuterWrapper.build().pageVO(page));
+	}
+
+	/**
+	 * 外部联系人分页
+	 */
+	@GetMapping("/outer-contact")
+	@ApiOperation(value = "外部联系人分页", notes = "传入deptId 分页参数")
+	@ApiOperationSupport(order = 2)
+	public R contactPage(@RequestParam Long deptId, Query query) {
+		IPage<ContactOuter> page = contactOuterService.contactPage(deptId, AuthUtil.getUserId(), Condition.getPage(query));
+		return R.data(ContactOuterUserWrapper.build().pageVO(page));
+	}
+
+
+	/**
+	 * 用户工作状态
+	 */
+	@GetMapping("/user-workStatus")
+	@ApiOperation(value = "用户工作状态", notes = "传入userId")
+	@ApiOperationSupport(order = 3)
+	public R workStatus(@RequestParam Long userId) {
+		WorkStatusVO workStatusVO = workStatusService.workStatus(userId);
+		return R.data(workStatusVO);
+	}
+
+	/**
+	 * 修改用户信息
+	 */
+	@PostMapping("/update-user")
+	@ApiOperation(value = "修改用户信息", notes = "传入")
+	@ApiOperationSupport(order = 3)
+	public R updateUser(@RequestBody @Valid UpdateUserDTO dto) {
+		return R.status(contactOuterService.updateUser(dto));
+	}
+
+
+}

+ 231 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/controller/FileAndFolderController.java

@@ -0,0 +1,231 @@
+package com.wtkj.controller;
+
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
+import com.wtkj.dto.SelectFileDTO;
+import com.wtkj.dto.UploadFileDTO;
+import com.wtkj.entity.FileAndFolder;
+import com.wtkj.entity.FileAndFolderHistory;
+import com.wtkj.entity.FileRead;
+import com.wtkj.service.ICommonService;
+import com.wtkj.service.IFileAndFolderHistoryService;
+import com.wtkj.service.IFileAndFolderService;
+import com.wtkj.service.IFileReadService;
+import com.wtkj.vo.FileAndFolderVO;
+import com.wtkj.wrapper.FileAndFolderHistoryWrapper;
+import com.wtkj.wrapper.FileAndFolderWrapper;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.AllArgsConstructor;
+import org.springblade.core.log.exception.ServiceException;
+import org.springblade.core.mp.support.Condition;
+import org.springblade.core.mp.support.Query;
+import org.springblade.core.secure.utils.AuthUtil;
+import org.springblade.core.tool.api.R;
+import org.springblade.core.tool.utils.Func;
+import org.springframework.web.bind.annotation.*;
+
+import javax.validation.Valid;
+import java.util.List;
+import java.util.Objects;
+
+import static com.wtkj.config.MagicValue.ONE;
+import static com.wtkj.config.MagicValue.TWO;
+
+/**
+ * @author Blizzard
+ * @create at 2023-09-14 15:06
+ * @describe
+ */
+@RestController
+@AllArgsConstructor
+@RequestMapping("/file-and-folder")
+@Api(value = "文件和文件夹模块", tags = "文件和文件夹模块")
+public class FileAndFolderController {
+
+	public final IFileAndFolderHistoryService historyService;
+	private final IFileAndFolderService fileAndFolderService;
+	private final ICommonService commonService;
+	private final IFileReadService fileReadService;
+
+	/**
+	 * 新建文件夹
+	 */
+	@PostMapping("/submit")
+	@ApiOperation(value = "创建修改文件夹或者文件", notes = "")
+	@ApiOperationSupport(order = 1)
+	public R<Boolean> createFolder(@RequestBody FileAndFolder folder) {
+		LambdaQueryWrapper<FileAndFolder> lqw = new LambdaQueryWrapper<>();
+		lqw.eq(FileAndFolder::getStageId, folder.getStageId());
+		lqw.eq(FileAndFolder::getTitle, folder.getTitle());
+		lqw.eq(FileAndFolder::getParentId, folder.getParentId());
+		if (folder.getIsPrivate() == 1) {
+			folder.setPrivateUser(AuthUtil.getUserId());
+		}
+		if (Objects.equals(folder.getType(), ONE)) {
+			lqw.eq(FileAndFolder::getType, ONE);
+			long cnt = fileAndFolderService.count(lqw);
+			if (cnt > 0L) {
+				throw new ServiceException("此项目阶段下已经存在同名文件");
+			}
+		} else if (Objects.equals(folder.getType(), TWO)) {
+			lqw.eq(FileAndFolder::getType, TWO);
+			long cnt = fileAndFolderService.count(lqw);
+			if (cnt > 0L) {
+				throw new ServiceException("此项目阶段下已经存在同名文件夹");
+			}
+		}
+		return R.status(fileAndFolderService.saveOrUpdate(folder));
+	}
+
+	/**
+	 * 上传文件
+	 */
+	@PostMapping("/upload-file")
+	@ApiOperationSupport(order = 2)
+	@ApiOperation(value = "上传文件提示覆盖", notes = "")
+	public R<Boolean> uploadFile(@Valid @RequestBody List<UploadFileDTO> files) {
+		//判断是否存在重名文件
+		boolean isExist = fileAndFolderService.isExistSameName(files);
+		if (isExist) {
+			//存同名文件 提示
+			return R.fail("存在重名文件,是否覆盖");
+		} else {
+			//不存在同名文件 直接上传
+			return R.status(commonService.uploadFile(files));
+		}
+	}
+
+	/**
+	 * 文件覆盖
+	 */
+	@PostMapping("/cover-file")
+	@ApiOperationSupport(order = 3)
+	@ApiOperation(value = "上传直接覆盖同名文件", notes = "")
+	public R<Boolean> coverFile(@Valid @RequestBody List<UploadFileDTO> files) {
+		return R.status(commonService.coverFile(files));
+	}
+
+	/**
+	 * 阶段下的文件夹和文件
+	 */
+	@GetMapping("/page-by-stage")
+	@ApiOperationSupport(order = 4)
+	@ApiOperation(value = "阶段下的顶级文件和文件夹", notes = "")
+	public R<IPage<FileAndFolderVO>> pageByStage(@RequestParam("stageId") Long stageId, Query query) {
+		IPage<FileAndFolder> page = fileAndFolderService.pageByStageId(stageId, Condition.getPage(query));
+		return R.data(FileAndFolderWrapper.build().pageVO(page));
+	}
+
+	/**
+	 * 文件夹下的文件和文件夹
+	 */
+	@GetMapping("/page-by-parent")
+	@ApiOperationSupport(order = 5)
+	@ApiOperation(value = "文件夹下的文件和文件夹", notes = "")
+	public R<IPage<FileAndFolderVO>> pageByParentId(@RequestParam("parentId") Long parentId, Query query) {
+		IPage<FileAndFolder> page = fileAndFolderService.pageByParentId(parentId, Condition.getPage(query));
+		return R.data(FileAndFolderWrapper.build().pageVO(page));
+	}
+
+	/**
+	 * 文件夹下的文件数量  页码数量
+	 */
+	@GetMapping("/file-and-page-amount")
+	@ApiOperationSupport(order = 6)
+	@ApiOperation(value = "文夹下的文件数量", notes = "传入文件夹主键id")
+	public R<JSONObject> getPageAmount(@RequestParam Long stageId, @RequestParam Long parentId) {
+		return R.data(fileAndFolderService.getPageAndFileAmount(stageId, parentId));
+	}
+
+	/**
+	 * 删除文件/文件夹
+	 */
+	@GetMapping("/remove")
+	@ApiOperationSupport(order = 7)
+	@ApiOperation(value = "删除文件夹或文件", notes = "")
+	public R<Boolean> delete(@RequestParam String ids) {
+		return R.status(commonService.remove(Func.toLongList(ids)));
+	}
+
+	/**
+	 * 文件或者文件夹移动
+	 */
+	@GetMapping("/move")
+	@ApiOperationSupport(order = 8)
+	@ApiOperation(value = "移动文件或者文件夹", notes = "")
+	public R<Boolean> move(String ids, Long stageId, Long parentId) {
+		return R.status(commonService.move(ids, stageId, parentId));
+	}
+
+	/**
+	 * 文件详情
+	 */
+	@GetMapping("/file-detail")
+	@ApiOperationSupport(order = 10)
+	@ApiOperation(value = "文件详情", notes = "")
+	public R<FileAndFolderVO> detail(@RequestParam Long id) {
+		FileAndFolder byId = fileAndFolderService.getById(id);
+		return R.data(FileAndFolderWrapper.build().entityVO(byId));
+	}
+
+	/**
+	 * 阅读文件
+	 */
+	@PostMapping("/read-file")
+	@ApiOperationSupport(order = 10)
+	@ApiOperation(value = "阅读文件", notes = "")
+	public R<Boolean> readFile(@RequestBody FileRead read) {
+		return R.status(fileReadService.readFile(read));
+	}
+
+
+	/**
+	 * 文件选择列表
+	 */
+	@PostMapping("/select-file")
+	@ApiOperationSupport(order = 11)
+	@ApiOperation(value = "选择文件", notes = "")
+	public R selectFile(@RequestBody @Valid SelectFileDTO dto) {
+		Query query = new Query();
+		query.setCurrent(dto.getCurrent());
+		query.setSize(dto.getSize());
+		IPage<FileAndFolder> page = fileAndFolderService.selectPage(dto.getProjectId(), dto.getStageId(), dto.getIsLatest(), Condition.getPage(query));
+		return R.data(FileAndFolderWrapper.build().pageVO(page));
+	}
+
+	/**
+	 * 文件历史
+	 */
+	@GetMapping("/v2/file-history")
+	@ApiOperationSupport(order = 21)
+	@ApiOperation(value = "文件历史", notes = "传入fileId字段,注意非主键id")
+	public R fileHistory(@RequestParam String fileId, Query query) {
+		IPage<FileAndFolderHistory> page = historyService.getPage(fileId, Condition.getPage(query));
+		return R.data(FileAndFolderHistoryWrapper.build().pageVO(page));
+	}
+
+	/**
+	 * 文件阅读记录
+	 */
+	@GetMapping("/file-read-user")
+	@ApiOperationSupport(order = 22)
+	@ApiOperation(value = "文件阅读人", notes = "传入文件id")
+	public R fileRead(@RequestParam String bladeFileId) {
+		return R.data(fileReadService.fileRead(bladeFileId));
+	}
+
+	/**
+	 * 是否阅读过
+	 */
+	@GetMapping("/is-read")
+	@ApiOperationSupport(order = 23)
+	@ApiOperation(value = "是否阅过文件", notes = "传入文件id")
+	public R isRead(@RequestParam String bladeFileId) {
+		return R.data(fileReadService.isRead(bladeFileId, AuthUtil.getUserId()));
+	}
+
+
+}

+ 140 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/controller/IndexController.java

@@ -0,0 +1,140 @@
+package com.wtkj.controller;
+
+import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
+import com.wtkj.entity.Task;
+import com.wtkj.entity.WorkStatus;
+import com.wtkj.service.IIndexService;
+import com.wtkj.service.IWorkStatusService;
+import com.wtkj.wrapper.IndexTaskScheduleWrapper;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.AllArgsConstructor;
+import org.springblade.core.mp.support.Condition;
+import org.springblade.core.mp.support.Query;
+import org.springblade.core.secure.utils.AuthUtil;
+import org.springblade.core.tool.api.R;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+import static com.wtkj.config.MagicValue.*;
+
+/**
+ * @author Blizzard
+ * @create at 2023-09-15 23:58
+ * @describe
+ */
+@RestController
+@RequestMapping("/index")
+@Api(value = "首页", tags = "首页")
+@AllArgsConstructor
+public class IndexController {
+
+	private final IWorkStatusService workStatus;
+	private final IIndexService indexService;
+
+	/**
+	 * 用户工作状态
+	 */
+	@GetMapping("/work-status")
+	@ApiOperationSupport(order = 1)
+	@ApiOperation(value = "我的状态", notes = "")
+	public R workStatus() {
+		Long userId = AuthUtil.getUserId();
+		return R.data(workStatus.workStatus(userId));
+	}
+
+	/**
+	 * 修改工作状态
+	 */
+	@PostMapping("/submit-work-status")
+	@ApiOperationSupport(order = 2)
+	@ApiOperation(value = "新增或者修改工作状态", notes = "")
+	public R submit(@RequestBody WorkStatus status) {
+		status.setUserId(AuthUtil.getUserId());
+		return R.status(workStatus.saveOrUpdate(status));
+	}
+
+	/**
+	 * 首页统计
+	 */
+	@GetMapping("/project-and-task")
+	@ApiOperationSupport(order = 3)
+	@ApiOperation(value = "项目和任务统计", notes = "")
+	public R projectAndTask(@RequestParam Long topDept) {
+		return R.data(indexService.projectAndTaskSummary(topDept));
+	}
+
+	/**
+	 * 待办事项
+	 */
+	@GetMapping("/todo-list")
+	@ApiOperationSupport(order = 4)
+	@ApiOperation(value = "待办事项", notes = "传入isRead查看状态 0:全部 1:已读 2: 未读 默认未读,分页参数")
+	public R todoList(@RequestParam(defaultValue = "2") Integer isRead, Query query) {
+		return R.data(indexService.todoList(isRead, Condition.getPage(query)));
+	}
+
+	/**
+	 * 学习资料
+	 */
+	@GetMapping("/study-list")
+	@ApiOperationSupport(order = 5)
+	@ApiOperation(value = "学习资料", notes = "")
+	public R noticeList(Query query) {
+		return R.data(indexService.studyList(Condition.getPage(query)));
+	}
+
+	/**
+	 * 阅读消息
+	 */
+	@GetMapping("/message-detail")
+	@ApiOperationSupport(order = 6)
+	@ApiOperation(value = "阅读待办", notes = "传入id")
+	public R messageDetail(@RequestParam Long id) {
+		return R.data(indexService.messageDetail(id));
+	}
+
+	/**
+	 * 工作日程
+	 */
+	@GetMapping("/user-schedule")
+	@ApiOperationSupport(order = 7)
+	@ApiOperation(value = "用户工作日程", notes = "传入登录用户的顶级机构id,日期字符串")
+	public R schedule(@RequestParam Long topDept, String date) {
+		return R.data(indexService.schedule(topDept, date));
+	}
+
+	/**
+	 * 工作日程展开
+	 */
+	@GetMapping("/user-schedule-expand")
+	@ApiOperationSupport(order = 8)
+	@ApiOperation(value = "用户工作日程展开", notes = "传入用户id,日期字符串")
+	public R scheduleExpand(@RequestParam Long userId, String date) {
+		List<Task> taskList = indexService.scheduleExpand(userId, date);
+		return R.data(IndexTaskScheduleWrapper.build().listVO(taskList));
+	}
+
+
+	/**
+	 * 任务分布
+	 */
+	@GetMapping("/task-statistics")
+	@ApiOperationSupport(order = 9)
+	@ApiOperation(value = "任务分布统计", notes = "传入日期")
+	public R taskTaskStatistics(@RequestParam Long topDept, @RequestParam String date) {
+		String userRole = AuthUtil.getUserRole();
+		if (userRole != null) {
+			if (userRole.contains(STAFF_ADMIN)) {
+				return R.data(indexService.mapStatistics(topDept, date));
+			} else if (userRole.contains(STAFF_SECOND_ADMIN)) {
+				return R.data(indexService.myStatistics(date));
+			} else if (userRole.contains(STAFF_USER)) {
+				return R.data(null);
+			}
+		}
+		return R.fail("获取用户角色失败");
+	}
+
+}

+ 184 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/controller/ProjectController.java

@@ -0,0 +1,184 @@
+package com.wtkj.controller;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
+import com.wtkj.dto.ProjectPageDTO;
+import com.wtkj.entity.Project;
+import com.wtkj.entity.ProjectGroup;
+import com.wtkj.entity.ProjectStage;
+import com.wtkj.service.IProjectGroupService;
+import com.wtkj.service.IProjectService;
+import com.wtkj.service.IProjectStageService;
+import com.wtkj.service.ITaskService;
+import com.wtkj.vo.MyTaskStatistics;
+import com.wtkj.vo.ProjectStageVO;
+import com.wtkj.wrapper.ProjectGroupWrapper;
+import com.wtkj.wrapper.ProjectStageWrapper;
+import com.wtkj.wrapper.ProjectWrapper;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.AllArgsConstructor;
+import org.springblade.core.mp.support.Condition;
+import org.springblade.core.mp.support.Query;
+import org.springblade.core.tool.api.R;
+import org.springblade.core.tool.utils.Func;
+import org.springframework.web.bind.annotation.*;
+
+import javax.validation.Valid;
+import java.util.List;
+
+/**
+ * @author Blizzard
+ * @create at 2023-09-13 15:50
+ * @describe
+ */
+@RestController
+@AllArgsConstructor
+@RequestMapping("/project")
+@Api(value = "项目模块", tags = "项目模块")
+public class ProjectController {
+
+	private final IProjectService projectService;
+
+
+	private final IProjectStageService stageService;
+
+	private final ITaskService taskService;
+
+	private final IProjectGroupService projectGroupService;
+
+	/**
+	 * 创建/修改项目
+	 */
+	@PostMapping("/submit")
+	@ApiOperation(value = "新建或者修改项目", notes = "传入project")
+	@ApiOperationSupport(order = 1)
+	public R<Boolean> create(@RequestBody @Valid Project project) {
+		return R.status(projectService.submit(project));
+	}
+
+	/**
+	 * 分页
+	 */
+	@PostMapping("/page")
+	@ApiOperation(value = "分页", notes = "")
+	@ApiOperationSupport(order = 2)
+	public R page(@RequestBody @Valid ProjectPageDTO dto) {
+		Query query = new Query();
+		query.setCurrent(dto.getCurrent());
+		query.setSize(dto.getSize());
+		IPage<Project> page = projectService.getPage(dto, Condition.getPage(query));
+		return R.data(ProjectWrapper.build().pageVO(page));
+	}
+
+	/**
+	 * 删除
+	 */
+	@GetMapping("/delete")
+	@ApiOperation(value = "删除", notes = "传入ids")
+	@ApiOperationSupport(order = 3)
+	public R<Boolean> delete(String ids) {
+		boolean flag = projectService.delete(Func.toLongList(ids));
+		return R.status(flag);
+	}
+
+	/**
+	 * 项目下的所有阶段
+	 */
+	@GetMapping("/stage-list")
+	@ApiOperation(value = "项目下的所有阶段", notes = "传入projectId")
+	@ApiOperationSupport(order = 4)
+	public R<List<ProjectStageVO>> stageList(Long projectId) {
+		List<ProjectStage> projectStages = stageService.listByProjectId(projectId);
+		return R.data(ProjectStageWrapper.build().listVO(projectStages));
+	}
+
+	/**
+	 * 修改阶段
+	 */
+	@PostMapping("/submit-stage")
+	@ApiOperation(value = "修改项目阶段", notes = "")
+	@ApiOperationSupport(order = 5)
+	public R submitStage(@RequestBody ProjectStage stage) {
+		return R.status(stageService.submit(stage));
+	}
+
+	/**
+	 * 阶段详情
+	 */
+	@GetMapping("/stage-detail")
+	@ApiOperation(value = "阶段详情", notes = "传入stageId")
+	@ApiOperationSupport(order = 6)
+	public R stageDetail(@RequestParam Long stageId) {
+		ProjectStage stage = stageService.getById(stageId);
+		return R.data(ProjectStageWrapper.build().entityVO(stage));
+	}
+
+	/**
+	 * 项目列表统计
+	 */
+	@GetMapping("/project-statistics")
+	@ApiOperation(value = "项目列表统计", notes = "")
+	@ApiOperationSupport(order = 6)
+	public R projectStatistics(@RequestParam Long topDept, @RequestParam Integer deptCategory, @RequestParam String year) {
+		return R.data(projectService.projectStatistics(topDept, deptCategory, year));
+	}
+
+	/**
+	 * 项目小组
+	 */
+	@GetMapping("/project-group-mem")
+	@ApiOperation(value = "项目组成员", notes = "传入stageId")
+	@ApiOperationSupport(order = 7)
+	public R groupMem(@RequestParam Long stageId) {
+		List<ProjectGroup> list = projectGroupService.getGroupByStageId(stageId);
+		return R.data(ProjectGroupWrapper.build().listVO(list));
+	}
+
+	@GetMapping("/project-detail")
+	@ApiOperation(value = "项目详情", notes = "")
+	@ApiOperationSupport(order = 8)
+	public R detail(@RequestParam Long projectId) {
+		Project byId = projectService.getById(projectId);
+		return R.data(ProjectWrapper.build().entityVO(byId));
+	}
+
+	/**
+	 * 工作台任务统计
+	 */
+	@GetMapping("/task-summary")
+	@ApiOperation(value = "项目任务统计", notes = "传入stageId")
+	@ApiOperationSupport(order = 9)
+	public R<MyTaskStatistics> taskStatistics(@RequestParam Long stageId) {
+		return R.data(taskService.taskStatistics(stageId, null, null));
+	}
+
+	/**
+	 * 任务分布
+	 */
+	@GetMapping("/task-distribution")
+	@ApiOperation(value = "任务分布", notes = "传入projectId")
+	@ApiOperationSupport(order = 10)
+	public R projectTaskSummary(@RequestParam Long stageId) {
+		return R.data(taskService.projectTaskSummary(stageId));
+	}
+
+	/**
+	 * 任务进展走势
+	 */
+	@GetMapping("/task-situation")
+	@ApiOperation(value = "任务进展走势", notes = "传入projectId")
+	@ApiOperationSupport(order = 11)
+	public R projectTaskSituation(@RequestParam Long stageId) {
+		return R.data(taskService.projectTaskSituation(stageId));
+	}
+
+	@GetMapping("/task-burnout")
+	@ApiOperation(value = "任务燃尽", notes = "传入projectId")
+	@ApiOperationSupport(order = 12)
+	public R projectTaskBurnout(@RequestParam Long stageId) {
+		return R.data(taskService.projectTaskBurnout(stageId));
+	}
+
+
+}

+ 147 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/controller/QrCodeController.java

@@ -0,0 +1,147 @@
+package com.wtkj.controller;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
+import com.wtkj.entity.ApplyJoin;
+import com.wtkj.entity.FileShare;
+import com.wtkj.service.IApplyJoinService;
+import com.wtkj.service.IQrcodeService;
+import com.wtkj.wrapper.ApplyJoinWrapper;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.AllArgsConstructor;
+import org.springblade.core.mp.support.Condition;
+import org.springblade.core.mp.support.Query;
+import org.springblade.core.tool.api.R;
+import org.springframework.web.bind.annotation.*;
+
+import javax.validation.Valid;
+
+/**
+ * @author Blizzard
+ * @create at 2023-09-19 17:25
+ * @describe
+ */
+@RestController
+@AllArgsConstructor
+@RequestMapping("/qrcode")
+@Api(value = "二维码模块", tags = "二维码模块")
+public class QrCodeController {
+
+	private final IQrcodeService qrcodeService;
+	private final IApplyJoinService applyJoinService;
+
+	/**
+	 * 生成二维码
+	 */
+	@GetMapping("/create-dept-qrcode")
+	@ApiOperation(value = "生成邀请用户至机构二维码", notes = "传入部门id")
+	@ApiOperationSupport(order = 1)
+	public R createQrcode(@RequestParam Long deptId) {
+		return R.data(qrcodeService.createDeptQrcode(deptId));
+	}
+
+	/**
+	 * 扫描二维码展现文字内容
+	 */
+	@GetMapping("/scan-invite-to-dept")
+	@ApiOperation(value = "扫描邀请至部门二维码", notes = "")
+	@ApiOperationSupport(order = 2)
+	public R scanInviteToDept(@RequestParam String qrcodeId, @RequestParam Long createUser, @RequestParam Long deptId) {
+		return R.data(qrcodeService.scanInviteToDept(qrcodeId, createUser, deptId));
+	}
+
+	/**
+	 * 邀请至机构下
+	 */
+	@GetMapping("/invite-to-dept")
+	@ApiOperation(value = "接受邀请加入机构", notes = "")
+	@ApiOperationSupport(order = 3)
+	public R inviteToDept(@RequestParam String qrcodeId, @RequestParam Long createUser, @RequestParam Long deptId) {
+		return R.status(qrcodeService.inviteToDept(qrcodeId, createUser, deptId));
+	}
+
+
+	@PostMapping("/apply-to-dept")
+	@ApiOperation(value = "申请加入机构", notes = "")
+	@ApiOperationSupport(order = 4)
+	public R applyToDept(@RequestBody @Valid ApplyJoin join) {
+		return R.status(applyJoinService.saveOrUpdate(join));
+	}
+
+	/**
+	 * 申请列表
+	 */
+	@GetMapping("/apply-page")
+	@ApiOperation(value = "申请列表", notes = "传入当前登录用户顶级机构id")
+	@ApiOperationSupport(order = 5)
+	public R applyPage(@RequestParam Long topDept, Query query) {
+		IPage<ApplyJoin> page = applyJoinService.page(Condition.getPage(query), new LambdaQueryWrapper<ApplyJoin>().eq(ApplyJoin::getDeptId, topDept));
+		return R.data(ApplyJoinWrapper.build().pageVO(page));
+	}
+
+	/**
+	 * 同意加入组织
+	 */
+	@GetMapping("/agree-apply")
+	@ApiOperation(value = "同意加入机构", notes = "传入记录主键id")
+	@ApiOperationSupport(order = 6)
+	public R agreeJoinDept(@RequestParam Long id) {
+		return R.status(applyJoinService.agreeApply(id));
+	}
+
+	/**
+	 * 生成邀请至项目组二维码
+	 */
+	@GetMapping("/create-group-qrcode")
+	@ApiOperation(value = "生成邀请至项目组二维码", notes = "")
+	@ApiOperationSupport(order = 7)
+	public R createGroupQrcode(@RequestParam Long projectId) {
+		return R.data(qrcodeService.createGroupQrcode(projectId));
+	}
+
+	/**
+	 * 扫描邀请至项目组二维码
+	 */
+	@GetMapping("/scan-invite-to-project")
+	@ApiOperation(value = "扫描邀请至项目组二维码", notes = "")
+	@ApiOperationSupport(order = 8)
+	public R scanInviteToProject(@RequestParam String qrcodeId, @RequestParam Long createUser, @RequestParam Long projectId, @RequestParam Long topDept) {
+		return R.data(R.data(qrcodeService.scanInviteToProject(qrcodeId, createUser, projectId, topDept)));
+	}
+
+
+	/**
+	 * 邀请至项目组
+	 */
+	@GetMapping("/invite-to-project")
+	@ApiOperation(value = "接受邀请至项目组", notes = "deptId:服务商的顶级机构id")
+	@ApiOperationSupport(order = 9)
+	public R inviteToProject(@RequestParam String qrcodeId, @RequestParam Long createUser, @RequestParam Long projectId, @RequestParam Long topDept) {
+		return R.status(qrcodeService.inviteToProject(qrcodeId, createUser, projectId, topDept));
+	}
+
+
+	/**
+	 * 生成一条分享记录
+	 */
+	@PostMapping("/save-share")
+	@ApiOperationSupport(order = 10)
+	@ApiOperation(value = "生成文件分享", notes = "ids:文件的")
+	public R saveShare(@RequestBody FileShare share) {
+		return R.data(qrcodeService.savaShare(share));
+	}
+
+	/**
+	 * 查看分享
+	 */
+	@PostMapping("/get-share")
+	@ApiOperationSupport(order = 11)
+	@ApiOperation(value = "查看文件分享", notes = "传入二维码返回ID")
+	public R getShare(@RequestParam Long id) {
+		return R.data(qrcodeService.getShare(id));
+	}
+
+
+}

+ 139 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/controller/ResourceController.java

@@ -0,0 +1,139 @@
+package com.wtkj.controller;
+
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
+import com.wtkj.dto.SearchProjectFileDTO;
+import com.wtkj.dto.UploadInnerFileDTO;
+import com.wtkj.entity.FileAndFolder;
+import com.wtkj.entity.InnerFileAndFolder;
+import com.wtkj.service.ICommonService;
+import com.wtkj.service.IInnerFileAndFolderService;
+import com.wtkj.wrapper.FileAndFolderWrapper;
+import com.wtkj.wrapper.InnerFileAndFolderWrapper;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.AllArgsConstructor;
+import org.springblade.core.log.exception.ServiceException;
+import org.springblade.core.mp.support.Condition;
+import org.springblade.core.mp.support.Query;
+import org.springblade.core.tool.api.R;
+import org.springblade.core.tool.utils.Func;
+import org.springframework.web.bind.annotation.*;
+
+import javax.validation.Valid;
+import java.util.List;
+import java.util.Objects;
+
+import static com.wtkj.config.MagicValue.ONE;
+import static com.wtkj.config.MagicValue.TWO;
+
+/**
+ * @author Blizzard
+ * @create at 2023-09-26 09:24
+ * @describe
+ */
+@RestController
+@AllArgsConstructor
+@RequestMapping("/resource")
+@Api(value = "资料库模块", tags = "资料库模块")
+public class ResourceController {
+
+	private final IInnerFileAndFolderService innerFileAndFolderService;
+
+	private final ICommonService commonService;
+
+	/**
+	 * 内部资料库
+	 */
+	@PostMapping("/submit-inner-folder")
+	@ApiOperation(value = "创建或者修改内部文件夹或者文件", notes = "")
+	@ApiOperationSupport(order = 1)
+	public R submitFolder(@RequestBody @Valid InnerFileAndFolder folder) {
+		LambdaQueryWrapper<InnerFileAndFolder> lqw = new LambdaQueryWrapper<>();
+		lqw.eq(InnerFileAndFolder::getParentId, folder.getParentId());
+		lqw.eq(InnerFileAndFolder::getTitle, folder.getTitle());
+		if (Objects.equals(folder.getType(), ONE)) {
+			lqw.eq(InnerFileAndFolder::getType, ONE);
+			long cnt = innerFileAndFolderService.count(lqw);
+			if (cnt > 0L) {
+				throw new ServiceException("此文件夹下已经存在同名文件");
+			}
+		} else if (Objects.equals(folder.getType(), TWO)) {
+			lqw.eq(InnerFileAndFolder::getType, TWO);
+			long cnt = innerFileAndFolderService.count(lqw);
+			if (cnt > 0L) {
+				throw new ServiceException("此文件夹下已经存在同名文件夹");
+			}
+		}
+		return R.status(innerFileAndFolderService.saveOrUpdate(folder));
+	}
+
+	/**
+	 * 删除文件/文件夹
+	 */
+	@GetMapping("/remove-inner-file")
+	@ApiOperation(value = "删除内部文件或者文件夹", notes = "")
+	@ApiOperationSupport(order = 2)
+	public R remove(@RequestParam String ids) {
+		return R.status(commonService.delete(Func.toLongList(ids)));
+	}
+
+	/**
+	 * 分页
+	 */
+	@GetMapping("/inner-page")
+	@ApiOperation(value = "内部文件夹 分页", notes = "传入parentId,分页参数")
+	@ApiOperationSupport(order = 3)
+	public R innerPage(@RequestParam Long deptId, @RequestParam Long parentId, @RequestParam String name, Query query) {
+		IPage<InnerFileAndFolder> page = innerFileAndFolderService.selectPage(deptId, parentId, name, Condition.getPage(query));
+		return R.data(InnerFileAndFolderWrapper.build().pageVO(page));
+	}
+
+	/**
+	 * 文件数量
+	 */
+	@GetMapping("/file-and-page-amount")
+	@ApiOperationSupport(order = 4)
+	@ApiOperation(value = "文夹下的文件数量", notes = "传入文件夹主键id")
+	public R<JSONObject> getPageAmount(@RequestParam Long deptId, @RequestParam Long parentId) {
+		return R.data(innerFileAndFolderService.getPageAndFileAmount(deptId, parentId));
+	}
+
+	/**
+	 * 上传文件
+	 */
+	@PostMapping("/upload-inner-file")
+	@ApiOperationSupport(order = 5)
+	@ApiOperation(value = "上传内部文件", notes = "传入文件夹主键id")
+	public R uploadInnerFile(@RequestBody @Valid List<UploadInnerFileDTO> files) {
+		return R.status(commonService.uploadInnerFile(files));
+	}
+
+
+	/**
+	 * 项目资料
+	 */
+	@PostMapping("/search-project-file")
+	@ApiOperationSupport(order = 7)
+	@ApiOperation(value = "项目资料", notes = "")
+	public R searchProjectFile(@RequestBody SearchProjectFileDTO dto) {
+		Query query = new Query();
+		query.setSize(dto.getSize());
+		query.setCurrent(dto.getCurrent());
+		IPage<FileAndFolder> page = commonService.esSearch(dto, Condition.getPage(query));
+		return R.data(FileAndFolderWrapper.build().pageVO(page));
+	}
+
+	/**
+	 * 打开文件
+	 */
+	@PostMapping("/open-search-file")
+	@ApiOperationSupport(order = 8)
+	@ApiOperation(value = "打开搜索结果文件", notes = "")
+	public R openSearch(@RequestParam Long projectId, @RequestParam Long fileId, @RequestParam String text) {
+		return R.data(commonService.openSearchFile(projectId, fileId, text));
+	}
+
+}

+ 307 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/controller/TaskController.java

@@ -0,0 +1,307 @@
+package com.wtkj.controller;
+
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
+import com.wtkj.dto.MyTaskPageDTO;
+import com.wtkj.dto.ProjectTaskPageDTO;
+import com.wtkj.entity.*;
+import com.wtkj.service.*;
+import com.wtkj.vo.*;
+import com.wtkj.wrapper.*;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.AllArgsConstructor;
+import org.springblade.core.mp.support.Condition;
+import org.springblade.core.mp.support.Query;
+import org.springblade.core.secure.utils.AuthUtil;
+import org.springblade.core.tool.api.R;
+import org.springblade.core.tool.utils.Func;
+import org.springblade.system.user.entity.User;
+import org.springframework.web.bind.annotation.*;
+
+import javax.validation.Valid;
+import java.time.LocalDate;
+import java.util.List;
+
+/**
+ * @author Blizzard
+ * @create at 2023-09-15 15:20
+ * @describe
+ */
+@RestController
+@AllArgsConstructor
+@RequestMapping("/task")
+@Api(value = "任务模块", tags = "任务模块")
+public class TaskController {
+
+	private final ITaskService taskService;
+
+	private final ITaskLogService taskLogService;
+
+	private final ITaskFileService taskFileService;
+
+	private final ITaskContractService taskContractService;
+
+	private final ITaskCostService taskCostService;
+
+	/**
+	 * 我的任务分页
+	 */
+
+	@PostMapping("/my-task-page")
+	@ApiOperationSupport(order = 1)
+	@ApiOperation(value = "我的任务列表", notes = "")
+	public R<IPage<TaskVO>> myTaskPage(@RequestBody @Valid MyTaskPageDTO dto) {
+		Query query = new Query();
+		query.setCurrent(dto.getCurrent());
+		query.setSize(dto.getSize());
+		IPage<Task> page = taskService.myTaskPage(dto, Condition.getPage(query));
+		return R.data(TaskWrapper.build().pageVO(page));
+	}
+
+	/**
+	 * 我的任务统计
+	 */
+	@GetMapping("/my-task-statistics")
+	@ApiOperationSupport(order = 2)
+	@ApiOperation(value = "我的任务统计", notes = "")
+	public R myTask(@RequestParam Integer year, @RequestParam Integer month) {
+		return R.data(taskService.taskStatistics(null, year, month));
+	}
+
+	/**
+	 * 创建、修改任务
+	 */
+	@PostMapping("/submit")
+	@ApiOperation(value = "创建、修改任务", notes = "")
+	@ApiOperationSupport(order = 3)
+	public R<Boolean> submitTask(@RequestBody @Valid Task task) {
+		return R.status(taskService.submit(task));
+	}
+
+	/**
+	 * 项目任务列表
+	 */
+	@PostMapping("/project-task-page")
+	@ApiOperationSupport(order = 4)
+	@ApiOperation(value = "项目任务列表", notes = "")
+	public R<IPage<TaskVO>> projectTask(@RequestBody @Valid ProjectTaskPageDTO dto) {
+		Query query = new Query();
+		query.setCurrent(dto.getCurrent());
+		query.setSize(dto.getSize());
+		IPage<Task> page = taskService.projectTaskPage(dto, Condition.getPage(query));
+		return R.data(TaskPageWrapper.build().pageVO(page));
+	}
+
+	/**
+	 * 删除任务
+	 */
+	@GetMapping("/delete-project-task")
+	@ApiOperationSupport(order = 5)
+	@ApiOperation(value = "删除项目任务", notes = "传入ids")
+	public R<Boolean> deleteTask(String ids) {
+		return R.status(taskService.removeByIds(Func.toLongList(ids)));
+	}
+
+	/**
+	 * 任务详情
+	 */
+	@GetMapping("/detail")
+	@ApiOperationSupport(order = 6)
+	@ApiOperation(value = "任务详情", notes = "传入任务主键id")
+	public R<TaskVO> detail(@RequestParam Long id) {
+		Task detail = taskService.getById(id);
+		return R.data(TaskWrapper.build().entityVO(detail));
+	}
+
+	/**
+	 * 任务成果文件
+	 */
+	@GetMapping("/result-file")
+	@ApiOperationSupport(order = 7)
+	@ApiOperation(value = "任务成果文件", notes = "传入任务主键id")
+	public R<List<TaskFileVO>> files(@RequestParam Long id) {
+		List<TaskFile> files = taskFileService.fileList(id);
+		return R.data(TaskFileWrapper.build().listVO(files));
+	}
+
+	/**
+	 * 上传成果文件
+	 */
+	@GetMapping("/upload-file")
+	@ApiOperationSupport(order = 8)
+	@ApiOperation(value = "上传成果文件", notes = "传入任务主键id,文件ids")
+	public R saveFile(@RequestParam Long taskId, @RequestParam String ids) {
+		return R.status(taskService.uploadFile(taskId, ids));
+	}
+
+	/**
+	 * 删除附件
+	 */
+	@GetMapping("/delete-file")
+	@ApiOperationSupport(order = 9)
+	@ApiOperation(value = "删除附件", notes = "传入主键ids")
+	public R deleteFile(@RequestParam String ids) {
+		return R.status(taskService.deleteFile(ids));
+	}
+
+	/**
+	 * 移动文件
+	 */
+	@GetMapping("/move-file")
+	@ApiOperationSupport(order = 10)
+	@ApiOperation(value = "移动文件", notes = "")
+	public R moveFile(@RequestParam Long stageId, @RequestParam Long folderId, @RequestParam String fileIds) {
+		return R.status(taskService.moveFile(stageId, folderId, fileIds));
+	}
+
+	/**
+	 * 任务相关动态
+	 */
+	@GetMapping("/task-log")
+	@ApiOperationSupport(order = 11)
+	@ApiOperation(value = "任务相关动态", notes = "传入任务主键id")
+	public R<IPage<TaskLogVO>> taskLog(Long id, Query query) {
+		LambdaQueryWrapper<TaskLog> lqw = new LambdaQueryWrapper<>();
+		lqw.eq(TaskLog::getTaskId, id);
+		lqw.orderByDesc(TaskLog::getCreateTime);
+		IPage<TaskLog> page = taskLogService.page(Condition.getPage(query), lqw);
+		return R.data(TaskLogWrapper.build().pageVO(page));
+	}
+
+	/**
+	 * 任务组成员
+	 */
+	@GetMapping("/task-group-mem")
+	@ApiOperationSupport(order = 12)
+	@ApiOperation(value = "任务组成员", notes = "传入任务主键id")
+	public R<List<User>> taskGroup(@RequestParam Long id) {
+		//todo 任务组成员
+		return R.data(taskLogService.getTaskGroupMen(id));
+	}
+
+	/**
+	 * 添加任务相关合同
+	 */
+	@PostMapping("/submit-task-contract")
+	@ApiOperationSupport(order = 13)
+	@ApiOperation(value = "新增或者修改任务合同", notes = "")
+	public R<Boolean> submitContracts(@RequestBody @Valid TaskContract contract) {
+		if (contract.getId() == null) {
+			int year = LocalDate.now().getYear();
+			contract.setYear(year);
+		}
+		return R.status(taskContractService.saveOrUpdate(contract));
+
+	}
+
+	/**
+	 * 删除任务合同
+	 */
+	@GetMapping("/delete-task-contract")
+	@ApiOperationSupport(order = 14)
+	@ApiOperation(value = "删除任务合同", notes = "传入主键ids")
+	public R<Boolean> deleteContracts(@RequestParam String ids) {
+		return R.status(taskContractService.removeByIds(Func.toLongList(ids)));
+	}
+
+	/**
+	 * 任务合同分页
+	 */
+	@GetMapping("/task-contract-page")
+	@ApiOperationSupport(order = 15)
+	@ApiOperation(value = "任务合同分页", notes = "传入主键taskId,分页参数")
+	public R<IPage<TaskContractVO>> contractPage(@RequestParam Long taskId, Query query) {
+		IPage<TaskContract> page = taskContractService.pageByTaskId(taskId, Condition.getPage(query));
+		return R.data(TaskContractWrapper.build().pageVO(page));
+	}
+
+
+	/**
+	 * 任务成本核算
+	 */
+	@PostMapping("/submit-task-cost")
+	@ApiOperationSupport(order = 16)
+	@ApiOperation(value = "新增或修改任务成本", notes = "")
+	public R<Boolean> submitCost(@RequestBody TaskCost cost) {
+		return R.data(taskCostService.saveOrUpdate(cost));
+	}
+
+	/**
+	 * 任务成本详情
+	 */
+	@GetMapping("/task-cost-detail")
+	@ApiOperationSupport(order = 17)
+	@ApiOperation(value = "成本详情", notes = "")
+	public R<TaskCostVO> costDetail(@RequestParam Long id) {
+		TaskCost detail = taskCostService.getById(id);
+		return R.data(TaskCostWrapper.build().entityVO(detail));
+	}
+
+	/**
+	 * 删除成本记录
+	 */
+	@GetMapping("/delete-task-cost")
+	@ApiOperationSupport(order = 18)
+	@ApiOperation(value = "删除成本记录", notes = "传入主键ids")
+	public R<Boolean> deleteCost(@RequestParam String ids) {
+		return R.status(taskCostService.removeByIds(Func.toLongList(ids)));
+	}
+
+	/**
+	 * 成本分页
+	 */
+	@GetMapping("/task-cost-page")
+	@ApiOperationSupport(order = 19)
+	@ApiOperation(value = "成本分页", notes = "传入taskId,分页参数")
+	public R<IPage<TaskCostVO>> costPage(@RequestParam Long taskId, Query query) {
+		IPage<TaskCost> page = taskCostService.pageByTaskId(taskId, Condition.getPage(query));
+		return R.data(TaskCostWrapper.build().pageVO(page));
+	}
+
+	/**
+	 * 成本统计
+	 */
+	@GetMapping("/task-cost-statistics")
+	@ApiOperationSupport(order = 20)
+	@ApiOperation(value = "任务成本统计", notes = "传入taskId")
+	public R<JSONObject> costStatistics(@RequestParam Long taskId) {
+		return R.data(taskCostService.costStatistics(taskId));
+	}
+
+	/**
+	 * 今日待完成
+	 */
+	@GetMapping("/today-todo-task")
+	@ApiOperationSupport(order = 21)
+	@ApiOperation(value = "登录用户指定日期待完成任务", notes = "")
+	public R<List<Task>> todayTodo(@RequestParam String date) {
+		return R.data(taskService.todayTodo(AuthUtil.getUserId(), date));
+	}
+
+	/**
+	 * 今日逾期
+	 */
+	@GetMapping("/today-expire-task")
+	@ApiOperationSupport(order = 22)
+	@ApiOperation(value = "登录用户指定日期逾期任务", notes = "")
+	public R<List<Task>> todayExpire(@RequestParam String date) {
+		return R.data(taskService.todayExpire(AuthUtil.getUserId(), date));
+	}
+
+
+	/**
+	 * 任务协作单位
+	 */
+	@GetMapping("/task-cops")
+	@ApiOperationSupport(order = 23)
+	@ApiOperation(value = "协作单位列表", notes = "")
+	public R cops(@RequestParam Long projectId) {
+		return R.data(taskService.taskCops(projectId));
+	}
+
+
+}
+

+ 81 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/controller/TypeAndStageController.java

@@ -0,0 +1,81 @@
+package com.wtkj.controller;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
+import com.wtkj.entity.TemplateTypeAndStage;
+import com.wtkj.service.ITypeAndStageService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.AllArgsConstructor;
+import org.springblade.core.mp.support.Condition;
+import org.springblade.core.mp.support.Query;
+import org.springblade.core.tool.api.R;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * @author Jimi Zhang
+ * @create at 2023-09-13 14:14
+ * @describe
+ */
+@RestController
+@AllArgsConstructor
+@RequestMapping("/typeAndStage")
+@Api(value = "项目类和项目阶段模块", tags = "项目类型和项目阶段")
+public class TypeAndStageController {
+
+	private final ITypeAndStageService typeAndStageService;
+
+	/**
+	 * 分页
+	 */
+	@GetMapping("/page")
+	@ApiOperationSupport(order = 1)
+	@ApiOperation(value = "项目类型分页", notes = " ")
+	public R<IPage<TemplateTypeAndStage>> page(Query query) {
+		LambdaQueryWrapper<TemplateTypeAndStage> lqw = Wrappers.lambdaQuery();
+		lqw.eq(TemplateTypeAndStage::getParentId, 0);
+		lqw.orderByDesc(TemplateTypeAndStage::getCreateTime);
+		IPage<TemplateTypeAndStage> page = typeAndStageService.page(Condition.getPage(query), lqw);
+		return R.data(page);
+	}
+
+	/**
+	 * 类型下的阶段
+	 */
+	@GetMapping("/v2/stage-list")
+	@ApiOperationSupport(order = 2)
+	@ApiOperation(value = "阶段列表", notes = "传入parentId")
+	public R<List<TemplateTypeAndStage>> list(@RequestParam(value = "parentId") Long parentId) {
+		List<TemplateTypeAndStage> list = typeAndStageService.list(new LambdaQueryWrapper<TemplateTypeAndStage>().eq(TemplateTypeAndStage::getParentId, parentId)
+			.orderByAsc(TemplateTypeAndStage::getSort));
+		return R.data(list);
+	}
+
+	/**
+	 * 新增或者修改
+	 */
+	@GetMapping("/submit")
+	@ApiOperationSupport(order = 3)
+	@ApiOperation(value = "新增或者修改", notes = "传入typeAndStage")
+	public R submit(@RequestBody TemplateTypeAndStage templateTypeAndStage) {
+		return R.status(typeAndStageService.submit(templateTypeAndStage));
+	}
+
+
+	/**
+	 * 详情
+	 */
+	@ApiOperationSupport(order = 4)
+	@ApiOperation(value = "查看类型或阶段详情", notes = "传入id")
+	@GetMapping("/v2/detail")
+	public R detail(Long id) {
+		TemplateTypeAndStage detail = typeAndStageService.getById(id);
+		return R.data(detail);
+	}
+
+
+}

+ 124 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/handler/EsFileHandler.java

@@ -0,0 +1,124 @@
+package com.wtkj.handler;
+
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.IdWorker;
+import com.wtkj.config.KafkaConstant;
+import com.wtkj.entity.FileAndFolder;
+import com.wtkj.handler.es.Document;
+import com.wtkj.service.IFileAndFolderService;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.kafka.clients.consumer.ConsumerRecord;
+import org.elasticsearch.action.index.IndexRequest;
+import org.elasticsearch.action.search.SearchRequest;
+import org.elasticsearch.action.search.SearchResponse;
+import org.elasticsearch.action.update.UpdateRequest;
+import org.elasticsearch.client.RequestOptions;
+import org.elasticsearch.client.RestHighLevelClient;
+import org.elasticsearch.common.xcontent.XContentType;
+import org.elasticsearch.index.query.BoolQueryBuilder;
+import org.elasticsearch.index.query.QueryBuilders;
+import org.elasticsearch.index.query.TermQueryBuilder;
+import org.elasticsearch.search.SearchHits;
+import org.elasticsearch.search.builder.SearchSourceBuilder;
+import org.springframework.kafka.annotation.KafkaListener;
+import org.springframework.kafka.support.Acknowledgment;
+import org.springframework.stereotype.Component;
+import org.springframework.util.CollectionUtils;
+
+import javax.annotation.Resource;
+import java.util.List;
+
+import static com.wtkj.config.MagicValue.PROJECT_RESOURCE_INDEX;
+
+/**
+ * @author Blizzard
+ * @create at 2023-09-27 11:31
+ * @describe
+ */
+@Slf4j
+@Component
+public class EsFileHandler {
+
+	@Resource
+	private RestHighLevelClient client;
+	@Resource
+	private IFileAndFolderService fileAndFolderService;
+
+
+	/**
+	 * 文件上传转为图片以后通知消息  --->保存至es
+	 */
+	@KafkaListener(groupId = "parse-file-group", topics = KafkaConstant.PARSE_SUCCESS_MESSAGE, containerFactory = "ackContainerFactory")
+	public void handSaveFileToEs(ConsumerRecord record, Acknowledgment ack) {
+		try {
+			String message = (String) record.value();
+			log.info("收到文件解析成功消息,即将处理存入es逻辑:{}", message);
+
+			JSONObject msg = (JSONObject) JSONObject.parse(message);
+			Long fileId = msg.getLong("fileId");
+			String content = msg.getString("content");
+			Integer currentPage = msg.getInteger("currentPage");
+
+			LambdaQueryWrapper<FileAndFolder> lqw = new LambdaQueryWrapper<>();
+			lqw.eq(FileAndFolder::getBladeFileId, fileId);
+			lqw.eq(FileAndFolder::getType, 1);
+			List<FileAndFolder> files = fileAndFolderService.list(lqw);
+			if (!CollectionUtils.isEmpty(files)) {
+				for (FileAndFolder file : files) {
+					Long projectId = file.getProjectId();
+					//使用自定义类作为数据存储容器
+					Document document = new Document();
+					document.setId(IdWorker.getIdStr());
+					document.setContent(content);
+					document.setFileId(fileId);
+					document.setFileName(file.getTitle());
+					document.setCreateUser(file.getCreateUser());
+					document.setCurrentPage(currentPage);
+					document.setProjectId(projectId);
+
+					//存在即更新  不存在即插入
+					SearchRequest request = new SearchRequest();
+					request.indices(PROJECT_RESOURCE_INDEX);
+					SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
+					BoolQueryBuilder boolQuery = QueryBuilders.boolQuery()
+						.must(new TermQueryBuilder("projectId", projectId))
+						.must(new TermQueryBuilder("fileId", fileId))
+						.must(new TermQueryBuilder("currentPage", currentPage));
+					searchSourceBuilder.query(boolQuery);
+					searchSourceBuilder.from(0);
+					searchSourceBuilder.size(1);
+					request.source(searchSourceBuilder);
+					SearchResponse response = client.search(request, RequestOptions.DEFAULT);
+					if (response != null) {
+						SearchHits hits = response.getHits();
+						int size = hits.getHits().length;
+						if (size > 0) {
+							//更新
+							for (int i = 0; i < hits.getHits().length; i++) {
+								String docId = hits.getHits()[i].getId();
+								UpdateRequest updateRequest = new UpdateRequest(PROJECT_RESOURCE_INDEX, docId);
+								updateRequest.doc(JSONObject.toJSONString(document), XContentType.JSON);
+								client.update(updateRequest, RequestOptions.DEFAULT);
+								//log.info("文档更新操作结果:" + updateResponse.toString());
+							}
+						} else {
+							//创建文档
+							IndexRequest indexRequest = new IndexRequest(PROJECT_RESOURCE_INDEX);
+							indexRequest.id(document.getId());
+							indexRequest.timeout("1s");
+							//将数据放入请求,将对象装为json格式
+							indexRequest.source(JSONObject.toJSONString(document), XContentType.JSON);
+							client.index(indexRequest, RequestOptions.DEFAULT);
+							//log.info("文档插入操作结果:" + putResponse.toString());
+						}
+					}
+				}
+			}
+		} catch (Exception e) {
+			log.error("文件存入es异常:" + e.getMessage());
+		} finally {
+			ack.acknowledge();
+		}
+	}
+}

+ 95 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/handler/Schedule.java

@@ -0,0 +1,95 @@
+package com.wtkj.handler;
+
+import com.wtkj.entity.Project;
+import com.wtkj.entity.ProjectStage;
+import com.wtkj.entity.Task;
+import com.wtkj.service.IProjectService;
+import com.wtkj.service.IProjectStageService;
+import com.wtkj.service.ITaskService;
+import lombok.extern.slf4j.Slf4j;
+import org.springblade.core.redis.cache.BladeRedis;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.util.CollectionUtils;
+
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+import java.util.List;
+
+/**
+ * @author Blizzard
+ * @create at 2023-10-05 11:47
+ * @describe 定时任务扫描任务状态
+ */
+@Configuration
+@Slf4j
+public class Schedule {
+
+	@Autowired
+	private ITaskService taskService;
+	@Autowired
+	private IProjectService projectService;
+	@Autowired
+	private IProjectStageService stageService;
+	@Autowired
+	private BladeRedis redis;
+
+
+	@Scheduled(cron = "0 0 3 * * ?")
+	private void task() {
+		DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); // 设置日期格式
+		String now = LocalDate.now().format(formatter);
+		//今天过期的任务
+		List<Task> tasks = taskService.getTodayToExpire(now);
+		if (!CollectionUtils.isEmpty(tasks)) {
+			tasks.forEach(task -> {
+				task.setTaskStatus(6);
+				Long projectId = task.getProjectId();
+				Project byId = projectService.getById(projectId);
+				if (byId != null) {
+					byId.setTodoTask(Math.max(byId.getTodoTask() - 1, 0));
+					projectService.updateById(byId);
+				}
+			});
+			taskService.updateBatchById(tasks);
+		}
+	}
+
+	@Scheduled(cron = "0 0 4 * * ?")
+	private void stageStatusTask() {
+		DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); // 设置日期格式
+		String now = LocalDate.now().format(formatter);
+
+		//1.是否有逾期任务
+		List<Task> tasks = taskService.getByStatus(6);
+		if (!CollectionUtils.isEmpty(tasks)) {
+			int expireSize = tasks.size();
+			tasks.forEach(task -> {
+				Long stageId = task.getStageId();
+				ProjectStage stage = stageService.getById(stageId);
+				if (stage != null) {
+					//有逾期 就为异常
+					stage.setStageStatus(2);
+
+					//失控  --->阶段下任务逾期数量 > 平均每天完成任务量
+					//1.阶段周期
+					List<LocalDate> dateList = redis.get("dateList::" + stageId);
+					if (!CollectionUtils.isEmpty(dateList)) {
+						int size = dateList.size();
+						List<Task> allTask = taskService.listByStageId(stageId);
+						if (!CollectionUtils.isEmpty(allTask)) {
+							int taskAmount = allTask.size();
+							// 理想每天任务完成量
+							float avg = (float) taskAmount / size;
+							if (expireSize > avg) {
+								stage.setStageStatus(3);
+							}
+						}
+					}
+					stageService.updateById(stage);
+				}
+			});
+		}
+	}
+}

+ 33 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/handler/es/Document.java

@@ -0,0 +1,33 @@
+package com.wtkj.handler.es;
+
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * @author Blizzard
+ * @create at 2023-09-27 14:50
+ * @describe
+ */
+@Data
+public class Document implements Serializable {
+
+	private String id;
+
+	@JsonSerialize(using = ToStringSerializer.class)
+	private Long projectId;
+
+	@JsonSerialize(using = ToStringSerializer.class)
+	private Long fileId;
+
+	private String fileName;
+
+	@JsonSerialize(using = ToStringSerializer.class)
+	private Long createUser;
+
+	private String content;
+
+	private Integer currentPage;
+}

+ 12 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/mapper/AnnouncementMapper.java

@@ -0,0 +1,12 @@
+package com.wtkj.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.wtkj.entity.Announcement;
+
+/**
+ * @author Blizzard
+ * @create at 2023-09-23 11:13
+ * @describe
+ */
+public interface AnnouncementMapper extends BaseMapper<Announcement> {
+}

+ 6 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/mapper/AnnouncementMapper.xml

@@ -0,0 +1,6 @@
+<?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.wtkj.mapper.AnnouncementMapper">
+
+
+</mapper>

+ 20 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/mapper/AnnouncementSendMapper.java

@@ -0,0 +1,20 @@
+package com.wtkj.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.wtkj.entity.AnnouncementSend;
+
+import java.util.List;
+
+/**
+ * @author Blizzard
+ * @create at 2023-09-23 11:15
+ * @describe
+ */
+public interface AnnouncementSendMapper extends BaseMapper<AnnouncementSend> {
+	List<AnnouncementSend> selectAnnouncementSendPage(IPage<AnnouncementSend> page, Long userId);
+
+	Integer notReadCount(Long userId);
+
+	List<AnnouncementSend> allNotRead(Long userId);
+}

+ 18 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/mapper/AnnouncementSendMapper.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.wtkj.mapper.AnnouncementSendMapper">
+
+
+    <select id="allNotRead" resultType="com.wtkj.entity.AnnouncementSend">
+        select * from blade_announcement_send where is_deleted = 0 and user_id = #{userId} and read_flag=0
+    </select>
+
+    <select id="notReadCount" resultType="java.lang.Integer">
+        select count(id) from blade_announcement_send where is_deleted = 0 and user_id = #{userId} and read_flag=0
+    </select>
+
+    <select id="selectAnnouncementSendPage" resultType="com.wtkj.entity.AnnouncementSend">
+        select * from blade_announcement_send where is_deleted = 0 and user_id = #{userId} order by
+        read_flag,create_time desc
+    </select>
+</mapper>

+ 12 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/mapper/ApplyJoinMapper.java

@@ -0,0 +1,12 @@
+package com.wtkj.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.wtkj.entity.ApplyJoin;
+
+/**
+ * @author Blizzard
+ * @create at 2023-10-06 10:46
+ * @describe
+ */
+public interface ApplyJoinMapper extends BaseMapper<ApplyJoin> {
+}

+ 6 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/mapper/ApplyJoinMapper.xml

@@ -0,0 +1,6 @@
+<?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.wtkj.mapper.ApplyJoinMapper">
+
+
+</mapper>

+ 22 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/mapper/ContactOuterMapper.java

@@ -0,0 +1,22 @@
+package com.wtkj.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.wtkj.entity.ContactOuter;
+
+import java.util.List;
+
+/**
+ * @author Blizzard
+ * @create at 2023-09-19 11:02
+ * @describe
+ */
+public interface ContactOuterMapper extends BaseMapper<ContactOuter> {
+	List<ContactOuter> pageByTopDept(Long topDept, IPage<ContactOuter> page);
+
+	List<ContactOuter> selectByTopDept(Long topDept);
+
+	List<ContactOuter> getPage(Long userId, IPage<ContactOuter> page);
+
+	List<ContactOuter> getUserPage(Long deptId, Long userId, IPage<ContactOuter> page);
+}

+ 22 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/mapper/ContactOuterMapper.xml

@@ -0,0 +1,22 @@
+<?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.wtkj.mapper.ContactOuterMapper">
+
+
+    <select id="pageByTopDept" resultType="com.wtkj.entity.ContactOuter">
+        select * from blade_contacts_outer where is_deleted = 0 and top_dept = #{param}
+    </select>
+
+    <select id="selectByTopDept" resultType="com.wtkj.entity.ContactOuter">
+        select * from blade_contacts_outer where is_deleted = 0 and top_dept = #{param}
+    </select>
+
+    <select id="getPage" resultType="com.wtkj.entity.ContactOuter">
+        select * from blade_contacts_outer where is_deleted = 0 and user_id = #{param1} group by related_dept_id
+    </select>
+
+    <select id="getUserPage" resultType="com.wtkj.entity.ContactOuter">
+        select * from blade_contacts_outer where is_deleted = 0 and related_dept_id = #{param1} and user_id = #{param2}
+        group by related_user_id
+    </select>
+</mapper>

+ 19 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/mapper/FileAndFolderHistoryMapper.java

@@ -0,0 +1,19 @@
+package com.wtkj.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.wtkj.entity.FileAndFolderHistory;
+
+import java.util.List;
+
+/**
+ * @author Blizzard
+ * @create at 2023-09-14 16:12
+ * @describe
+ */
+public interface FileAndFolderHistoryMapper extends BaseMapper<FileAndFolderHistory> {
+	List<FileAndFolderHistory> selectByLatestId(Long bladeFileId);
+
+
+	List<FileAndFolderHistory> getPage(String fileId, IPage<FileAndFolderHistory> page);
+}

+ 15 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/mapper/FileAndFolderHistoryMapper.xml

@@ -0,0 +1,15 @@
+<?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.wtkj.mapper.FileAndFolderHistoryMapper">
+
+
+    <select id="selectByLatestId" resultType="com.wtkj.entity.FileAndFolderHistory">
+        select * from blade_file_and_folder_history where is_deleted = 0 and latest_id = #{param}
+    </select>
+
+
+    <select id="getPage" resultType="com.wtkj.entity.FileAndFolderHistory">
+        select * from blade_file_and_folder_history where is_deleted = 0 and latest_id = #{param1}
+        order by create_time desc
+    </select>
+</mapper>

+ 30 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/mapper/FileAndFolderMapper.java

@@ -0,0 +1,30 @@
+package com.wtkj.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.wtkj.entity.FileAndFolder;
+
+import java.util.List;
+
+/**
+ * @author Blizzard
+ * @create at 2023-09-14 15:03
+ * @describe
+ */
+public interface FileAndFolderMapper extends BaseMapper<FileAndFolder> {
+	List<FileAndFolder> selectByStage(Long stageId, IPage<FileAndFolder> page);
+
+	Integer getFileAmountByFolderId(Long stageId, Long folderId);
+
+	List<FileAndFolder> getChildrenFolderList(Long stageId, Long folderId);
+
+	List<FileAndFolder> selectByParent(Long parentId, IPage<FileAndFolder> page);
+
+	List<FileAndFolder> getChildrenFileList(Long stageId, Long parentId);
+
+	List<FileAndFolder> getChildren(Long stageId, Long parentId);
+
+	List<FileAndFolder> getPage(String projectId, Long stageId, Integer isLatest, IPage<FileAndFolder> page);
+
+	Integer selectFileAmountByStageId(Long stageId);
+}

+ 69 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/mapper/FileAndFolderMapper.xml

@@ -0,0 +1,69 @@
+<?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.wtkj.mapper.FileAndFolderMapper">
+
+
+    <select id="selectByStage" resultType="com.wtkj.entity.FileAndFolder">
+        select * from blade_file_and_folder where is_deleted = 0 and parent_id = 0 and stage_id = #{param1}
+        order by type desc,create_time desc, is_private
+    </select>
+
+    <select id="getFileAmountByFolderId" resultType="java.lang.Integer">
+        select count(id) from blade_file_and_folder where is_deleted = 0 and type = 1
+        <if test="param1 != null">
+            and stage_id = #{param1}
+        </if>
+        <if test="param2 != null">
+            and parent_id = #{param2}
+        </if>
+    </select>
+
+    <select id="getChildrenFolderList" resultType="com.wtkj.entity.FileAndFolder">
+        select * from blade_file_and_folder where is_deleted = 0 and type = 2
+        <if test="param1 != null">
+            and stage_id = #{param1}
+        </if>
+        <if test="param2 != null">
+            and parent_id = #{param2}
+        </if>
+    </select>
+
+    <select id="selectByParent" resultType="com.wtkj.entity.FileAndFolder">
+        select * from blade_file_and_folder where is_deleted = 0 and parent_id = #{param1}
+        order by type desc, create_time desc,is_private
+    </select>
+
+    <select id="getChildrenFileList" resultType="com.wtkj.entity.FileAndFolder">
+        select * from blade_file_and_folder where is_deleted = 0 and type = 1
+        <if test="param1 != null">
+            and stage_id = #{param1}
+        </if>
+        <if test="param2 != null">
+            and parent_id = #{param2}
+        </if>
+    </select>
+
+    <select id="getChildren" resultType="com.wtkj.entity.FileAndFolder">
+        select * from blade_file_and_folder where is_deleted = 0
+        <if test="param1 != null">
+            and stage_id = #{param1}
+        </if>
+        <if test="param2 != null">
+            and parent_id = #{param2}
+        </if>
+    </select>
+
+    <select id="getPage" resultType="com.wtkj.entity.FileAndFolder">
+        select * from blade_file_and_folder where is_deleted = 0 and type = 1 and project_id = #{param1}
+        <if test="param2 != null">
+            and stage_id = #{param2}
+        </if>
+        <if test="param3 != null ">
+            and DATE(create_time) >=DATE_SUB(CURDATE(), INTERVAL 15 DAY)
+        </if>
+        order by create_time desc
+    </select>
+    <select id="selectFileAmountByStageId" resultType="java.lang.Integer">
+        select count(id) from blade_file_and_folder where is_deleted = 0 and type = 1 and stage_id = #{param}
+    </select>
+</mapper>

+ 17 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/mapper/FileReadMapper.java

@@ -0,0 +1,17 @@
+package com.wtkj.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.wtkj.entity.FileRead;
+
+import java.util.List;
+
+/**
+ * @author Blizzard
+ * @create at 2023-09-15 11:13
+ * @describe
+ */
+public interface FileReadMapper extends BaseMapper<FileRead> {
+	List<Long> getReadUser(String fileId);
+
+	List<FileRead> selectByFileIds(Long userId);
+}

+ 12 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/mapper/FileReadMapper.xml

@@ -0,0 +1,12 @@
+<?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.wtkj.mapper.FileReadMapper">
+
+    <select id="getReadUser" resultType="java.lang.Long">
+        select user_id from blade_file_read where is_deleted = 0 and blade_file_id = #{param}
+    </select>
+
+    <select id="selectByFileIds" resultType="com.wtkj.entity.FileRead">
+        select * from blade_file_read where is_deleted = 0 and user_id = #{param}
+    </select>
+</mapper>

+ 12 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/mapper/FileShareMapper.java

@@ -0,0 +1,12 @@
+package com.wtkj.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.wtkj.entity.FileShare;
+
+/**
+ * @author Blizzard
+ * @create at 2023-09-26 15:17
+ * @describe
+ */
+public interface FileShareMapper extends BaseMapper<FileShare> {
+}

+ 6 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/mapper/FileShareMapper.xml

@@ -0,0 +1,6 @@
+<?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.wtkj.mapper.FileShareMapper">
+
+
+</mapper>

+ 12 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/mapper/IndexMessageMapper.java

@@ -0,0 +1,12 @@
+package com.wtkj.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.wtkj.entity.IndexMessage;
+
+/**
+ * @author Blizzard
+ * @create at 2023-08-21 15:24
+ * @describe
+ */
+public interface IndexMessageMapper extends BaseMapper<IndexMessage> {
+}

+ 6 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/mapper/IndexMessageMapper.xml

@@ -0,0 +1,6 @@
+<?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.wtkj.mapper.IndexMessageMapper">
+
+
+</mapper>

+ 24 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/mapper/InnerFileAndFolderMapper.java

@@ -0,0 +1,24 @@
+package com.wtkj.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.wtkj.entity.InnerFileAndFolder;
+
+import java.util.List;
+
+/**
+ * @author Blizzard
+ * @create at 2023-09-26 14:41
+ * @describe
+ */
+public interface InnerFileAndFolderMapper extends BaseMapper<InnerFileAndFolder> {
+	List<InnerFileAndFolder> getChildren(Long parentId);
+
+	List<InnerFileAndFolder> getChildrenFolderList(Long deptId, Long parentId);
+
+	List<InnerFileAndFolder> getPage(Long deptId, Long parentId, String name, IPage<InnerFileAndFolder> page);
+
+	int getFileAmountByFolderId(Long deptId, Long parentId);
+
+	List<InnerFileAndFolder> getChildrenFileList(Long deptId, Long parentId);
+}

+ 53 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/mapper/InnerFileAndFolderMapper.xml

@@ -0,0 +1,53 @@
+<?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.wtkj.mapper.InnerFileAndFolderMapper">
+
+
+    <select id="getChildren" resultType="com.wtkj.entity.InnerFileAndFolder">
+        select * from blade_inner_file_and_folder where is_deleted = 0
+        <if test="param != null">
+            and parent_id = #{param}
+        </if>
+    </select>
+
+    <select id="getChildrenFolderList" resultType="com.wtkj.entity.InnerFileAndFolder">
+        select * from blade_inner_file_and_folder where is_deleted = 0 and type = 2
+        <if test="param1 != null">
+            and dept_id = #{param1}
+        </if>
+        <if test="param2 != null">
+            and parent_id = #{param2}
+        </if>
+    </select>
+    <select id="getPage" resultType="com.wtkj.entity.InnerFileAndFolder">
+        select * from blade_inner_file_and_folder where is_deleted = 0
+        <if test="param1 != null">
+            and dept_id = #{param1}
+        </if>
+        <if test="param2 != null">
+            and parent_id = #{param2}
+        </if>
+        <if test="param3 != null and param3 != ''">
+            and title like concat(concat('%',#{param3}),'%')
+        </if>
+    </select>
+
+    <select id="getFileAmountByFolderId" resultType="java.lang.Integer">
+        select count(id) from blade_inner_file_and_folder where is_deleted = 0 and type = 1
+        <if test="param1 != null">
+            and dept_id = #{param1}
+        </if>
+        <if test="param2 != null">
+            and parent_id = #{param2}
+        </if>
+    </select>
+    <select id="getChildrenFileList" resultType="com.wtkj.entity.InnerFileAndFolder">
+        select * from blade_inner_file_and_folder where is_deleted = 0 and type = 1
+        <if test="param1 != null">
+            and dept_id = #{param1}
+        </if>
+        <if test="param2 != null">
+            and parent_id = #{param2}
+        </if>
+    </select>
+</mapper>

+ 18 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/mapper/ProjectAuthMapper.java

@@ -0,0 +1,18 @@
+package com.wtkj.mapper;
+
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.wtkj.entity.ProjectAuth;
+
+import java.util.List;
+
+/**
+ * @author Blizzard
+ * @create at 2023-09-13 17:35
+ * @describe
+ */
+public interface ProjectAuthMapper extends BaseMapper<ProjectAuth> {
+	List<ProjectAuth> selectByDeptAndUser(Long topDept, Long deptId, Long userId);
+
+	List<ProjectAuth> selectByUser(Long userId);
+}

+ 25 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/mapper/ProjectAuthMapper.xml

@@ -0,0 +1,25 @@
+<?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.wtkj.mapper.ProjectAuthMapper">
+
+
+    <select id="selectByDeptAndUser" resultType="com.wtkj.entity.ProjectAuth">
+        select * from blade_project_auth where is_deleted = 0
+        <if test="param1 != null">
+            and top_dept = #{param1}
+        </if>
+        <if test="param2 != null">
+            and user_dept = #{param2}
+        </if>
+        <if test="param3 != null">
+            and user_id = #{param3}
+        </if>
+    </select>
+
+    <select id="selectByUser" resultType="com.wtkj.entity.ProjectAuth">
+        select * from blade_project_auth where is_deleted = 0
+        <if test="param != null">
+            and user_id = #{param}
+        </if>
+    </select>
+</mapper>

+ 17 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/mapper/ProjectGroupMapper.java

@@ -0,0 +1,17 @@
+package com.wtkj.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.wtkj.entity.ProjectGroup;
+
+import java.util.List;
+
+/**
+ * @author Blizzard
+ * @create at 2023-09-19 21:29
+ * @describe
+ */
+public interface ProjectGroupMapper extends BaseMapper<ProjectGroup> {
+	List<ProjectGroup> selectGroupByStageId(Long stageId);
+
+	List<ProjectGroup> selectUserByBeInvitedDept(Long projectId, Long beInvitedDept);
+}

+ 14 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/mapper/ProjectGroupMapper.xml

@@ -0,0 +1,14 @@
+<?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.wtkj.mapper.ProjectGroupMapper">
+
+
+    <select id="selectGroupByStageId" resultType="com.wtkj.entity.ProjectGroup">
+        select * from blade_project_group where is_deleted = 0 and stage_id = #{param}
+    </select>
+
+    <select id="selectUserByBeInvitedDept" resultType="com.wtkj.entity.ProjectGroup">
+        select * from blade_project_group where is_deleted = 0 and project_id = #{param1} and (invite_dept = #{param2}
+        or be_invited_dept = #{param2})
+    </select>
+</mapper>

+ 12 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/mapper/ProjectMapper.java

@@ -0,0 +1,12 @@
+package com.wtkj.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.wtkj.entity.Project;
+
+/**
+ * @author Blizzard
+ * @create at 2023-09-13 16:01
+ * @describe
+ */
+public interface ProjectMapper extends BaseMapper<Project> {
+}

+ 6 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/mapper/ProjectMapper.xml

@@ -0,0 +1,6 @@
+<?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.wtkj.mapper.ProjectMapper">
+
+
+</mapper>

+ 16 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/mapper/ProjectStageMapper.java

@@ -0,0 +1,16 @@
+package com.wtkj.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.wtkj.entity.ProjectStage;
+
+import java.util.List;
+
+/**
+ * @author Blizzard
+ * @create at 2023-09-13 16:46
+ * @describe
+ */
+public interface ProjectStageMapper extends BaseMapper<ProjectStage> {
+	List<ProjectStage> selectByProjectId(Long projectId);
+
+}

+ 9 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/mapper/ProjectStageMapper.xml

@@ -0,0 +1,9 @@
+<?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.wtkj.mapper.ProjectStageMapper">
+
+
+    <select id="selectByProjectId" resultType="com.wtkj.entity.ProjectStage">
+        select * from blade_project_stage where is_deleted = 0 and project_id = #{param}
+    </select>
+</mapper>

+ 21 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/mapper/TaskContractMapper.java

@@ -0,0 +1,21 @@
+package com.wtkj.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.wtkj.entity.TaskContract;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author Blizzard
+ * @create at 2023-09-18 09:50
+ * @describe
+ */
+public interface TaskContractMapper extends BaseMapper<TaskContract> {
+	List<TaskContract> selectByTaskId(Long taskId, IPage<TaskContract> page);
+
+	List<TaskContract> getByProjectIds(Set<Long> projectIds);
+
+	List<TaskContract> getByOrgDeptId(Long topDept, Integer year, Set<Long> taskIds);
+}

+ 32 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/mapper/TaskContractMapper.xml

@@ -0,0 +1,32 @@
+<?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.wtkj.mapper.TaskContractMapper">
+
+    <select id="selectByTaskId" resultType="com.wtkj.entity.TaskContract">
+        select * from blade_task_contract where is_deleted = 0 and task_id = #{param1} order by create_time desc;
+    </select>
+
+    <select id="getByProjectIds" resultType="com.wtkj.entity.TaskContract">
+        select * from blade_task_contract where is_deleted = 0 and project_id in
+        <foreach collection="param" index="index" item="item" open="(" separator="," close=")">
+            #{item}
+        </foreach>
+    </select>
+
+    <select id="getByOrgDeptId" resultType="com.wtkj.entity.TaskContract">
+        select * from blade_task_contract where is_deleted = 0
+        <if test="param1 != null">
+            and org_dept_id = #{param1}
+        </if>
+        <if test="param2 != null">
+            and year = #{param2}
+        </if>
+        <if test="param3 != null">
+            and task_id in
+            <foreach collection="param3" index="index" item="item" open="(" separator="," close=")">
+                #{item}
+            </foreach>
+        </if>
+        order by create_time desc;
+    </select>
+</mapper>

+ 18 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/mapper/TaskCostMapper.java

@@ -0,0 +1,18 @@
+package com.wtkj.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.wtkj.entity.TaskCost;
+
+import java.util.List;
+
+/**
+ * @author Blizzard
+ * @create at 2023-09-18 14:13
+ * @describe
+ */
+public interface TaskCostMapper extends BaseMapper<TaskCost> {
+	List<TaskCost> selectByTaskId(Long taskId, IPage<TaskCost> page);
+
+	List<TaskCost> listByTaskId(Long taskId);
+}

+ 12 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/mapper/TaskCostMapper.xml

@@ -0,0 +1,12 @@
+<?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.wtkj.mapper.TaskCostMapper">
+
+    <select id="selectByTaskId" resultType="com.wtkj.entity.TaskCost">
+        select * from blade_task_cost where is_deleted = 0 and task_id = #{param1}
+    </select>
+
+    <select id="listByTaskId" resultType="com.wtkj.entity.TaskCost">
+        select * from blade_task_cost where is_deleted = 0 and task_id = #{param}
+    </select>
+</mapper>

+ 14 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/mapper/TaskFileMapper.java

@@ -0,0 +1,14 @@
+package com.wtkj.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.wtkj.entity.TaskFile;
+
+/**
+ * @author Blizzard
+ * @create at 2023-09-15 21:17
+ * @describe
+ */
+public interface TaskFileMapper extends BaseMapper<TaskFile> {
+	TaskFile getByBladeFileId(Long taskId, Long bladeFileId);
+
+}

+ 9 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/mapper/TaskFileMapper.xml

@@ -0,0 +1,9 @@
+<?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.wtkj.mapper.TaskFileMapper">
+
+    <select id="getByBladeFileId" resultType="com.wtkj.entity.TaskFile">
+        select * from blade_task_file where is_deleted = 0 and task_id = #{param1} and blade_file_id = #{param2}
+
+    </select>
+</mapper>

+ 15 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/mapper/TaskLogMapper.java

@@ -0,0 +1,15 @@
+package com.wtkj.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.wtkj.entity.TaskLog;
+
+import java.util.List;
+
+/**
+ * @author Blizzard
+ * @create at 2023-09-15 15:54
+ * @describe
+ */
+public interface TaskLogMapper extends BaseMapper<TaskLog> {
+	List<TaskLog> listByTaskId(Long taskId);
+}

+ 8 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/mapper/TaskLogMapper.xml

@@ -0,0 +1,8 @@
+<?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.wtkj.mapper.TaskLogMapper">
+
+    <select id="listByTaskId" resultType="com.wtkj.entity.TaskLog">
+        select * from blade_task_log where is_deleted = 0 and task_id =#{param}
+    </select>
+</mapper>

+ 44 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/mapper/TaskMapper.java

@@ -0,0 +1,44 @@
+package com.wtkj.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.wtkj.entity.Task;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author Blizzard
+ * @create at 2023-09-15 15:17
+ * @describe
+ */
+public interface TaskMapper extends BaseMapper<Task> {
+	List<Task> selectByExecute(Long deptId, String userId);
+
+	List<Task> todayTo(String userId, String date);
+
+	List<Task> todayExpire(String userId, String date);
+
+	List<Task> getTodoAndExpireByUserId(String userId, String date);
+
+	List<Task> getByDeptAndDate(Long topDept, Long executeDept, String user, String date);
+
+	List<Task> getByExecuteDept(Long deptId);
+
+	List<Task> selectByCompetentUnit(Long deptId);
+
+	List<Task> getTodayTodoByOrgDeptId(Long topDept, String date);
+
+	List<Task> getTodoByYear(Set<Long> projectIds, Integer year);
+
+	List<Task> selectLeftByDateAndStage(Long stageId, String date);
+
+	List<Task> selectByDateAndStageAndStatus(Long stageId, String formatDate, Integer taskStatus);
+
+	List<Task> selectCurrentDateCompleteByStageAndDate(Long stageId, String formatDate, Integer taskStatus);
+
+	List<Task> getTodayToExpire(String date);
+
+	List<Task> selectByTaskStatus(Integer status);
+
+	List<Task> getByProjectId(Long projectId);
+}

+ 112 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/mapper/TaskMapper.xml

@@ -0,0 +1,112 @@
+<?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.wtkj.mapper.TaskMapper">
+
+    <select id="selectByExecute" resultType="com.wtkj.entity.Task">
+        select * from blade_task where is_deleted = 0
+        <if test="param1 != null">
+            and org_dept_id = #{param1}
+        </if>
+        <if test="param2 != null">
+            and execute_user like concat(concat('%',#{param2}),'%')
+        </if>
+    </select>
+
+
+    <select id="todayTo" resultType="com.wtkj.entity.Task">
+        select * from blade_task where is_deleted = 0 and execute_user like concat(concat('%',#{param1}),'%')
+        and
+        DATE_FORMAT(end_time,'%Y-%m-%d') = DATE_FORMAT(#{param2},'%Y-%m-%d') and task_status != 4 and task_status != 5
+        order by create_time
+    </select>
+
+    <select id="todayExpire" resultType="com.wtkj.entity.Task">
+        select * from blade_task where is_deleted = 0 and execute_user like concat(concat('%',#{param1}),'%')
+        and
+        DATE_FORMAT(#{param2},'%Y-%m-%d') > DATE_FORMAT(end_time,'%Y-%m-%d') and task_status != 4 and task_status != 5
+        order by create_time
+    </select>
+
+    <select id="getTodoAndExpireByUserId" resultType="com.wtkj.entity.Task">
+        select * from blade_task where is_deleted = 0 and execute_user like concat(concat('%',#{param1}),'%')
+        and
+        DATE_FORMAT(#{param2},'%Y-%m-%d') >= DATE_FORMAT(end_time,'%Y-%m-%d') and task_status != 4 and task_status != 5
+        order by create_time
+    </select>
+
+    <select id="getByDeptAndDate" resultType="com.wtkj.entity.Task">
+        select * from blade_task where is_deleted = 0
+        <if test="param1 != null">
+            and org_dept_id = #{param1}
+        </if>
+        <if test="param2 != null">
+            and execute_dept = #{param2}
+        </if>
+        <if test="param3 != null">
+            and execute_user like concat(concat('%',#{param3}),'%')
+        </if>
+        <if test="param4 != null">
+            and DATE_FORMAT(#{param4},'%Y-%m-%d') >= DATE_FORMAT(end_time,'%Y-%m-%d') and task_status != 4 and
+            task_status != 5
+        </if>
+        order by create_time
+    </select>
+
+    <select id="getByExecuteDept" resultType="com.wtkj.entity.Task">
+        select * from blade_task where is_deleted = 0 and execute_dept = #{param}
+        order by create_time
+    </select>
+
+    <select id="selectByCompetentUnit" resultType="com.wtkj.entity.Task">
+        select * from blade_task where is_deleted = 0 and competent_unit = #{param}
+        order by create_time
+    </select>
+
+    <select id="getTodayTodoByOrgDeptId" resultType="com.wtkj.entity.Task">
+        select * from blade_task where is_deleted = 0 and org_dept_id = #{param1} and
+        DATE_FORMAT(#{param2},'%Y-%m-%d') = DATE_FORMAT(end_time,'%Y-%m-%d') and task_status != 4 and task_status != 5
+        order by create_time
+    </select>
+
+    <select id="getTodoByYear" resultType="com.wtkj.entity.Task">
+        select * from blade_task where is_deleted = 0 and year = #{param2} and task_status != 4 and task_status != 5 and
+        task_status != 6 and
+        project_id in
+        <foreach collection="param1" index="index" item="item" open="(" separator="," close=")">
+            #{item}
+        </foreach>
+    </select>
+
+    <select id="selectLeftByDateAndStage" resultType="com.wtkj.entity.Task">
+        select * from blade_task where is_deleted = 0 and stage_id = #{param1} and
+        DATE_FORMAT(#{param2},'%Y-%m-%d') = DATE_FORMAT(end_time,'%Y-%m-%d') and task_status != 4 and task_status != 5
+    </select>
+
+    <select id="selectByDateAndStageAndStatus" resultType="com.wtkj.entity.Task">
+        select * from blade_task where is_deleted = 0 and stage_id = #{param1} and
+        DATE_FORMAT(#{param2},'%Y-%m-%d') = DATE_FORMAT(end_time,'%Y-%m-%d') and task_status = #{param3}
+    </select>
+
+    <select id="selectCurrentDateCompleteByStageAndDate" resultType="com.wtkj.entity.Task">
+        select * from blade_task where is_deleted = 0 and stage_id = #{param1} and
+        DATE_FORMAT(#{param2},'%Y-%m-%d') = DATE_FORMAT(confirm_time,'%Y-%m-%d')
+        <if test="param3 != null">
+            and task_status = #{param3}
+        </if>
+    </select>
+
+    <select id="getTodayToExpire" resultType="com.wtkj.entity.Task">
+        select * from blade_task where is_deleted = 0 and
+        DATE_FORMAT(#{param},'%Y-%m-%d') > DATE_FORMAT(end_time,'%Y-%m-%d') and task_status != 4 and task_status != 5
+        and task_status != 6
+    </select>
+
+    <select id="selectByTaskStatus" resultType="com.wtkj.entity.Task">
+        select * from blade_task where is_deleted = 0 and task_status = #{param}
+    </select>
+
+    <select id="getByProjectId" resultType="com.wtkj.entity.Task">
+        select * from blade_task where is_deleted = 0 and project_id = #{param}
+    </select>
+
+</mapper>

+ 16 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/mapper/TypeStageMapper.java

@@ -0,0 +1,16 @@
+package com.wtkj.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.wtkj.entity.TemplateTypeAndStage;
+
+import java.util.List;
+
+/**
+ * @author Jimi Zhang
+ * @create at 2022-12-12 12:00
+ * @describe
+ */
+public interface TypeStageMapper extends BaseMapper<TemplateTypeAndStage> {
+
+	List<TemplateTypeAndStage> selectStages(Long projectType);
+}

+ 12 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/mapper/TypeStageMapper.xml

@@ -0,0 +1,12 @@
+<?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.wtkj.mapper.TypeStageMapper">
+
+    <select id="selectStages" resultType="com.wtkj.entity.TemplateTypeAndStage">
+        select * from blade_template_type_and_stage where is_deleted = 0
+        <if test="param1 != null">
+            and parent_id = #{param1}
+        </if>
+    </select>
+
+</mapper>

+ 12 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/mapper/WorkStatusMapper.java

@@ -0,0 +1,12 @@
+package com.wtkj.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.wtkj.entity.WorkStatus;
+
+/**
+ * @author Blizzard
+ * @create at 2023-09-15 23:50
+ * @describe
+ */
+public interface WorkStatusMapper extends BaseMapper<WorkStatus> {
+}

+ 5 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/mapper/WorkStatusMapper.xml

@@ -0,0 +1,5 @@
+<?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.wtkj.mapper.WorkStatusMapper">
+
+</mapper>

+ 38 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/service/IAnnouncementSendService.java

@@ -0,0 +1,38 @@
+package com.wtkj.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.wtkj.entity.AnnouncementSend;
+import org.springblade.core.mp.base.BaseService;
+
+/**
+ * @author Blizzard
+ * @create at 2023-09-23 11:22
+ * @describe
+ */
+public interface IAnnouncementSendService extends BaseService<AnnouncementSend> {
+	IPage<AnnouncementSend> selectAnnouncementSendPage(IPage<AnnouncementSend> page, Long userId);
+
+	/**
+	 * 获取用户未读数量
+	 *
+	 * @param userId
+	 * @return
+	 */
+	Integer notReadCount(Long userId);
+
+	/**
+	 * 用户阅读状态修改
+	 *
+	 * @param id
+	 * @return
+	 */
+	Boolean updateReadFlag(Long id);
+
+	/**
+	 * 一键全部消息已读
+	 *
+	 * @param userId
+	 * @return
+	 */
+	Boolean allRead(Long userId);
+}

+ 12 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/service/IAnnouncementService.java

@@ -0,0 +1,12 @@
+package com.wtkj.service;
+
+import com.wtkj.entity.Announcement;
+import org.springblade.core.mp.base.BaseService;
+
+/**
+ * @author Blizzard
+ * @create at 2023-09-23 11:20
+ * @describe
+ */
+public interface IAnnouncementService extends BaseService<Announcement> {
+}

+ 13 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/service/IApplyJoinService.java

@@ -0,0 +1,13 @@
+package com.wtkj.service;
+
+import com.wtkj.entity.ApplyJoin;
+import org.springblade.core.mp.base.BaseService;
+
+/**
+ * @author Blizzard
+ * @create at 2023-10-06 10:47
+ * @describe
+ */
+public interface IApplyJoinService extends BaseService<ApplyJoin> {
+	boolean agreeApply(Long id);
+}

+ 40 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/service/IAsyncService.java

@@ -0,0 +1,40 @@
+package com.wtkj.service;
+
+import com.wtkj.entity.Project;
+import com.wtkj.entity.Task;
+import org.springblade.core.secure.BladeUser;
+
+/**
+ * @author Blizzard
+ * @create at 2023-09-13 16:32
+ * @describe
+ */
+public interface IAsyncService {
+
+	/**
+	 * 异步创建项目 阶段 项目权限等处理
+	 */
+	void createProject(Project project, BladeUser user);
+
+	void createTask(Task task);
+
+
+	//指定执行单位日志
+	// type: 1 指定执行单位 2.指定任务执行部门  3.指定项目经理 4.执行任务执行者 5.指定任务审查者 6.提交任务 7.审查任务 8.二次审查 8.确认 10.取消
+	void alterTask(Task afterUpdate, Task beforeUpdate, Long userId);
+
+	//第一次审查通知
+	void firstCheck(Long userId, Task task);
+
+	//二次审查通知
+	void secondCheck(Long userId, Task task);
+
+	//下达任务通知
+	void dispatchTask(Long userId, Task task);
+
+	//通知主管
+	void dispatchToDept(Long userId, Task task);
+
+	//通知机构管理员
+	void dispatchToOrg(Long userId, Task task);
+}

+ 38 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/service/ICommonService.java

@@ -0,0 +1,38 @@
+package com.wtkj.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.wtkj.dto.SearchProjectFileDTO;
+import com.wtkj.dto.UploadFileDTO;
+import com.wtkj.dto.UploadInnerFileDTO;
+import com.wtkj.entity.FileAndFolder;
+import com.wtkj.vo.AuthUserInfo;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author Blizzard
+ * @create at 2023-09-14 16:07
+ * @describe 公共service 避免本类调用事务失效的问题
+ */
+public interface ICommonService {
+
+	boolean uploadFile(List<UploadFileDTO> files);
+
+	boolean coverFile(List<UploadFileDTO> files);
+
+	boolean remove(List<Long> ids);
+
+	boolean move(String ids, Long stageId, Long parentId);
+
+	boolean delete(List<Long> ids);
+
+	boolean uploadInnerFile(List<UploadInnerFileDTO> files);
+
+	IPage<FileAndFolder> esSearch(SearchProjectFileDTO dto, IPage<FileAndFolder> page);
+
+	Set<Integer> openSearchFile(Long projectId, Long fileId, String text);
+
+	AuthUserInfo userInfo();
+
+}

+ 21 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/service/IContactOuterService.java

@@ -0,0 +1,21 @@
+package com.wtkj.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.wtkj.dto.UpdateUserDTO;
+import com.wtkj.entity.ContactOuter;
+import org.springblade.core.mp.base.BaseService;
+
+/**
+ * @author Blizzard
+ * @create at 2023-09-19 11:01
+ * @describe
+ */
+public interface IContactOuterService extends BaseService<ContactOuter> {
+
+	IPage<ContactOuter> selectPage(Long userId, IPage<ContactOuter> page);
+
+	IPage<ContactOuter> contactPage(Long deptId, Long userId, IPage<ContactOuter> page);
+
+	boolean updateUser(UpdateUserDTO dto);
+}
+

+ 19 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/service/IFileAndFolderHistoryService.java

@@ -0,0 +1,19 @@
+package com.wtkj.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.wtkj.entity.FileAndFolderHistory;
+import org.springblade.core.mp.base.BaseService;
+
+import java.util.List;
+
+/**
+ * @author Blizzard
+ * @create at 2023-09-14 16:13
+ * @describe
+ */
+public interface IFileAndFolderHistoryService extends BaseService<FileAndFolderHistory> {
+	List<FileAndFolderHistory> getByLatestId(Long bladeFileId);
+
+
+	IPage<FileAndFolderHistory> getPage(String fileId, IPage<FileAndFolderHistory> page);
+}

+ 39 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/service/IFileAndFolderService.java

@@ -0,0 +1,39 @@
+package com.wtkj.service;
+
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.wtkj.dto.UploadFileDTO;
+import com.wtkj.entity.FileAndFolder;
+import org.springblade.core.mp.base.BaseService;
+
+import java.util.List;
+
+/**
+ * @author Blizzard
+ * @create at 2023-09-14 15:04
+ * @describe
+ */
+public interface IFileAndFolderService extends BaseService<FileAndFolder> {
+	boolean isExistSameName(List<UploadFileDTO> files);
+
+	IPage<FileAndFolder> pageByStageId(Long stageId, IPage<FileAndFolder> page);
+
+	/**
+	 * 文件夹下的文件数量
+	 */
+	Integer getFileAmountByFolderId(Long stageId, Long parentId);
+
+	IPage<FileAndFolder> pageByParentId(Long parentId, IPage<FileAndFolder> page);
+
+	JSONObject getPageAndFileAmount(Long stageId, Long parentId);
+
+	List<FileAndFolder> getChildrenFilesByFolderId(Long stageId, Long parentId);
+
+	List<FileAndFolder> getChildrenFolderByFolderId(Long stageId, Long parentId);
+
+	List<FileAndFolder> getChildren(Long stageId, Long parentId);
+
+	IPage<FileAndFolder> selectPage(String projectId, Long stageId, Integer isLatest, IPage<FileAndFolder> page);
+
+	Integer getFileAmountByStageId(Long stageId);
+}

+ 22 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/service/IFileReadService.java

@@ -0,0 +1,22 @@
+package com.wtkj.service;
+
+import com.wtkj.entity.FileRead;
+import org.springblade.core.mp.base.BaseService;
+import org.springblade.system.user.entity.User;
+
+import java.util.List;
+
+/**
+ * @author Blizzard
+ * @create at 2023-09-15 11:14
+ * @describe
+ */
+public interface IFileReadService extends BaseService<FileRead> {
+	boolean readFile(FileRead read);
+
+	List<FileRead> getByUser(Long userId);
+
+	List<User> fileRead(String bladeFileId);
+
+	boolean isRead(String bladeFileId, Long userId);
+}

+ 12 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/service/IFileShareService.java

@@ -0,0 +1,12 @@
+package com.wtkj.service;
+
+import com.wtkj.entity.FileShare;
+import org.springblade.core.mp.base.BaseService;
+
+/**
+ * @author Blizzard
+ * @create at 2023-09-26 15:18
+ * @describe
+ */
+public interface IFileShareService extends BaseService<FileShare> {
+}

+ 12 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/service/IIndexMessageService.java

@@ -0,0 +1,12 @@
+package com.wtkj.service;
+
+import com.wtkj.entity.IndexMessage;
+import org.springblade.core.mp.base.BaseService;
+
+/**
+ * @author Blizzard
+ * @create at 2023-09-15 22:13
+ * @describe
+ */
+public interface IIndexMessageService extends BaseService<IndexMessage> {
+}

+ 35 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/service/IIndexService.java

@@ -0,0 +1,35 @@
+package com.wtkj.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.wtkj.entity.IndexMessage;
+import com.wtkj.entity.Task;
+import com.wtkj.vo.IndexProjectAndTaskSummaryVO;
+import com.wtkj.vo.MyIndexTaskStatistics;
+import com.wtkj.vo.ScheduleUserVO;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author Blizzard
+ * @create at 2023-09-20 14:51
+ * @describe
+ */
+public interface IIndexService {
+	IndexProjectAndTaskSummaryVO projectAndTaskSummary(Long topDept);
+
+
+	IPage<IndexMessage> todoList(Integer isRead, IPage<IndexMessage> page);
+
+	Object studyList(IPage<Object> page);
+
+	IndexMessage messageDetail(Long id);
+
+	List<ScheduleUserVO> schedule(Long topDept, String date);
+
+	List<Task> scheduleExpand(Long userId, String date);
+
+	List<Map<String, Integer>> mapStatistics(Long topDept, String date);
+
+	MyIndexTaskStatistics myStatistics(String date);
+}

+ 30 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/service/IInnerFileAndFolderService.java

@@ -0,0 +1,30 @@
+package com.wtkj.service;
+
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.wtkj.entity.InnerFileAndFolder;
+import org.springblade.core.mp.base.BaseService;
+
+import java.util.List;
+
+/**
+ * @author Blizzard
+ * @create at 2023-09-26 14:43
+ * @describe
+ */
+public interface IInnerFileAndFolderService extends BaseService<InnerFileAndFolder> {
+
+
+	List<InnerFileAndFolder> getChildren(Long deptId, Long parentId);
+
+	IPage<InnerFileAndFolder> selectPage(Long deptId, Long parentId, String name, IPage<InnerFileAndFolder> page);
+
+	JSONObject getPageAndFileAmount(Long deptId, Long parentId);
+
+	Integer getFileAmountByFolderId(Long deptId, Long parentId);
+
+	List<InnerFileAndFolder> getChildrenFilesByFolderId(Long deptId, Long parentId);
+
+	List<InnerFileAndFolder> getChildrenFolderByFolderId(Long deptId, Long parentId);
+
+}

+ 17 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/service/IProjectAuthService.java

@@ -0,0 +1,17 @@
+package com.wtkj.service;
+
+import com.wtkj.entity.ProjectAuth;
+import org.springblade.core.mp.base.BaseService;
+
+import java.util.List;
+
+/**
+ * @author Blizzard
+ * @create at 2023-09-13 17:37
+ * @describe
+ */
+public interface IProjectAuthService extends BaseService<ProjectAuth> {
+	List<ProjectAuth> getByDeptAndUser(Long topDept, Long deptId, Long userId);
+
+	List<ProjectAuth> getByUserId(Long userId);
+}

+ 17 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/service/IProjectGroupService.java

@@ -0,0 +1,17 @@
+package com.wtkj.service;
+
+import com.wtkj.entity.ProjectGroup;
+import org.springblade.core.mp.base.BaseService;
+
+import java.util.List;
+
+/**
+ * @author Blizzard
+ * @create at 2023-09-19 21:30
+ * @describe
+ */
+public interface IProjectGroupService extends BaseService<ProjectGroup> {
+	List<ProjectGroup> getGroupByStageId(Long stageId);
+
+	List<ProjectGroup> getUserByBeInvitedDept(Long projectId, Long beInvitedDept);
+}

+ 26 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/service/IProjectService.java

@@ -0,0 +1,26 @@
+package com.wtkj.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.wtkj.dto.ProjectPageDTO;
+import com.wtkj.entity.Project;
+import com.wtkj.vo.ProjectStatisticsVO;
+import org.springblade.core.mp.base.BaseService;
+
+import java.util.List;
+
+/**
+ * @author Blizzard
+ * @create at 2023-09-13 16:00
+ * @describe
+ */
+public interface IProjectService extends BaseService<Project> {
+	boolean submit(Project project);
+
+	IPage<Project> getPage(ProjectPageDTO dto, IPage<Project> page);
+
+
+	ProjectStatisticsVO projectStatistics(Long topDept, Integer deptCategory, String year);
+
+	boolean delete(List<Long> projectIds);
+
+}

+ 17 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/service/IProjectStageService.java

@@ -0,0 +1,17 @@
+package com.wtkj.service;
+
+import com.wtkj.entity.ProjectStage;
+import org.springblade.core.mp.base.BaseService;
+
+import java.util.List;
+
+/**
+ * @author Blizzard
+ * @create at 2023-09-13 16:49
+ * @describe
+ */
+public interface IProjectStageService extends BaseService<ProjectStage> {
+	List<ProjectStage> listByProjectId(Long projectId);
+
+	boolean submit(ProjectStage stage);
+}

+ 33 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/service/IQrcodeService.java

@@ -0,0 +1,33 @@
+package com.wtkj.service;
+
+import com.alibaba.fastjson.JSONObject;
+import com.wtkj.entity.FileShare;
+import com.wutong.file.entity.FileAttach;
+
+import java.util.List;
+
+/**
+ * @author Blizzard
+ * @create at 2023-09-19 17:35
+ * @describe
+ */
+public interface IQrcodeService {
+
+
+	JSONObject createDeptQrcode(Long deptId);
+
+	boolean inviteToDept(String qrcodeId, Long createUser, Long deptId);
+
+	JSONObject scanInviteToDept(String qrcodeId, Long createUser, Long deptId);
+
+	boolean inviteToProject(String qrcodeId, Long createUser, Long projectId, Long topDept);
+
+	JSONObject scanInviteToProject(String qrcodeId, Long createUser, Long projectId, Long topDept);
+
+	JSONObject createGroupQrcode(Long projectId);
+
+	Long savaShare(FileShare share);
+
+	List<FileAttach> getShare(Long id);
+
+}

+ 22 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/service/ITaskContractService.java

@@ -0,0 +1,22 @@
+package com.wtkj.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.wtkj.entity.TaskContract;
+import org.springblade.core.mp.base.BaseService;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author Blizzard
+ * @create at 2023-09-18 09:52
+ * @describe
+ */
+public interface ITaskContractService extends BaseService<TaskContract> {
+	IPage<TaskContract> pageByTaskId(Long taskId, IPage<TaskContract> page);
+
+	List<TaskContract> getByProjectIds(Set<Long> projectIds);
+
+	List<TaskContract> getByDeptIdAndYear(Long topDept, Integer year, Set<Long> taskIds);
+
+}

+ 21 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/service/ITaskCostService.java

@@ -0,0 +1,21 @@
+package com.wtkj.service;
+
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.wtkj.entity.TaskCost;
+import org.springblade.core.mp.base.BaseService;
+
+import java.util.List;
+
+/**
+ * @author Blizzard
+ * @create at 2023-09-18 14:15
+ * @describe
+ */
+public interface ITaskCostService extends BaseService<TaskCost> {
+	IPage<TaskCost> pageByTaskId(Long taskId, IPage<TaskCost> page);
+
+	List<TaskCost> listByTaskId(Long taskId);
+
+	JSONObject costStatistics(Long taskId);
+}

+ 17 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/service/ITaskFileService.java

@@ -0,0 +1,17 @@
+package com.wtkj.service;
+
+import com.wtkj.entity.TaskFile;
+import org.springblade.core.mp.base.BaseService;
+
+import java.util.List;
+
+/**
+ * @author Blizzard
+ * @create at 2023-09-15 21:22
+ * @describe
+ */
+public interface ITaskFileService extends BaseService<TaskFile> {
+	List<TaskFile> fileList(Long id);
+
+	TaskFile getByBladeFileId(Long taskId, Long bladeFileId);
+}

+ 18 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/service/ITaskLogService.java

@@ -0,0 +1,18 @@
+package com.wtkj.service;
+
+import com.wtkj.entity.TaskLog;
+import org.springblade.core.mp.base.BaseService;
+import org.springblade.system.user.entity.User;
+
+import java.util.List;
+
+/**
+ * @author Blizzard
+ * @create at 2023-09-15 15:55
+ * @describe
+ */
+public interface ITaskLogService extends BaseService<TaskLog> {
+	List<TaskLog> listByTaskId(Long taskId);
+
+	List<User> getTaskGroupMen(Long id);
+}

+ 104 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/service/ITaskService.java

@@ -0,0 +1,104 @@
+package com.wtkj.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.wtkj.dto.MyTaskPageDTO;
+import com.wtkj.dto.ProjectTaskPageDTO;
+import com.wtkj.entity.LineChartDataSet;
+import com.wtkj.entity.Task;
+import com.wtkj.util.Workload;
+import com.wtkj.vo.MyTaskStatistics;
+import org.springblade.core.mp.base.BaseService;
+import org.springblade.system.entity.Dept;
+
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author Blizzard
+ * @create at 2023-09-15 15:18
+ * @describe
+ */
+public interface ITaskService extends BaseService<Task> {
+	boolean submit(Task task);
+
+	IPage<Task> projectTaskPage(ProjectTaskPageDTO dto, IPage<Task> page);
+
+	boolean uploadFile(Long taskId, String ids);
+
+	boolean moveFile(Long stageId, Long folderId, String fileIds);
+
+	boolean deleteFile(String ids);
+
+	IPage<Task> myTaskPage(MyTaskPageDTO dto, IPage<Task> page);
+
+	/**
+	 * 复用  复用
+	 */
+	MyTaskStatistics taskStatistics(Long stageId, Integer year, Integer month);
+
+
+	List<Task> listByUser(Long userId, Integer year, Integer month);
+
+
+	List<Task> listByStageId(Long stageId);
+
+	List<Task> getByExecute(Long deptId, String userId);
+
+	/**
+	 * 用户当日待完成任务
+	 */
+	List<Task> todayTodo(Long userId, String date);
+
+	/**
+	 * 用户当日逾期任务
+	 */
+	List<Task> todayExpire(Long userId, String date);
+
+	/**
+	 * 机构下当日待完成的任务和逾期任务列表
+	 */
+	List<Task> getByDeptAndDate(Long topDept, Long executeDept, String user, String date);
+
+	/**
+	 * 用户当日待完成和逾期的任务
+	 */
+	List<Task> getTodoAndExpireByUserId(Long userId, String date);
+
+	/**
+	 * 机构下当日待完成的任务
+	 */
+	List<Task> getTodayTodoByOrgDeptId(Long topDept, String date);
+
+	List<Task> getTodoByYear(Set<Long> projectIds, String year);
+
+	/**
+	 * 项目任务饼图
+	 */
+	List<Map<String, String>> projectTaskSummary(Long stageId);
+
+	/**
+	 * 项目和项目执行人
+	 */
+	List<Task> listByUserAndProject(Long userId, Long stageId);
+
+	LineChartDataSet projectTaskSituation(Long stageId);
+
+	LineChartDataSet projectTaskBurnout(Long stageId);
+
+	List<Task> getTodayToExpire(String date);
+
+	List<Workload> exportList(String startDate, String endDate);
+
+	void export(List<Workload> list, HttpServletResponse response) throws IOException;
+
+	List<Task> getByExecuteDept(Long deptId);
+
+	List<Task> getByCompetentUnit(Long deptId);
+
+	List<Task> getByStatus(Integer status);
+
+	List<Dept> taskCops(Long projectId);
+}

+ 19 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/service/ITypeAndStageService.java

@@ -0,0 +1,19 @@
+package com.wtkj.service;
+
+import com.wtkj.entity.TemplateTypeAndStage;
+import org.springblade.core.mp.base.BaseService;
+
+import java.util.List;
+
+/**
+ * @author Jimi Zhang
+ * @create at 2022-12-12 14:05
+ * @describe
+ */
+public interface ITypeAndStageService extends BaseService<TemplateTypeAndStage> {
+
+
+	boolean submit(TemplateTypeAndStage templateTypeAndStage);
+
+	List<TemplateTypeAndStage> getStages(Long projectType);
+}

+ 14 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/service/IWorkStatusService.java

@@ -0,0 +1,14 @@
+package com.wtkj.service;
+
+import com.wtkj.entity.WorkStatus;
+import com.wtkj.vo.WorkStatusVO;
+import org.springblade.core.mp.base.BaseService;
+
+/**
+ * @author Blizzard
+ * @create at 2023-09-15 23:52
+ * @describe
+ */
+public interface IWorkStatusService extends BaseService<WorkStatus> {
+	WorkStatusVO workStatus(Long userId);
+}

+ 60 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/service/impl/AnnouncementSendServiceImpl.java

@@ -0,0 +1,60 @@
+package com.wtkj.service.impl;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.wtkj.entity.AnnouncementSend;
+import com.wtkj.mapper.AnnouncementSendMapper;
+import com.wtkj.service.IAnnouncementSendService;
+import lombok.AllArgsConstructor;
+import org.springblade.core.mp.base.BaseServiceImpl;
+import org.springblade.core.tool.utils.DateUtil;
+import org.springblade.core.tool.utils.ObjectUtil;
+import org.springframework.stereotype.Service;
+import org.springframework.util.CollectionUtils;
+
+import java.util.List;
+
+/**
+ * @author Blizzard
+ * @create at 2023-09-23 11:22
+ * @describe
+ */
+@Service
+@AllArgsConstructor
+public class AnnouncementSendServiceImpl extends BaseServiceImpl<AnnouncementSendMapper, AnnouncementSend> implements IAnnouncementSendService {
+	@Override
+	public IPage<AnnouncementSend> selectAnnouncementSendPage(IPage<AnnouncementSend> page, Long userId) {
+		return page.setRecords(baseMapper.selectAnnouncementSendPage(page, userId));
+	}
+
+	@Override
+	public Integer notReadCount(Long userId) {
+		return baseMapper.notReadCount(userId);
+	}
+
+	@Override
+	public Boolean updateReadFlag(Long id) {
+		boolean flag = false;
+		AnnouncementSend announcementSend = this.getById(id);
+		if (ObjectUtil.isNotEmpty(announcementSend)) {
+			if (announcementSend.getReadFlag() == 0) {//还未阅读
+				announcementSend.setReadFlag(1);
+				announcementSend.setReadTime(DateUtil.now());
+				flag = this.updateById(announcementSend);
+			}
+		}
+		return flag;
+	}
+
+	@Override
+	public Boolean allRead(Long userId) {
+		boolean flag = false;
+		List<AnnouncementSend> list = baseMapper.allNotRead(userId);
+		if (!CollectionUtils.isEmpty(list)) {
+			list.forEach(e -> e.setReadFlag(1));
+			flag = this.updateBatchById(list);
+		}
+		return flag;
+	}
+
+
+}

+ 18 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/service/impl/AnnouncementServiceImpl.java

@@ -0,0 +1,18 @@
+package com.wtkj.service.impl;
+
+import com.wtkj.entity.Announcement;
+import com.wtkj.mapper.AnnouncementMapper;
+import com.wtkj.service.IAnnouncementService;
+import lombok.AllArgsConstructor;
+import org.springblade.core.mp.base.BaseServiceImpl;
+import org.springframework.stereotype.Service;
+
+/**
+ * @author Blizzard
+ * @create at 2023-09-23 11:21
+ * @describe
+ */
+@Service
+@AllArgsConstructor
+public class AnnouncementServiceImpl extends BaseServiceImpl<AnnouncementMapper, Announcement> implements IAnnouncementService {
+}

+ 37 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/service/impl/ApplyJoinServiceImpl.java

@@ -0,0 +1,37 @@
+package com.wtkj.service.impl;
+
+import com.wtkj.entity.ApplyJoin;
+import com.wtkj.mapper.ApplyJoinMapper;
+import com.wtkj.service.IApplyJoinService;
+import io.seata.spring.annotation.GlobalTransactional;
+import lombok.AllArgsConstructor;
+import org.springblade.core.mp.base.BaseServiceImpl;
+import org.springblade.system.user.feign.IUserClient;
+import org.springframework.stereotype.Service;
+
+/**
+ * @author Blizzard
+ * @create at 2023-10-06 10:48
+ * @describe
+ */
+@Service
+@AllArgsConstructor
+public class ApplyJoinServiceImpl extends BaseServiceImpl<ApplyJoinMapper, ApplyJoin> implements IApplyJoinService {
+
+	private final IUserClient userClient;
+
+	@Override
+	@GlobalTransactional(rollbackFor = Exception.class)
+	public boolean agreeApply(Long id) {
+		boolean flag = false;
+		ApplyJoin byId = this.getById(id);
+		if (byId != null) {
+			Long userId = byId.getUserId();
+			Long deptId = byId.getDeptId();
+			userClient.bindUser(userId, deptId);
+			byId.setIsAgree(1);
+			flag = this.updateById(byId);
+		}
+		return flag;
+	}
+}

+ 978 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/service/impl/AsyncServiceImpl.java

@@ -0,0 +1,978 @@
+package com.wtkj.service.impl;
+
+import com.baomidou.mybatisplus.core.toolkit.IdWorker;
+import com.tencentcloudapi.common.Credential;
+import com.tencentcloudapi.common.profile.ClientProfile;
+import com.tencentcloudapi.common.profile.HttpProfile;
+import com.tencentcloudapi.sms.v20190711.SmsClient;
+import com.tencentcloudapi.sms.v20190711.models.SendSmsRequest;
+import com.tencentcloudapi.sms.v20190711.models.SendSmsResponse;
+import com.wtkj.config.NacosConfigValue;
+import com.wtkj.entity.*;
+import com.wtkj.mapper.ProjectMapper;
+import com.wtkj.service.*;
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springblade.core.secure.BladeUser;
+import org.springblade.core.tool.api.R;
+import org.springblade.core.tool.utils.CollectionUtil;
+import org.springblade.core.tool.utils.DateUtil;
+import org.springblade.core.tool.utils.Func;
+import org.springblade.core.tool.utils.StringUtil;
+import org.springblade.system.entity.Dept;
+import org.springblade.system.entity.Role;
+import org.springblade.system.feign.ISysClient;
+import org.springblade.system.user.entity.User;
+import org.springblade.system.user.feign.IUserClient;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.stereotype.Service;
+import org.springframework.util.CollectionUtils;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import static com.wtkj.config.MagicValue.ZERO;
+
+/**
+ * @author Blizzard
+ * @create at 2023-09-13 16:32
+ * @describe
+ */
+@Service
+@AllArgsConstructor
+@Slf4j
+public class AsyncServiceImpl implements IAsyncService {
+
+	private final ITypeAndStageService typeAndStageService;
+	private final IProjectStageService stageService;
+	private final IProjectAuthService projectAuthService;
+	private final ISysClient sysClient;
+	private final IUserClient userClient;
+	private final ITaskLogService taskLogService;
+	private final IProjectGroupService projectGroupService;
+	private final ProjectMapper projectMapper;
+	private final IIndexMessageService indexMessageService;
+
+	@Override
+	@Async("asyncPoolTaskExecutor")
+	public void createProject(Project project, BladeUser user) {
+		//1.项目类型  --> 使用类型对应的模版阶段创建项目阶段
+		Long projectType = project.getProjectType();
+		List<TemplateTypeAndStage> templateStage = typeAndStageService.getStages(projectType);
+		//2.创建项目阶段
+		if (!CollectionUtils.isEmpty(templateStage)) {
+			List<ProjectStage> stagesList = new ArrayList<>();
+			templateStage.forEach(template -> {
+				//项目的阶段记录表
+				Long id = IdWorker.getId();
+				ProjectStage stage = new ProjectStage();
+				stage.setId(id);
+				stage.setProjectId(project.getId());
+				stage.setName(template.getName());
+				stage.setSort(template.getSort());
+				stage.setCreateUser(project.getCreateUser());
+				stage.setCreateDept(project.getCreateDept());
+				stage.setCreateTime(DateUtil.now());
+				stage.setUpdateTime(DateUtil.now());
+				stage.setUpdateUser(project.getUpdateUser());
+				//添加默认阶段
+				if (template.getSort() == 1) {
+					project.setCurrentStage(id);
+					projectMapper.updateById(project);
+				}
+				stagesList.add(stage);
+			});
+			if (!CollectionUtils.isEmpty(stagesList)) {
+				stageService.saveBatch(stagesList);
+			}
+		}
+
+	}
+
+
+	@Override
+	@Async("asyncPoolTaskExecutor")
+	public void createTask(Task task) {
+		Long projectId = task.getProjectId();
+		Project project = projectMapper.selectById(projectId);
+		if (project != null) {
+			//修改项目下任务数量
+			project.setTodoTask(project.getTodoTask() + 1);
+			projectMapper.updateById(project);
+
+			//1.任务日志
+			Long createUser = task.getCreateUser();
+			Long projectManager = task.getProjectManager();
+			Long firstCheckUser = task.getFirstCheckUser();
+			Long secondCheckUser = task.getSecondCheckUser();
+			String executeUser = task.getExecuteUser();
+
+			List<ProjectAuth> auths = new ArrayList<>();
+			List<ProjectGroup> groups = new ArrayList<>();
+
+			List<Long> userIds = new ArrayList<>();
+			userIds.add(createUser);
+			if (projectManager != null) {
+				userIds.add(projectManager);
+			}
+			if (firstCheckUser != null) {
+				userIds.add(firstCheckUser);
+			}
+			if (secondCheckUser != null) {
+				userIds.add(secondCheckUser);
+			}
+			if (StringUtil.isNotBlank(executeUser)) {
+				userIds.addAll(Func.toLongList(executeUser));
+			}
+
+			if (createUser != null) {
+				R<User> userR = userClient.userInfoById(createUser);
+				if (userR.isSuccess()) {
+
+					TaskLog log = new TaskLog();
+					log.setId(IdWorker.getId());
+					log.setTaskId(task.getId());
+					log.setContent(userR.getData().getName() + " 创建了任务");
+					log.setRelatedUser(String.valueOf(userR.getData().getId()));
+					log.setCreateDept(task.getCreateDept());
+					log.setCreateUser(task.getCreateUser());
+					log.setUpdateUser(task.getUpdateUser());
+					Date time = DateUtil.now();
+					log.setCreateTime(time);
+					log.setUpdateTime(time);
+					taskLogService.save(log);
+
+					Long orgDeptId = null;
+					if (task.getOrgDeptId() != null && task.getOrgDeptId() > 0L) {
+						orgDeptId = task.getOrgDeptId();
+						R<Dept> dept = sysClient.getDept(orgDeptId);
+						if (dept.isSuccess()) {
+							//日志
+							TaskLog taskLog = new TaskLog();
+							taskLog.setId(IdWorker.getId());
+							taskLog.setTaskId(task.getId());
+							taskLog.setContent(userR.getData().getName() + " 指定了执行单位为" + dept.getData().getDeptName());
+							taskLog.setRelatedUser(Func.join(userIds));
+							taskLog.setCreateDept(task.getCreateDept());
+							taskLog.setCreateUser(task.getCreateUser());
+							taskLog.setUpdateUser(task.getUpdateUser());
+							taskLog.setCreateTime(DateUtil.now());
+							taskLog.setUpdateTime(DateUtil.now());
+							taskLogService.save(taskLog);
+
+							//项目权限
+							ProjectAuth auth = new ProjectAuth();
+							auth.setTopDept(orgDeptId);
+							auth.setProjectId(task.getProjectId());
+							auth.setCreateDept(task.getCreateDept());
+							auth.setCreateUser(task.getCreateUser());
+							auth.setUpdateUser(task.getUpdateUser());
+							auth.setCreateTime(DateUtil.now());
+							auth.setUpdateTime(DateUtil.now());
+							projectAuthService.save(auth);
+
+							//把创建任务的人加入项目组
+							Long deptId = null;
+							String deptStr = userR.getData().getDeptId();
+							R<Dept> rpc = sysClient.getDept(Long.valueOf(deptStr));
+							if (rpc.isSuccess()) {
+								String ancestors = rpc.getData().getAncestors();
+								// ancestors 0,1689540492698267649
+								if (ancestors != null && ancestors.contains(String.valueOf(ZERO))) {
+									List<Long> longList = Func.toLongList(ancestors);
+									if (!CollectionUtils.isEmpty(longList)) {
+										if (longList.size() > 1) {
+											deptId = longList.get(1);
+										} else {
+											deptId = Long.valueOf(deptStr);
+										}
+									}
+								}
+							}
+							ProjectGroup group = new ProjectGroup();
+							group.setStageId(task.getStageId());
+							group.setProjectId(projectId);
+							group.setBeInvitedDept(deptId);
+							group.setUserId(createUser);
+							groups.add(group);
+						}
+
+						// 项目创建人、项目经理 、任务审查人、执行人
+						userIds.remove(createUser);
+						Long finalOrgDeptId = orgDeptId;
+						if (!CollectionUtils.isEmpty(userIds)) {
+							userIds.forEach(userId -> {
+								R<User> rpc = userClient.userInfoById(userId);
+								if (rpc.isSuccess()) {
+									//项目权限
+									ProjectAuth auth = new ProjectAuth();
+									auth.setTopDept(finalOrgDeptId);
+									auth.setProjectId(task.getProjectId());
+									auth.setUserId(userId);
+									auth.setUserDept(Long.valueOf(rpc.getData().getDeptId()));
+									auth.setCreateDept(task.getCreateDept());
+									auth.setCreateUser(task.getCreateUser());
+									auth.setUpdateUser(task.getUpdateUser());
+									auth.setCreateTime(DateUtil.now());
+									auth.setUpdateTime(DateUtil.now());
+									auths.add(auth);
+
+									//项目组
+									ProjectGroup group = new ProjectGroup();
+									group.setUserId(userId);
+									group.setBeInvitedDept(finalOrgDeptId);
+									group.setStageId(task.getStageId());
+									group.setProjectId(task.getProjectId());
+									groups.add(group);
+								}
+							});
+						}
+					}
+					if (!CollectionUtils.isEmpty(auths)) {
+						projectAuthService.saveBatch(auths);
+					}
+					if (!CollectionUtils.isEmpty(groups)) {
+						projectGroupService.saveBatch(groups);
+					}
+				}
+			}
+		}
+	}
+
+	@Override
+	@Async("asyncPoolTaskExecutor")
+	public void alterTask(Task afterUpdate, Task beforeUpdate, Long userId) {
+		R<User> userR = userClient.userInfoById(userId);
+		if (userR.isSuccess()) {
+			List<ProjectAuth> auths = new ArrayList<>();
+			List<ProjectGroup> groups = new ArrayList<>();
+
+			Long orgDeptId = afterUpdate.getOrgDeptId();
+
+			Integer newStatus = afterUpdate.getTaskStatus();
+			Integer oldStatus = beforeUpdate.getTaskStatus();
+
+			Long projectId = afterUpdate.getProjectId();
+
+			//1.指定了执行单位
+			if ((beforeUpdate.getOrgDeptId() == null || beforeUpdate.getOrgDeptId() < 0L) && afterUpdate.getOrgDeptId() != null && afterUpdate.getOrgDeptId() > 0L) {
+				R<Dept> dept = sysClient.getDept(orgDeptId);
+				if (dept.isSuccess()) {
+					TaskLog log = new TaskLog();
+					log.setTaskId(afterUpdate.getId());
+					log.setContent(userR.getData().getName() + " 指定了执行单位为" + dept.getData().getDeptName());
+					log.setRelatedUser(String.valueOf(userR.getData().getId()));
+					log.setCreateDept(afterUpdate.getCreateDept());
+					log.setCreateUser(afterUpdate.getCreateUser());
+					log.setUpdateUser(afterUpdate.getUpdateUser());
+					log.setCreateTime(DateUtil.now());
+					log.setUpdateTime(DateUtil.now());
+					taskLogService.save(log);
+
+					ProjectAuth auth = new ProjectAuth();
+					auth.setTopDept(orgDeptId);
+					auth.setProjectId(afterUpdate.getProjectId());
+					auths.add(auth);
+				}
+			}
+
+			//2.指定任务执行部门
+			if ((beforeUpdate.getExecuteDept() == null || beforeUpdate.getExecuteDept() < 0L) && afterUpdate.getExecuteDept() != null && afterUpdate.getExecuteDept() > 0L) {
+				Long executeDept = afterUpdate.getExecuteDept();
+				R<Dept> dept1 = sysClient.getDept(executeDept);
+				if (dept1.isSuccess()) {
+					TaskLog log1 = new TaskLog();
+					log1.setTaskId(afterUpdate.getId());
+					log1.setContent(userR.getData().getName() + " 指定了任务执行部门为" + dept1.getData().getDeptName());
+					log1.setRelatedUser(String.valueOf(userR.getData().getId()));
+					log1.setCreateUser(userId);
+					log1.setUpdateUser(userId);
+					log1.setCreateTime(DateUtil.now());
+					log1.setUpdateTime(DateUtil.now());
+					taskLogService.save(log1);
+
+					ProjectAuth auth = new ProjectAuth();
+					auth.setTopDept(orgDeptId);
+					auth.setUserDept(executeDept);
+					auth.setProjectId(afterUpdate.getProjectId());
+					auths.add(auth);
+				}
+			}
+
+			//3.指定项目经理
+			if ((beforeUpdate.getProjectManager() == null || beforeUpdate.getProjectManager() < 0L) && afterUpdate.getProjectManager() != null && afterUpdate.getProjectManager() > 0L) {
+				Long projectManager = afterUpdate.getProjectManager();
+				R<User> userR1 = userClient.userInfoById(projectManager);
+				if (userR1.isSuccess()) {
+					TaskLog log2 = new TaskLog();
+					log2.setTaskId(afterUpdate.getId());
+					log2.setContent(userR.getData().getName() + " 指定了项目经理为 " + userR1.getData().getName());
+					List<Long> users = new ArrayList<>();
+					users.add(userR.getData().getId());
+					users.add(userR1.getData().getId());
+					log2.setRelatedUser(Func.join(users));
+					log2.setCreateUser(userId);
+					log2.setUpdateUser(userId);
+					log2.setCreateTime(DateUtil.now());
+					log2.setUpdateTime(DateUtil.now());
+					taskLogService.save(log2);
+
+					String deptStr = userR1.getData().getDeptId();
+					if (StringUtil.isNotBlank(deptStr) && orgDeptId != null) {
+						//项目权限
+						Long deptId = Func.firstLong(deptStr);
+						ProjectAuth auth = new ProjectAuth();
+						auth.setTopDept(orgDeptId);
+						auth.setUserDept(deptId);
+						auth.setProjectId(afterUpdate.getProjectId());
+						auth.setUserId(projectManager);
+						auths.add(auth);
+
+						//项目组
+						ProjectGroup group = new ProjectGroup();
+						group.setInviteDept(null);
+						group.setProjectId(afterUpdate.getProjectId());
+						group.setStageId(afterUpdate.getStageId());
+						group.setBeInvitedDept(orgDeptId);
+						group.setUserId(projectManager);
+						groups.add(group);
+					}
+				}
+			}
+
+			//4.指定任务执行者
+			if (StringUtil.isBlank(beforeUpdate.getExecuteUser()) && StringUtil.isNotBlank(afterUpdate.getExecuteUser())) {
+				List<Long> userIds = Func.toLongList(afterUpdate.getExecuteUser());
+				List<String> str = new ArrayList<>();
+				userIds.forEach(id -> {
+					R<User> rpc = userClient.userInfoById(id);
+					if (rpc.isSuccess()) {
+						str.add(rpc.getData().getName());
+
+						String deptStr = rpc.getData().getDeptId();
+						if (StringUtil.isNotBlank(deptStr) && orgDeptId != null) {
+							Long deptId = Func.firstLong(deptStr);
+							ProjectAuth auth = new ProjectAuth();
+							auth.setTopDept(orgDeptId);
+							auth.setUserDept(deptId);
+							auth.setProjectId(afterUpdate.getProjectId());
+							auth.setUserId(id);
+							auths.add(auth);
+
+							ProjectGroup group = new ProjectGroup();
+							group.setInviteDept(null);
+							group.setProjectId(afterUpdate.getProjectId());
+							group.setStageId(afterUpdate.getStageId());
+							group.setBeInvitedDept(orgDeptId);
+							group.setUserId(id);
+							groups.add(group);
+						}
+					}
+				});
+				if (!CollectionUtils.isEmpty(str)) {
+					TaskLog log3 = new TaskLog();
+					log3.setTaskId(afterUpdate.getId());
+					log3.setContent(userR.getData().getName() + " 指定了任务执行者 " + Func.join(str));
+					List<Long> users = new ArrayList<>();
+					users.add(userR.getData().getId());
+					users.addAll(userIds);
+					log3.setRelatedUser(Func.join(users));
+					log3.setCreateUser(userId);
+					log3.setUpdateUser(userId);
+					log3.setCreateTime(DateUtil.now());
+					log3.setUpdateTime(DateUtil.now());
+					taskLogService.save(log3);
+				}
+			}
+
+			//5.指定任务审查者
+			if ((beforeUpdate.getFirstCheckUser() == null && afterUpdate.getFirstCheckUser() != null) || (beforeUpdate.getSecondCheckUser() == null && afterUpdate.getSecondCheckUser() != null)) {
+				Long first = afterUpdate.getFirstCheckUser();
+				Long second = afterUpdate.getSecondCheckUser();
+				List<Long> checkUsers = new ArrayList<>();
+				if (first != null) {
+					checkUsers.add(first);
+				}
+				if (second != null) {
+					checkUsers.add(second);
+				}
+				List<String> checks = new ArrayList<>();
+				checkUsers.forEach(id -> {
+					R<User> rpc = userClient.userInfoById(id);
+					if (rpc.isSuccess()) {
+						checks.add(rpc.getData().getName());
+
+						String deptStr = rpc.getData().getDeptId();
+						if (StringUtil.isNotBlank(deptStr) && orgDeptId != null) {
+							Long deptId = Func.firstLong(deptStr);
+							ProjectAuth auth = new ProjectAuth();
+							auth.setTopDept(orgDeptId);
+							auth.setUserDept(deptId);
+							auth.setProjectId(afterUpdate.getProjectId());
+							auth.setUserId(id);
+							auths.add(auth);
+
+							ProjectGroup group = new ProjectGroup();
+							group.setInviteDept(null);
+							group.setProjectId(afterUpdate.getProjectId());
+							group.setStageId(afterUpdate.getStageId());
+							group.setBeInvitedDept(orgDeptId);
+							group.setUserId(id);
+							groups.add(group);
+						}
+					}
+				});
+				if (!CollectionUtils.isEmpty(checks)) {
+					TaskLog log4 = new TaskLog();
+					log4.setTaskId(afterUpdate.getId());
+					log4.setContent(userR.getData().getName() + " 指定了任务审查者 " + Func.join(checks));
+					List<Long> users = new ArrayList<>();
+					users.add(userR.getData().getId());
+					users.addAll(checkUsers);
+					log4.setRelatedUser(Func.join(users));
+
+					log4.setCreateUser(userId);
+					log4.setUpdateUser(userId);
+					log4.setCreateTime(DateUtil.now());
+					log4.setUpdateTime(DateUtil.now());
+					taskLogService.save(log4);
+				}
+			}
+
+			//6.提交了任务
+			if (newStatus != null && oldStatus != null && !oldStatus.equals(3) && newStatus.equals(3)) {
+				//提交成果文件
+				TaskLog log = new TaskLog();
+				log.setTaskId(afterUpdate.getId());
+				log.setContent(userR.getData().getName() + " 提交了成果文件");
+				log.setCreateUser(userId);
+				log.setUpdateUser(userId);
+				log.setCreateTime(DateUtil.now());
+				log.setUpdateTime(DateUtil.now());
+				taskLogService.save(log);
+			}
+
+			//7.审查任务
+			if (newStatus != null && oldStatus != null && !oldStatus.equals(7) && newStatus.equals(7)) {
+				//审查任务
+				TaskLog log = new TaskLog();
+				log.setTaskId(afterUpdate.getId());
+				log.setContent(userR.getData().getName() + " 审查了成果文件");
+				log.setCreateUser(userId);
+				log.setUpdateUser(userId);
+				log.setCreateTime(DateUtil.now());
+				log.setUpdateTime(DateUtil.now());
+				taskLogService.save(log);
+			}
+
+			//8.二次审查任务
+			if (newStatus != null && oldStatus != null && !oldStatus.equals(8) && newStatus.equals(8)) {
+				//二次审查任务
+				TaskLog log = new TaskLog();
+				log.setTaskId(afterUpdate.getId());
+				log.setContent(userR.getData().getName() + " 二次审查了成果文件");
+				log.setCreateUser(userId);
+				log.setUpdateUser(userId);
+				log.setCreateTime(DateUtil.now());
+				log.setUpdateTime(DateUtil.now());
+				taskLogService.save(log);
+			}
+
+			//9.确认任务
+			if (newStatus != null && oldStatus != null && !oldStatus.equals(4) && newStatus.equals(4)) {
+				//确认任务
+				TaskLog log = new TaskLog();
+				log.setTaskId(afterUpdate.getId());
+				log.setContent(userR.getData().getName() + " 确认任务已完成");
+				log.setCreateUser(userId);
+				log.setUpdateUser(userId);
+				log.setCreateTime(DateUtil.now());
+				log.setUpdateTime(DateUtil.now());
+				taskLogService.save(log);
+
+				//项目下待完成的任务减少
+				Project project = projectMapper.selectById(projectId);
+				if (project != null) {
+					project.setTodoTask(Math.max(project.getTodoTask() - 1, 0));
+					projectMapper.updateById(project);
+				}
+			}
+
+			//10.取消任务
+			if (newStatus != null && oldStatus != null && !oldStatus.equals(5) && newStatus.equals(5)) {
+				TaskLog log = new TaskLog();
+				log.setTaskId(afterUpdate.getId());
+				log.setContent(userR.getData().getName() + " 取消了任务");
+				log.setCreateUser(userId);
+				log.setUpdateUser(userId);
+				log.setCreateTime(DateUtil.now());
+				log.setUpdateTime(DateUtil.now());
+				taskLogService.save(log);
+
+				//项目下待完成的任务减少
+				Project project = projectMapper.selectById(projectId);
+				if (project != null) {
+					project.setTodoTask(Math.max(project.getTodoTask() - 1, 0));
+					projectMapper.updateById(project);
+				}
+			}
+			if (!CollectionUtils.isEmpty(auths)) {
+				projectAuthService.saveBatch(auths);
+			}
+			if (!CollectionUtils.isEmpty(groups)) {
+				projectGroupService.saveBatch(groups);
+			}
+		}
+	}
+
+	@Override
+	@Async("asyncPoolTaskExecutor")
+	public void firstCheck(Long userId, Task task) {
+		R<User> userR = userClient.userInfoById(userId);
+		Long firstCheckUser = task.getFirstCheckUser();
+		Long projectId = task.getProjectId();
+		Project project = projectMapper.selectById(projectId);
+		R<User> checkR = userClient.userInfoById(firstCheckUser);
+		if (userR.isSuccess() && checkR.isSuccess() && project != null) {
+			String name = userR.getData().getName();
+			String phone = checkR.getData().getPhone();
+
+			if (StringUtil.isNotBlank(name) && StringUtil.isNotBlank(phone)) {
+				try {
+					//发送短信
+					// 1.创建一个认真对象
+					Credential cred = new Credential(NacosConfigValue.txSecretId, NacosConfigValue.txSecretKey);
+					//2.实例化一个http选项
+					HttpProfile httpProfile = new HttpProfile();
+					httpProfile.setReqMethod("POST");
+					httpProfile.setConnTimeout(60);
+					httpProfile.setEndpoint("sms.tencentcloudapi.com");
+					//3实例化一个客户端配置对象
+					ClientProfile clientProfile = new ClientProfile();
+					clientProfile.setSignMethod("HmacSHA256");
+					clientProfile.setHttpProfile(httpProfile);
+					SmsClient client = new SmsClient(cred, "ap-guangzhou", clientProfile);
+
+					//4.实例化请求对象
+					SendSmsRequest req = new SendSmsRequest();
+					String sdkAppId = "1400785942";
+					req.setSmsSdkAppid(sdkAppId);
+
+					String signName = "梧桐树网";
+					req.setSign(signName);
+
+					String templateId = "1948441";
+					req.setTemplateID(templateId);
+
+					/* 模板参数: 模板参数的个数需要与 TemplateId 对应模板的变量个数保持一致,若无模板参数,则设置为空 */
+					String[] templateParamSet = {name};
+					req.setTemplateParamSet(templateParamSet);
+
+					String[] phoneNumberSet = {"+86" + phone};
+					req.setPhoneNumberSet(phoneNumberSet);
+
+					SendSmsResponse res = client.SendSms(req);
+					log.info(SendSmsResponse.toJsonString(res));
+				} catch (Exception e) {
+					log.error("发送短信失败" + e.getMessage());
+				}
+
+				//发送消息到首页
+				IndexMessage msg = new IndexMessage();
+				msg.setToUser(firstCheckUser);
+				msg.setContent(name + "已经完成了" + project.getName() + task.getTitle() + "的任务,请及时审核");
+				msg.setCategory(1);
+				msg.setOpenUrl("/task");
+				msg.setCreateUser(userId);
+				msg.setUpdateUser(userId);
+				indexMessageService.save(msg);
+			}
+		}
+	}
+
+	@Override
+	@Async("asyncPoolTaskExecutor")
+	public void secondCheck(Long userId, Task task) {
+		R<User> userR = userClient.userInfoById(userId);
+		Long secondCheckUser = task.getSecondCheckUser();
+		Long projectId = task.getProjectId();
+		Project project = projectMapper.selectById(projectId);
+		R<User> checkR = userClient.userInfoById(secondCheckUser);
+
+		if (userR.isSuccess() && checkR.isSuccess() && project != null) {
+			String name = userR.getData().getName();
+			String phone = checkR.getData().getPhone();
+
+			if (StringUtil.isNotBlank(name) && StringUtil.isNotBlank(phone)) {
+				try {
+					//发送短信
+					// 1.创建一个认证对象
+					Credential cred = new Credential(NacosConfigValue.txSecretId, NacosConfigValue.txSecretKey);
+					//2.实例化一个http选项
+					HttpProfile httpProfile = new HttpProfile();
+					httpProfile.setReqMethod("POST");
+					httpProfile.setConnTimeout(60);
+					httpProfile.setEndpoint("sms.tencentcloudapi.com");
+					//3实例化一个客户端配置对象
+					ClientProfile clientProfile = new ClientProfile();
+					clientProfile.setSignMethod("HmacSHA256");
+					clientProfile.setHttpProfile(httpProfile);
+					SmsClient client = new SmsClient(cred, "ap-guangzhou", clientProfile);
+
+					//4.实例化请求对象
+					SendSmsRequest req = new SendSmsRequest();
+					String sdkAppId = "1400785942";
+					req.setSmsSdkAppid(sdkAppId);
+
+					String signName = "梧桐树网";
+					req.setSign(signName);
+
+					String templateId = "1948455";
+					req.setTemplateID(templateId);
+
+					/* 模板参数: 模板参数的个数需要与 TemplateId 对应模板的变量个数保持一致,若无模板参数,则设置为空 */
+					String[] templateParamSet = {name};
+					req.setTemplateParamSet(templateParamSet);
+
+					String[] phoneNumberSet = {"+86" + phone};
+					req.setPhoneNumberSet(phoneNumberSet);
+
+					SendSmsResponse res = client.SendSms(req);
+					log.info(SendSmsResponse.toJsonString(res));
+				} catch (Exception e) {
+					log.error("发送短信失败" + e.getMessage());
+				}
+
+				//发送消息到首页
+				IndexMessage msg = new IndexMessage();
+				msg.setToUser(secondCheckUser);
+				msg.setContent(name + "已经完成了" + project.getName() + task.getTitle() + "的任务一次审核,请及时二次审核");
+				msg.setCategory(1);
+				msg.setOpenUrl("/task");
+				msg.setCreateUser(userId);
+				msg.setUpdateUser(userId);
+				indexMessageService.save(msg);
+			}
+
+		}
+	}
+
+	@Override
+	@Async("asyncPoolTaskExecutor")
+	public void dispatchTask(Long userId, Task task) {
+		R<User> userR = userClient.userInfoById(userId);
+		String executeUser = task.getExecuteUser();
+		List<Long> users = Func.toLongList(executeUser);
+		Long projectId = task.getProjectId();
+		Project project = projectMapper.selectById(projectId);
+		Date endTime = task.getEndTime();
+		String format = DateUtil.format(endTime, "yyyy-MM-dd");
+
+		if (userR.isSuccess() && project != null) {
+			String name = userR.getData().getName();
+			users.forEach(user -> {
+				R<User> rpc = userClient.userInfoById(userId);
+				if (rpc.isSuccess()) {
+					String phone = rpc.getData().getPhone();
+					if (StringUtil.isNotBlank(name) && StringUtil.isNotBlank(phone)) {
+						try {
+							//发送短信
+							// 1.创建一个认证对象
+							Credential cred = new Credential(NacosConfigValue.txSecretId, NacosConfigValue.txSecretKey);
+							//2.实例化一个http选项
+							HttpProfile httpProfile = new HttpProfile();
+							httpProfile.setReqMethod("POST");
+							httpProfile.setConnTimeout(60);
+							httpProfile.setEndpoint("sms.tencentcloudapi.com");
+							//3实例化一个客户端配置对象
+							ClientProfile clientProfile = new ClientProfile();
+							clientProfile.setSignMethod("HmacSHA256");
+							clientProfile.setHttpProfile(httpProfile);
+							SmsClient client = new SmsClient(cred, "ap-guangzhou", clientProfile);
+
+							//4.实例化请求对象
+							SendSmsRequest req = new SendSmsRequest();
+							String sdkAppId = "1400785942";
+							req.setSmsSdkAppid(sdkAppId);
+
+							String signName = "梧桐树网";
+							req.setSign(signName);
+
+							//任务下发通知模版id
+							String templateId = "1948622";
+							req.setTemplateID(templateId);
+
+							/* 模板参数: 模板参数的个数需要与 TemplateId 对应模板的变量个数保持一致,若无模板参数,则设置为空 */
+							String[] templateParamSet = {name, format};
+							req.setTemplateParamSet(templateParamSet);
+
+							String[] phoneNumberSet = {"+86" + phone};
+							req.setPhoneNumberSet(phoneNumberSet);
+
+							SendSmsResponse res = client.SendSms(req);
+							log.info(SendSmsResponse.toJsonString(res));
+						} catch (Exception e) {
+							log.error("发送短信失败" + e.getMessage());
+						}
+
+						//发送消息到首页
+						List<IndexMessage> messages = new ArrayList<>();
+						IndexMessage msg = new IndexMessage();
+						msg.setToUser(user);
+						msg.setContent(name + "指派" + project.getName() + task.getTitle() + "的任务,请及时完成");
+						msg.setCategory(1);
+						msg.setOpenUrl("/task");
+						msg.setCreateUser(userId);
+						msg.setUpdateUser(userId);
+						messages.add(msg);
+
+						IndexMessage message = new IndexMessage();
+						message.setToUser(user);
+						message.setContent(project.getName() + task.getTitle() + "的任务截至时间为" + format + ",请及时完成");
+						message.setCategory(1);
+						message.setOpenUrl("/task");
+						message.setCreateUser(userId);
+						message.setUpdateUser(userId);
+						messages.add(message);
+						indexMessageService.saveBatch(messages);
+					}
+				}
+			});
+		}
+	}
+
+	@Override
+	@Async("asyncPoolTaskExecutor")
+	public void dispatchToDept(Long userId, Task task) {
+		Long createUser = task.getCreateUser();
+		R<User> userR = userClient.userInfoById(createUser);
+
+		Long charge = task.getFirstCheckUser();
+		R<User> chargeR = userClient.userInfoById(charge);
+
+		Long projectId = task.getProjectId();
+		Project project = projectMapper.selectById(projectId);
+
+		if (userR.isSuccess() && chargeR.isSuccess() && project != null) {
+			String name = userR.getData().getName();
+			String title = task.getTitle();
+			String phone = chargeR.getData().getPhone();
+
+			if (StringUtil.isNotBlank(name) && StringUtil.isNotBlank(phone)) {
+				try {
+					//发送短信
+					// 1.创建一个认证对象
+					Credential cred = new Credential(NacosConfigValue.txSecretId, NacosConfigValue.txSecretKey);
+					//2.实例化一个http选项
+					HttpProfile httpProfile = new HttpProfile();
+					httpProfile.setReqMethod("POST");
+					httpProfile.setConnTimeout(60);
+					httpProfile.setEndpoint("sms.tencentcloudapi.com");
+					//3实例化一个客户端配置对象
+					ClientProfile clientProfile = new ClientProfile();
+					clientProfile.setSignMethod("HmacSHA256");
+					clientProfile.setHttpProfile(httpProfile);
+					SmsClient client = new SmsClient(cred, "ap-guangzhou", clientProfile);
+
+					//4.实例化请求对象
+					SendSmsRequest req = new SendSmsRequest();
+					String sdkAppId = "1400785942";
+					req.setSmsSdkAppid(sdkAppId);
+
+					String signName = "梧桐树网";
+					req.setSign(signName);
+
+					//分配任务通知
+					String templateId = "1948437";
+					req.setTemplateID(templateId);
+
+					/* 模板参数: 模板参数的个数需要与 TemplateId 对应模板的变量个数保持一致,若无模板参数,则设置为空 */
+					String[] templateParamSet = {name, title};
+					req.setTemplateParamSet(templateParamSet);
+
+					String[] phoneNumberSet = {"+86" + phone};
+					req.setPhoneNumberSet(phoneNumberSet);
+
+					SendSmsResponse res = client.SendSms(req);
+					log.info(SendSmsResponse.toJsonString(res));
+				} catch (Exception e) {
+					log.error("发送短信失败" + e.getMessage());
+				}
+
+				//发送消息到首页
+				IndexMessage msg = new IndexMessage();
+				msg.setToUser(charge);
+				msg.setContent(name + "创建了" + project.getName() + task.getTitle() + "的任务,请及时跟进任务分配");
+				msg.setCategory(1);
+				msg.setOpenUrl("/task");
+				msg.setCreateUser(userId);
+				msg.setUpdateUser(userId);
+				indexMessageService.save(msg);
+			}
+
+		}
+	}
+
+	@Override
+	@Async("asyncPoolTaskExecutor")
+	public void dispatchToOrg(Long userId, Task task) {
+
+		Long createUser = task.getCreateUser();
+		R<User> userR = userClient.userInfoById(createUser);
+
+		Long projectId = task.getProjectId();
+		Project project = projectMapper.selectById(projectId);
+
+		Long orgDeptId = task.getOrgDeptId();
+
+		//1.此dept下的所有用户 2.用户的角色是管理员角色的
+		R<List<User>> rpc = userClient.getUserByDeptId(String.valueOf(orgDeptId));
+		if (rpc.isSuccess()) {
+			List<User> data = rpc.getData();
+			//次级机构管理员
+			R<Role> roleR = sysClient.getRoleByRoleAlias("staff_admin");
+			if (roleR.isSuccess()) {
+				Set<User> users = data.stream().filter(f -> f.getRoleId() != null && f.getRoleId().contains(String.valueOf(roleR.getData().getId()))).collect(Collectors.toSet());
+				if (!CollectionUtil.isEmpty(users) && userR.isSuccess() && project != null) {
+					String name = userR.getData().getName();
+					String title = task.getTitle();
+					users.forEach(user -> {
+						String phone = user.getPhone();
+						try {
+							//发送短信
+							// 1.创建一个认证对象
+							Credential cred = new Credential(NacosConfigValue.txSecretId, NacosConfigValue.txSecretKey);
+							//2.实例化一个http选项
+							HttpProfile httpProfile = new HttpProfile();
+							httpProfile.setReqMethod("POST");
+							httpProfile.setConnTimeout(60);
+							httpProfile.setEndpoint("sms.tencentcloudapi.com");
+							//3实例化一个客户端配置对象
+							ClientProfile clientProfile = new ClientProfile();
+							clientProfile.setSignMethod("HmacSHA256");
+							clientProfile.setHttpProfile(httpProfile);
+							SmsClient client = new SmsClient(cred, "ap-guangzhou", clientProfile);
+
+							//4.实例化请求对象
+							SendSmsRequest req = new SendSmsRequest();
+							String sdkAppId = "1400785942";
+							req.setSmsSdkAppid(sdkAppId);
+
+							String signName = "梧桐树网";
+							req.setSign(signName);
+
+							//分配任务通知
+							String templateId = "1948437";
+							req.setTemplateID(templateId);
+
+							/* 模板参数: 模板参数的个数需要与 TemplateId 对应模板的变量个数保持一致,若无模板参数,则设置为空 */
+							String[] templateParamSet = {name, title};
+							req.setTemplateParamSet(templateParamSet);
+
+							String[] phoneNumberSet = {"+86" + phone};
+							req.setPhoneNumberSet(phoneNumberSet);
+
+							SendSmsResponse res = client.SendSms(req);
+							log.info(SendSmsResponse.toJsonString(res));
+						} catch (Exception e) {
+							log.error("发送短信失败" + e.getMessage());
+						}
+
+						//发送消息到首页
+						IndexMessage msg = new IndexMessage();
+						msg.setToUser(user.getId());
+						msg.setContent(userR.getData().getName() + "创建了" + project.getName() + task.getTitle() + "的任务,请及时跟进任务分配");
+						msg.setCategory(1);
+						msg.setOpenUrl("/task");
+						msg.setCreateUser(userId);
+						msg.setUpdateUser(userId);
+						indexMessageService.save(msg);
+					});
+				}
+			}
+		}
+
+		String executeUser = task.getExecuteUser();
+		if (!StringUtil.isNotBlank(executeUser)) {
+			Date endTime = task.getEndTime();
+			String format = DateUtil.format(endTime, "yyyy-MM-dd");
+			List<Long> users = Func.toLongList(executeUser);
+			if (userR.isSuccess() && project != null) {
+				String name = userR.getData().getName();
+				users.forEach(user -> {
+					R<User> userR1 = userClient.userInfoById(userId);
+					if (userR1.isSuccess()) {
+						String phone = userR1.getData().getPhone();
+						if (StringUtil.isNotBlank(name) && StringUtil.isNotBlank(phone)) {
+							try {
+								//发送短信
+								// 1.创建一个认证对象
+								Credential cred = new Credential(NacosConfigValue.txSecretId, NacosConfigValue.txSecretKey);
+								//2.实例化一个http选项
+								HttpProfile httpProfile = new HttpProfile();
+								httpProfile.setReqMethod("POST");
+								httpProfile.setConnTimeout(60);
+								httpProfile.setEndpoint("sms.tencentcloudapi.com");
+								//3实例化一个客户端配置对象
+								ClientProfile clientProfile = new ClientProfile();
+								clientProfile.setSignMethod("HmacSHA256");
+								clientProfile.setHttpProfile(httpProfile);
+								SmsClient client = new SmsClient(cred, "ap-guangzhou", clientProfile);
+
+								//4.实例化请求对象
+								SendSmsRequest req = new SendSmsRequest();
+								String sdkAppId = "1400785942";
+								req.setSmsSdkAppid(sdkAppId);
+
+								String signName = "梧桐树网";
+								req.setSign(signName);
+
+								//任务下发通知模版id
+								String templateId = "1948622";
+								req.setTemplateID(templateId);
+
+								/* 模板参数: 模板参数的个数需要与 TemplateId 对应模板的变量个数保持一致,若无模板参数,则设置为空 */
+								String[] templateParamSet = {name, format};
+								req.setTemplateParamSet(templateParamSet);
+
+								String[] phoneNumberSet = {"+86" + phone};
+								req.setPhoneNumberSet(phoneNumberSet);
+
+								SendSmsResponse res = client.SendSms(req);
+								log.info(SendSmsResponse.toJsonString(res));
+							} catch (Exception e) {
+								log.error("发送短信失败" + e.getMessage());
+							}
+
+							//发送消息到首页
+							List<IndexMessage> messages = new ArrayList<>();
+							IndexMessage msg = new IndexMessage();
+							msg.setToUser(user);
+							msg.setContent(name + "指派" + project.getName() + task.getTitle() + "的任务,请及时完成");
+							msg.setCategory(1);
+							msg.setOpenUrl("/task");
+							msg.setCreateUser(userId);
+							msg.setUpdateUser(userId);
+							messages.add(msg);
+
+							IndexMessage message = new IndexMessage();
+							message.setToUser(user);
+							message.setContent(project.getName() + task.getTitle() + "的任务截至时间为" + format + ",请及时完成");
+							message.setCategory(1);
+							message.setOpenUrl("/task");
+							message.setCreateUser(userId);
+							message.setUpdateUser(userId);
+							messages.add(message);
+							indexMessageService.saveBatch(messages);
+						}
+					}
+				});
+			}
+
+		}
+	}
+
+}

+ 423 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/service/impl/CommonServiceImpl.java

@@ -0,0 +1,423 @@
+package com.wtkj.service.impl;
+
+import com.alibaba.fastjson.JSON;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.wtkj.dto.SearchProjectFileDTO;
+import com.wtkj.dto.UploadFileDTO;
+import com.wtkj.dto.UploadInnerFileDTO;
+import com.wtkj.entity.FileAndFolder;
+import com.wtkj.entity.FileAndFolderHistory;
+import com.wtkj.entity.InnerFileAndFolder;
+import com.wtkj.entity.ProjectAuth;
+import com.wtkj.handler.es.Document;
+import com.wtkj.service.*;
+import com.wtkj.vo.AuthUserInfo;
+import com.wutong.file.feign.IFileClient;
+import com.wutong.file.vo.FileVO;
+import lombok.AllArgsConstructor;
+import lombok.SneakyThrows;
+import org.elasticsearch.action.search.SearchRequest;
+import org.elasticsearch.action.search.SearchResponse;
+import org.elasticsearch.client.RequestOptions;
+import org.elasticsearch.client.RestHighLevelClient;
+import org.elasticsearch.index.query.BoolQueryBuilder;
+import org.elasticsearch.index.query.QueryBuilders;
+import org.elasticsearch.search.SearchHits;
+import org.elasticsearch.search.builder.SearchSourceBuilder;
+import org.springblade.core.log.exception.ServiceException;
+import org.springblade.core.secure.BladeUser;
+import org.springblade.core.secure.utils.AuthUtil;
+import org.springblade.core.tool.api.R;
+import org.springblade.core.tool.utils.BeanUtil;
+import org.springblade.core.tool.utils.Func;
+import org.springblade.core.tool.utils.StringUtil;
+import org.springblade.core.tool.utils.WebUtil;
+import org.springblade.system.entity.Dept;
+import org.springblade.system.feign.ISysClient;
+import org.springblade.system.user.entity.User;
+import org.springblade.system.user.feign.IUserClient;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.CollectionUtils;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+import static com.wtkj.config.MagicValue.*;
+
+/**
+ * @author Blizzard
+ * @create at 2023-09-14 16:07
+ * @describe
+ */
+@Service
+@AllArgsConstructor
+public class CommonServiceImpl implements ICommonService {
+
+	private final IFileClient fileClient;
+	private final IFileAndFolderService fileAndFolderService;
+	private final IFileAndFolderHistoryService historyService;
+	private final IInnerFileAndFolderService innerFileAndFolderService;
+	private final IProjectAuthService projectAuthService;
+	private final RestHighLevelClient client;
+	private final ISysClient sysClient;
+	private final IUserClient userClient;
+
+
+	@Override
+	public boolean uploadFile(List<UploadFileDTO> files) {
+		boolean flag = false;
+		List<FileAndFolder> fileList = new ArrayList<>();
+		if (!CollectionUtils.isEmpty(files)) {
+			Long projectId = files.get(0).getProjectId();
+			Long parentId = files.get(0).getParentId();
+			Long stageId = files.get(0).getStageId();
+			files.forEach(file -> {
+				Long fileId = file.getBladeFileId();
+				R<FileVO> rpc = fileClient.findById(fileId);
+				if (rpc.isSuccess()) {
+					FileAndFolder newFile = new FileAndFolder();
+					newFile.setProjectId(projectId);
+					newFile.setStageId(stageId);
+					newFile.setParentId(parentId);
+					newFile.setBladeFileId(file.getBladeFileId());
+					newFile.setType(1);
+					newFile.setTitle(rpc.getData().getOriginalFileName());
+					if (parentId != null && parentId > 0L) {
+						FileAndFolder folder = fileAndFolderService.getById(parentId);
+						if (folder != null) {
+							newFile.setIsPrivate(folder.getIsPrivate());
+							newFile.setPrivateUser(folder.getPrivateUser());
+						}
+					}
+					fileList.add(newFile);
+				}
+			});
+
+			flag = fileAndFolderService.saveBatch(fileList);
+		}
+		return flag;
+	}
+
+	@Override
+	@Transactional(rollbackFor = Exception.class)
+	public boolean coverFile(List<UploadFileDTO> files) {
+		boolean flag = false;
+		List<FileAndFolder> fileList = new ArrayList<>();
+		List<FileAndFolderHistory> histories = new ArrayList<>();
+		if (!CollectionUtils.isEmpty(files)) {
+			Long projectId = files.get(0).getProjectId();
+			Long parentId = files.get(0).getParentId();
+			Long stageId = files.get(0).getStageId();
+			files.forEach(file -> {
+				Long fileId = file.getBladeFileId();
+				R<FileVO> rpc = fileClient.findById(fileId);
+				if (rpc.isSuccess()) {
+					//是否存在同名文件
+					LambdaQueryWrapper<FileAndFolder> lqw = Wrappers.lambdaQuery();
+					lqw.eq(FileAndFolder::getStageId, stageId);
+					lqw.eq(FileAndFolder::getParentId, parentId);
+					lqw.eq(FileAndFolder::getTitle, rpc.getData().getOriginalFileName());
+					FileAndFolder old = fileAndFolderService.getOne(lqw);
+					if (old != null) {
+						//存在同名文件
+						//此处不删除旧的同名文件,直接修改值 ---> 再保存历史记录信息  修改已存在的的数据 更新url 文件大小等信息
+						//先根据旧的fileId判断是否存在历史记录
+						List<FileAndFolderHistory> hisList = historyService.getByLatestId(old.getBladeFileId());
+						if (!CollectionUtils.isEmpty(hisList)) {
+							hisList.forEach(h -> {
+								h.setLatestId(String.valueOf(fileId));
+								histories.add(h);
+							});
+						}
+						//历史文件和新上传文件不是同一个的时候才保存
+						if (!fileId.equals(old.getBladeFileId())) {
+							FileAndFolderHistory his = new FileAndFolderHistory();
+							his.setLatestId(String.valueOf(fileId));
+							his.setHistoryId(String.valueOf(old.getBladeFileId()));
+							histories.add(his);
+						}
+						old.setBladeFileId(fileId);
+						fileList.add(old);
+					} else {
+						FileAndFolder newFile = new FileAndFolder();
+						newFile.setProjectId(projectId);
+						newFile.setStageId(stageId);
+						newFile.setParentId(parentId);
+						newFile.setBladeFileId(file.getBladeFileId());
+						newFile.setType(1);
+						newFile.setTitle(rpc.getData().getOriginalFileName());
+						if (parentId != null && parentId > 0L) {
+							FileAndFolder folder = fileAndFolderService.getById(parentId);
+							if (folder != null) {
+								newFile.setIsPrivate(folder.getIsPrivate());
+								newFile.setPrivateUser(folder.getPrivateUser());
+							}
+						}
+						fileList.add(newFile);
+					}
+				}
+			});
+			if (!CollectionUtils.isEmpty(histories)) {
+				historyService.saveOrUpdateBatch(histories);
+			}
+			flag = fileAndFolderService.saveOrUpdateBatch(fileList);
+		}
+		return flag;
+	}
+
+	@Override
+	public boolean remove(List<Long> ids) {
+		boolean flag = false;
+		if (!CollectionUtils.isEmpty(ids)) {
+			ids.forEach(id -> {
+				FileAndFolder byId = fileAndFolderService.getById(id);
+				//如果是文件夹
+				if (Objects.equals(byId.getType(), TWO)) {
+					List<FileAndFolder> children = fileAndFolderService.getChildren(null, id);
+					if (!CollectionUtils.isEmpty(children)) {
+						throw new ServiceException("删除文件夹失败:请先删除下级");
+					}
+				}
+			});
+			flag = fileAndFolderService.removeByIds(ids);
+		}
+		return flag;
+	}
+
+	@Override
+	public boolean move(String ids, Long stageId, Long parentId) {
+		boolean flag = false;
+		if (StringUtil.isNotBlank(ids)) {
+			List<FileAndFolder> list = new ArrayList<>();
+			List<Long> idList = Func.toLongList(ids);
+			idList.forEach(id -> {
+				FileAndFolder byId = fileAndFolderService.getById(id);
+				if (byId != null) {
+					byId.setStageId(stageId);
+					byId.setParentId(parentId);
+					list.add(byId);
+				}
+			});
+			flag = fileAndFolderService.updateBatchById(list);
+		}
+		return flag;
+	}
+
+	@Override
+	public boolean delete(List<Long> ids) {
+		boolean flag = false;
+		Long deptId = Func.firstLong(AuthUtil.getDeptId());
+		if (!CollectionUtils.isEmpty(ids)) {
+			ids.forEach(id -> {
+				InnerFileAndFolder byId = innerFileAndFolderService.getById(id);
+				//如果是文件夹
+				if (byId != null && Objects.equals(byId.getType(), TWO)) {
+					if (!deptId.equals(byId.getDeptId())) {
+						throw new ServiceException("非你部门下文件,禁止删除");
+					}
+					List<InnerFileAndFolder> children = innerFileAndFolderService.getChildren(byId.getDeptId(), id);
+					if (!CollectionUtils.isEmpty(children)) {
+						throw new ServiceException("删除文件夹失败:请先删除下级");
+					}
+				}
+			});
+			flag = innerFileAndFolderService.removeByIds(ids);
+		}
+		return flag;
+
+	}
+
+	@Override
+	public boolean uploadInnerFile(List<UploadInnerFileDTO> files) {
+		boolean flag = false;
+		List<InnerFileAndFolder> fileList = new ArrayList<>();
+		if (!CollectionUtils.isEmpty(files)) {
+			Long parentId = files.get(0).getParentId();
+			Long deptId = files.get(0).getDeptId();
+			files.forEach(file -> {
+				Long fileId = file.getBladeFileId();
+				R<FileVO> rpc = fileClient.findById(fileId);
+				if (rpc.isSuccess()) {
+					InnerFileAndFolder newFile = new InnerFileAndFolder();
+					newFile.setDeptId(deptId);
+					newFile.setParentId(parentId);
+					newFile.setBladeFileId(file.getBladeFileId());
+					newFile.setType(1);
+					newFile.setTitle(rpc.getData().getOriginalFileName());
+					fileList.add(newFile);
+				}
+			});
+			flag = innerFileAndFolderService.saveBatch(fileList);
+		}
+		return flag;
+
+
+	}
+
+	@SneakyThrows
+	@Override
+	public IPage<FileAndFolder> esSearch(SearchProjectFileDTO dto, IPage<FileAndFolder> page) {
+		LambdaQueryWrapper<FileAndFolder> lqw = new LambdaQueryWrapper<>();
+		Long deptId = dto.getTopDeptId();
+		String text = dto.getText();
+		Long projectId = dto.getProjectId();
+		Long createUser = dto.getCreateUser();
+		Set<Long> projectIds = new HashSet<>();
+		if (projectId != null && projectId > 0L) {
+			projectIds.add(projectId);
+		} else {
+			//如果projectId为空 则查询机构下所有项目
+			//此机构下的项目
+			List<ProjectAuth> auths = projectAuthService.getByDeptAndUser(deptId, null, null);
+			if (!CollectionUtils.isEmpty(auths)) {
+				Set<Long> ids = auths.stream().map(ProjectAuth::getProjectId).filter(Objects::nonNull).collect(Collectors.toSet());
+				projectIds.addAll(ids);
+			}
+		}
+
+		// select * from xxx where projectId in (...) and create_user = #{createUser} and (title like %text% or content like %text%)
+
+		SearchRequest request = new SearchRequest();
+		request.indices(PROJECT_RESOURCE_INDEX);
+		SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
+
+		// 1.创建BoolQueryBuilder
+		BoolQueryBuilder condition = QueryBuilders.boolQuery();
+
+		//2. 添加must子句
+		condition.must(QueryBuilders.termsQuery("projectId", projectIds));
+		if (createUser != null) {
+			condition.must(QueryBuilders.termQuery("createUser", createUser));
+		}
+		if (StringUtil.isNotBlank(text)) {
+			// 3.添加should子句
+			condition.should(QueryBuilders.matchQuery("title", text));
+			condition.should(QueryBuilders.matchQuery("content", text));
+		}
+		searchSourceBuilder.query(condition);
+		searchSourceBuilder.from(0);
+		searchSourceBuilder.size(100);
+		request.source(searchSourceBuilder);
+
+		//执行查询
+		SearchResponse response = client.search(request, RequestOptions.DEFAULT);
+		Set<Document> set = new HashSet<>();
+		if (response != null) {
+			SearchHits hits = response.getHits();
+			int size = hits.getHits().length;
+			for (int i = 0; i < size; i++) {
+				String str = hits.getHits()[i].getSourceAsString();
+				Document document = JSON.parseObject(str, Document.class);
+				set.add(document);
+			}
+		}
+		if (!CollectionUtils.isEmpty(set)) {
+			Set<Long> fileIds = set.stream().map(Document::getFileId).collect(Collectors.toSet());
+			lqw.in(FileAndFolder::getBladeFileId, fileIds);
+		}
+		lqw.eq(FileAndFolder::getType, 1);
+		return fileAndFolderService.page(page, lqw);
+	}
+
+	@SneakyThrows
+	@Override
+	public Set<Integer> openSearchFile(Long projectId, Long fileId, String text) {
+		Long userId = AuthUtil.getUserId();
+		List<ProjectAuth> list = projectAuthService.getByUserId(userId);
+		if (!CollectionUtils.isEmpty(list)) {
+			Set<Long> collect = list.stream().map(ProjectAuth::getProjectId).collect(Collectors.toSet());
+			if (!collect.contains(projectId)) {
+				throw new ServiceException("对不起,你暂未拥有此项目权限");
+			}
+		}
+
+		SearchRequest request = new SearchRequest();
+		request.indices(PROJECT_RESOURCE_INDEX);
+		SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
+
+		// 1.创建BoolQueryBuilder
+		BoolQueryBuilder condition = QueryBuilders.boolQuery();
+
+		//2. 添加must子句
+		condition.must(QueryBuilders.termQuery("projectId", projectId));
+		condition.must(QueryBuilders.termQuery("fileId", fileId));
+		condition.must(QueryBuilders.matchQuery("title", text));
+
+		searchSourceBuilder.query(condition);
+		searchSourceBuilder.from(0);
+		searchSourceBuilder.size(100);
+		request.source(searchSourceBuilder);
+
+		searchSourceBuilder.query(condition);
+		searchSourceBuilder.from(0);
+		searchSourceBuilder.size(100);
+		request.source(searchSourceBuilder);
+
+		//执行查询
+		SearchResponse response = client.search(request, RequestOptions.DEFAULT);
+		//返回页码
+		Set<Integer> set = new HashSet<>();
+		if (response != null) {
+			SearchHits hits = response.getHits();
+			int size = hits.getHits().length;
+			for (int i = 0; i < size; i++) {
+				String str = hits.getHits()[i].getSourceAsString();
+				Document document = JSON.parseObject(str, Document.class);
+				set.add(document.getCurrentPage());
+			}
+		}
+		return set;
+	}
+
+	@Override
+	public AuthUserInfo userInfo() {
+		BladeUser user = AuthUtil.getUser();
+		if (user != null) {
+			AuthUserInfo userInfo = Objects.requireNonNull(BeanUtil.copy(user, AuthUserInfo.class));
+			String deptIdStr = userInfo.getDeptId();
+			if (StringUtil.isNotBlank(deptIdStr)) {
+				R<Dept> rpc = sysClient.getDept(Long.valueOf(deptIdStr));
+				if (rpc.isSuccess()) {
+					userInfo.setDeptCategory(rpc.getData().getDeptCategory());
+					userInfo.setDeptName(rpc.getData().getDeptName());
+					String ancestors = rpc.getData().getAncestors();
+					// ancestors 0,1689540492698267649
+					if (ancestors != null && ancestors.contains(String.valueOf(ZERO))) {
+						List<Long> longList = Func.toLongList(ancestors);
+						if (!CollectionUtils.isEmpty(longList)) {
+							if (longList.size() > 1) {
+								Long deptId = longList.get(1);
+								userInfo.setTopDept(deptId);
+								R<Dept> dept = sysClient.getDept(deptId);
+								if (dept.isSuccess()) {
+									userInfo.setTopDeptName(dept.getData().getDeptName());
+								}
+							} else {
+								userInfo.setTopDept(Long.valueOf(deptIdStr));
+								userInfo.setTopDeptName(rpc.getData().getDeptName());
+							}
+						}
+					}
+				}
+			}
+			Long userId = user.getUserId();
+			R<User> userR = userClient.userInfoById(userId);
+			if (userR.isSuccess()) {
+				userInfo.setUser(userR.getData());
+			}
+
+			//登录成功通知 仅pc端
+			String platform = WebUtil.getHeader("platform");
+			if (StringUtil.isNotBlank(platform) && platform.equals("pc")) {
+
+			}
+			return userInfo;
+		}
+		return null;
+	}
+
+
+}

+ 79 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/service/impl/ContactOuterServiceImpl.java

@@ -0,0 +1,79 @@
+package com.wtkj.service.impl;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.wtkj.dto.UpdateUserDTO;
+import com.wtkj.entity.ContactOuter;
+import com.wtkj.mapper.ContactOuterMapper;
+import com.wtkj.service.IContactOuterService;
+import lombok.AllArgsConstructor;
+import org.springblade.core.mp.base.BaseServiceImpl;
+import org.springblade.core.tool.api.R;
+import org.springblade.core.tool.utils.BeanUtil;
+import org.springblade.core.tool.utils.Func;
+import org.springblade.system.entity.Role;
+import org.springblade.system.feign.ISysClient;
+import org.springblade.system.user.entity.User;
+import org.springblade.system.user.feign.IUserClient;
+import org.springframework.stereotype.Service;
+import org.springframework.util.CollectionUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * @author Blizzard
+ * @create at 2023-09-19 11:04
+ * @describe
+ */
+@Service
+@AllArgsConstructor
+public class ContactOuterServiceImpl extends BaseServiceImpl<ContactOuterMapper, ContactOuter> implements IContactOuterService {
+
+	private final IUserClient userClient;
+	private final ISysClient sysClient;
+
+	@Override
+	public IPage<ContactOuter> selectPage(Long userId, IPage<ContactOuter> page) {
+		return page.setRecords(baseMapper.getPage(userId, page));
+	}
+
+	@Override
+	public IPage<ContactOuter> contactPage(Long deptId, Long userId, IPage<ContactOuter> page) {
+		return page.setRecords(baseMapper.getUserPage(deptId, userId, page));
+	}
+
+	@Override
+	public boolean updateUser(UpdateUserDTO dto) {
+		boolean flag = false;
+		Long userId = dto.getId();
+		Long roleId = dto.getNewRoleId();
+		R<User> userR = userClient.userInfoById(userId);
+		if (userR.isSuccess() && userR.getData() != null) {
+			User user = Objects.requireNonNull(BeanUtil.copy(dto, User.class));
+			if (roleId != null) {
+				String roleStr = userR.getData().getRoleId();
+				List<Long> roleList = Func.toLongList(roleStr);
+				List<Long> temp = new ArrayList<>(roleList);
+				if (!CollectionUtils.isEmpty(roleList)) {
+					//去掉服务商的相关角色  重新赋值
+					List<Role> staffs = sysClient.getRoleList("staff").getData();
+					if (!CollectionUtils.isEmpty(staffs)) {
+						for (Role staff : staffs) {
+							Long id = staff.getId();
+							temp.remove(id);
+						}
+					}
+					temp.add(roleId);
+					String join = Func.join(temp);
+					user.setRoleId(join);
+				} else {
+					user.setRoleId(String.valueOf(roleId));
+				}
+			}
+			R<Boolean> booleanR = userClient.updateUser(user);
+			flag = booleanR.isSuccess();
+		}
+		return flag;
+	}
+}

+ 31 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/service/impl/FileAndFolderHistoryServiceImpl.java

@@ -0,0 +1,31 @@
+package com.wtkj.service.impl;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.wtkj.entity.FileAndFolderHistory;
+import com.wtkj.mapper.FileAndFolderHistoryMapper;
+import com.wtkj.service.IFileAndFolderHistoryService;
+import lombok.AllArgsConstructor;
+import org.springblade.core.mp.base.BaseServiceImpl;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/**
+ * @author Blizzard
+ * @create at 2023-09-14 16:14
+ * @describe
+ */
+@Service
+@AllArgsConstructor
+public class FileAndFolderHistoryServiceImpl extends BaseServiceImpl<FileAndFolderHistoryMapper, FileAndFolderHistory> implements IFileAndFolderHistoryService {
+	@Override
+	public List<FileAndFolderHistory> getByLatestId(Long bladeFileId) {
+		return baseMapper.selectByLatestId(bladeFileId);
+	}
+
+	@Override
+	public IPage<FileAndFolderHistory> getPage(String fileId, IPage<FileAndFolderHistory> page) {
+		return page.setRecords(baseMapper.getPage(fileId, page));
+	}
+
+}

+ 177 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/service/impl/FileAndFolderServiceImpl.java

@@ -0,0 +1,177 @@
+package com.wtkj.service.impl;
+
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
+import com.wtkj.dto.UploadFileDTO;
+import com.wtkj.entity.FileAndFolder;
+import com.wtkj.mapper.FileAndFolderMapper;
+import com.wtkj.service.IFileAndFolderService;
+import com.wutong.file.feign.IFileClient;
+import com.wutong.file.vo.FileVO;
+import lombok.AllArgsConstructor;
+import org.springblade.core.mp.base.BaseServiceImpl;
+import org.springblade.core.tool.api.R;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author Blizzard
+ * @create at 2023-09-14 15:05
+ * @describe
+ */
+@Service
+@AllArgsConstructor
+public class FileAndFolderServiceImpl extends BaseServiceImpl<FileAndFolderMapper, FileAndFolder> implements IFileAndFolderService {
+
+	private final IFileClient fileClient;
+
+	@Override
+	public boolean isExistSameName(List<UploadFileDTO> files) {
+		boolean flag = false;
+		List<FileAndFolder> isExists = new ArrayList<>();
+		if (!CollectionUtils.isEmpty(files)) {
+			files.forEach(f -> {
+				Long fileId = f.getBladeFileId();
+				R<FileVO> rpc = fileClient.findById(fileId);
+				if (rpc.isSuccess()) {
+					Long parentId = f.getParentId();
+					//是否存在重名文件
+					LambdaQueryWrapper<FileAndFolder> lqw = new LambdaQueryWrapper<>();
+					lqw.eq(FileAndFolder::getStageId, f.getStageId());
+					lqw.eq(FileAndFolder::getParentId, parentId);
+					lqw.eq(FileAndFolder::getTitle, rpc.getData().getOriginalFileName());
+					List<FileAndFolder> list = this.list(lqw);
+					if (!CollectionUtils.isEmpty(list)) {
+						isExists.addAll(list);
+					}
+				}
+			});
+		}
+		if (!CollectionUtils.isEmpty(isExists)) {
+			flag = true;
+		}
+		return flag;
+	}
+
+	@Override
+	public IPage<FileAndFolder> pageByStageId(Long stageId, IPage<FileAndFolder> page) {
+		return page.setRecords(baseMapper.selectByStage(stageId, page));
+	}
+
+	@Override
+	public Integer getFileAmountByFolderId(Long stageId, Long parentId) {
+		//递归子级文件夹 获取文件个数
+		return getChildrenFileAmountByFolderId(0, stageId, parentId);
+	}
+
+	@Override
+	public IPage<FileAndFolder> pageByParentId(Long parentId, IPage<FileAndFolder> page) {
+		return page.setRecords(baseMapper.selectByParent(parentId, page));
+	}
+
+	@Override
+	public JSONObject getPageAndFileAmount(Long stageId, Long parentId) {
+		JSONObject result = new JSONObject();
+		//文件数量
+		Integer fileAmount = this.getFileAmountByFolderId(stageId, parentId);
+		result.put("amount", fileAmount);
+		//文件
+		int totalPage = 0;
+		int volume = 0;
+		List<FileAndFolder> files = this.getChildrenFilesByFolderId(stageId, parentId);
+		if (!CollectionUtils.isEmpty(files)) {
+			totalPage = files.stream().filter(f -> f.getBladeFileId() != null).map(f -> fileClient.findImageList(f.getBladeFileId())).filter(rpc -> rpc.isSuccess() && rpc.getData() != null).map(R::getData).mapToInt(List::size).sum();
+			volume = files.stream().filter(f -> f.getBladeFileId() != null).map(f -> fileClient.findById(f.getBladeFileId())).filter(rpc -> rpc.isSuccess() && rpc.getData() != null).map(R::getData).map(FileVO::getVolume).mapToInt(Integer::parseInt).sum();
+		}
+		result.put("totalPage", totalPage);
+		result.put("volume", volume);
+		int folderAmount = 0;
+		List<FileAndFolder> folders = this.getChildrenFolderByFolderId(stageId, parentId);
+		if (!CollectionUtils.isEmpty(folders)) {
+			folderAmount = folders.size();
+		}
+		result.put("folderAmount", folderAmount);
+		return result;
+	}
+
+	@Override
+	public List<FileAndFolder> getChildrenFilesByFolderId(Long stageId, Long parentId) {
+		return getChildrenFileByFolderId(new ArrayList<>(), stageId, parentId);
+	}
+
+	@Override
+	public List<FileAndFolder> getChildrenFolderByFolderId(Long stageId, Long parentId) {
+		return baseMapper.getChildrenFolderList(stageId, parentId);
+	}
+
+	@Override
+	public List<FileAndFolder> getChildren(Long stageId, Long parentId) {
+		return getChildrenByFolderId(new ArrayList<>(), stageId, parentId);
+	}
+
+	@Override
+	public IPage<FileAndFolder> selectPage(String projectId, Long stageId, Integer isLatest, IPage<FileAndFolder> page) {
+		List<FileAndFolder> list = baseMapper.getPage(projectId, stageId, isLatest, page);
+		return page.setRecords(list);
+	}
+
+	@Override
+	public Integer getFileAmountByStageId(Long stageId) {
+		return baseMapper.selectFileAmountByStageId(stageId);
+	}
+
+
+	private List<FileAndFolder> getChildrenByFolderId(ArrayList<FileAndFolder> result, Long stageId, Long parentId) {
+		//文件下的文件和文件夹
+		List<FileAndFolder> children = baseMapper.getChildren(stageId, parentId);
+		if (!org.springframework.util.CollectionUtils.isEmpty(children)) {
+			result.addAll(children);
+		}
+		//本级的文件夹
+		List<FileAndFolder> childrenFolder = baseMapper.getChildrenFolderList(stageId, parentId);
+		if (!org.springframework.util.CollectionUtils.isEmpty(childrenFolder)) {
+			for (FileAndFolder folder : childrenFolder) {
+				getChildrenByFolderId(result, folder.getStageId(), folder.getId());
+			}
+		}
+		return result;
+	}
+
+	private List<FileAndFolder> getChildrenFileByFolderId(ArrayList<FileAndFolder> result, Long stageId, Long parentId) {
+		//本级下的文件
+		List<FileAndFolder> files = baseMapper.getChildrenFileList(stageId, parentId);
+		if (!org.springframework.util.CollectionUtils.isEmpty(files)) {
+			result.addAll(files);
+		}
+		//本级的文件夹
+		List<FileAndFolder> childrenFolder = baseMapper.getChildrenFolderList(stageId, parentId);
+		//递归出口,子集不为空时,一直去遍历
+		if (!CollectionUtils.isEmpty(childrenFolder)) {
+			for (FileAndFolder folder : childrenFolder) {
+				getChildrenFileByFolderId(result, folder.getStageId(), folder.getId());
+			}
+		}
+		return result;
+	}
+
+
+	private Integer getChildrenFileAmountByFolderId(int count, Long stageId, Long folderId) {
+		//本级下的文件数量
+		count = count + baseMapper.getFileAmountByFolderId(stageId, folderId);
+		//本级下的文件夹
+		List<FileAndFolder> children = baseMapper.getChildrenFolderList(stageId, folderId);
+		//递归出口,子集不为空时,一直去遍历
+		if (children != null && !children.isEmpty()) {
+			for (FileAndFolder child : children) {
+				int cnt = getChildrenFileAmountByFolderId(0, child.getStageId(), child.getId());
+				count = cnt + count;
+			}
+		}
+		return count;
+	}
+
+}

+ 66 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/service/impl/FileReadServiceImpl.java

@@ -0,0 +1,66 @@
+package com.wtkj.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.wtkj.entity.FileRead;
+import com.wtkj.mapper.FileReadMapper;
+import com.wtkj.service.IFileReadService;
+import lombok.AllArgsConstructor;
+import org.springblade.core.mp.base.BaseServiceImpl;
+import org.springblade.core.secure.utils.AuthUtil;
+import org.springblade.core.tool.api.R;
+import org.springblade.system.user.entity.User;
+import org.springblade.system.user.feign.IUserClient;
+import org.springframework.stereotype.Service;
+import org.springframework.util.CollectionUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+/**
+ * @author Blizzard
+ * @create at 2023-09-15 11:15
+ * @describe
+ */
+@Service
+@AllArgsConstructor
+public class FileReadServiceImpl extends BaseServiceImpl<FileReadMapper, FileRead> implements IFileReadService {
+
+	private final IUserClient userClient;
+
+	@Override
+	public boolean readFile(FileRead read) {
+		read.setUserId(AuthUtil.getUserId());
+		return save(read);
+	}
+
+	@Override
+	public List<FileRead> getByUser(Long userId) {
+		return baseMapper.selectByFileIds(userId);
+	}
+
+	@Override
+	public List<User> fileRead(String bladeFileId) {
+		List<User> res = new ArrayList<>();
+		List<Long> userIds = baseMapper.getReadUser(bladeFileId);
+		if (!CollectionUtils.isEmpty(userIds)) {
+			Set<User> users = userIds.stream().map(userClient::userInfoById).filter(userR1 -> userR1.isSuccess()).map(R::getData).collect(Collectors.toSet());
+			res.addAll(users);
+		}
+		return res;
+	}
+
+	@Override
+	public boolean isRead(String bladeFileId, Long userId) {
+		boolean flag = false;
+		LambdaQueryWrapper<FileRead> lqw = new LambdaQueryWrapper<>();
+		lqw.eq(FileRead::getBladeFileId, bladeFileId);
+		lqw.eq(FileRead::getUserId, userId);
+		List<FileRead> list = this.list(lqw);
+		if (!CollectionUtils.isEmpty(list)) {
+			flag = true;
+		}
+		return flag;
+	}
+}

+ 18 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/service/impl/FileShareServiceImpl.java

@@ -0,0 +1,18 @@
+package com.wtkj.service.impl;
+
+import com.wtkj.entity.FileShare;
+import com.wtkj.mapper.FileShareMapper;
+import com.wtkj.service.IFileShareService;
+import lombok.AllArgsConstructor;
+import org.springblade.core.mp.base.BaseServiceImpl;
+import org.springframework.stereotype.Service;
+
+/**
+ * @author Blizzard
+ * @create at 2023-09-26 15:18
+ * @describe
+ */
+@Service
+@AllArgsConstructor
+public class FileShareServiceImpl extends BaseServiceImpl<FileShareMapper, FileShare> implements IFileShareService {
+}

+ 37 - 0
blade-service/wutong-okr/src/main/java/com/wtkj/service/impl/ITaskContractServiceImpl.java

@@ -0,0 +1,37 @@
+package com.wtkj.service.impl;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.wtkj.entity.TaskContract;
+import com.wtkj.mapper.TaskContractMapper;
+import com.wtkj.service.ITaskContractService;
+import lombok.AllArgsConstructor;
+import org.springblade.core.mp.base.BaseServiceImpl;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author Blizzard
+ * @create at 2023-09-18 09:53
+ * @describe
+ */
+@Service
+@AllArgsConstructor
+public class ITaskContractServiceImpl extends BaseServiceImpl<TaskContractMapper, TaskContract> implements ITaskContractService {
+
+	@Override
+	public IPage<TaskContract> pageByTaskId(Long taskId, IPage<TaskContract> page) {
+		return page.setRecords(baseMapper.selectByTaskId(taskId, page));
+	}
+
+	@Override
+	public List<TaskContract> getByProjectIds(Set<Long> projectIds) {
+		return baseMapper.getByProjectIds(projectIds);
+	}
+
+	@Override
+	public List<TaskContract> getByDeptIdAndYear(Long topDept, Integer year, Set<Long> taskIds) {
+		return baseMapper.getByOrgDeptId(topDept, year, taskIds);
+	}
+}

Some files were not shown because too many files changed in this diff