Browse Source

处理docx无法预览问题

yangg 7 tháng trước cách đây
mục cha
commit
987df86185
55 tập tin đã thay đổi với 207 bổ sung48 xóa
  1. 1 1
      .env.development
  2. 0 0
      dist/index.html
  3. 0 0
      dist/static/css/app.4fbb2ade.css
  4. 0 0
      dist/static/js/app.1ed7f7f6.js
  5. 0 0
      dist/static/js/app.25c8e37a.js
  6. 0 0
      dist/static/js/chunk-016e5c0e.f2ad30fe.js
  7. 0 0
      dist/static/js/chunk-01f26467.b9ad1512.js
  8. 0 0
      dist/static/js/chunk-079de15b.5b8a4888.js
  9. 0 0
      dist/static/js/chunk-091613b3.23400b92.js
  10. 0 0
      dist/static/js/chunk-09f78c22.00601006.js
  11. 0 0
      dist/static/js/chunk-0a1f2758.bbd3cca5.js
  12. 0 0
      dist/static/js/chunk-0ec56e2a.daa0fe36.js
  13. 0 0
      dist/static/js/chunk-10bfc27e.f16a8c4e.js
  14. 0 0
      dist/static/js/chunk-11ff1a32.fdba969f.js
  15. 0 0
      dist/static/js/chunk-138f7583.0c377df1.js
  16. 0 0
      dist/static/js/chunk-1e25476d.6ea6318d.js
  17. 0 0
      dist/static/js/chunk-254ac533.d0260054.js
  18. 0 0
      dist/static/js/chunk-276e7119.da5239d4.js
  19. 0 0
      dist/static/js/chunk-2a11f130.23376042.js
  20. 0 0
      dist/static/js/chunk-2d0d3705.e4dbb0c4.js
  21. 0 0
      dist/static/js/chunk-35464144.093f9f95.js
  22. 0 0
      dist/static/js/chunk-3ab88ac2.a79bb761.js
  23. 0 0
      dist/static/js/chunk-3d8a6649.a615ca0d.js
  24. 0 0
      dist/static/js/chunk-44eee83d.7cc4a6f5.js
  25. 0 0
      dist/static/js/chunk-461baa1d.53bde1d6.js
  26. 0 0
      dist/static/js/chunk-4ac7f82e.50b7f9ed.js
  27. 0 0
      dist/static/js/chunk-5a3bdf57.f32b49b1.js
  28. 0 0
      dist/static/js/chunk-5bc2c8fb.994c1e22.js
  29. 0 0
      dist/static/js/chunk-5c6eee35.75b74208.js
  30. 0 0
      dist/static/js/chunk-6111b966.f0d647f8.js
  31. 0 0
      dist/static/js/chunk-683feb49.951d7b90.js
  32. 0 0
      dist/static/js/chunk-6a80e4ca.ec953840.js
  33. 0 0
      dist/static/js/chunk-6ddf6871.2535fbfe.js
  34. 0 0
      dist/static/js/chunk-6f0044a0.2ab24bbd.js
  35. 0 0
      dist/static/js/chunk-708604c0.9d3cc632.js
  36. 0 0
      dist/static/js/chunk-708c45dc.a37e24d5.js
  37. 0 0
      dist/static/js/chunk-77486988.40cb0769.js
  38. 0 0
      dist/static/js/chunk-77a58a9f.a11cd920.js
  39. 0 0
      dist/static/js/chunk-77bc8fb9.89ae95e6.js
  40. 0 0
      dist/static/js/chunk-77e1dd82.96a0102c.js
  41. 0 0
      dist/static/js/chunk-7a88741c.f00689c1.js
  42. 0 0
      dist/static/js/chunk-7b81ddc1.233c67eb.js
  43. 0 0
      dist/static/js/chunk-8b374628.f9809d7e.js
  44. 0 0
      dist/static/js/chunk-9235c1ae.4cb85052.js
  45. 0 0
      dist/static/js/chunk-b144ff6a.47b8959e.js
  46. 0 0
      dist/static/js/chunk-cdf4eda6.3c5ce573.js
  47. 0 0
      dist/static/js/chunk-d9c71bc2.3b36e683.js
  48. 0 0
      dist/static/js/chunk-e90c2844.682d7d1b.js
  49. 0 0
      dist/static/js/chunk-ec55d346.b1edb4a7.js
  50. 0 0
      dist/static/js/chunk-f49247ee.ecbcaa06.js
  51. 0 0
      dist/static/js/chunk-f67aa65a.01b660dd.js
  52. 0 0
      dist/static/js/chunk-fa78c2d4.a8e0d98e.js
  53. 0 0
      dist/static/js/chunk-libs.36792d92.js
  54. 2 1
      package.json
  55. 204 46
      src/components/FilePreview/index.vue

