Ver Fonte

add file version

zero há 7 meses atrás
pai
commit
5b45154a6f
23 ficheiros alterados com 1216 adições e 2 exclusões
  1. 148 0
      src/main/java/com/example/fms/common/core/Constants.java
  2. 13 0
      src/main/java/com/example/fms/common/core/base/WebSocketConfig.java
  3. 11 0
      src/main/java/com/example/fms/common/model/dto/FileVersionCallbackHistoryDTO.java
  4. 9 0
      src/main/java/com/example/fms/common/model/dto/QueryFileVersionDTO.java
  5. 11 0
      src/main/java/com/example/fms/common/model/vo/FileVersionCallbackVO.java
  6. 26 0
      src/main/java/com/example/fms/common/model/vo/FileVersionInfoVO.java
  7. 14 0
      src/main/java/com/example/fms/common/model/vo/WebSocketMessageVO.java
  8. 62 0
      src/main/java/com/example/fms/common/utils/RandomUtil.java
  9. 2 1
      src/main/java/com/example/fms/common/utils/ResponseEnum.java
  10. 46 0
      src/main/java/com/example/fms/controller/FileVersionController.java
  11. 27 0
      src/main/java/com/example/fms/domain/FileOperateRecord.java
  12. 49 0
      src/main/java/com/example/fms/domain/FileVersion.java
  13. 116 0
      src/main/java/com/example/fms/domain/Personnel.java
  14. 11 0
      src/main/java/com/example/fms/mapper/FileOperateRecordMapper.java
  15. 16 0
      src/main/java/com/example/fms/mapper/FileVersionMapper.java
  16. 193 0
      src/main/java/com/example/fms/service/FileVersionService.java
  17. 23 0
      src/main/java/com/example/fms/service/permissions/MessageService.java
  18. 251 0
      src/main/java/com/example/fms/service/permissions/PermissionService.java
  19. 113 0
      src/main/java/com/example/fms/service/permissions/WebSocketServer.java
  20. 4 1
      src/main/resources/application-dev.yml
  21. 5 0
      src/main/resources/mapper/FileOperateRecord.xml
  22. 25 0
      src/main/resources/mapper/FileVersionMapper.xml
  23. 41 0
      src/test/java/com/example/fms/FileVersionTest.java

+ 148 - 0
src/main/java/com/example/fms/common/core/Constants.java

@@ -0,0 +1,148 @@
+package com.example.fms.common.core;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class Constants {
+
+    public static final String ADMIN_USERNAME = "admin";
+
+    public static final String PROJECT_INFO_FILE_NAME = "project.json";
+    public static final String PROJECT_REPORT_DIRECTORY_NAME = "project-report";
+    public static final String PROJECT_REPORT_FILE_NAME = "project-report.json";
+    public static final String PROJECT_FILE_DIRECTORY_NAME = "project-file";
+    public static final String PROJECT_FILE_FILE_NAME = "project-file.json";
+    public static final String PROJECT_PATENT_LINK_FILE_NAME = "project-patent-link.json";
+    public static final String PATENT_IMAGE_DIRECTORY_NAME = "patent-image";
+    public static final String PATENT_IMAGE_FILE_NAME = "patent-image.json";
+    public static final String PATENT_INSTRUCTION_DIRECTORY_NAME = "patent-instruction";
+    public static final String PATENT_INSTRUCTION_FILE_NAME = "patent-instruction.json";
+    public static final String PATENT_APPLICANT_MERGE_LINK_FILE_NAME = "patent-applicant-merge-link.json";
+    public static final String PATENT_APPLICANT_FILE_NAME = "patent-applicant.json";
+    public static final String PATENT_APPLICANT_LINK_FILE_NAME = "patent-applicant-link.json";
+    public static final String PATENT_FILE_NAME = "patent.json";
+    public static final String PATENT_ID_PATENT_NO_FILE_NAME = "patent-id-patentno.json";
+    public static final String PATENT_AFFAIR_FILE_NAME = "patent-affair.json";
+    public static final String PATENT_AGENCY_FILE_NAME = "patent-agency.json";
+    public static final String PATENT_AGENT_LINK_FILE_NAME = "patent-agent-link.json";
+    public static final String PATENT_AGENT_FILE_NAME = "patent-agent.json";
+    public static final String PATENT_INSTRUCTION_TEXT_FILE_NAME = "patent-instruction-text.json";
+    public static final String PATENT_INVENTOR_LINK_FILE_NAME = "patent-inventor-link.json";
+    public static final String PATENT_INVENTOR_MERGE_FILE_NAME = "patent-inventor-merge.json";
+    public static final String PATENT_INVENTOR_FILE_NAME = "patent-inventor.json";
+    public static final String PATENT_LICENSOR_FILE_NAME = "patent-licensor.json";
+    public static final String PATENT_PLEDGE_FILE_NAME = "patent-pledge.json";
+    public static final String PATENT_RIGHT_FILE_NAME = "patent-right.json";
+    public static final String PATENT_FAMILY_LINK_FILE_NAME = "patent-family-link.json";
+    public static final String PATENT_FAMILY_FILE_NAME = "patent-family.json";
+    public static final String PATENT_CLASS_NUMBER_FILE_NAME = "patent-class-number.json";
+    public static final String PATENT_LABEL_FILE_NAME = "patent-label.json";
+    public static final String PROJECT_FIELD_FILE_NAME = "project-field.json";
+    public static final String PROJECT_FIELD_OPTION_FILE_NAME = "project-field-option.json";
+    public static final String PROJECT_FIELD_TREE_FILE_NAME = "project-field-tree.json";
+    public static final String PROJECT_FIELD_TEXT_FILE_NAME = "project-field-text.json";
+    public static final String PROJECT_FIELD_PATENT_LINK_FILE_NAME = "project-field-patent-link.json";
+
+    public static final String API_XiaoSHI = "/api/xiaoshi";
+
+    public static final Integer PATENT_CLASS_NUMBER_IPC = 1;
+    public static final Integer PATENT_CLASS_NUMBER_CPC = 2;
+    public static final Integer PATENT_CLASS_NUMBER_UPC = 3;
+    public static final Integer PATENT_CLASS_NUMBER_LOC = 4;
+    public static final Integer MAX_IMPORT_TASK_COUNT=5;
+    public static final  Integer IMPORT_PATENT_TO=1;
+    public static final String   IMPORT_TASK_CONFIG="importTaskConfig";
+    /**
+     * 分隔符-竖线
+     */
+    public static final String SEPARATOR_VERTICAL_BAR = " | ";
+
+    /**
+     * 系统字段类型-查询检索
+     */
+    public static final String SYSTEM_FIELD_QUERY = "query";
+
+    /**
+     * 系统字段类型-专利导出
+     */
+    public static final String SYSTEM_FIELD_EXPORT = "export";
+
+    /**
+     * 系统字段类型-专利列表
+     */
+    public static final String SYSTEM_FIELD_PATENT_LIST = "list";
+
+    /**
+     * 系统字段类型-专题库字段
+     */
+    public static final String SYSTEM_FIELD_PROJECT = "project";
+
+    /**
+     * 专题库导入专利任务名称
+     */
+    public static final Integer TASK_IMPORT_PATENT = 1;
+
+    /**
+     * 专利说明书导入任务名称
+     */
+    public static final Integer TASK_IMPORT_PATENT_INSTRUCTION = 3;
+
+    /**
+     * 专利导出任务名称
+     */
+    public static final Integer TASK_EXPORT_PATENT = 2;
+
+    /**
+     * 日期位移值
+     */
+    public static final Map<String, Integer> DATE_OFFSET = new HashMap<String, Integer>() {{
+        put("月", -1);
+        put("季", -3);
+        put("半年", -6);
+        put("年", -12);
+        put("2年", -24);
+        put("3年", -36);
+        put("5年", -60);
+    }};
+
+    /**
+     * 专利类型
+     */
+    public static final String PATENT_TYPE = "PATENT_TYPE";
+
+    /**
+     * 机构类型
+     */
+    public static final String ORGAN_TYPE = "ORGAN_TYPE";
+
+    /**
+     * 许可人/被许可人
+     */
+    public static final String LICENSOR_TYPE = "LICENSOR_TYPE";
+
+    /**
+     * 简单法律状态
+     */
+    public static final String PATENT_SIMPLE_STATUS = "PATENT_SIMPLE_STATUS";
+
+    /**
+     * 国家
+     */
+    public static final String COUNTRIES = "COUNTRIES";
+
+    /**
+     * 法律状态
+     */
+    public static final String PATENT_STATUS = "PATENT_STATUS";
+
+    /**
+     * 企业应用场景
+     */
+    public static final String ENTERPRISE_APPLICATION_SCENARIO = "ENTERPRISE_APPLICATION_SCENARIO";
+
+    /**
+     * 调查类型
+     */
+    public static final String INVESTIGATION_TYPE = "INVESTIGATION_TYPE";
+
+}

