浏览代码

feat: 1.ES save file
2.inner files

Blizzard 11 月之前
父节点
当前提交
64e3dfebe6
共有 37 个文件被更改,包括 1274 次插入12 次删除
  1. 34 0
      blade-service-api/wt-okr-api/src/main/java/com/wtkj/dto/SearchProjectFileDTO.java
  2. 31 0
      blade-service-api/wt-okr-api/src/main/java/com/wtkj/dto/UploadInnerFileDTO.java
  3. 28 0
      blade-service-api/wt-okr-api/src/main/java/com/wtkj/entity/FileShare.java
  4. 47 0
      blade-service-api/wt-okr-api/src/main/java/com/wtkj/entity/InnerFileAndFolder.java
  5. 26 0
      blade-service-api/wt-okr-api/src/main/java/com/wtkj/vo/FileAndFolderHistoryVO.java
  6. 27 0
      blade-service-api/wt-okr-api/src/main/java/com/wtkj/vo/InnerFileAndFolderVO.java
  7. 35 0
      blade-service/wt-okr/pom.xml
  8. 83 0
      blade-service/wt-okr/src/main/java/com/wtkj/config/KafkaConfig.java
  9. 16 0
      blade-service/wt-okr/src/main/java/com/wtkj/config/KafkaConstant.java
  10. 2 0
      blade-service/wt-okr/src/main/java/com/wtkj/config/MagicValue.java
  11. 67 0
      blade-service/wt-okr/src/main/java/com/wtkj/config/es/EsConfig.java
  12. 20 2
      blade-service/wt-okr/src/main/java/com/wtkj/controller/FileAndFolderController.java
  13. 1 0
      blade-service/wt-okr/src/main/java/com/wtkj/controller/IndexController.java
  14. 22 0
      blade-service/wt-okr/src/main/java/com/wtkj/controller/QrCodeController.java
  15. 123 0
      blade-service/wt-okr/src/main/java/com/wtkj/controller/ResourceController.java
  16. 122 0
      blade-service/wt-okr/src/main/java/com/wtkj/handler/EsFileHandler.java
  17. 28 0
      blade-service/wt-okr/src/main/java/com/wtkj/handler/es/Document.java
  18. 2 0
      blade-service/wt-okr/src/main/java/com/wtkj/mapper/FileAndFolderHistoryMapper.java
  19. 4 2
      blade-service/wt-okr/src/main/java/com/wtkj/mapper/FileAndFolderHistoryMapper.xml
  20. 12 0
      blade-service/wt-okr/src/main/java/com/wtkj/mapper/FileShareMapper.java
  21. 6 0
      blade-service/wt-okr/src/main/java/com/wtkj/mapper/FileShareMapper.xml
  22. 24 0
      blade-service/wt-okr/src/main/java/com/wtkj/mapper/InnerFileAndFolderMapper.java
  23. 53 0
      blade-service/wt-okr/src/main/java/com/wtkj/mapper/InnerFileAndFolderMapper.xml
  24. 3 3
      blade-service/wt-okr/src/main/java/com/wtkj/mapper/TaskMapper.xml
  25. 5 0
      blade-service/wt-okr/src/main/java/com/wtkj/service/ICommonService.java
  26. 2 0
      blade-service/wt-okr/src/main/java/com/wtkj/service/IFileAndFolderHistoryService.java
  27. 12 0
      blade-service/wt-okr/src/main/java/com/wtkj/service/IFileShareService.java
  28. 30 0
      blade-service/wt-okr/src/main/java/com/wtkj/service/IInnerFileAndFolderService.java
  29. 7 0
      blade-service/wt-okr/src/main/java/com/wtkj/service/IQrcodeService.java
  30. 56 0
      blade-service/wt-okr/src/main/java/com/wtkj/service/impl/CommonServiceImpl.java
  31. 6 0
      blade-service/wt-okr/src/main/java/com/wtkj/service/impl/FileAndFolderHistoryServiceImpl.java
  32. 18 0
      blade-service/wt-okr/src/main/java/com/wtkj/service/impl/FileShareServiceImpl.java
  33. 135 0
      blade-service/wt-okr/src/main/java/com/wtkj/service/impl/InnerFileAndFolderServiceImpl.java
  34. 1 1
      blade-service/wt-okr/src/main/java/com/wtkj/service/impl/ProjectServiceImpl.java
  35. 51 4
      blade-service/wt-okr/src/main/java/com/wtkj/service/impl/QrcodeServiceImpl.java
  36. 73 0
      blade-service/wt-okr/src/main/java/com/wtkj/wrapper/FileAndFolderHistoryWrapper.java
  37. 62 0
      blade-service/wt-okr/src/main/java/com/wtkj/wrapper/InnerFileAndFolderWrapper.java