+ 1 - 1
.env.development

@@ -2,7 +2,7 @@
 ENV = 'development'
 port = 8080
 # base api
-VUE_APP_BASE_API = 'http://183.195.216.54:8084'
+VUE_APP_BASE_API = 'http://192.168.66.187:8084'
 #192.168.66.187
 
 #183.195.216.54

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 0 - 0
dist/index.html


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 0 - 0
dist/static/css/app.4fbb2ade.css


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 0 - 0
dist/static/js/app.1ed7f7f6.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 0 - 0
dist/static/js/app.25c8e37a.js


+ 0 - 0
dist/static/js/chunk-016e5c0e.595cfe68.js → dist/static/js/chunk-016e5c0e.f2ad30fe.js


+ 0 - 0
dist/static/js/chunk-01f26467.77ede427.js → dist/static/js/chunk-01f26467.b9ad1512.js


+ 0 - 0
dist/static/js/chunk-079de15b.24d57a9c.js → dist/static/js/chunk-079de15b.5b8a4888.js


+ 0 - 0
dist/static/js/chunk-091613b3.7440dbcc.js → dist/static/js/chunk-091613b3.23400b92.js


+ 0 - 0
dist/static/js/chunk-09f78c22.8742a933.js → dist/static/js/chunk-09f78c22.00601006.js


+ 0 - 0
dist/static/js/chunk-0a1f2758.9e573037.js → dist/static/js/chunk-0a1f2758.bbd3cca5.js


+ 0 - 0
dist/static/js/chunk-0ec56e2a.de9328a9.js → dist/static/js/chunk-0ec56e2a.daa0fe36.js


+ 0 - 0
dist/static/js/chunk-10bfc27e.7b3728e7.js → dist/static/js/chunk-10bfc27e.f16a8c4e.js


+ 0 - 0
dist/static/js/chunk-11ff1a32.fffd4532.js → dist/static/js/chunk-11ff1a32.fdba969f.js


+ 0 - 0
dist/static/js/chunk-138f7583.842a6e15.js → dist/static/js/chunk-138f7583.0c377df1.js


+ 0 - 0
dist/static/js/chunk-1e25476d.0fc289da.js → dist/static/js/chunk-1e25476d.6ea6318d.js


+ 0 - 0
dist/static/js/chunk-254ac533.0042cf24.js → dist/static/js/chunk-254ac533.d0260054.js


+ 0 - 0
dist/static/js/chunk-276e7119.38f3c435.js → dist/static/js/chunk-276e7119.da5239d4.js


+ 0 - 0
dist/static/js/chunk-2a11f130.b1a50d85.js → dist/static/js/chunk-2a11f130.23376042.js


+ 0 - 0
dist/static/js/chunk-2d0d3705.6e4a9a9c.js → dist/static/js/chunk-2d0d3705.e4dbb0c4.js


+ 0 - 0
dist/static/js/chunk-35464144.87555f07.js → dist/static/js/chunk-35464144.093f9f95.js