+ 13 - 0
src/main/java/com/example/fms/common/core/base/WebSocketConfig.java

@@ -0,0 +1,13 @@
+package com.example.fms.common.core.base;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.socket.server.standard.ServerEndpointExporter;
+
+@Configuration
+public class WebSocketConfig {
+//    @Bean
+//    public ServerEndpointExporter serverEndpointExporter() {
+//        return new ServerEndpointExporter();
+//    }
+}

+ 11 - 0
src/main/java/com/example/fms/common/model/dto/FileVersionCallbackHistoryDTO.java

@@ -0,0 +1,11 @@
+package com.example.fms.common.model.dto;
+
+import lombok.Data;
+
+@Data
+public class FileVersionCallbackHistoryDTO {
+
+    private String changes;
+
+    private String serverVersion;
+}

+ 9 - 0
src/main/java/com/example/fms/common/model/dto/QueryFileVersionDTO.java

@@ -0,0 +1,9 @@
+package com.example.fms.common.model.dto;
+
+import lombok.Data;
+
+@Data
+public class QueryFileVersionDTO {
+
+    private String guid;
+}

+ 11 - 0
src/main/java/com/example/fms/common/model/vo/FileVersionCallbackVO.java

@@ -0,0 +1,11 @@
+package com.example.fms.common.model.vo;
+
+import lombok.Data;
+
+@Data
+public class FileVersionCallbackVO {
+
+    private String data;
+
+    private Integer code;
+}

+ 26 - 0
src/main/java/com/example/fms/common/model/vo/FileVersionInfoVO.java

@@ -0,0 +1,26 @@
+package com.example.fms.common.model.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.util.Date;
+
+@Data
+public class FileVersionInfoVO {
+    private Integer fileVersionId;
+    private String fileName;
+    private String fileType;
+    private String fileKey;
+    private String url;
+    private String changesUrl;
+    private Integer version;
+    private String originalFile;
+    private String changes;
+    private String serverVersion;
+    private Integer previousVersion;
+    private String user;
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
+    @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd")
+    private Date created;
+}

+ 14 - 0
src/main/java/com/example/fms/common/model/vo/WebSocketMessageVO.java

@@ -0,0 +1,14 @@
+package com.example.fms.common.model.vo;
+
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+/**
+ * 拆分保存特征的前端传输DTO类
+ */
+@Data
+@Accessors(chain = true)
+public class WebSocketMessageVO {
+    private Integer code;
+    private String message;
+}