+ 34 - 0
blade-service-api/wt-okr-api/src/main/java/com/wtkj/dto/SearchProjectFileDTO.java

@@ -0,0 +1,34 @@
+package com.wtkj.dto;
+
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
+import lombok.Data;
+
+import javax.validation.constraints.NotNull;
+import java.io.Serializable;
+
+/**
+ * @author Blizzard
+ * @create at 2023-09-27 09:52
+ * @describe
+ */
+@Data
+public class SearchProjectFileDTO implements Serializable {
+
+	private static final long serialVersionUID = 1L;
+
+	@JsonSerialize(using = ToStringSerializer.class)
+	@NotNull(message = "deptId can't be null")
+	private Long deptId;
+
+	private Long projectId;
+
+	private Long createUser;
+
+	private String title;
+
+	private Integer current;
+
+	private Integer size;
+
+}

+ 31 - 0
blade-service-api/wt-okr-api/src/main/java/com/wtkj/dto/UploadInnerFileDTO.java

@@ -0,0 +1,31 @@
+package com.wtkj.dto;
+
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
+import lombok.Data;
+
+import javax.validation.constraints.NotNull;
+import java.io.Serializable;
+
+/**
+ * @author Blizzard
+ * @create at 2023-09-14 15:19
+ * @describe
+ */
+@Data
+public class UploadInnerFileDTO implements Serializable {
+
+	private static final long serialVersionUID = 1L;
+
+	@JsonSerialize(using = ToStringSerializer.class)
+	@NotNull(message = "deptId不可为空")
+	private Long deptId;
+
+	@JsonSerialize(using = ToStringSerializer.class)
+	@NotNull(message = "parentId不可为空")
+	private Long parentId = 0L;
+
+	@JsonSerialize(using = ToStringSerializer.class)
+	@NotNull(message = "bladeFileId不可为空")
+	private Long bladeFileId;
+}

+ 28 - 0
blade-service-api/wt-okr-api/src/main/java/com/wtkj/entity/FileShare.java

@@ -0,0 +1,28 @@
+package com.wtkj.entity;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableName;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.springblade.core.mp.base.BaseEntity;
+
+import javax.validation.constraints.NotNull;
+
+/**
+ * @author Blizzard
+ * @create at 2023-09-26 15:04
+ * @describe
+ */
+@EqualsAndHashCode(callSuper = true)
+@TableName("blade_file_share")
+@Data
+public class FileShare extends BaseEntity {
+
+
+	@ApiModelProperty("文件bladeFileIds")
+	@TableField("blade_file_ids")
+	@NotNull(message = "文件bladeFileIds不可为空")
+	private String bladeFileIds;
+
+}

+ 47 - 0
blade-service-api/wt-okr-api/src/main/java/com/wtkj/entity/InnerFileAndFolder.java

@@ -0,0 +1,47 @@
+package com.wtkj.entity;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.springblade.core.mp.base.BaseEntity;
+
+import javax.validation.constraints.NotNull;
+
+/**
+ * @author Blizzard
+ * @create at 2023-09-26 11:20
+ * @describe
+ */
+@EqualsAndHashCode(callSuper = true)
+@Data
+@TableName("blade_inner_file_and_folder")
+public class InnerFileAndFolder extends BaseEntity {
+
+	private static final long serialVersionUID = 1L;
+
+	@JsonSerialize(using = ToStringSerializer.class)
+	@TableField("dept_id")
+	@NotNull(message = "deptId不可为空")
+	private Long deptId;
+
+	@JsonSerialize(using = ToStringSerializer.class)
+	@TableField("parent_id")
+	private Long parentId = 0L;
+
+	@TableField("title")
+	private String title;
+
+	@TableField("type")
+	@ApiModelProperty(value = "1:文件 2:文件夹")
+	@NotNull(message = "type不可为空")
+	private Integer type;
+
+	@JsonSerialize(using = ToStringSerializer.class)
+	@TableField("blade_file_id")
+	private Long bladeFileId;
+
+}

+ 26 - 0
blade-service-api/wt-okr-api/src/main/java/com/wtkj/vo/FileAndFolderHistoryVO.java