+ 0 - 0
dist/static/js/chunk-3ab88ac2.57409d35.js → dist/static/js/chunk-3ab88ac2.a79bb761.js


+ 0 - 0
dist/static/js/chunk-3d8a6649.277269b0.js → dist/static/js/chunk-3d8a6649.a615ca0d.js


+ 0 - 0
dist/static/js/chunk-44eee83d.c7a0dd6d.js → dist/static/js/chunk-44eee83d.7cc4a6f5.js


+ 0 - 0
dist/static/js/chunk-461baa1d.ad076d94.js → dist/static/js/chunk-461baa1d.53bde1d6.js


+ 0 - 0
dist/static/js/chunk-4ac7f82e.7468e419.js → dist/static/js/chunk-4ac7f82e.50b7f9ed.js


+ 0 - 0
dist/static/js/chunk-5a3bdf57.b83cc3e1.js → dist/static/js/chunk-5a3bdf57.f32b49b1.js


+ 0 - 0
dist/static/js/chunk-5bc2c8fb.c96f9e4d.js → dist/static/js/chunk-5bc2c8fb.994c1e22.js


+ 0 - 0
dist/static/js/chunk-5c6eee35.e1997460.js → dist/static/js/chunk-5c6eee35.75b74208.js


+ 0 - 0
dist/static/js/chunk-6111b966.ccb6f3cf.js → dist/static/js/chunk-6111b966.f0d647f8.js


+ 0 - 0
dist/static/js/chunk-683feb49.57361db1.js → dist/static/js/chunk-683feb49.951d7b90.js


+ 0 - 0
dist/static/js/chunk-6a80e4ca.5c8531cc.js → dist/static/js/chunk-6a80e4ca.ec953840.js


+ 0 - 0
dist/static/js/chunk-6ddf6871.6c624768.js → dist/static/js/chunk-6ddf6871.2535fbfe.js


+ 0 - 0
dist/static/js/chunk-6f0044a0.094bdbc7.js → dist/static/js/chunk-6f0044a0.2ab24bbd.js


+ 0 - 0
dist/static/js/chunk-708604c0.bdfe9e33.js → dist/static/js/chunk-708604c0.9d3cc632.js


+ 0 - 0
dist/static/js/chunk-708c45dc.f5615ac7.js → dist/static/js/chunk-708c45dc.a37e24d5.js


+ 0 - 0
dist/static/js/chunk-77486988.e847d469.js → dist/static/js/chunk-77486988.40cb0769.js


+ 0 - 0
dist/static/js/chunk-77a58a9f.15d0cb62.js → dist/static/js/chunk-77a58a9f.a11cd920.js


+ 0 - 0
dist/static/js/chunk-77bc8fb9.6e2dcd55.js → dist/static/js/chunk-77bc8fb9.89ae95e6.js


+ 0 - 0
dist/static/js/chunk-77e1dd82.0e145b6d.js → dist/static/js/chunk-77e1dd82.96a0102c.js


+ 0 - 0
dist/static/js/chunk-7a88741c.29036f89.js → dist/static/js/chunk-7a88741c.f00689c1.js


+ 0 - 0
dist/static/js/chunk-7b81ddc1.cd2bc177.js → dist/static/js/chunk-7b81ddc1.233c67eb.js


+ 0 - 0
dist/static/js/chunk-8b374628.1bb643aa.js → dist/static/js/chunk-8b374628.f9809d7e.js


+ 0 - 0
dist/static/js/chunk-9235c1ae.1549c27b.js → dist/static/js/chunk-9235c1ae.4cb85052.js


+ 0 - 0
dist/static/js/chunk-b144ff6a.76f23abc.js → dist/static/js/chunk-b144ff6a.47b8959e.js


+ 0 - 0
dist/static/js/chunk-cdf4eda6.c91e60ff.js → dist/static/js/chunk-cdf4eda6.3c5ce573.js


+ 0 - 0
dist/static/js/chunk-d9c71bc2.0ac20024.js → dist/static/js/chunk-d9c71bc2.3b36e683.js