+ 62 - 0
src/main/java/com/example/fms/common/utils/RandomUtil.java

@@ -0,0 +1,62 @@
+package com.example.fms.common.utils;
+
+import java.security.SecureRandom;
+import java.util.Random;
+import java.util.UUID;
+
+public class RandomUtil {
+
+    // 定义可用来生成邀请码的字符集
+    private static final String CHARACTERS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
+    // 定义邀请码的长度
+    private static final int CODE_LENGTH = 10;
+
+    private static String[] STR_ARR = new String[] { "a", "b", "c", "d", "e",
+            "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r",
+            "s", "t", "u", "v", "w", "x", "y", "z", "A", "B", "C", "D", "E",
+            "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R",
+            "S", "T", "U", "V", "W", "X", "Y", "Z", "1", "2", "3", "4", "5",
+            "6", "7", "8", "9", "0"};
+
+    /**
+     * 随机验证码
+     * @return
+     */
+    public static String getSixRandom(){
+        return String.valueOf((int) ((Math.random() * 9 + 1) * Math.pow(10, 5)));
+    }
+
+    /**
+     * 随机生成code码的方法
+     * @param length
+     * @return
+     */
+    public static String generateRandomString(int length) {
+        StringBuilder sb = new StringBuilder();
+        Random rand = new Random();
+        for (int i = 0; i < length; i++) {
+            sb.append(STR_ARR[rand.nextInt(STR_ARR.length)]);
+        }
+        return sb.toString();
+    }
+
+    /**
+     * 生成随机邀请码的方法
+     *
+     * @return 生成的邀请码
+     */
+    public static String generateInvitationCode() {
+        SecureRandom random = new SecureRandom();
+        StringBuilder codeBuilder = new StringBuilder(CODE_LENGTH);
+
+        for (int i = 0; i < CODE_LENGTH; i++) {
+            int index = random.nextInt(CHARACTERS.length());
+            codeBuilder.append(CHARACTERS.charAt(index));
+        }
+
+        return codeBuilder.toString();
+    }
+    public static  String getOnlyCode(){
+      return   UUID.randomUUID().toString().replace("-","");
+    }
+}

+ 2 - 1
src/main/java/com/example/fms/common/utils/ResponseEnum.java