@@ -0,0 +1,26 @@
+package com.wtkj.vo;
+
+import com.wtkj.entity.FileAndFolderHistory;
+import com.wutong.file.vo.FileVO;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * @author Blizzard
+ * @create at 2023-09-26 14:27
+ * @describe
+ */
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class FileAndFolderHistoryVO extends FileAndFolderHistory {
+
+	private FileVO fileVO;
+
+	private String userName;
+
+	private String deptName;
+
+	private String coverUser;
+
+	private String coverDept;
+}

+ 27 - 0
blade-service-api/wt-okr-api/src/main/java/com/wtkj/vo/InnerFileAndFolderVO.java

@@ -0,0 +1,27 @@
+package com.wtkj.vo;
+
+import com.wtkj.entity.InnerFileAndFolder;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * @author Blizzard
+ * @create at 2023-09-26 22:50
+ * @describe
+ */
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class InnerFileAndFolderVO extends InnerFileAndFolder {
+
+	private static final long serialVersionUID = 1L;
+
+	private String createUserName;
+
+	private Integer fileAmount;
+
+	private String volume;
+
+	private String suffix;
+
+	private String url;
+}

+ 35 - 0
blade-service/wt-okr/pom.xml

@@ -41,6 +41,41 @@
             <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>
     </dependencies>
 
 

+ 83 - 0
blade-service/wt-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/wt-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";
+
+}

+ 2 - 0
blade-service/wt-okr/src/main/java/com/wtkj/config/MagicValue.java

@@ -34,4 +34,6 @@ public interface MagicValue {
 	Integer ONE = 1;
 
 	Integer TWO = 2;
+
+	String PROJECT_RESOURCE_INDEX = "project_resource_index";
 }

+ 67 - 0
blade-service/wt-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);
+	}
+
+
+}

+ 20 - 2
blade-service/wt-okr/src/main/java/com/wtkj/controller/FileAndFolderController.java

@@ -7,11 +7,14 @@ 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;
@@ -47,6 +50,7 @@ public class FileAndFolderController {
 
 	private final IFileReadService fileReadService;
 
+	public final IFileAndFolderHistoryService historyService;
 
 	/**
 	 * 新建文件夹
@@ -58,11 +62,12 @@ public class FileAndFolderController {
 		LambdaQueryWrapper<FileAndFolder> lqw = new LambdaQueryWrapper<>();
 		lqw.eq(FileAndFolder::getStageId, folder.getStageId());
 		lqw.eq(FileAndFolder::getTitle, folder.getTitle());
+		lqw.eq(FileAndFolder::getParentId, folder.getParentId());
 		if (Objects.equals(folder.getType(), ONE)) {
 			lqw.eq(FileAndFolder::getType, ONE);
 			long cnt = fileAndFolderService.count(lqw);
 			if (cnt > 0L) {
-				throw new ServiceException("此项目阶段下已经存在同名文件");
+				throw new ServiceException("此项目阶段下已经存在同名文件");
 			}
 		} else if (Objects.equals(folder.getType(), TWO)) {
 			lqw.eq(FileAndFolder::getType, TWO);
@@ -159,7 +164,7 @@ public class FileAndFolderController {
 	 */
 	@GetMapping("/file-detail")
 	@ApiOperationSupport(order = 10)
-	@ApiOperation(value = "阅读文件", notes = "")
+	@ApiOperation(value = "文件详情", notes = "")
 	public R<FileAndFolderVO> detail(@RequestParam Long id) {
 		FileAndFolder byId = fileAndFolderService.getById(id);
 		return R.data(FileAndFolderWrapper.build().entityVO(byId));
@@ -190,4 +195,17 @@ public class FileAndFolderController {
 		return R.data(FileAndFolderWrapper.build().pageVO(page));
 	}
 
+	/**
+	 * 文件历史
+	 */
+	@GetMapping("/v2/file-history")
+	@ApiOperationSupport(order = 21)
+	@ApiOperation(value = "文件历史", notes = "传入fileId字段,注意非主键id")
+	public R fileHistory(@RequestParam Long fileId, Query query) {
+		IPage<FileAndFolderHistory> page = historyService.getPage(fileId, Condition.getPage(query));
+		return R.data(FileAndFolderHistoryWrapper.build().pageVO(page));
+	}
+
+
+
 }

+ 1 - 0
blade-service/wt-okr/src/main/java/com/wtkj/controller/IndexController.java

@@ -51,6 +51,7 @@ public class IndexController {
 	@ApiOperationSupport(order = 2)
 	@ApiOperation(value = "新增或者修改工作状态", notes = "")
 	public R submit(@RequestBody WorkStatus status) {
+		status.setUserId(AuthUtil.getUserId());
 		return R.status(workStatus.saveOrUpdate(status));
 	}
 

+ 22 - 0
blade-service/wt-okr/src/main/java/com/wtkj/controller/QrCodeController.java

@@ -2,6 +2,7 @@ package com.wtkj.controller;
 
 import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
 import com.wtkj.dto.InviteToDeptDTO;
+import com.wtkj.entity.FileShare;
 import com.wtkj.service.IQrcodeService;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
@@ -66,4 +67,25 @@ public class QrCodeController {
 		return R.status(qrcodeService.inviteToProject(qrcodeId, topDept, projectId));
 	}
 
+
+	/**
+	 * 生成一条分享记录
+	 */
+	@PostMapping("/save-share")
+	@ApiOperationSupport(order = 5)
+	@ApiOperation(value = "生成文件分享", notes = "ids:文件的")
+	public R saveShare(@RequestBody FileShare share) {
+		return R.data(qrcodeService.savaShare(share));
+	}
+
+	/**
+	 * 查看分享
+	 */
+	@PostMapping("/get-share")
+	@ApiOperationSupport(order = 6)
+	@ApiOperation(value = "查看文件分享", notes = "传入二维码返回ID")
+	public R getShare(@RequestParam Long id) {
+		return R.data(qrcodeService.getShare(id));
+	}
+
 }

+ 123 - 0
blade-service/wt-okr/src/main/java/com/wtkj/controller/ResourceController.java

@@ -0,0 +1,123 @@
+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.InnerFileAndFolder;
+import com.wtkj.service.ICommonService;
+import com.wtkj.service.IInnerFileAndFolderService;
+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) {
+		return R.data(null);
+	}
+
+}

