onloyoffice历史版本功能实现,版本恢复功能,编辑器功能实现 springboot+vue2

文章目录

  • [onloyoffice历史版本功能实现,版本恢复功能,编辑器功能实现 springboot+vue2](#onloyoffice历史版本功能实现,版本恢复功能,编辑器功能实现 springboot+vue2)
  • [前提 需要注意把这个 (改成自己服务器的ip或者域名) 改成 自己服务器的域名或者地址](#前提 需要注意把这个 (改成自己服务器的ip或者域名) 改成 自己服务器的域名或者地址)
  • [我使用的onloyoffice版本 8.1.3.4](#我使用的onloyoffice版本 8.1.3.4)
  • [1. onloyoffice服务器部署 搜索其他文章](#1. onloyoffice服务器部署 搜索其他文章)
  • [2. 前段代码 vue 2](#2. 前段代码 vue 2)
    • [2.1 需要注意把这个 (改成自己服务器的ip或者域名) 改成 自己服务器的域名或者地址](#2.1 需要注意把这个 (改成自己服务器的ip或者域名) 改成 自己服务器的域名或者地址)
    • [2.2. openedit getHistoryData 这两个 是调用后端的 接口 改成自己项目的写法 都是 post 请求](#2.2. openedit getHistoryData 这两个 是调用后端的 接口 改成自己项目的写法 都是 post 请求)
    • [2.3 下面是整个页面代码 需要 别的页面进入下面这个页面 入参是 文件id](#2.3 下面是整个页面代码 需要 别的页面进入下面这个页面 入参是 文件id)
    • 举例
    • [进入editer.vue 页面的 页面代码 row.id 是文件id 也就是 onloyoffice 文件id](#进入editer.vue 页面的 页面代码 row.id 是文件id 也就是 onloyoffice 文件id)
      • [文件名字 editer.vue](#文件名字 editer.vue)
  • [3. 后端java 代码](#3. 后端java 代码)
    • [3.1 controller 代码](#3.1 controller 代码)
    • [3.2 service 代码](#3.2 service 代码)
    • [3.3 serviceImpl 代码](#3.3 serviceImpl 代码)
    • 3.3公共方法代码
  • 4.效果图
  • 5.可以参考此文章优化代码

onloyoffice历史版本功能实现,版本恢复功能,编辑器功能实现 springboot+vue2

前提 需要注意把这个 (改成自己服务器的ip或者域名) 改成 自己服务器的域名或者地址

我使用的onloyoffice版本 8.1.3.4

1. onloyoffice服务器部署 搜索其他文章

2. 前段代码 vue 2

2.1 需要注意把这个 (改成自己服务器的ip或者域名) 改成 自己服务器的域名或者地址

2.2. openedit getHistoryData 这两个 是调用后端的 接口 改成自己项目的写法 都是 post 请求

2.3 下面是整个页面代码 需要 别的页面进入下面这个页面 入参是 文件id

举例

进入editer.vue 页面的 页面代码 row.id 是文件id 也就是 onloyoffice 文件id

csharp 复制代码
//row.id 是文件id 也就是 onloyoffice 文件id
//  /only/editer/   这是页面路由的地址需要在路由里面配置
//页面
openFile(row) {
      window.open('#/only/editer/' + row.id,'_blank');
    },

文件名字 editer.vue

js 复制代码
<template>
  <div>
    <div id="onlyoffice-container" ref="editorContainer"></div>
  </div>
</template>

<script>
import {openedit, getHistoryData, restoreVersion, editHistory} from '@/http/http';

export default {
  name: 'OnlyOfficeEditor',
  props: {
    isEdit: {
      type: Boolean,
      default: true
    }
  },
  data() {
    return {
      docEditor: null,
      currentVersion: null,
      fileToken: null,
      historyData: null,
      historys: [],
      historyList: []
    };
  },
  mounted() {
    this.loadScript().then(() => {
      this.initEditor();
    });
  },
  methods: {
    // 加载脚本
    loadScript() {
      return new Promise((resolve, reject) => {
        const scriptId = "onlyoffice-api-script";
        if (!document.getElementById(scriptId)) {
          const script = document.createElement('script');
          script.id = scriptId;
          script.src = "https://(替换为自己的域名或者ip)/ds-vpath/web-apps/apps/api/documents/api.js";
          script.type = "text/javascript";
          script.onload = resolve;
          script.onerror = reject;
          document.head.appendChild(script);
        } else {
          resolve();
        }
      });
    },
    // 初始化编辑器
    initEditor() {
      if (this.docEditor) {
        this.docEditor.destroyEditor();
        this.docEditor = null;
      }
      openedit({"fileId": this.$route.params.id})
        .then((res) => {
          if (res.code === 200) {
            const config = res.data.openedit;
            config.events = this.getEditorEvents();
            this.docEditor = new window.DocsAPI.DocEditor(this.$refs.editorContainer.id, config);
          }
        })
        .catch(this.handleError);
    },
    // 获取编辑器事件配置
    getEditorEvents() {
      return {
        onRequestHistory: this.handleRequestHistory,
        onRequestHistoryClose: this.handleRequestHistoryClose,
        onRequestHistoryData: this.handleRequestHistoryData,
        onRequestRestore: this.handleRequestRestore
      };
    },
    // 处理请求历史记录事件
    handleRequestHistory() {
      editHistory({"fileId": this.$route.params.id})
        .then((res) => {
          if (res.code === 200) {
            const historyList = res.data.editHistory;
            const fileToken = res.data.fileToken;
            const currentVersion = historyList[historyList.length - 1].version;
            this.docEditor.refreshHistory({
              currentVersion,
              token: fileToken,
              history: historyList
            });
          }
        })
        .catch(this.handleError);
    },
    // 处理关闭历史记录事件
    handleRequestHistoryClose() {
      document.location.reload();
    },
    // 处理请求历史记录数据事件
    handleRequestHistoryData(event) {
      const version = event.data;
      getHistoryData({"fileId": this.$route.params.id, "version": version})
        .then((res) => {
          if (res.code === 200) {
            const historyData = res.data.historyData;
            this.docEditor.setHistoryData(historyData);
          }
        })
        .catch(this.handleError);
    },
    // 处理版本恢复事件
    handleRequestRestore(event) {
      const version = event.data.version;
      restoreVersion({"fileId": this.$route.params.id, "version": version})
        .then((res) => {
          if (res.code === 200) {
            const historyList = res.data.editHistory;
            const currentVersion = historyList[historyList.length - 1].version;
            this.docEditor.refreshHistory({
              currentVersion,
              history: historyList
            });
          }
        })
        .catch(this.handleError);
    },
    // 统一错误处理
    handleError(err) {
      console.log(err);
    },
    // 销毁编辑器
    destroyEditor() {
      if (this.docEditor) {
        this.docEditor.destroyEditor();
        this.docEditor = null;
      }
      if (this.DocsAPIInterval) {
        clearInterval(this.DocsAPIInterval);
      }
    }
  },
  beforeDestroy() {
    this.destroyEditor();
  },
  beforeRouteLeave(to, from, next) {
    this.destroyEditor();
    next();
  },
};
</script>

<style>
iframe {
  border: none;
  width: 100%;
  height: 100vh;
}
</style>

3. 后端java 代码

3.1 controller 代码

java 复制代码
    @PostMapping("/openedit")
    public RestResultDTO openedit(HttpServletRequest request, @RequestBody OnlyofficeRequestDTO params) {
        try {
            if (CommonFunctions.isEmpty(params.getFileId())) {
                throw new BusinessServiceException("非空校验失败");
            }
            Map<String, Object> resultMap  = onlyofficeService.openedit(params);
            return RestResultDTO.success(resultMap);
        } catch (Exception e) {
            LOGGER.error("openedit 方法发生异常: ", e);
            return RestResultDTO.error(ResponseCodeDTO.INTERNAL_SERVER_ERROR, e.getMessage());
        }
    }
java 复制代码
    @PostMapping("/getHistoryData")
    public RestResultDTO getHistoryData(HttpServletRequest request, @RequestBody OnlyofficeRequestDTO params) {
        try {
            if (CommonFunctions.isEmpty(params.getFileId()) || CommonFunctions.isEmpty(params.getVersion())) {
                throw new BusinessServiceException("非空校验失败");
            }
            Map<String, Object> resultMap  = onlyofficeService.getHistoryData(params);
            return RestResultDTO.success(resultMap);
        } catch (Exception e) {
            LOGGER.error("openedit 方法发生异常: ", e);
            return RestResultDTO.error(ResponseCodeDTO.INTERNAL_SERVER_ERROR, e.getMessage());
        }
    }
java 复制代码
    /**
     * 还原版本
     *
     * @return
     * @request: fileId   personId
     */
    @PostMapping("/restoreVersion")
    public RestResultDTO restoreVersion(HttpServletRequest request, @RequestBody OnlyofficeRequestDTO params) {
        try {
            if (CommonFunctions.isEmpty(params.getFileId()) || CommonFunctions.isEmpty(params.getVersion())) {
                throw new BusinessServiceException("非空校验失败");
            }
            Map<String, Object> resultMap  = onlyofficeService.restoreVersion(params);
            return RestResultDTO.success(resultMap);
        } catch (Exception e) {
            LOGGER.error("restoreVersion 方法发生异常: ", e);
            return RestResultDTO.error(ResponseCodeDTO.INTERNAL_SERVER_ERROR, e.getMessage());
        }
    }
java 复制代码
    /**
     * 修改历史
     *
     * @return
     * @request: fileId   personId
     */
    @PostMapping("/editHistory")
    public RestResultDTO editHistory(HttpServletRequest request, @RequestBody OnlyofficeRequestDTO params) {
        try {
            if (CommonFunctions.isEmpty(params.getFileId())) {
                throw new BusinessServiceException("非空校验失败");
            }
            Map<String, Object> resultMap  = onlyofficeService.editHistory(params);
            return RestResultDTO.success(resultMap);
        } catch (Exception e) {
            LOGGER.error("editHistory 方法发生异常: ", e);
            return RestResultDTO.error(ResponseCodeDTO.INTERNAL_SERVER_ERROR, e.getMessage());
        }
    }

3.2 service 代码

java 复制代码
    Map<String, Object> openedit(OnlyofficeRequestDTO params);
java 复制代码
 //获取文件的初始化配置
    Map<String, Object> getHistoryData(OnlyofficeRequestDTO params);
java 复制代码
    Map<String, Object> restoreVersion(OnlyofficeRequestDTO params);
java 复制代码
    Map<String, Object> editHistory(OnlyofficeRequestDTO params);

3.3 serviceImpl 代码

java 复制代码
       @Override
    public Map<String, Object> openedit(OnlyofficeRequestDTO params) {
    String fileId = params.getFileId();
        String permissionType = "";
        JSONObject onlyOfficeConfig = null;
        try {
            String result = HttpUtils.executeRequestOnlyoffice(HttpUtils.O_SHAREFILE_URL + fileId + "/openedit", null, null, "UTF-8", "get");
            JSONObject resJsonObject = JSONObject.parseObject(result);
            if (CollectionUtils.isEmpty(resJsonObject)) {
                throw new BusinessServiceException("获取配置文件异常");
            } else if (resJsonObject.getInteger("statusCode") == 200) {
                onlyOfficeConfig = resJsonObject.getJSONObject("response");
            } else if (resJsonObject.getInteger("statusCode") == 500) {
                throw new BusinessServiceException(resJsonObject.getJSONObject("error").getString("message"));
            } else {
                throw new BusinessServiceException("获取配置文件异常");
            }
             //只读
            if ("4".equals(permissionType)) {
                onlyOfficeConfig.getJSONObject("editorConfig").put("mode", "view");
            }
        } catch (Exception e) {
            LOGGER.error("解析JSON响应失败", e);
            throw new BusinessServiceException("", e);
        }
        // 使用 Map 封装多个 JSON 对象
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("openedit", onlyOfficeConfig);
        return resultMap;
    }
java 复制代码
    @Override
    public Map<String, Object> getHistoryData(OnlyofficeRequestDTO params) {
        String fileId = params.getFileId();
        String version = params.getVersion();
        JSONObject responseArray = null;
        try {
            String result = HttpUtils.executeRequestOnlyoffice(HttpUtils.O_FILES_URL + "/edit-diff-url?fileId=" + fileId + "&version=" + version, null, null, "UTF-8", "get");
            responseArray = JSONObject.parseObject(result);
            if (CollectionUtils.isEmpty(responseArray))  {
                throw new BusinessServiceException("获取配置文件异常");
            }
        } catch (Exception e) {
            LOGGER.error("解析JSON响应失败", e);
            throw new BusinessServiceException("", e);
        }
        // 使用 Map 封装多个 JSON 对象
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("historyData", responseArray);
        return resultMap;
    }
java 复制代码
    @Override
    public Map<String, Object> restoreVersion(OnlyofficeRequestDTO params) {
        String fileId = params.getFileId();
        String version = params.getVersion();
        JSONArray responseArray = null;
        try {
            String result = HttpUtils.executeRequestOnlyoffice(HttpUtils.O_FILES_URL + "/restore-version?fileId=" + fileId + "&version=" + version, null, null, "UTF-8", "put");
            // 尝试解析为 JSONArray
            JSONArray resJsonArray = JSONArray.parseArray(result);
            if (CollectionUtils.isEmpty(resJsonArray))  {
                throw new BusinessServiceException("获取配置文件异常");
            }
        } catch (Exception e) {
            LOGGER.error(" 解析JSON响应失败", e);
            throw new BusinessServiceException("", e);
        }
        Map<String, Object> stringObjectMap = this.editHistory(params);
        return stringObjectMap;
    }
java 复制代码
 @Override
    public Map<String, Object> editHistory(OnlyofficeRequestDTO params) {
        String fileId = params.getFileId();
        JSONArray responseArray = null;
        try {
            String result = HttpUtils.executeRequestOnlyoffice(HttpUtils.O_FILES_URL  + "/edit-history?fileId=" + fileId, null, null, "UTF-8", "get");
            // 尝试解析为 JSONArray
            JSONArray resJsonArray = JSONArray.parseArray(result);
            if (CollectionUtils.isEmpty(resJsonArray))  {
                throw new BusinessServiceException("获取配置文件异常");
            }
            responseArray = resJsonArray;
        } catch (Exception e) {
            LOGGER.error(" 解析JSON响应失败", e);
            throw new BusinessServiceException("", e);
        }
        // 使用 Map 封装多个 JSON 对象
        Map<String, Object> resultMap = new HashMap<>();
        try {
            resultMap.put("fileToken",HttpUtils.renovateAuthorizationToken());
        } catch (Exception e) {
            LOGGER.error(" 获取token失败", e);
            throw new BusinessServiceException("", e);
        }
        resultMap.put("editHistory", responseArray);
        return resultMap;
    }

3.3公共方法代码

java 复制代码
  /**
     * 根据请求类型执行POST或PUT请求
     */
    public static String executeRequestOnlyoffice(String url, Map<String, Object> params, Map<String, String> headers, String encoding, String requestType) throws Exception {
        Map<String, String> headersCover = new HashMap<>();
        String authorizationToken = getAuthorizationToken();
        //覆盖默认请求头
        headersCover.put("Authorization", authorizationToken);
        headersCover.put("Accept", "application/json");
        headersCover.put("Content-Type", "application/json");
        if (headers != null) {
            for (Map.Entry<String, String> entry : headers.entrySet()) {
                headersCover.put(entry.getKey(), entry.getValue());
            }
        }

        switch (requestType.toLowerCase()) {
            case "get":
                return executeGetRequestCommon(url, params, headersCover, encoding);
            case "post":
                return executePostRequestCommon(url, params, headersCover, encoding);
            case "put":
                return executePutRequestCommon(url, params, headersCover, encoding);
            case "delete":
                return executeDeleteRequestCommon(url, params, headersCover, encoding);
            default:
                throw new IllegalArgumentException("Unsupported request type: " + requestType);
        }
    }
java 复制代码
 /**
     * 获取授权Token
     */
    public static synchronized void refreshAuthorizationToken() throws Exception {
        Map<String, Object> params = new HashMap<>();
        params.put("userName", "");//输入onloyoffice 登录用户名
        params.put("password", "");//输入onloyoffice登录密码

        Map<String, String> headers = new HashMap<>();
        headers.put("Accept", "application/json");
        headers.put("Content-Type", "application/json");

        String result = executePostRequestCommon(HttpUtils.O_AUTH_URL, params, headers, "UTF-8");
        JSONObject jsonObject = JSONObject.parseObject(result);
        HttpUtils.authorizationToken = "Bearer " + jsonObject.getJSONObject("response").getString("token");
    }

    // 获取Token的方法
    @PostConstruct
    public static String getAuthorizationToken() throws Exception {
        if (CommonFunctions.isEmpty(HttpUtils.authorizationToken)) {
            refreshAuthorizationToken();
        }
        return HttpUtils.authorizationToken;
    }
java 复制代码
    /**
     * 执行GET通用请求
     */
    public static String executeGetRequestCommon(String url, Map<String, Object> params, Map<String, String> headers, String encoding) throws Exception {
        // 创建一个带有默认配置的HttpClient,并设置超时时间
        RequestConfig requestConfig = RequestConfig.custom()
                .setConnectTimeout(5000) // 连接超时时间
                .setSocketTimeout(10000) // 读取超时时间
                .build();

        try (CloseableHttpClient httpClient = HttpClients.custom().setDefaultRequestConfig(requestConfig).build()) {
            // 构建带有查询参数的URL
            if (params != null && !params.isEmpty()) {
                StringBuilder queryString = new StringBuilder(url);
                if (!url.contains("?")) {
                    queryString.append("?");
                } else {
                    queryString.append("&");
                }
                for (String key : params.keySet()) {
                    queryString.append(key).append("=").append(params.get(key)).append("&");
                }
                // 去掉最后一个多余的&
                if (queryString.toString().endsWith("&")) {
                    queryString.setLength(queryString.length() - 1);
                }
                url = queryString.toString();
            }

            HttpGet httpGet = new HttpGet(url);

            // 添加自定义头信息
            if (headers != null) {
                for (Map.Entry<String, String> entry : headers.entrySet()) {
                    httpGet.addHeader(entry.getKey(), entry.getValue());
                }
            }

            // 执行请求并获取响应
            try (CloseableHttpResponse response = httpClient.execute(httpGet)) {
                HttpEntity entity = response.getEntity();
                return entity != null ? EntityUtils.toString(entity, encoding != null ? encoding : "UTF-8") : null;
            }
        } catch (IOException e) {
            logger.error("Error executing GET request to URL: {}. Exception: {}", url, e.getMessage(), e);
            throw e;
        }
    }
java 复制代码
public static String O_FILES_URL = "https://(自己服务器ip或者域名)/Products/Files/Services/WCFService/service.svc"

public static String O_SHAREFILE_URL = "https://(自己服务器ip或者域名)/api/2.0/files/file/"
java 复制代码
/**
 * 获取授权Token
 * @return 授权Token字符串
 * @throws Exception 如果请求或解析失败
 */
    public static String renovateAuthorizationToken() throws Exception {
        // 构造请求参数
        Map<String, Object> params = new HashMap<>();
        params.put("userName", "");//输入onloyoffice 登录用户名
        params.put("password", "");//输入onloyoffice登录密码

        // 构造请求头
        Map<String, String> headers = new HashMap<>();
        headers.put("Accept", "application/json");
        headers.put("Content-Type", "application/json");

        // 执行POST请求并获取结果
        String result = executePostRequestCommon(HttpUtils.O_AUTH_URL, params, headers, "UTF-8");

        // 解析JSON结果
        JSONObject jsonObject = JSONObject.parseObject(result);
        return jsonObject.getJSONObject("response").getString("token");
    }

4.效果图


5.可以参考此文章优化代码

java 复制代码
https://www.cnblogs.com/gamepen/p/17849005.html
相关推荐
上上迁11 分钟前
分布式生成 ID 策略的演进和最佳实践,含springBoot 实现(Java版本)
java·spring boot·分布式
骑自行车的码农12 分钟前
React短文系列 遍历fiber树 App的创建
前端·react.js
AskSky16 分钟前
为了搞一个完美的健身APP,我真是费尽心机
前端
斯~内克21 分钟前
基于Vue.js和PDF-Lib的条形码生成与批量打印方案
前端·vue.js·pdf
阴阳怪气乌托邦22 分钟前
别再啃OA代码了!低代码"搭积木"式搞数智化,我直接少写500行
前端·低代码
秋千码途25 分钟前
小架构step系列07:查找日志配置文件
spring boot·后端·架构
beelan27 分钟前
v-on的思考
前端
山河木马29 分钟前
前端学习C++之:.h(.hpp)与.cpp文件
前端·javascript·c++
用户92724725021930 分钟前
PHP + CSS + JS + JSON 数据采集与展示系统,支持伪静态
前端
努力只为躺平34 分钟前
一文搞懂 Promise 并发控制:批量执行 vs 最大并发数,实用场景全解析!
前端·javascript