+ 0 - 0
dist/static/js/chunk-e90c2844.99cccfe7.js → dist/static/js/chunk-e90c2844.682d7d1b.js


+ 0 - 0
dist/static/js/chunk-ec55d346.e43b8f82.js → dist/static/js/chunk-ec55d346.b1edb4a7.js


+ 0 - 0
dist/static/js/chunk-f49247ee.45ae8836.js → dist/static/js/chunk-f49247ee.ecbcaa06.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 0 - 0
dist/static/js/chunk-f67aa65a.01b660dd.js


+ 0 - 0
dist/static/js/chunk-fa78c2d4.43c18551.js → dist/static/js/chunk-fa78c2d4.a8e0d98e.js


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 0 - 0
dist/static/js/chunk-libs.36792d92.js


+ 2 - 1
package.json

@@ -29,6 +29,7 @@
     "core-js": "3.6.5",
     "cos-js-sdk-v5": "^1.4.22",
     "docx": "^8.5.0",
+    "docx-preview": "^0.3.3",
     "docxtemplater": "^3.46.0",
     "docxtemplater-image-module-free": "^1.1.1",
     "driver.js": "0.9.5",
@@ -48,7 +49,7 @@
     "js-table2excel": "^1.1.2",
     "jsonlint": "1.6.3",
     "jspdf": "^2.5.1",
-    "jszip": "^3.2.1",
+    "jszip": "^3.10.1",
     "jszip-utils": "^0.1.0",
     "lodash-es": "^4.17.21",
     "luckyexcel": "^1.0.1",

+ 204 - 46
src/components/FilePreview/index.vue

@@ -18,14 +18,38 @@
       />
 
       <!-- Word 文档预览 -->
-      <div
+      <div v-if="isWord" class="word-container">
+        <!-- 加载中状态 -->
+        <div v-if="!wordLoaded && !previewError" class="loading-word">
+          <el-progress
+            v-if="loadingProgress > 0"
+            type="circle"
+            :percentage="loadingProgress"
+          ></el-progress>
+          <span v-else>文档加载中...</span>
+        </div>
+
+        <!-- 预览错误状态 -->
+        <div v-else-if="previewError" class="preview-error">
+          <i class="el-icon-warning-outline"></i>
+          <p>{{ errorMessage }}</p>
+          <div class="error-actions">
+            <el-button type="primary" @click="retryPreview">重试</el-button>
+            <el-button @click="downloadFile">下载文件</el-button>
+          </div>
+        </div>
+
+        <!-- 预览内容 -->
+        <div v-else v-html="wordContent" class="word-preview"></div>
+      </div>
+      <!--  <div
         v-if="isWord && wordLoaded"
         v-html="wordContent"
         class="word-preview"
       ></div>
       <div v-else-if="isWord && !wordLoaded" class="loading-word">
         {{ wordLoadingError ? "加载失败,请重试" : "加载中..." }}
-      </div>
+      </div> -->
       <div
         v-if="isExcel"
         id="luckysheet"
@@ -57,6 +81,8 @@ import { searchTaskInfo } from "@/api/knowledge";
 import mammoth from "mammoth";
 // 添加 LuckyExcel 导入
 import LuckyExcel from "luckyexcel";