+ 122 - 0
blade-service/wt-okr/src/main/java/com/wtkj/handler/EsFileHandler.java

@@ -0,0 +1,122 @@
+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.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();
+		}
+	}
+}

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

@@ -0,0 +1,28 @@
+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 content;
+
+	private Integer currentPage;
+}

+ 2 - 0
blade-service/wt-okr/src/main/java/com/wtkj/mapper/FileAndFolderHistoryMapper.java

@@ -1,6 +1,7 @@
 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;
@@ -14,4 +15,5 @@ public interface FileAndFolderHistoryMapper extends BaseMapper<FileAndFolderHist
 	List<FileAndFolderHistory> selectByLatestId(Long bladeFileId);
 
 
+	List<FileAndFolderHistory> getPage(Long fileId, IPage<FileAndFolderHistory> page);
 }

+ 4 - 2
blade-service/wt-okr/src/main/java/com/wtkj/mapper/FileAndFolderHistoryMapper.xml

@@ -7,7 +7,9 @@
         select * from blade_file_and_folder_history where is_deleted = 0 and latest_id = #{param}
     </select>
 
-    <select id="getFileAmountByFolderId" resultType="java.lang.Integer">
-        select count(id) from blade_file_folder where is_deleted = 0 and parent_id = #{param1} and type = 1
+
+    <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>

+ 12 - 0
blade-service/wt-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/wt-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>

+ 24 - 0
blade-service/wt-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/wt-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>

+ 3 - 3
blade-service/wt-okr/src/main/java/com/wtkj/mapper/TaskMapper.xml

@@ -26,13 +26,13 @@
     <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 is_confirmed = 0 order_by create_time
+        DATE_FORMAT(end_time,'%Y-%m-%d') = DATE_FORMAT(#{param2},'%Y-%m-%d') and is_confirmed = 0 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 is_confirmed = 0 order_by create_time
+        DATE_FORMAT(#{param2},'%Y-%m-%d') > DATE_FORMAT(end_time,'%Y-%m-%d') and is_confirmed = 0 order by create_time
     </select>
 
     <select id="getByOrgDeptId" resultType="com.wtkj.entity.Task">
@@ -46,7 +46,7 @@
     <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 is_confirmed = 0 order_by create_time
+        DATE_FORMAT(#{param2},'%Y-%m-%d') >= DATE_FORMAT(end_time,'%Y-%m-%d') and is_confirmed = 0 order by create_time
     </select>
 
     <select id="getTodayTodoByOrgDeptId" resultType="com.wtkj.entity.Task">

+ 5 - 0
blade-service/wt-okr/src/main/java/com/wtkj/service/ICommonService.java

@@ -1,6 +1,7 @@
 package com.wtkj.service;
 
 import com.wtkj.dto.UploadFileDTO;
+import com.wtkj.dto.UploadInnerFileDTO;
 
 import java.util.List;
 
@@ -18,4 +19,8 @@ public interface ICommonService {
 	boolean remove(List<Long> ids);
 
 	boolean move(String ids, Long stageId, Long parentId);
+
+	boolean delete(List<Long> ids);
+
+	boolean uploadInnerFile(List<UploadInnerFileDTO> files);
 }

+ 2 - 0
blade-service/wt-okr/src/main/java/com/wtkj/service/IFileAndFolderHistoryService.java

@@ -1,5 +1,6 @@
 package com.wtkj.service;
 
+import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.wtkj.entity.FileAndFolderHistory;
 import org.springblade.core.mp.base.BaseService;
 
@@ -14,4 +15,5 @@ public interface IFileAndFolderHistoryService extends BaseService<FileAndFolderH
 	List<FileAndFolderHistory> getByLatestId(Long bladeFileId);
 
 
+	IPage<FileAndFolderHistory> getPage(Long fileId, IPage<FileAndFolderHistory> page);
 }

+ 12 - 0
blade-service/wt-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> {
+}

+ 30 - 0
blade-service/wt-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);
+
+}

