From 49cdc0884a9a4381cd968cffff65e2a332bc675a Mon Sep 17 00:00:00 2001
From: liding <756868258@qq.com>
Date: 星期六, 24 十月 2026 21:05:29 +0800
Subject: [PATCH] feat(cnas-search): 1.标准查新模块 2.印章使用记录
---
src/components/Onlyoffice/onlyoffice.vue | 185 ++++++++++++++++++++++++++++++++++------------
1 files changed, 137 insertions(+), 48 deletions(-)
diff --git a/src/components/Onlyoffice/onlyoffice.vue b/src/components/Onlyoffice/onlyoffice.vue
index 00db4a5..eb69148 100644
--- a/src/components/Onlyoffice/onlyoffice.vue
+++ b/src/components/Onlyoffice/onlyoffice.vue
@@ -8,13 +8,39 @@
class="native-pdf-preview"
title="PDF棰勮"
></iframe>
- <div v-else id="vabOnlyOffice"></div>
+ <template v-else>
+ <div :id="editorId"></div>
+ <div v-if="editorWarning" class="editor-warning">{{ editorWarning }}</div>
+ <div v-if="editorState !== 'ready'" class="editor-status">
+ <template v-if="editorState === 'failed'">
+ <p>{{ editorError }}</p>
+ <el-button type="primary" @click="setEditor(option)">閲嶆柊鍔犺浇</el-button>
+ </template>
+ <span v-else>姝e湪杩炴帴鏂囨。鏈嶅姟骞跺姞杞芥姤鍛�...</span>
+ </div>
+ </template>
</div>
</template>
<script>
// OnlyOffice 鏂囨。鏈嶅姟鍦板潃锛屾寜鐜閰嶇疆锛涜剼鏈湪鐪熸闇�瑕侀瑙堟椂鎵嶅姞杞�
const OFFICE_API_BASE = import.meta.env.VITE_APP_ONLYOFFICE_API || "http://192.168.21.53:9001";
+
+function normalizeOptions(source = {}) {
+ return {
+ url: source.url || "",
+ isEdit: source.isEdit === true || source.isEdit === "true",
+ fileType: source.fileType || "",
+ title: source.title || "",
+ lang: source.lang || "zh-CN",
+ isPrint: source.isPrint !== false,
+ user: { id: source.user_id, name: source.user_name },
+ editUrl: source.editUrl || "",
+ key: source.key || "",
+ model: source.model,
+ token: source.token
+ };
+}
// 澶氫釜椤甸潰鍏辩敤缂栬緫鍣紝api.js 鍙姞杞戒竴娆�
let docsApiPromise = null;
@@ -26,14 +52,23 @@
docsApiPromise = new Promise((resolve, reject) => {
const script = document.createElement("script");
script.src = OFFICE_API_BASE.replace(/\/$/, "") + "/web-apps/apps/api/documents/api.js";
+ const timeout = window.setTimeout(() => {
+ script.remove();
+ reject(new Error("OnlyOffice 鏂囨。鏈嶅姟杩炴帴瓒呮椂"));
+ }, 15000);
script.onload = () => {
+ window.clearTimeout(timeout);
if (window.DocsAPI) {
resolve(window.DocsAPI);
} else {
reject(new Error("api.js 鍔犺浇瀹屾垚浣嗘湭娉ㄥ唽 DocsAPI"));
}
};
- script.onerror = () => reject(new Error("OnlyOffice 鏂囨。鏈嶅姟鑴氭湰鍔犺浇澶辫触锛�" + script.src));
+ script.onerror = () => {
+ window.clearTimeout(timeout);
+ script.remove();
+ reject(new Error("OnlyOffice 鏂囨。鏈嶅姟鑴氭湰鍔犺浇澶辫触"));
+ };
document.head.appendChild(script);
});
// 鍔犺浇澶辫触鍚庡厑璁镐笅娆¢噸璇�
@@ -47,21 +82,18 @@
export default {
name: "VabOnlyOffice",
props: ['options'],
+ emits: ['ready', 'error'],
data() {
return {
+ editorId: `onlyoffice-${this._uid || Math.random().toString(36).slice(2)}`,
doctype: "",
docEditor: null,
- //鍙傝�僾abOnlyOffice缁勪欢鍙傛暟閰嶇疆
- option: {
- url: "",
- isEdit: false,
- fileType: "",
- title: "",
- lang: "zh-CN",
- isPrint: true,
- user: {},
- editUrl: ""
- }
+ editorGeneration: 0,
+ editorState: 'loading',
+ editorError: '',
+ editorWarning: '',
+ readyTimer: null,
+ option: normalizeOptions(this.options || this.$route.query)
};
},
computed: {
@@ -69,41 +101,24 @@
return this.isPdfFile(this.option);
}
},
- created() {
- if(this.options){
- const option = this.options
- this.option.url = option.url
- this.option.isEdit = option.isEdit === "true" ? true : false
- this.option.fileType = option.fileType
- this.option.title = option.title
- this.option.lang = option.lang
- this.option.isPrint = option.isPrint
- this.option.user.id = option.user_id
- this.option.user.name = option.user_name
- this.option.editUrl = option.editUrl
- }else{
- const option = this.$route.query
- this.option.url = option.url
- this.option.isEdit = option.isEdit === "true" ? true : false
- this.option.fileType = option.fileType
- this.option.title = option.title
- this.option.lang = option.lang
- this.option.isPrint = option.isPrint
- this.option.user.id = option.user_id
- this.option.user.name = option.user_name
- this.option.editUrl = option.editUrl
- }
- },
beforeUnmount() {
+ this.editorGeneration++;
+ window.clearTimeout(this.readyTimer);
this.destroyEditor();
},
watch: {
- option: {
- handler: function(n) {
- this.setEditor(n);
- this.doctype = this.getFileType(n.fileType);
+ options: {
+ handler(newOptions) {
+ this.option = normalizeOptions(newOptions || this.$route.query);
+ this.setEditor(this.option);
},
deep: true
+ },
+ '$route.query'(query) {
+ if (!this.options) {
+ this.option = normalizeOptions(query);
+ this.setEditor(this.option);
+ }
}
},
mounted() {
@@ -114,19 +129,32 @@
methods: {
destroyEditor() {
if (this.docEditor !== null) {
- this.docEditor.destroyEditor();
+ try {
+ this.docEditor.destroyEditor();
+ } catch (error) {
+ console.error('閿�姣� OnlyOffice 缂栬緫鍣ㄥけ璐�', error);
+ }
this.docEditor = null;
}
},
async setEditor(option) {
+ const generation = ++this.editorGeneration;
+ window.clearTimeout(this.readyTimer);
this.destroyEditor();
// PDF 浣跨敤娴忚鍣ㄥ師鐢熼瑙堬紱鍏朵粬鏂囨。鎵嶅垵濮嬪寲 OnlyOffice銆�
if (!option || !option.url || this.isPdfFile(option)) {
return;
}
+ this.editorState = 'loading';
+ this.editorError = '';
+ this.editorWarning = '';
// 绛夊緟 v-else 涓殑 OnlyOffice 瀹瑰櫒瀹屾垚娓叉煋銆�
await this.$nextTick();
this.doctype = this.getFileType(option.fileType);
+ if (!this.doctype) {
+ this.failEditor('鎶ュ憡鏂囦欢鏍煎紡涓嶅彈鏀寔', generation);
+ return;
+ }
let config = {
document: {
//鍚庣紑
@@ -149,6 +177,7 @@
//瀹氬埗
customization: {
autosave: true, //鏄惁鑷姩淇濆瓨
+ forcesave: true, //鐐瑰嚮淇濆瓨鏃剁珛鍗冲洖璋冧笟鍔℃湇鍔�
chat: true,
comments: false,
help: false,
@@ -164,20 +193,54 @@
},
width: "100%",
height: "100%",
- token: option.token || ""
+ token: option.token || "",
+ events: {
+ onDocumentReady: () => {
+ if (generation === this.editorGeneration) {
+ window.clearTimeout(this.readyTimer);
+ this.editorState = 'ready';
+ this.$emit('ready');
+ }
+ },
+ onError: (event) => {
+ const detail = event && event.data && (event.data.errorDescription || event.data.errorCode);
+ this.failEditor(detail ? `鎶ュ憡鍔犺浇澶辫触锛�${detail}` : '鎶ュ憡鍔犺浇澶辫触锛岃妫�鏌ユ枃妗f湇鍔�', generation);
+ }
+ }
};
try {
await loadDocsApi();
} catch (error) {
console.error(error);
- this.$message.error("鏂囨。鏈嶅姟鏆傛椂涓嶅彲鐢紝鏃犳硶棰勮");
+ this.failEditor(error.message || '鏂囨。鏈嶅姟鏆傛椂涓嶅彲鐢�', generation);
return;
}
- if (this._isDestroyed) {
+ if (generation !== this.editorGeneration || !this.$el?.isConnected) {
return;
}
- this.docEditor = new window.DocsAPI.DocEditor("vabOnlyOffice", config);
+ try {
+ this.readyTimer = window.setTimeout(() => {
+ this.failEditor('鎶ュ憡鍔犺浇瓒呮椂锛岃妫�鏌ユ枃妗f湇鍔′笌鎶ュ憡鍦板潃', generation);
+ }, 30000);
+ this.docEditor = new window.DocsAPI.DocEditor(this.editorId, config);
+ } catch (error) {
+ window.clearTimeout(this.readyTimer);
+ console.error(error);
+ this.failEditor('鏂囨。缂栬緫鍣ㄥ垵濮嬪寲澶辫触锛岃閲嶈瘯', generation);
+ }
+ },
+ failEditor(message, generation) {
+ if (generation !== this.editorGeneration) return;
+ window.clearTimeout(this.readyTimer);
+ if (this.editorState === 'ready') {
+ this.editorWarning = String(message);
+ this.$emit('error', this.editorWarning);
+ return;
+ }
+ this.editorError = String(message);
+ this.editorState = 'failed';
+ this.$emit('error', this.editorError);
},
isPdfFile(option) {
if (!option) {
@@ -253,10 +316,36 @@
<style scoped>
.document-preview,
.native-pdf-preview,
-#vabOnlyOffice {
+.document-preview > div {
width: 100%;
height: 100%;
}
+.document-preview {
+ position: relative;
+}
+.editor-status {
+ position: absolute;
+ inset: 0;
+ z-index: 2;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ gap: 12px;
+ background: #fff;
+ color: #606266;
+}
+.editor-warning {
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ z-index: 2;
+ height: auto !important;
+ padding: 8px 12px;
+ background: #fff3e0;
+ color: #a35d00;
+}
.native-pdf-preview {
display: block;
border: 0;
--
Gitblit v1.9.3