vue3使用ONLYOFFICE 实现在线Word,Excel等文档

vue3使用ONLYOFFICE 实现在线Word,Excel等文档

文章目录

安装

bash 复制代码
npm install @onlyoffice/document-editor-vue --save

创建组件OnlyOfficeEditor.vue

html 复制代码
<template>
  <div class="onlyoffice-editor" :style="{ height: height }">
    <DocumentEditor
      :id="id"
      :documentServerUrl="documentServerUrl"
      :config="mergedConfig"
      :events_onDocumentReady="handleDocumentReady"
      :events_onSave="handleSave"
      :events_onError="handleError"
      :events_onDestroy="handleDestroy"
      v-bind="$attrs"
    />
  </div>
</template>

<script setup>
import { ref, computed, watch } from 'vue';
import { DocumentEditor } from '@onlyoffice/document-editor-vue';

// 定义组件 props
const props = defineProps({
  // 编辑器唯一ID(默认自动生成)
  id: {
    type: String,
    default: () => `onlyoffice-editor-${Date.now()}`
  },
  // OnlyOffice 服务地址(必填)
  documentServerUrl: {
    type: String,
    required: true
  },
  // 文档配置(核心配置,必填)
  documentConfig: {
    type: Object,
    required: true,
    // 结构校验
    validator: (val) => {
      return val.document?.url && val.document?.fileType && val.document?.key;
    }
  },
  // 编辑器高度(默认800px)
  height: {
    type: String,
    default: '800px'
  },
  // 编辑模式(edit/view)
  mode: {
    type: String,
    default: 'edit',
    validator: (val) => ['edit', 'view'].includes(val)
  },
  // 语言(默认中文)
  lang: {
    type: String,
    default: 'zh-CN'
  }
});

// 定义组件事件
const emit = defineEmits([
  'document-ready',   // 文档加载完成
  'save',             // 保存事件
  'error',            // 错误事件
  'destroy',          // 组件销毁
  'custom-event'      // 自定义事件透传
]);

// 合并基础配置和用户配置
const mergedConfig = computed(() => {
  return {
    ...props.documentConfig,
    editorConfig: {
      // 基础配置(可被用户配置覆盖)
      mode: props.mode,
      lang: props.lang,
      // 合并用户传入的 editorConfig
      ...props.documentConfig.editorConfig,
      // 强制覆盖用户可能误设置的关键参数
      user: {
        ...props.documentConfig.editorConfig?.user,
        // 确保用户名存在(默认匿名)
        name: props.documentConfig.editorConfig?.user?.name || 'Anonymous'
      }
    }
  };
});

// 事件处理函数
const handleDocumentReady = () => {
  emit('document-ready');
};

const handleSave = (event) => {
  emit('save', event);
};

const handleError = (error) => {
  emit('error', error);
  console.error('OnlyOffice 错误:', error);
};

const handleDestroy = () => {
  emit('destroy');
};

// 监听模式变化,动态更新编辑器
watch(
  () => props.mode,
  (newMode) => {
    // 调用 OnlyOffice 实例方法切换模式
    const editor = window.DocEditor.getInstance(props.id);
    if (editor) {
      editor.setMode(newMode);
    }
  }
);

// 暴露给父组件的方法
defineExpose({
  // 手动触发保存
  saveDocument() {
    const editor = window.DocEditor.getInstance(props.id);
    if (editor) {
      editor.save();
    }
  },
  // 获取编辑器实例
  getEditorInstance() {
    return window.DocEditor.getInstance(props.id);
  }
});
</script>

<style scoped>
.onlyoffice-editor {
  width: 100%;
  overflow: hidden;
}
</style>

组件使用

html 复制代码
<template>
  <div>
    <button @click="handleManualSave">手动保存</button>
    <OnlyOfficeEditor
      ref="editorRef"
      :documentServerUrl="documentServerUrl"
      :documentConfig="docConfig"
      height="90vh"
      mode="edit"
      @document-ready="onDocReady"
      @save="onDocSave"
      @error="onDocError"
    />
  </div>
</template>

<script setup>
import OnlyOfficeEditor from '@/components/OnlyOfficeEditor.vue';
import { ref } from 'vue';
    
// 组件引用
const editorRef = ref(null);

// OnlyOffice 服务地址(替换为你的服务地址)
const documentServerUrl = ref('https://your-onlyoffice-server.com/');

// 文档配置(核心)
const docConfig = ref({
  document: {
    fileType: 'docx',
    key: 'doc-123456', // 文档唯一标识(建议用文件哈希)
    title: '测试文档.docx',
    url: 'https://your-server.com/files/test.docx' // 文档下载地址
  },
  editorConfig: {
    callbackUrl: 'https://your-server.com/api/onlyoffice/callback', // 保存回调地址
    user: {
      id: 'user-1',
      name: '张三' // 显示在编辑器中的名称
    },
    // 其他配置(如是否允许评论、打印等)
    allowComments: true,
    allowPrint: true
  }
});

// 事件处理
const onDocReady = () => {
  console.log('文档加载完成');
};

const onDocSave = (event) => {
  console.log('文档保存中', event);
};

const onDocError = (error) => {
  console.error('文档错误', error);
};

// 手动保存
const handleManualSave = () => {
  // 通过 ref 调用子组件方法
  editorRef.value?.saveDocument();
};
</script>
相关推荐
杨芋爽6 小时前
管理后台列表页为什么一直转圈?从一次 1+N 请求扇出聊聊前端性能优化
javascript
晴天166 小时前
Chrome DevTools 深度调试指南
前端·chrome·chrome devtools
林冠宏_指尖下的幽灵6 小时前
AI发展下的后编程时代思考
前端·人工智能·后端
_山海7 小时前
Bun入门指南
前端·javascript·后端
想睡懒觉7 小时前
我用 CSS 3D 做了个星空隧道 Loading,没有 Three.js
前端
labixiong7 小时前
transition 写在 CSS 变量上为什么不生效?给变量补张「类型身份证」
前端·css·html
YHL7 小时前
🧠 Agent 记忆进阶:总结压缩与向量检索 —— 从截断到 Milvus 长期记忆
前端·人工智能
YHL7 小时前
🎯 JavaScript 单例模式(Singleton Pattern)—— 从理论到实战
javascript·设计模式
用户921080262867 小时前
前端 Vue 专栏 05:从 Object.defineProperty 到 Proxy,彻底理解 Vue 响应式原理
前端