+ 7 - 0
blade-service/wt-okr/src/main/java/com/wtkj/service/IQrcodeService.java

@@ -1,6 +1,10 @@
 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
@@ -18,4 +22,7 @@ public interface IQrcodeService {
 
 	JSONObject createGroupQrcode(Long projectId);
 
+	Long savaShare(FileShare share);
+
+	List<FileAttach> getShare(Long id);
 }

+ 56 - 0
blade-service/wt-okr/src/main/java/com/wtkj/service/impl/CommonServiceImpl.java

@@ -3,15 +3,19 @@ package com.wtkj.service.impl;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 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.service.ICommonService;
 import com.wtkj.service.IFileAndFolderHistoryService;
 import com.wtkj.service.IFileAndFolderService;
+import com.wtkj.service.IInnerFileAndFolderService;
 import com.wutong.file.feign.IFileClient;
 import com.wutong.file.vo.FileVO;
 import lombok.AllArgsConstructor;
 import org.springblade.core.log.exception.ServiceException;
+import org.springblade.core.secure.utils.AuthUtil;
 import org.springblade.core.tool.api.R;
 import org.springblade.core.tool.utils.Func;
 import org.springblade.core.tool.utils.StringUtil;
@@ -37,6 +41,7 @@ public class CommonServiceImpl implements ICommonService {
 	private final IFileClient fileClient;
 	private final IFileAndFolderService fileAndFolderService;
 	private final IFileAndFolderHistoryService historyService;
+	private final IInnerFileAndFolderService innerFileAndFolderService;
 
 
 	@Override
@@ -176,4 +181,55 @@ public class CommonServiceImpl implements ICommonService {
 		}
 		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;
+
+
+	}
 }

+ 6 - 0
blade-service/wt-okr/src/main/java/com/wtkj/service/impl/FileAndFolderHistoryServiceImpl.java

@@ -1,5 +1,6 @@
 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;
@@ -22,4 +23,9 @@ public class FileAndFolderHistoryServiceImpl extends BaseServiceImpl<FileAndFold
 		return baseMapper.selectByLatestId(bladeFileId);
 	}
 
+	@Override
+	public IPage<FileAndFolderHistory> getPage(Long fileId, IPage<FileAndFolderHistory> page) {
+		return page.setRecords(baseMapper.getPage(fileId, page));
+	}
+
 }

+ 18 - 0
blade-service/wt-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 {
+}

+ 135 - 0
blade-service/wt-okr/src/main/java/com/wtkj/service/impl/InnerFileAndFolderServiceImpl.java

