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
相关推荐
飞翔的佩奇26 分钟前
【完整源码+数据集+部署教程】【天线&水】舰船战舰检测与分类图像分割系统源码&数据集全套:改进yolo11-repvit
前端·python·yolo·计算机视觉·数据集·yolo11·舰船战舰检测与分类图像分割系统
哆啦A梦15881 小时前
点击Top切换数据
前端·javascript·vue.js
程序猿追2 小时前
Vue组件化开发
前端·html
摇滚侠2 小时前
Spring Boot 3零基础教程,WEB 开发 Thymeleaf 核心语法 笔记39
spring boot·笔记·后端·thymeleaf
艾德金的溪2 小时前
redis-7.4.6部署安装
前端·数据库·redis·缓存
小光学长2 小时前
基于Vue的2025年哈尔滨亚冬会志愿者管理系统5zqg6m36(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
前端·数据库·vue.js
@PHARAOH2 小时前
WHAT - 受控组件和非受控组件
前端·javascript·react.js
生莫甲鲁浪戴2 小时前
Android Studio新手开发第二十六天
android·前端·android studio
九丶弟3 小时前
SpringBoot的cache使用说明
java·spring boot·spring·cache
JH30733 小时前
B/S架构、HTTP协议与Web服务器详解
前端·http·架构