@@ -7,7 +7,8 @@ package com.example.fms.common.utils;
 public enum ResponseEnum {
 
     SUCCESS(200, "请求成功"),
-    WEB_SOCKET_SUCCESS(2, "WebSocket请求成功"),
+    WEB_SOCKET_SUCCESS(702, "WebSocket请求成功"),
+    WEB_SOCKET_RECOVER_SUCCESS(703, "WebSocket恢复请求成功"),
     BATCH_UPLOAD_INSTRUCTION_TASK_SUCCESS(900, "WebSocket请求成功"),
     PROJECT_IMPORT_TASK_SUCCESS(901, "WebSocket请求成功"),
     PROJECT_EXPORT_TASK_SUCCESS(902, "WebSocket请求成功"),

+ 46 - 0
src/main/java/com/example/fms/controller/FileVersionController.java

@@ -0,0 +1,46 @@
+package com.example.fms.controller;
+
+import com.example.fms.common.model.dto.QueryFileVersionDTO;
+import com.example.fms.common.model.vo.FileVersionCallbackVO;
+import com.example.fms.common.model.vo.FileVersionInfoVO;
+import com.example.fms.common.utils.Response;
+import com.example.fms.service.FileVersionService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.io.IOException;
+import java.util.Map;
+
+@Tag(name = "文件版本模块")
+@Slf4j
+@RestController
+@RequiredArgsConstructor
+@RequestMapping("/fileVersion")
+public class FileVersionController {
+
+    @Autowired
+    private FileVersionService fileVersionService;
+
+    @PostMapping("/callback")
+    @Operation(summary = "onlyoffice回调函数(文件保存)")
+    public FileVersionCallbackVO callback(@RequestBody Map<String, Object> params, @RequestParam String guid,
+                                          @RequestParam String fileName, @RequestParam String user,
+                                          @RequestParam Integer previousVersion) throws IOException {
+        Integer code = fileVersionService.callback(params, guid, fileName, user, previousVersion);
+        FileVersionCallbackVO callbackVO = new FileVersionCallbackVO();
+        callbackVO.setData("error");
+        callbackVO.setCode(code);
+        return callbackVO;
+    }
+
+    @PostMapping("/getCurrentVersionData")
+    @Operation(summary = "获取当前显示版本数据")
+    public String getCurrentVersionData(@RequestBody QueryFileVersionDTO vo) throws IOException {
+        FileVersionInfoVO versionData = fileVersionService.getCurrentVersionData(vo);
+        return Response.success(versionData);
+    }
+}

+ 27 - 0
src/main/java/com/example/fms/domain/FileOperateRecord.java

@@ -0,0 +1,27 @@
+package com.example.fms.domain;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.example.fms.common.model.BaseEntity;
+import lombok.Data;
+
+import java.util.Date;
+
+@Data
+@TableName("FILE_OPERATE_RECORD")
+public class FileOperateRecord extends BaseEntity<FileOperateRecord> {
+    @TableField("current_version")
+    private Integer currentVersion;
+    @TableField("previous_version")
+    private Integer previousVersion;
+    @TableField("original_file")
+    private String originalFile;
+    @TableField("operate")
+    private String operate;
+    @TableField("user_id")
+    private String userId;
+    @TableField("user_name")
+    private String userName;
+    @TableField("create_time")
+    private Date createTime;
+}

+ 49 - 0
src/main/java/com/example/fms/domain/FileVersion.java

@@ -0,0 +1,49 @@
+package com.example.fms.domain;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.example.fms.common.model.BaseEntity;
+import lombok.Data;
+
+import java.util.Date;
+
+
+@Data
+@TableName("FILE_VERSION")
+public class FileVersion extends BaseEntity<FileVersion> {
+    //文件名称
+    @TableField("file_name")
+    private String fileName;
+    //文件类型
+    @TableField("file_type")
+    private String fileType;
+    //自定义随机数字串
+    @TableField("file_key")
+    private String fileKey;
+    //回调文件guid
+    @TableField("url")
+    private String url;
+    //回调zip文件guid
+    @TableField("changes_url")
+    private String changesUrl;
+    //版本
+    @TableField("version")
+    private Integer version;
+    //原始文件
+    @TableField("original_file")
+    private String originalFile;
+
+    @TableField("changes")
+    private String changes;
+    @TableField("server_version")
+    private String serverVersion;
+    //上一个版本
+    @TableField("previous_version")
+    private Integer previousVersion;
+    //编辑人
+    @TableField("user")
+    private String user;
+    //创建时间
+    @TableField("created")
+    private Date created;
+}

+ 116 - 0
src/main/java/com/example/fms/domain/Personnel.java

@@ -0,0 +1,116 @@
+package com.example.fms.domain;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.example.fms.common.model.BaseEntity;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+/**
+ * @author 沈永艺
+ * @date 2022-8-2
+ * @description 人员类 数据库对应实体
+ */
+
+@Data
+@Accessors(chain = true)
+@EqualsAndHashCode(callSuper = true)
+@TableName(value = "PERSONNEL")
+public class Personnel extends BaseEntity<Personnel> {
+
+
+
+    /**
+     * 人员账号
+     */
+    @TableField(value = "PERSONNEL_USERNAME")
+    private String personnelUserName;
+
+    /**
+     * 人员密码
+     */
+    @TableField(value = "PERSONNEL_PASSWORD")
+    private String personnelPassword;
+
+    /**
+     * 人员名称
+     */
+    @TableField(value = "PERSONNEL_NAME")
+    private String personnelName;
+
+    /**
+     * 人员性别(1男0女)
+     */
+    @TableField(value = "PERSONNEL_SEX")
+    private Integer personnelUserSex;
+
+    /**
+     * 人员联系电话
+     */
+    @TableField(value = "PERSONNEL_PHONE")
+    private String personnelPhone;
+
+    /**
+     * 人员邮箱
+     */
+    @TableField(value = "PERSONNEL_EMAIL")
+    private String personnelEmail;
+
+    /**
+     * 人员QQ号
+     */
+    @TableField(value = "PERSONNEL_QQ")
+    private String personnelQQ;
+
+    /**
+     * 人员微信号
+     */
+    @TableField(value = "PERSONNEL_WECHAT")
+    private String personnelWechat;
+
+    /**
+     * 人员钉钉号
+     */
+    @TableField(value = "PERSONNEL_DING")
+    private String personnelDing;
+
+    /**
+     * 人员描述
+     */
+    @TableField(value = "PERSONNEL_DESCRIPTION")
+    private String personnelDescription;
+
+    /**
+     * 人员账号状态(1启用0停用)
+     */
+    @TableField(value = "PERSONNEL_STATUS")
+    private Integer personnelStatus;
+
+    /**
+     * 租户ID
+     */
+    @TableField(value = "TENANT_ID")
+    private Integer tenantId;
+
+    /**
+     * 私钥
+     */
+    @TableField(value = "PRIVATE_KEY")
+    private String privateKey;
+
+    /**
+     * 公钥
+     */
+    @TableField(value = "PUBLIC_KEY")
+    private String publicKey;
+
+    /**
+     * 对称密钥
+     */
+    @TableField(value = "SYMMETRY_KEY")
+    private String symmetryKey;
+
+    @TableField(value = "PERSON_CONFIG")
+    private String personConfig;
+}

+ 11 - 0
src/main/java/com/example/fms/mapper/FileOperateRecordMapper.java

@@ -0,0 +1,11 @@
+package com.example.fms.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.example.fms.domain.FileOperateRecord;
+import org.apache.ibatis.annotations.Mapper;
+import org.springframework.stereotype.Repository;
+
+@Repository
+@Mapper
+public interface FileOperateRecordMapper extends BaseMapper<FileOperateRecord> {
+}

+ 16 - 0
src/main/java/com/example/fms/mapper/FileVersionMapper.java

@@ -0,0 +1,16 @@
+package com.example.fms.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.example.fms.domain.FileVersion;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+import org.springframework.stereotype.Repository;
+
+@Repository
+@Mapper
+public interface FileVersionMapper extends BaseMapper<FileVersion> {
+
+    FileVersion queryFileVersionByGuid(@Param("guid") String guid);
+
+    FileVersion queryCurrentFileVersionInfo(@Param("guid") String guid);
+}

+ 193 - 0
src/main/java/com/example/fms/service/FileVersionService.java

@@ -0,0 +1,193 @@
+package com.example.fms.service;
+
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.example.fms.common.model.dto.FileVersionCallbackHistoryDTO;
+import com.example.fms.common.model.dto.QueryFileVersionDTO;
+import com.example.fms.common.model.vo.FileVersionInfoVO;
+import com.example.fms.common.model.vo.WebSocketMessageVO;
+import com.example.fms.common.utils.FileUtils;
+import com.example.fms.common.utils.RandomUtil;
+import com.example.fms.domain.FileOperateRecord;
+import com.example.fms.domain.FileVersion;
+import com.example.fms.domain.Personnel;
+import com.example.fms.mapper.FileOperateRecordMapper;
+import com.example.fms.mapper.FileVersionMapper;
+import com.example.fms.service.permissions.MessageService;
+import com.example.fms.service.permissions.PermissionService;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.ObjectUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.util.CollectionUtils;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.*;
+
+@RequiredArgsConstructor
+@Slf4j
+@Service
+public class FileVersionService {
+
+    @Autowired
+    private MessageService messageService;
+
+    @Autowired
+    private PermissionService permissionService;
+
+    @Autowired
+    private FileMangerService fileMangerService;
+
+    @Autowired
+    private FileVersionMapper fileVersionMapper;
+
+    @Autowired
+    private FileOperateRecordMapper fileOperateRecordMapper;
+
+    /**
+     * onlyoffice回调函数(文件保存)
+     * @param params
+     * @param guid
+     * @param fileName
+     * @param user
+     * @param previousVersion
+     * @return
+     * @throws IOException
+     */
+    public Integer callback(Map<String, Object> params, String guid, String fileName,
+                            String user, Integer previousVersion) throws IOException {
+        boolean flag = true;
+        if (!CollectionUtils.isEmpty(params)) {
+            int status = Integer.parseInt(params.get("status").toString());
+            String url = params.get("url").toString();
+            String changesUrl = params.get("changesurl").toString();
+            if (status == 6 && StringUtils.isNotEmpty(url)) {
+                File file = FileUtils.urlToFile(url);
+                MultipartFile multipartFile = FileUtils.fileToMultipartFile(file);
+                String replaceFile = fileMangerService.replaceFile(multipartFile, guid, 1);
+                if (StringUtils.isEmpty(replaceFile)) {
+                    flag = false;
+                }
+                WebSocketMessageVO messageVO = new WebSocketMessageVO();
+                messageVO.setMessage("文件已保存");
+                messageVO.setCode(702);
+                messageService.sendMessage(messageVO);
+            }
+            if (status == 2) {
+                if (StringUtils.isNotEmpty(url)) {
+                    File file = FileUtils.urlToFile(url);
+                    MultipartFile multipartFile = FileUtils.fileToMultipartFile(file);
+                    List<String> list = fileMangerService.uploadFile(Arrays.asList(multipartFile), 1);
+                    if (!CollectionUtils.isEmpty(list)) {
+                        url = list.get(0);
+                    } else {
+                        url = "";
+                    }
+                }
+                if (StringUtils.isNotEmpty(changesUrl)) {
+                    File file1 = FileUtils.urlToFile(changesUrl);
+                    MultipartFile multipartFile1 = FileUtils.fileToMultipartFile(file1);
+                    List<String> list1 = fileMangerService.uploadFile(Arrays.asList(multipartFile1), 1);
+                    if (!CollectionUtils.isEmpty(list1)) {
+                        changesUrl = list1.get(0);
+                    } else {
+                        changesUrl = "";
+                    }
+                }
+                this.addFileVersion(params,guid,fileName,user,previousVersion,url,changesUrl);
+            }
+        }
+        if (flag) {
+            return 0;
+        } else {
+            return 1;
+        }
+    }
+
+    public void addFileVersion(Map<String, Object> params, String guid, String fileName,
+                               String user, Integer previousVersion, String url,
+                               String changesUrl) throws IOException {
+        String fileType = params.get("filetype").toString();
+        String key = RandomUtil.generateInvitationCode();
+        String changes = "";
+        String serverVersion = "";
+        String history = params.get("history").toString();
+        if (StringUtils.isNotEmpty(history)) {
+            FileVersionCallbackHistoryDTO historyDTO = JSONObject.parseObject(history, FileVersionCallbackHistoryDTO.class);
+            changes = historyDTO.getChanges();
+            serverVersion = historyDTO.getServerVersion();
+        }
+        int version = 1;
+        String originalFile = guid;
+        FileVersion fileVersion = fileVersionMapper.queryFileVersionByGuid(originalFile);
+        if (ObjectUtils.isNotEmpty(fileVersion)) {
+            version = fileVersion.getVersion();
+            originalFile = fileVersion.getOriginalFile();
+        } else {
+            FileVersion fileVersion1 = new FileVersion();
+            fileVersion1.setFileName(fileName);
+            fileVersion1.setFileType(fileType);
+            fileVersion1.setFileKey(key);
+            fileVersion1.setUrl(url);
+            fileVersion1.setVersion(version);
+            fileVersion1.setOriginalFile(guid);
+            fileVersion1.setUser(user);
+            fileVersion1.insert();
+        }
+        version += 1;
+        //添加新版本数据
+        FileVersion version1 = new FileVersion();
+        version1.setFileName(fileName);
+        version1.setFileType(fileType);
+        version1.setFileKey(key);
+        version1.setUrl(url);
+        version1.setChangesUrl(changesUrl);
+        version1.setVersion(version);
+        version1.setOriginalFile(originalFile);
+        version1.setChanges(changes);
+        version1.setServerVersion(serverVersion);
+        version1.setPreviousVersion(previousVersion);
+        version1.setUser(user);
+        version1.insert();
+
+        //查询编辑人
+        List<Personnel> personnels = new ArrayList<>();
+        if (StringUtils.isNotEmpty(user)) {
+            String res = permissionService.getPersonnelByIdsFromPCS(Collections.singletonList(user));
+            JSONObject jsonObject = JSONObject.parseObject(res);
+            personnels = JSONObject.parseArray(jsonObject.getString("data"), Personnel.class);
+        }
+        //添加当前操作版本
+        FileOperateRecord operateRecord = new FileOperateRecord();
+        operateRecord.setUserId(user);
+        Personnel personnel = personnels.stream().filter(i -> i.getId().toString().equals(user)).findFirst().orElse(null);
+        if (ObjectUtils.isNotEmpty(personnel)) {
+            operateRecord.setUserName(personnel.getPersonnelName());
+        }
+        operateRecord.setCurrentVersion(version);
+        operateRecord.setPreviousVersion(previousVersion);
+        operateRecord.setOperate("2");
+        operateRecord.setOriginalFile(originalFile);
+        operateRecord.insert();
+    }
+
+    /**
+     * 获取当前显示版本数据
+     * @param vo
+     * @return
+     */
+    public FileVersionInfoVO getCurrentVersionData(QueryFileVersionDTO vo) {
+        FileVersion fileVersion = fileVersionMapper.queryCurrentFileVersionInfo(vo.getGuid());
+        FileVersionInfoVO infoVO = new FileVersionInfoVO();
+        if (ObjectUtils.isNotEmpty(fileVersion)) {
+            BeanUtils.copyProperties(fileVersion, infoVO);
+            infoVO.setFileVersionId(fileVersion.getId());
+        }
+        return infoVO;
+    }
+}

+ 23 - 0
src/main/java/com/example/fms/service/permissions/MessageService.java

@@ -0,0 +1,23 @@
+package com.example.fms.service.permissions;
+
+
+import com.example.fms.common.model.vo.WebSocketMessageVO;
+import com.example.fms.common.utils.Response;
+import com.example.fms.common.utils.ResponseEnum;
+import org.springframework.stereotype.Service;
+
+/**
+ * 处理消息通知
+ *
+ * @Author 李仁杰
+ */
+@Service
+public class MessageService {
+
+    public void sendMessage(WebSocketMessageVO webSocketMessageVO) {
+        //通过WebSocket 在每一次循环结束后 向前端发送完成进度
+        //当任务状态为完成时,flag为true
+        WebSocketServer.sendInfo(Response.websocket(webSocketMessageVO, ResponseEnum.WEB_SOCKET_SUCCESS), null);
+    }
+
+}

+ 251 - 0
src/main/java/com/example/fms/service/permissions/PermissionService.java

@@ -0,0 +1,251 @@
+package com.example.fms.service.permissions;
+
+import com.alibaba.fastjson.JSON;
+import com.google.gson.Gson;
+import okhttp3.MediaType;
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+import okhttp3.RequestBody;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * 获取权限系统数据接口
+ */
+@Service
+public class PermissionService {
+    @Value("${authorUrl}")
+    private String PCSUrl;
+
+    /**
+     * 根据名称模糊查询人员接口
+     * @param personName
+     * @return
+     * @throws IOException
+     */
+    public String getPersonIdByNamePCS(String personName, Boolean ifEqual) throws IOException {
+        OkHttpClient okHttpClient = new OkHttpClient();
+        Request request = new Request.Builder()
+                .url(PCSUrl + "/permission/api/system/getPersonIdByName?personName=" + personName+"&ifEqual="+ifEqual)
+                .get()
+                .build();
+        return Objects.requireNonNull(okHttpClient.newCall(request).execute().body()).string();
+    }
+
+    /**
+     * 获得所有人员排序接口
+     * @param orderType
+     * @return
+     * @throws IOException
+     */
+    public String getPersonIdOrders(Integer orderType) throws IOException {
+        OkHttpClient okHttpClient = new OkHttpClient();
+        Request request = new Request.Builder()
+                .url(PCSUrl + "/permission/api/system/getPersonIdOrders?orderType=" + orderType)
+                .get()
+                .build();
+        return Objects.requireNonNull(okHttpClient.newCall(request).execute().body()).string();
+    }
+
+    /**
+     * 根据人员ids查询人员列表
+     *
+     * @param ids 人员ids
+     * @return 返回装载着人员列表数据的data的String
+     */
+    public String getPersonnelByIdsFromPCS(List<String> ids) throws IOException {
+        String param = new Gson().toJson(ids);
+        RequestBody requestBody = RequestBody.create(MediaType.parse("application/json"), param);
+        OkHttpClient okHttpClient = new OkHttpClient.Builder()
+                .connectTimeout(60, TimeUnit.SECONDS)
+                .writeTimeout(60, TimeUnit.SECONDS)
+                .readTimeout(60, TimeUnit.SECONDS)
+                .build();
+        Request request = new Request.Builder()
+                .url(PCSUrl + "/permission/api/system/getPersonnelByIds")
+                .post(requestBody)
+                .build();
+        return Objects.requireNonNull(okHttpClient.newCall(request).execute().body()).string();
+    }
+
+
+    /**
+     * 根据客户ids查询客户列表
+     *
+     * @param ids 客户ids
+     * @return 返回装载着客户列表数据的data的String
+     */
+    public String getClientByIdsFromPCS(List<Integer> ids) throws IOException {
+        String param = new Gson().toJson(ids);
+        RequestBody requestBody = RequestBody.create(MediaType.parse("application/json"), param);
+        OkHttpClient okHttpClient = new OkHttpClient.Builder()
+                .connectTimeout(60, TimeUnit.SECONDS)
+                .writeTimeout(60, TimeUnit.SECONDS)
+                .readTimeout(60, TimeUnit.SECONDS)
+                .build();
+        Request request = new Request.Builder()
+                .url(PCSUrl + "/permission/api/system/getClintByIds")
+                .post(requestBody)
+                .build();
+        return Objects.requireNonNull(okHttpClient.newCall(request).execute().body()).string();
+    }
+
+    /**
+     * 根据名称模糊查询客户接口
+     * @param clientName
+     * @return
+     * @throws IOException
+     */
+    public String getClientIdByNamePCS(String clientName,Boolean ifEqual) throws IOException {
+        OkHttpClient okHttpClient = new OkHttpClient();
+        Request request = new Request.Builder()
+                .url(PCSUrl + "/permission/api/system/getClientIdByName?clientName=" + clientName+"&ifEqual="+ifEqual)
+                .get()
+                .build();
+        return Objects.requireNonNull(okHttpClient.newCall(request).execute().body()).string();
+    }
+
+
+    /**
+     * 获得所有客户排序接口
+     * @param orderType
+     * @return
+     * @throws IOException
+     */
+    public String getClientIdOrders(Integer orderType) throws IOException {
+        OkHttpClient okHttpClient = new OkHttpClient();
+        Request request = new Request.Builder()
+                .url(PCSUrl + "/permission/api/system/getClientIdOrders?orderType=" + orderType)
+                .get()
+                .build();
+        return Objects.requireNonNull(okHttpClient.newCall(request).execute().body()).string();
+    }
+
+    /**
+     * 根据部门ids查询部门列表
+     *
+     * @param ids 部门id
+     * @return 返回装载着客户列表数据的data的String
+     */
+    public String getDepartmentByIdsFromPCS(List<String> ids) throws IOException {
+        String param = new Gson().toJson(ids);
+        RequestBody requestBody = RequestBody.create(MediaType.parse("application/json"), param);
+        OkHttpClient okHttpClient = new OkHttpClient.Builder()
+                .connectTimeout(60, TimeUnit.SECONDS)
+                .writeTimeout(60, TimeUnit.SECONDS)
+                .readTimeout(60, TimeUnit.SECONDS)
+                .build();
+        Request request = new Request.Builder()
+                .url(PCSUrl + "/permission/api/system/getDeparts")
+                .post(requestBody)
+                .build();
+        return Objects.requireNonNull(okHttpClient.newCall(request).execute().body()).string();
+    }
+
+    /**
+     * 获得所有部门排序接口
+     * @param orderType
+     * @return
+     * @throws IOException
+     */
+    public String getDepartmentOrders(Integer orderType) throws IOException {
+        OkHttpClient okHttpClient = new OkHttpClient();
+        Request request = new Request.Builder()
+                .url(PCSUrl + "/permission/api/system/getDepartmentOrders?orderType=" + orderType)
+                .get()
+                .build();
+        return Objects.requireNonNull(okHttpClient.newCall(request).execute().body()).string();
+    }
+
+    /**
+     * 获得所有委托方排序接口
+     * @param orderType
+     * @return
+     * @throws IOException
+     */
+    public String getEntrustsOrder(Integer orderType) throws IOException {
+        OkHttpClient okHttpClient = new OkHttpClient();
+        Request request = new Request.Builder()
+                .url(PCSUrl + "/permission/api/system/getEntrustsOrder?orderType=" + orderType)
+                .get()
+                .build();
+        return Objects.requireNonNull(okHttpClient.newCall(request).execute().body()).string();
+    }
+
+    /**
+     * 根据名称获得委托方id和类型接口
+     * @param
+     * @return
+     * @throws IOException
+     */
+    public String getEntrustsByName(String name,Integer type) throws IOException {
+        OkHttpClient okHttpClient = new OkHttpClient();
+        Request request = new Request.Builder()
+                .url(PCSUrl + "/permission/api/system/getEntrustsByName?name=" + name+"&type="+type)
+                .get()
+                .build();
+        return Objects.requireNonNull(okHttpClient.newCall(request).execute().body()).string();
+    }
+
+
+    /**
+     * 根据部门ids查询部门列表
+     *
+     * @param ids 部门id
+     * @return 返回装载着客户列表数据的data的String
+     */
+    public String getEntrustsByIdAndType(List<String> ids) throws IOException {
+        String param = new Gson().toJson(ids);
+        RequestBody requestBody = RequestBody.create(MediaType.parse("application/json"), param);
+        OkHttpClient okHttpClient = new OkHttpClient.Builder()
+                .connectTimeout(60, TimeUnit.SECONDS)
+                .writeTimeout(60, TimeUnit.SECONDS)
+                .readTimeout(60, TimeUnit.SECONDS)
+                .build();
+        Request request = new Request.Builder()
+                .url(PCSUrl + "/permission/api/system/getEntrustsByIdAndType")
+                .post(requestBody)
+                .build();
+        return Objects.requireNonNull(okHttpClient.newCall(request).execute().body()).string();
+    }
+
+
+
+
+    /**
+     * 根据名称模糊查询部门接口
+     * @param
+     * @return
+     * @throws IOException
+     */
+    public String getDepartmentIdByName(String departmentName, Boolean ifEqual) throws IOException {
+        OkHttpClient okHttpClient = new OkHttpClient();
+        Request request = new Request.Builder()
+                .url(PCSUrl + "/permission/api/system/getDepartmentIdByName?departmentName=" + departmentName+"&ifEqual="+ifEqual)
+                .get()
+                .build();
+        return Objects.requireNonNull(okHttpClient.newCall(request).execute().body()).string();
+    }
+
+    public List<String> getPersonIdsByName(String name){
+
+        List<String> ids = new ArrayList<>();
+        try {
+            String json = this.getPersonIdByNamePCS(name, false);
+            ids = JSON.parseArray(json, String.class);
+        } catch (Exception e) {
+        }
+        if (ids == null || ids.size() == 0) {
+            ids = new ArrayList<>();
+            ids.add("0");
+        }
+        return ids;
+
+    }
+}

+ 113 - 0
src/main/java/com/example/fms/service/permissions/WebSocketServer.java

@@ -0,0 +1,113 @@
+package com.example.fms.service.permissions;
+
+import com.example.fms.common.core.Constants;
+import com.example.fms.common.utils.Response;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+
+import javax.websocket.*;
+import javax.websocket.server.PathParam;
+import javax.websocket.server.ServerEndpoint;
+import java.io.IOException;
+import java.util.concurrent.CopyOnWriteArraySet;
+
+@Slf4j
+@Component
+@ServerEndpoint(Constants.API_XiaoSHI + "/ws/{sid}")
+public class WebSocketServer {
+
+    //静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
+    private static int onlineCount = 0;
+    //concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。
+    private static CopyOnWriteArraySet<WebSocketServer> webSocketSet
+            = new CopyOnWriteArraySet<WebSocketServer>();
+    //与某个客户端的连接会话,需要通过它来给客户端发送数据
+    private Session session;
+    //接收sid
+    private String sid = "";
+
+    /**
+     * 连接建立成功调用的方法
+     */
+    @OnOpen
+    public void onOpen(Session session, @PathParam("sid") String sid) {
+        this.session = session;
+        webSocketSet.add(this);     //加入set中
+        addOnlineCount();           //在线数加1
+        log.info("有新窗口开始监听:" + sid + ",当前在线人数为" + getOnlineCount());
+        this.sid = sid;
+        try {
+            sendMessage(Response.success("连接成功").toString());
+        } catch (IOException e) {
+            log.error("websocket IO异常");
+        }
+    }
+
+    /**
+     * 连接关闭调用的方法
+     */
+    @OnClose
+    public void onClose() {
+        webSocketSet.remove(this);  //从set中删除
+        subOnlineCount();           //在线数减1
+        log.info("有一连接关闭!当前在线人数为" + getOnlineCount());
+    }
+
+    /**
+     * 收到客户端消息后调用的方法
+     *
+     * @param message 客户端发送过来的消息
+     */
+    @OnMessage
+    public void onMessage(String message, Session session) {
+        log.info("收到来自窗口" + sid + "的信息:" + message);
+        //群发消息
+        for (WebSocketServer item : webSocketSet) {
+            try {
+                item.sendMessage(message);
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+    }
+
+    @OnError
+    public void onError(Session session, Throwable error) {
+        log.error("发生错误");
+        error.printStackTrace();
+    }
+
+    //实现服务器主动推送
+    public synchronized void sendMessage(String message) throws IOException {
+        this.session.getBasicRemote().sendText(message);
+    }
+
+    //群发自定义消息
+    public synchronized static void sendInfo(String message, @PathParam("sid") String sid) {
+        log.info("推送消息到窗口" + sid + ",推送内容:" + message);
+        for (WebSocketServer item : webSocketSet) {
+            try {
+                //这里可以设定只推送给这个sid的,为null则全部推送
+                if (sid == null || "null".equals(sid)) {
+                    item.sendMessage(message);
+                } else if (item.sid.equals(sid)) {
+                    item.sendMessage(message);
+                }
+            } catch (IOException e) {
+                continue;
+            }
+        }
+    }
+
+    public static synchronized int getOnlineCount() {
+        return onlineCount;
+    }
+
+    public static synchronized void addOnlineCount() {
+        WebSocketServer.onlineCount++;
+    }
+
+    public static synchronized void subOnlineCount() {
+        WebSocketServer.onlineCount--;
+    }
+}

+ 4 - 1
src/main/resources/application-dev.yml

@@ -27,4 +27,7 @@ spring:
         login-password: 123456
       web-stat-filter:
         exclusions: "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*"
-queueName: emailProd.queue
+queueName: emailProd.queue
+authorUrl: http://192.168.2.109:8880
+PCSUrl: http://192.168.2.109:8880
+PASUrl: http://localhost:8879

+ 5 - 0
src/main/resources/mapper/FileOperateRecord.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.example.fms.mapper.FileOperateRecordMapper">
+</mapper>

+ 25 - 0
src/main/resources/mapper/FileVersionMapper.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.example.fms.mapper.FileVersionMapper">
+    <sql id="Base_Column_File_Version">
+        id,file_name,file_type,file_key,url,changes_url,version,
+        original_file,changes,server_version,previous_version,user,created
+    </sql>
+
+    <select id="queryFileVersionByGuid" resultType="com.example.fms.domain.FileVersion">
+        select <include refid="Base_Column_File_Version"/>
+        from FILE_VERSION
+        where original_file = #{guid}
+        order by version desc
+        limit 1
+    </select>
+
+    <select id="queryCurrentFileVersionInfo" resultType="com.example.fms.domain.FileVersion">
+        select <include refid="Base_Column_File_Version"/>
+        from FILE_VERSION
+        where original_file = #{guid}
+        and version = (select current_version from FILE_OPERATE_RECORD where original_file = #{guid} order by ID desc limit 1)
+    </select>
+
+</mapper>

+ 41 - 0
src/test/java/com/example/fms/FileVersionTest.java

@@ -0,0 +1,41 @@
+package com.example.fms;
+
+import com.example.fms.common.model.dto.QueryFileVersionDTO;
+import com.example.fms.common.model.vo.FileVersionInfoVO;
+import com.example.fms.service.FileVersionService;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+@SpringBootTest
+public class FileVersionTest {
+
+    @Autowired
+    private FileVersionService fileVersionService;
+
+    @Test
+    public void callback() throws IOException {
+        Map<String, Object> params = new HashMap<>();
+        params.put("status", 2);
+        params.put("url", "");
+        params.put("changesurl", "");
+        String guid = "1";
+        String fileName = "1";
+        String user = "1";
+        Integer previousVersion = 1;
+        Integer num = fileVersionService.callback(params, guid, fileName, user, previousVersion);
+        System.out.println(num);
+    }
+
+    @Test
+    public void getCurrentVersionData() {
+        QueryFileVersionDTO versionDTO = new QueryFileVersionDTO();
+        versionDTO.setGuid("1");
+        FileVersionInfoVO versionData = fileVersionService.getCurrentVersionData(versionDTO);
+        System.out.println(versionData);
+    }
+}