@@ -0,0 +1,135 @@
+package com.wtkj.service.impl;
+
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.wtkj.entity.InnerFileAndFolder;
+import com.wtkj.mapper.InnerFileAndFolderMapper;
+import com.wtkj.service.IInnerFileAndFolderService;
+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.springblade.core.tool.utils.StringUtil;
+import org.springframework.stereotype.Service;
+import org.springframework.util.CollectionUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author Blizzard
+ * @create at 2023-09-26 14:44
+ * @describe
+ */
+@Service
+@AllArgsConstructor
+public class InnerFileAndFolderServiceImpl extends BaseServiceImpl<InnerFileAndFolderMapper, InnerFileAndFolder> implements IInnerFileAndFolderService {
+
+	private final IFileClient fileClient;
+
+	@Override
+	public List<InnerFileAndFolder> getChildren(Long deptId, Long parentId) {
+		return getChildrenByFolderId(new ArrayList<>(), deptId, parentId);
+	}
+
+	@Override
+	public IPage<InnerFileAndFolder> selectPage(Long deptId, Long parentId, String name, IPage<InnerFileAndFolder> page) {
+		if (StringUtil.isNotBlank(name)) {
+			parentId = null;
+		}
+		return page.setRecords(baseMapper.getPage(deptId, parentId, name, page));
+	}
+
+	@Override
+	public JSONObject getPageAndFileAmount(Long deptId, Long parentId) {
+
+		JSONObject result = new JSONObject();
+		//文件数量
+		Integer fileAmount = this.getFileAmountByFolderId(deptId, parentId);
+		result.put("amount", fileAmount);
+		//文件
+		int totalPage = 0;
+		int volume = 0;
+		List<InnerFileAndFolder> files = this.getChildrenFilesByFolderId(deptId, 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<InnerFileAndFolder> folders = this.getChildrenFolderByFolderId(deptId, parentId);
+		if (!CollectionUtils.isEmpty(folders)) {
+			folderAmount = folders.size();
+		}
+		result.put("folderAmount", folderAmount);
+		return result;
+	}
+
+	@Override
+	public Integer getFileAmountByFolderId(Long deptId, Long parentId) {
+		//递归子级文件夹 获取文件个数
+		return getChildrenFileAmountByFolderId(0, deptId, parentId);
+	}
+
+	@Override
+	public List<InnerFileAndFolder> getChildrenFilesByFolderId(Long deptId, Long parentId) {
+		return getChildrenFileByFolderId(new ArrayList<>(), deptId, parentId);
+	}
+
+	@Override
+	public List<InnerFileAndFolder> getChildrenFolderByFolderId(Long deptId, Long parentId) {
+		return baseMapper.getChildrenFolderList(deptId, parentId);
+	}
+
+
+	private List<InnerFileAndFolder> getChildrenFileByFolderId(ArrayList<InnerFileAndFolder> result, Long deptId, Long parentId) {
+		//本级下的文件
+		List<InnerFileAndFolder> files = baseMapper.getChildrenFileList(deptId, parentId);
+		if (!org.springframework.util.CollectionUtils.isEmpty(files)) {
+			result.addAll(files);
+		}
+		//本级的文件夹
+		List<InnerFileAndFolder> childrenFolder = baseMapper.getChildrenFolderList(deptId, parentId);
+		//递归出口,子集不为空时,一直去遍历
+		if (!com.baomidou.mybatisplus.core.toolkit.CollectionUtils.isEmpty(childrenFolder)) {
+			for (InnerFileAndFolder folder : childrenFolder) {
+				getChildrenFileByFolderId(result, folder.getDeptId(), folder.getId());
+			}
+		}
+		return result;
+	}
+
+	private Integer getChildrenFileAmountByFolderId(int count, Long deptId, Long parentId) {
+		//本级下的文件数量
+		count = count + baseMapper.getFileAmountByFolderId(deptId, parentId);
+		//本级下的文件夹
+		List<InnerFileAndFolder> children = baseMapper.getChildrenFolderList(deptId, parentId);
+		//递归出口,子集不为空时,一直去遍历
+		if (children != null && !children.isEmpty()) {
+			for (InnerFileAndFolder child : children) {
+				int cnt = getChildrenFileAmountByFolderId(0, child.getDeptId(), child.getId());
+				count = cnt + count;
+			}
+		}
+		return count;
+
+	}
+
+	private List<InnerFileAndFolder> getChildrenByFolderId(ArrayList<InnerFileAndFolder> result, Long deptId, Long parentId) {
+		//文件下的文件和文件夹
+		List<InnerFileAndFolder> children = baseMapper.getChildren(parentId);
+		if (!org.springframework.util.CollectionUtils.isEmpty(children)) {
+			result.addAll(children);
+		}
+		//本级的文件夹
+		List<InnerFileAndFolder> childrenFolder = baseMapper.getChildrenFolderList(deptId, parentId);
+		if (!CollectionUtils.isEmpty(childrenFolder)) {
+			for (InnerFileAndFolder folder : childrenFolder) {
+				getChildrenByFolderId(result, folder.getDeptId(), folder.getId());
+			}
+		}
+		return result;
+	}
+}

+ 1 - 1
blade-service/wt-okr/src/main/java/com/wtkj/service/impl/ProjectServiceImpl.java

@@ -156,7 +156,7 @@ public class ProjectServiceImpl extends BaseServiceImpl<ProjectMapper, Project>
 			lqw.eq(dto.getYear() != null, Project::getYear, dto.getYear());
 			//项目名称
 			if (StringUtil.isNotBlank(dto.getName())) {
-				lqw.eq(Project::getName, dto.getName());
+				lqw.like(Project::getName, dto.getName());
 			}
 			//区域
 			if (StringUtil.isNotBlank(dto.getAreaCode())) {

+ 51 - 4
blade-service/wt-okr/src/main/java/com/wtkj/service/impl/QrcodeServiceImpl.java

@@ -2,11 +2,10 @@ package com.wtkj.service.impl;
 
 import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.toolkit.IdWorker;
-import com.wtkj.entity.ContactOuter;
-import com.wtkj.entity.Project;
-import com.wtkj.entity.ProjectAuth;
-import com.wtkj.entity.ProjectGroup;
+import com.wtkj.entity.*;
 import com.wtkj.service.*;
+import com.wutong.file.entity.FileAttach;
+import com.wutong.file.feign.IFileClient;
 import io.seata.spring.annotation.GlobalTransactional;
 import lombok.AllArgsConstructor;
 import org.springblade.core.log.exception.ServiceException;
@@ -19,6 +18,8 @@ import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
 import java.time.Duration;
+import java.util.ArrayList;
+import java.util.List;
 
 import static com.wtkj.config.NacosConfigValue.expireIn;
 import static com.wtkj.config.NacosConfigValue.scanCount;
@@ -38,6 +39,8 @@ public class QrcodeServiceImpl implements IQrcodeService {
 	private final IProjectGroupService projectGroupService;
 	private final IContactOuterService contactOuterService;
 	private final IProjectService projectService;
+	private final IFileShareService fileShareService;
+	private final IFileClient fileClient;
 
 	@Override
 	public JSONObject createQrcode() {
@@ -113,6 +116,35 @@ public class QrcodeServiceImpl implements IQrcodeService {
 		return res;
 	}
 
+	@Override
+	public Long savaShare(FileShare share) {
+		Long key = null;
+		boolean save = fileShareService.save(share);
+		if (save) {
+			key = share.getId();
+			redis.setEx(String.valueOf(key), 0, Duration.ofDays(3));
+		}
+		return key;
+	}
+
+	@Override
+	public List<FileAttach> getShare(Long id) {
+		List<FileAttach> res = new ArrayList<>();
+		boolean available = isAvailable(String.valueOf(id));
+		if (available) {
+			FileShare byId = fileShareService.getById(id);
+			if (byId != null) {
+				String bladeFileIds = byId.getBladeFileIds();
+				R<List<FileAttach>> rpc = fileClient.fileList(bladeFileIds);
+				if (rpc.isSuccess()) {
+					res = rpc.getData();
+				}
+
+			}
+		}
+		return res;
+	}
+
 	/**
 	 * 判断二维码是否有效和是否达到扫描上限
 	 */
@@ -130,4 +162,19 @@ public class QrcodeServiceImpl implements IQrcodeService {
 		}
 		return flag;
 	}
+
+	private boolean isAvailable(String key) {
+		boolean flag = false;
+		Boolean exists = redis.exists(key);
+		//如果存在
+		if (exists) {
+			Long count = redis.incrBy(key, 1);
+			if (count > 20) {
+				throw new ServiceException("二维码只能扫描" + 20 + "次数");
+			} else {
+				flag = true;
+			}
+		}
+		return flag;
+	}
 }

+ 73 - 0
blade-service/wt-okr/src/main/java/com/wtkj/wrapper/FileAndFolderHistoryWrapper.java

@@ -0,0 +1,73 @@
+package com.wtkj.wrapper;
+
+import com.wtkj.entity.FileAndFolderHistory;
+import com.wtkj.vo.FileAndFolderHistoryVO;
+import com.wutong.file.feign.IFileClient;
+import com.wutong.file.vo.FileVO;
+import org.springblade.core.mp.support.BaseEntityWrapper;
+import org.springblade.core.tool.api.R;
+import org.springblade.core.tool.utils.BeanUtil;
+import org.springblade.core.tool.utils.SpringUtil;
+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 java.util.Objects;
+
+/**
+ * @author Blizzard
+ * @create at 2023-09-26 14:28
+ * @describe
+ */
+public class FileAndFolderHistoryWrapper extends BaseEntityWrapper<FileAndFolderHistory, FileAndFolderHistoryVO> {
+
+	private static IFileClient fileClient;
+
+	private static IUserClient userClient;
+
+	private static ISysClient sysClient;
+
+	public static FileAndFolderHistoryWrapper build() {
+
+		fileClient = SpringUtil.getBean(IFileClient.class);
+		userClient = SpringUtil.getBean(IUserClient.class);
+		sysClient = SpringUtil.getBean(ISysClient.class);
+
+		return new FileAndFolderHistoryWrapper();
+	}
+
+	@Override
+	public FileAndFolderHistoryVO entityVO(FileAndFolderHistory entity) {
+		FileAndFolderHistoryVO vo = Objects.requireNonNull(BeanUtil.copy(entity, FileAndFolderHistoryVO.class));
+		//覆盖者 覆盖人
+		Long createUser = entity.getCreateUser();
+		Long createDept = entity.getCreateDept();
+		R<User> userR = userClient.userInfoById(createUser);
+		if (userR.isSuccess()) {
+			vo.setCoverUser(userR.getData().getName());
+		}
+		R<Dept> deptR = sysClient.getDept(createDept);
+		if (deptR.isSuccess()) {
+			vo.setCoverDept(deptR.getData().getDeptName());
+		}
+		//文件
+		Long historyId = entity.getHistoryId();
+		R<FileVO> byId = fileClient.findById(historyId);
+		if (byId.isSuccess()) {
+			FileVO data = byId.getData();
+			vo.setFileVO(data);
+			Long createUser1 = data.getCreateUser();
+			Long createDept1 = data.getCreateDept();
+			R<User> userR1 = userClient.userInfoById(createUser1);
+			if (userR1.isSuccess()) {
+				vo.setUserName(userR1.getData().getName());
+			}
+			R<Dept> deptR1 = sysClient.getDept(createDept1);
+			if (deptR1.isSuccess()) {
+				vo.setDeptName(deptR1.getData().getDeptName());
+			}
+		}
+		return vo;
+	}
+}

+ 62 - 0
blade-service/wt-okr/src/main/java/com/wtkj/wrapper/InnerFileAndFolderWrapper.java

@@ -0,0 +1,62 @@
+package com.wtkj.wrapper;
+
+import com.wtkj.entity.InnerFileAndFolder;
+import com.wtkj.service.IInnerFileAndFolderService;
+import com.wtkj.vo.InnerFileAndFolderVO;
+import com.wutong.file.feign.IFileClient;
+import com.wutong.file.vo.FileVO;
+import org.springblade.core.mp.support.BaseEntityWrapper;
+import org.springblade.core.tool.api.R;
+import org.springblade.core.tool.utils.BeanUtil;
+import org.springblade.core.tool.utils.SpringUtil;
+import org.springblade.system.user.entity.User;
+import org.springblade.system.user.feign.IUserClient;
+
+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 22:51
+ * @describe
+ */
+public class InnerFileAndFolderWrapper extends BaseEntityWrapper<InnerFileAndFolder, InnerFileAndFolderVO> {
+
+	private static IUserClient userClient;
+	private static IInnerFileAndFolderService innerFileAndFolderService;
+	private static IFileClient fileClient;
+
+	public static InnerFileAndFolderWrapper build() {
+		userClient = SpringUtil.getBean(IUserClient.class);
+		innerFileAndFolderService = SpringUtil.getBean(IInnerFileAndFolderService.class);
+		fileClient = SpringUtil.getBean(IFileClient.class);
+		return new InnerFileAndFolderWrapper();
+	}
+
+	@Override
+	public InnerFileAndFolderVO entityVO(InnerFileAndFolder entity) {
+		InnerFileAndFolderVO vo = Objects.requireNonNull(BeanUtil.copy(entity, InnerFileAndFolderVO.class));
+		Long createUser = entity.getCreateUser();
+		R<User> userR = userClient.userInfoById(createUser);
+		if (userR.isSuccess()) {
+			vo.setCreateUserName(userR.getData().getName());
+		}
+
+		//如果是文件夹  展示文件夹下文件数量 如果是文件 展示大小和url
+		if (vo.getType() != null && vo.getType().equals(TWO)) {
+			Integer fileAmount = innerFileAndFolderService.getFileAmountByFolderId(null, vo.getId());
+			vo.setFileAmount(fileAmount);
+		} else if (vo.getType() != null && vo.getType().equals(ONE)) {
+			R<FileVO> rpc = fileClient.findById(vo.getBladeFileId());
+			if (rpc.isSuccess()) {
+				vo.setVolume(rpc.getData().getVolume());
+				vo.setUrl(rpc.getData().getFilePath());
+				vo.setSuffix(rpc.getData().getSuffix());
+			}
+		}
+
+		return vo;
+	}
+}