+import { saveAs } from "file-saver";
+import JSZip from "jszip";
 export default {
   props: {
     fileUrl: {
@@ -93,6 +119,13 @@ export default {
       wordLoaded: false,
       wordLoadingError: false,
       internalFileUrl: "", // 新增:内部使用的 URL
+
+      loadingProgress: 0,
+      wordContent: "",
+      wordLoaded: false,
+      previewError: false,
+      errorMessage: "",
+      docData: null, // 保存文档数据用于下载
     };
   },
   watch: {
@@ -100,13 +133,25 @@ export default {
       immediate: true,
       handler(newValue) {
         /* this.internalFileUrl = newValue; */
-        /* if (this.isWord) {
+        if (this.isWord) {
           this.loadWordContent();
-        } */
+        }
       },
     },
   },
   computed: {
+    officePreviewUrl() {
+      // 添加此计算属性
+      if (this.isOffice) {
+        // 使用微软Office Online Viewer
+        return `https://view.officeapps.live.com/op/embed.aspx?src=${encodeURIComponent(
+          this.fileUrl
+        )}`;
+        // 或者使用Google Docs Viewer
+        // return `https://docs.google.com/gview?url=${encodeURIComponent(this.fileUrl)}&embedded=true`;
+      }
+      return "";
+    },
     isSupported() {
       return this.supportedTypes.includes(this.fileType);
     },
@@ -114,7 +159,7 @@ export default {
       return ["jpg", "jpeg", "png", "gif"].includes(this.fileType);
     },
     isWord() {
-      return ["doc", "docx"].includes(this.fileType);
+      return ["doc", "docx"].includes(this.fileType) || this.type === "doc";
     },
     isExcel() {
       return ["xls", "xlsx"].includes(this.fileType);
@@ -124,58 +169,131 @@ export default {
     },
   },
   mounted() {
-    console.log(this.isExcel);
+    console.log(this.isWord);
     if (this.fileType === "txt") {
       this.loadTextContent();
     } else if (this.isWord) {
       this.loadWordContent();
-    } else if (this.$route.query.type=='xlsx') {
+    } else if (this.$route.query.type == "xlsx") {
       this.loadExcelContent();
     }
   },
   methods: {
     async loadWordContent() {
       this.wordLoaded = false;
-      this.wordLoadingError = false;
-      try {
-        // 获取文档 URL
-        /* if (this.type !== "ai") { */
-          const res = await searchTaskInfo({
-            page: 1,
-            page_size: 10,
-            document_id: this.$route.query.id,
-          });
-          this.internalFileUrl = res.data.documentUrl;
-      /*   } else {
-          this.internalFileUrl = localStorage.getItem("href");
-        } */
+      this.loadingProgress = 0;
+      this.previewError = false;
+      this.errorMessage = "";
 
-        // 使用 fetch 获取文件内容,指定 responseType 为 'arraybuffer'
-        const response = await fetch(this.internalFileUrl, {
-          method: "GET",
-          headers: {
-            "Content-Type":
-              "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
-          },
+      try {
+        // 获取文档URL
+        const res = await searchTaskInfo({
+          page: 1,
+          page_size: 10,
+          document_id: this.$route.query.id,
         });
 
-        if (!response.ok) {
-          throw new Error(`HTTP error! status: ${response.status}`);
+        const docUrl = res.data.documentUrl;
+
+        // 下载文件并显示进度
+        const response = await fetch(docUrl);
+        const reader = response.body.getReader();
+        const contentLength = +response.headers.get("Content-Length");
+
+        let receivedLength = 0;
+        let chunks = [];
+
+        while (true) {
+          const { done, value } = await reader.read();
+
+          if (done) break;
+
+          chunks.push(value);
+          receivedLength += value.length;
+
+          this.loadingProgress = Math.round(
+            (receivedLength / contentLength) * 100
+          );
         }
 
-        const arrayBuffer = await response.arrayBuffer();
-        const result = await mammoth.convertToHtml({ arrayBuffer });
-        this.wordContent = result.value;
-        this.wordLoaded = true;
+        // 合并数据
+        this.docData = new Uint8Array(receivedLength);
+        let position = 0;
+        for (let chunk of chunks) {
+          this.docData.set(chunk, position);
+          position += chunk.length;
+        }
+
+        // 处理不同的文档格式
+        if (this.fileType === "doc") {
+          try {
+            const result = await mammoth.convertToHtml({
+              arrayBuffer: this.docData.buffer,
+            });
+            this.wordContent = this.enhanceWordContent(result.value);
+            this.wordLoaded = true;
+          } catch (error) {
+            throw new Error("无法预览该文档,可能是格式不兼容或文件已损坏");
+          }
+        } else if (this.fileType === "docx") {
+          const result = await mammoth.convertToHtml({
+            arrayBuffer: this.docData.buffer,
+          });
+          this.wordContent = this.enhanceWordContent(result.value);
+          this.wordLoaded = true;
+        }
       } catch (error) {
-        console.error("加载Word文档内容时出错:", error);
-        this.wordContent = `无法加载Word文档内容: ${error.message}`;
-        this.wordLoadingError = true;
-        this.$message.error(`文档加载失败: ${error.message}`);
-      } finally {
-        this.wordLoaded = true;
+        console.error("文档加载失败:", error);
+        this.previewError = true;
+        this.errorMessage = error.message || "文档加载失败,请重试或下载查看";
       }
     },
+
+    // 重试预览
+    retryPreview() {
+      this.loadWordContent();
+    },
+
+    // 下载文件
+    downloadFile() {
+      if (this.docData) {
+        const blob = new Blob([this.docData], {
+          type:
+            this.fileType === "doc"
+              ? "application/msword"
+              : "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
+        });
+        saveAs(blob, `document.${this.fileType}`);
+      } else {
+        this.$message.error("文件数据不存在,请重试");
+      }
+    },
+
+    // 增强文档内容显示
+    enhanceWordContent(content) {
+      return `
+        <div class="enhanced-word-content">
+          <style>
+            .enhanced-word-content {
+              font-family: "Microsoft YaHei", Arial, sans-serif;
+              line-height: 1.6;
+              color: #333;
+              padding: 20px;
+            }
+            .enhanced-word-content h1 { font-size: 24px; margin: 20px 0; }
+            .enhanced-word-content h2 { font-size: 20px; margin: 16px 0; }
+            .enhanced-word-content p { margin: 12px 0; }
+            .enhanced-word-content img { max-width: 100%; height: auto; }
+            .enhanced-word-content table { border-collapse: collapse; width: 100%; }
+            .enhanced-word-content td, .enhanced-word-content th { 
+              border: 1px solid #ddd; 
+              padding: 8px; 
+            }
+          </style>
+          ${content}
+        </div>
+      `;
+    },
     blobToArrayBuffer(blob) {
       return new Promise((resolve, reject) => {
         const reader = new FileReader();
@@ -187,13 +305,13 @@ export default {
     async loadTextContent() {
       try {
         // 获取文档 URL
-     /*    if (this.type !== "ai") { */
-          const res = await searchTaskInfo({
-            page: 1,
-            page_size: 10,
-            document_id: this.$route.query.id,
-          });
-          this.internalFileUrl = res.data.documentUrl;
+        /*    if (this.type !== "ai") { */
+        const res = await searchTaskInfo({
+          page: 1,
+          page_size: 10,
+          document_id: this.$route.query.id,
+        });
+        this.internalFileUrl = res.data.documentUrl;
         /* } else {
           this.internalFileUrl = localStorage.getItem("href");
         } */
@@ -283,4 +401,44 @@ export default {
   font-size: 18px;
   color: #909399;
 }
+.preview-error {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  justify-content: center;
+  height: 400px;
+  color: #909399;
+  text-align: center;
+}
+
+.preview-error i {
+  font-size: 48px;
+  color: #f56c6c;
+  margin-bottom: 20px;
+}
+
+.preview-error p {
+  font-size: 16px;
+  margin-bottom: 20px;
+}
+
+.error-actions {
+  display: flex;
+  gap: 12px;
+}
+
+.loading-word {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  justify-content: center;
+  height: 400px;
+  gap: 16px;
+}
+
+.word-preview {
+  overflow-y: auto;
+  max-height: 830px;
+  padding: 20px;
+}
 </style>

Một số tệp đã không được hiển thị bởi vì quá nhiều tập tin thay đổi trong này khác