yangg 7 сар өмнө
parent
commit
1c740fba83
71 өөрчлөгдсөн 566 нэмэгдсэн , 46 устгасан
  1. 1 1
      .env.development
  2. 22 0
      dist/3f3f568521694a37b5f7.worker.js
  3. 0 0
      dist/index.html
  4. 0 0
      dist/static/css/app.d44a50a6.css
  5. 0 0
      dist/static/css/chunk-2216f77a.30cf7b33.css
  6. 0 0
      dist/static/css/chunk-3125e59e.e7ff2f91.css
  7. 1 0
      dist/static/css/chunk-429eba8b.81be44bf.css
  8. 0 0
      dist/static/css/chunk-57ca2e2b.925ec081.css
  9. 0 1
      dist/static/css/chunk-6f0044a0.2ee72984.css
  10. 0 0
      dist/static/css/chunk-a61249b0.cf8f9f2d.css
  11. 0 0
      dist/static/css/chunk-e2b9dfdc.efe6f170.css
  12. 0 0
      dist/static/css/chunk-libs.a8bd5ebe.css
  13. 0 0
      dist/static/js/app.2489d937.js
  14. 0 0
      dist/static/js/app.60e751ba.js
  15. 0 0
      dist/static/js/chunk-0074d5fe.c1436b98.js
  16. 0 0
      dist/static/js/chunk-01f26467.d812d0c8.js
  17. 0 0
      dist/static/js/chunk-038644fe.7bd3e669.js
  18. 0 0
      dist/static/js/chunk-079de15b.d7760b3e.js
  19. 0 0
      dist/static/js/chunk-091613b3.8c11eea6.js
  20. 0 0
      dist/static/js/chunk-09f78c22.eee9c21f.js
  21. 0 0
      dist/static/js/chunk-0c69682a.43a8fabc.js
  22. 0 0
      dist/static/js/chunk-0c69682a.47a2a742.js
  23. 0 0
      dist/static/js/chunk-0ec56e2a.499ad863.js
  24. 0 0
      dist/static/js/chunk-11ff1a32.71613439.js
  25. 0 0
      dist/static/js/chunk-138f7583.5920e15c.js
  26. 0 0
      dist/static/js/chunk-1bb467bc.c7550e05.js
  27. 0 0
      dist/static/js/chunk-2216f77a.bb7f3893.js
  28. 0 0
      dist/static/js/chunk-254ac533.a0d7787e.js
  29. 0 0
      dist/static/js/chunk-2a11f130.8750a584.js
  30. 0 0
      dist/static/js/chunk-2bb7cc0a.97525803.js
  31. 0 0
      dist/static/js/chunk-2d0d3705.6c0bd1f2.js
  32. 0 0
      dist/static/js/chunk-3125e59e.d745aa7a.js
  33. 0 0
      dist/static/js/chunk-3429c79e.5ffbf1cb.js
  34. 0 0
      dist/static/js/chunk-35464144.42134520.js
  35. 0 0
      dist/static/js/chunk-429eba8b.05402737.js
  36. 0 0
      dist/static/js/chunk-44eee83d.cd40a825.js
  37. 0 0
      dist/static/js/chunk-461baa1d.ad052acd.js
  38. 0 0
      dist/static/js/chunk-48f27aa5.d9888afd.js
  39. 0 0
      dist/static/js/chunk-4a670a7f.4561d794.js
  40. 0 0
      dist/static/js/chunk-4ac7f82e.18f20846.js
  41. 0 0
      dist/static/js/chunk-57ca2e2b.b7478c6b.js
  42. 0 0
      dist/static/js/chunk-5a3bdf57.9f478b75.js
  43. 0 0
      dist/static/js/chunk-5d47eef5.0350fcf8.js
  44. 0 0
      dist/static/js/chunk-5f2ff500.5ebc1c70.js
  45. 0 0
      dist/static/js/chunk-6111b966.7669d489.js
  46. 0 0
      dist/static/js/chunk-683feb49.a3e8b1f1.js
  47. 0 0
      dist/static/js/chunk-6a80e4ca.7cac3124.js
  48. 0 0
      dist/static/js/chunk-6ddf6871.8834fc35.js
  49. 0 0
      dist/static/js/chunk-6ec5c8f6.70827d97.js
  50. 0 0
      dist/static/js/chunk-6f0044a0.8c7340af.js
  51. 0 0
      dist/static/js/chunk-708604c0.f4d9629d.js
  52. 0 0
      dist/static/js/chunk-708c45dc.d358c815.js
  53. 0 0
      dist/static/js/chunk-72e66010.d3539583.js
  54. 0 0
      dist/static/js/chunk-77bc8fb9.98f6551b.js
  55. 0 0
      dist/static/js/chunk-7a88741c.e0a32ae3.js
  56. 0 0
      dist/static/js/chunk-7b81ddc1.5587853c.js
  57. 0 0
      dist/static/js/chunk-9235c1ae.eafdb69a.js
  58. 0 0
      dist/static/js/chunk-a61249b0.2d618739.js
  59. 0 0
      dist/static/js/chunk-b83b1a34.3883aeb1.js
  60. 0 0
      dist/static/js/chunk-c0d178b4.600a5f90.js
  61. 0 0
      dist/static/js/chunk-c46a82fe.039e553a.js
  62. 0 0
      dist/static/js/chunk-cda0aa98.df79cfe9.js
  63. 0 0
      dist/static/js/chunk-cdf4eda6.358b9435.js
  64. 0 0
      dist/static/js/chunk-e08ed888.ca37f882.js
  65. 0 0
      dist/static/js/chunk-e2b9dfdc.9f15f426.js
  66. 0 0
      dist/static/js/chunk-libs.82b96695.js
  67. 1 0
      package.json
  68. 439 9
      src/components/FilePreview/index.vue
  69. 33 14
      src/views/dashboard/admin/chart.vue
  70. 36 7
      src/views/knowledgeMenu/category/infoList.vue
  71. 33 14
      src/views/knowledgeMenu/category/knowledgeSet.vue

+ 1 - 1
.env.development

@@ -2,7 +2,7 @@
 ENV = 'development'
 port = 8080
 # base api
-VUE_APP_BASE_API = 'http://192.168.66.208:8084'
+VUE_APP_BASE_API = 'http://192.168.66.163:8084'
 #192.168.66.208
 #朱:192.168.66.163
 #测试服务器:121.36.251.245

Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 22 - 0
dist/3f3f568521694a37b5f7.worker.js


Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 0 - 0
dist/index.html


Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 0 - 0
dist/static/css/app.d44a50a6.css


+ 0 - 0
dist/static/css/chunk-2bb7cc0a.e7ff2f91.css → dist/static/css/chunk-2216f77a.30cf7b33.css


+ 0 - 0
dist/static/css/chunk-b83b1a34.30cf7b33.css → dist/static/css/chunk-3125e59e.e7ff2f91.css


+ 1 - 0
dist/static/css/chunk-429eba8b.81be44bf.css

@@ -0,0 +1 @@
+.project-search[data-v-a32694b2]{display:-webkit-box;display:-ms-flexbox;display:flex;padding:10px;font-size:12px}.listClass[data-v-a32694b2]{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between}.excel-table[data-v-a32694b2]{width:100%;overflow-y:auto}.excel-table table[data-v-a32694b2]{border-collapse:collapse;width:100%;margin-bottom:20px}.excel-table td[data-v-a32694b2],.excel-table th[data-v-a32694b2]{border:1px solid #ddd;padding:8px;text-align:left;white-space:nowrap}.excel-table th[data-v-a32694b2]{background-color:#f2f2f2;font-weight:700;position:sticky;top:0;z-index:1}.excel-table tr[data-v-a32694b2]:nth-child(2n){background-color:#f9f9f9}.no-data[data-v-a32694b2]{font-size:18px;color:#909399;text-align:center;margin-top:50px}.pagination[data-v-a32694b2]{position:fixed;bottom:0;right:51%}.movable-dialog[data-v-a32694b2]{position:absolute!important}[data-v-a32694b2] .el-dialog__header{cursor:move}

Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 0 - 0
dist/static/css/chunk-57ca2e2b.925ec081.css


+ 0 - 1
dist/static/css/chunk-6f0044a0.2ee72984.css

@@ -1 +0,0 @@
-.project-search[data-v-39a9cf3e]{display:-webkit-box;display:-ms-flexbox;display:flex;padding:10px;font-size:12px}.listClass[data-v-39a9cf3e]{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between}.excel-table[data-v-39a9cf3e]{width:100%;overflow-y:auto}.excel-table table[data-v-39a9cf3e]{border-collapse:collapse;width:100%;margin-bottom:20px}.excel-table td[data-v-39a9cf3e],.excel-table th[data-v-39a9cf3e]{border:1px solid #ddd;padding:8px;text-align:left;white-space:nowrap}.excel-table th[data-v-39a9cf3e]{background-color:#f2f2f2;font-weight:700;position:sticky;top:0;z-index:1}.excel-table tr[data-v-39a9cf3e]:nth-child(2n){background-color:#f9f9f9}.no-data[data-v-39a9cf3e]{font-size:18px;color:#909399;text-align:center;margin-top:50px}.pagination[data-v-39a9cf3e]{position:fixed;bottom:0;right:51%}.movable-dialog[data-v-39a9cf3e]{position:absolute!important}[data-v-39a9cf3e] .el-dialog__header{cursor:move}

Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 0 - 0
dist/static/css/chunk-a61249b0.cf8f9f2d.css


Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 0 - 0
dist/static/css/chunk-e2b9dfdc.efe6f170.css


Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 0 - 0
dist/static/css/chunk-libs.a8bd5ebe.css


Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 0 - 0
dist/static/js/app.2489d937.js


Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 0 - 0
dist/static/js/app.60e751ba.js


+ 0 - 0
dist/static/js/chunk-0074d5fe.5c548739.js → dist/static/js/chunk-0074d5fe.c1436b98.js


+ 0 - 0
dist/static/js/chunk-01f26467.1a5361e8.js → dist/static/js/chunk-01f26467.d812d0c8.js


+ 0 - 0
dist/static/js/chunk-038644fe.ce588b95.js → dist/static/js/chunk-038644fe.7bd3e669.js


+ 0 - 0
dist/static/js/chunk-079de15b.f02245ea.js → dist/static/js/chunk-079de15b.d7760b3e.js


+ 0 - 0
dist/static/js/chunk-091613b3.10ec101e.js → dist/static/js/chunk-091613b3.8c11eea6.js


+ 0 - 0
dist/static/js/chunk-09f78c22.88230094.js → dist/static/js/chunk-09f78c22.eee9c21f.js


Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 0 - 0
dist/static/js/chunk-0c69682a.43a8fabc.js


Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 0 - 0
dist/static/js/chunk-0c69682a.47a2a742.js


+ 0 - 0
dist/static/js/chunk-0ec56e2a.ac32c727.js → dist/static/js/chunk-0ec56e2a.499ad863.js


+ 0 - 0
dist/static/js/chunk-11ff1a32.5a52f70c.js → dist/static/js/chunk-11ff1a32.71613439.js


+ 0 - 0
dist/static/js/chunk-138f7583.d42376cc.js → dist/static/js/chunk-138f7583.5920e15c.js


+ 0 - 0
dist/static/js/chunk-1bb467bc.4140970a.js → dist/static/js/chunk-1bb467bc.c7550e05.js


Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 0 - 0
dist/static/js/chunk-2216f77a.bb7f3893.js


+ 0 - 0
dist/static/js/chunk-254ac533.d9b45f83.js → dist/static/js/chunk-254ac533.a0d7787e.js


+ 0 - 0
dist/static/js/chunk-2a11f130.6c137937.js → dist/static/js/chunk-2a11f130.8750a584.js


Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 0 - 0
dist/static/js/chunk-2bb7cc0a.97525803.js


+ 0 - 0
dist/static/js/chunk-2d0d3705.563bf010.js → dist/static/js/chunk-2d0d3705.6c0bd1f2.js


Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 0 - 0
dist/static/js/chunk-3125e59e.d745aa7a.js


+ 0 - 0
dist/static/js/chunk-3429c79e.cc16357b.js → dist/static/js/chunk-3429c79e.5ffbf1cb.js


+ 0 - 0
dist/static/js/chunk-35464144.2a7f9639.js → dist/static/js/chunk-35464144.42134520.js


Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 0 - 0
dist/static/js/chunk-429eba8b.05402737.js


+ 0 - 0
dist/static/js/chunk-44eee83d.22915da1.js → dist/static/js/chunk-44eee83d.cd40a825.js


+ 0 - 0
dist/static/js/chunk-461baa1d.86f20ee6.js → dist/static/js/chunk-461baa1d.ad052acd.js


+ 0 - 0
dist/static/js/chunk-48f27aa5.6cc16cc7.js → dist/static/js/chunk-48f27aa5.d9888afd.js


+ 0 - 0
dist/static/js/chunk-4a670a7f.cd9e5300.js → dist/static/js/chunk-4a670a7f.4561d794.js


+ 0 - 0
dist/static/js/chunk-4ac7f82e.17490404.js → dist/static/js/chunk-4ac7f82e.18f20846.js


Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 0 - 0
dist/static/js/chunk-57ca2e2b.b7478c6b.js


+ 0 - 0
dist/static/js/chunk-5a3bdf57.4b61eeb9.js → dist/static/js/chunk-5a3bdf57.9f478b75.js


Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 0 - 0
dist/static/js/chunk-5d47eef5.0350fcf8.js


+ 0 - 0
dist/static/js/chunk-5f2ff500.a8624792.js → dist/static/js/chunk-5f2ff500.5ebc1c70.js


+ 0 - 0
dist/static/js/chunk-6111b966.f5fad10a.js → dist/static/js/chunk-6111b966.7669d489.js


+ 0 - 0
dist/static/js/chunk-683feb49.594625b2.js → dist/static/js/chunk-683feb49.a3e8b1f1.js


+ 0 - 0
dist/static/js/chunk-6a80e4ca.4cd4cfec.js → dist/static/js/chunk-6a80e4ca.7cac3124.js


+ 0 - 0
dist/static/js/chunk-6ddf6871.a6c4fc7b.js → dist/static/js/chunk-6ddf6871.8834fc35.js


+ 0 - 0
dist/static/js/chunk-6ec5c8f6.063b6a0d.js → dist/static/js/chunk-6ec5c8f6.70827d97.js


Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 0 - 0
dist/static/js/chunk-6f0044a0.8c7340af.js


+ 0 - 0
dist/static/js/chunk-708604c0.4534fef5.js → dist/static/js/chunk-708604c0.f4d9629d.js


+ 0 - 0
dist/static/js/chunk-708c45dc.6602cc2f.js → dist/static/js/chunk-708c45dc.d358c815.js


+ 0 - 0
dist/static/js/chunk-72e66010.791f4cac.js → dist/static/js/chunk-72e66010.d3539583.js


+ 0 - 0
dist/static/js/chunk-77bc8fb9.252e8dda.js → dist/static/js/chunk-77bc8fb9.98f6551b.js


+ 0 - 0
dist/static/js/chunk-7a88741c.91bfb402.js → dist/static/js/chunk-7a88741c.e0a32ae3.js


+ 0 - 0
dist/static/js/chunk-7b81ddc1.81b47473.js → dist/static/js/chunk-7b81ddc1.5587853c.js


+ 0 - 0
dist/static/js/chunk-9235c1ae.81ac9858.js → dist/static/js/chunk-9235c1ae.eafdb69a.js


Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 0 - 0
dist/static/js/chunk-a61249b0.2d618739.js


Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 0 - 0
dist/static/js/chunk-b83b1a34.3883aeb1.js


+ 0 - 0
dist/static/js/chunk-c0d178b4.dc121bb2.js → dist/static/js/chunk-c0d178b4.600a5f90.js


+ 0 - 0
dist/static/js/chunk-c46a82fe.626ca9aa.js → dist/static/js/chunk-c46a82fe.039e553a.js


+ 0 - 0
dist/static/js/chunk-cda0aa98.7cfab00f.js → dist/static/js/chunk-cda0aa98.df79cfe9.js


+ 0 - 0
dist/static/js/chunk-cdf4eda6.246e5402.js → dist/static/js/chunk-cdf4eda6.358b9435.js


+ 0 - 0
dist/static/js/chunk-e08ed888.b7a2af8a.js → dist/static/js/chunk-e08ed888.ca37f882.js


Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 0 - 0
dist/static/js/chunk-e2b9dfdc.9f15f426.js


Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 0 - 0
dist/static/js/chunk-libs.82b96695.js


+ 1 - 0
package.json

@@ -71,6 +71,7 @@
     "vue": "2.6.10",
     "vue-class-component": "^7.2.6",
     "vue-count-to": "1.0.13",
+    "vue-pdf": "^4.3.0",
     "vue-property-decorator": "^9.1.2",
     "vue-quill-editor": "^3.0.6",
     "vue-router": "^3.5.3",

+ 439 - 9
src/components/FilePreview/index.vue

@@ -2,12 +2,50 @@
   <div class="file-preview">
     <div v-if="isSupported">
       <!-- PDF 预览 -->
-      <iframe
-        v-if="fileType === 'pdf'"
-        :src="fileUrl"
-        width="100%"
-        height="830px"
-      ></iframe>
+      <div v-if="fileType === 'pdf'" class="pdf-container">
+        <pdf
+          ref="pdfComponent"
+          v-if="pdfUrl"
+          :src="pdfUrl"
+          :page="currentPage"
+          :rotate="0"
+          @loaded="loadCompleted"
+          @num-pages="pageCount = $event"
+          class="pdf-viewer"
+        ></pdf>
+
+        <!-- 将高亮层移到PDF组件后面 -->
+        <div class="highlight-layer">
+          <div
+            v-for="(highlight, index) in highlights"
+            :key="index"
+            class="highlight-rect"
+            :style="getHighlightStyle(highlight)"
+          ></div>
+        </div>
+
+        <!-- PDF控制器 -->
+        <div v-if="pdfLoadComplete" class="pdf-controls">
+          <el-button-group>
+            <el-button @click="prevPage" :disabled="currentPage <= 1"
+              >上一页</el-button
+            >
+            <el-button @click="nextPage" :disabled="currentPage >= pageCount"
+              >下一页</el-button
+            >
+          </el-button-group>
+          <span class="page-info">{{ currentPage }} / {{ pageCount }}</span>
+        </div>
+
+        <!-- PDF加载状态 -->
+        <div v-if="!pdfLoadComplete" class="pdf-loading">
+          <el-progress
+            type="circle"
+            :percentage="loadingProgress"
+          ></el-progress>
+          <span>PDF加载中...</span>
+        </div>
+      </div>
 
       <!-- 图片预览 -->
       <img
@@ -83,7 +121,12 @@ import mammoth from "mammoth";
 import LuckyExcel from "luckyexcel";
 import { saveAs } from "file-saver";
 import JSZip from "jszip";
+import pdf from "vue-pdf";
+
 export default {
+  components: {
+    pdf,
+  },
   props: {
     fileUrl: {
       type: String,
@@ -97,6 +140,14 @@ export default {
       type: String,
       required: true,
     },
+    pageNum: {
+      type: String,
+      required: true,
+    },
+    coordinate: {
+      type: String,
+      required: true,
+    },
   },
   data() {
     return {
@@ -126,6 +177,15 @@ export default {
       previewError: false,
       errorMessage: "",
       docData: null, // 保存文档数据用于下载
+      pdfUrl: null,
+      pdfLoadComplete: false,
+      currentPage: 1,
+      pageCount: 0,
+      highlights: [], // 存储高亮区域
+      pdfScale: 1, // PDF缩放比例
+      pdfViewport: null, // PDF视口信息
+      startX: 0,
+      endY: 0,
     };
   },
   watch: {
@@ -138,6 +198,31 @@ export default {
         }
       },
     },
+    pageNum: {
+      immediate: true,
+      handler(newValue) {
+        if (this.fileType === "pdf" && newValue) {
+          this.currentPage = parseInt(newValue);
+        }
+      },
+    },
+
+    fileUrl: {
+      immediate: true,
+      async handler(newValue) {
+        if (this.fileType === "pdf" && newValue) {
+          await this.initPdf();
+        }
+      },
+    },
+    coordinate: {
+      handler(newValue) {
+        console.log(newValue);
+        if (newValue && this.pdfLoadComplete) {
+          this.addHighlight(newValue);
+        }
+      },
+    },
   },
   computed: {
     officePreviewUrl() {
@@ -167,6 +252,13 @@ export default {
     isOffice() {
       return ["ppt", "pptx"].includes(this.fileType);
     },
+    pdfViewerUrl() {
+      if (this.fileType === "pdf") {
+        // 确保添加初始页码参数
+        return `${this.fileUrl}#page=${this.pageNum}`;
+      }
+      return this.fileUrl;
+    },
   },
   mounted() {
     console.log(this.isWord);
@@ -177,8 +269,55 @@ export default {
     } else if (this.$route.query.type == "xlsx") {
       this.loadExcelContent();
     }
+    window.addEventListener("resize", this.updateHighlightPosition);
   },
   methods: {
+    /* 翻页 */
+
+    scrollToPage(pageNumber) {
+      const iframe = this.$refs.previewFrame;
+      if (!iframe || !iframe.contentWindow) return;
+
+      const tryScrollMethods = [
+        // 方法1: 使用PDFViewerApplication API
+        () => {
+          iframe.contentWindow.PDFViewerApplication.page = parseInt(pageNumber);
+          return true;
+        },
+        // 方法2: 使用PDFViewerApplication.pdfViewer
+        () => {
+          iframe.contentWindow.PDFViewerApplication.pdfViewer.currentPageNumber =
+            parseInt(pageNumber);
+          return true;
+        },
+        // 方法3: 通过URL参数重新加载
+        () => {
+          const newUrl = this.fileUrl.split("#")[0] + `#page=${pageNumber}`;
+          if (iframe.src !== newUrl) {
+            iframe.src = newUrl;
+          }
+          return true;
+        },
+      ];
+
+      // 依次尝试不同的方法
+      for (const method of tryScrollMethods) {
+        try {
+          if (method()) {
+            console.log("PDF页面跳转成功");
+            return;
+          }
+        } catch (error) {
+          console.log("尝试下一种跳转方法");
+          continue;
+        }
+      }
+
+      // 所有方法都失败时的处理
+      console.warn("PDF跳转失败,请检查PDF查看器配置");
+      this.$message.warning("PDF跳转可能不成功,请手动滚动到目标页面");
+    },
+
     async loadWordContent() {
       this.wordLoaded = false;
       this.loadingProgress = 0;
@@ -269,7 +408,7 @@ export default {
       }
     },
 
-    // 增强文档内容显
+    // 增强文档内容显
     enhanceWordContent(content) {
       return `
         <div class="enhanced-word-content">
@@ -371,6 +510,177 @@ export default {
         this.$message.error(`Excel文档加载失败: ${error.message}`);
       }
     },
+    // 添加 iframe 加载完成的处理函数
+    handleIframeLoad() {
+      const iframe = this.$refs.previewFrame;
+      if (iframe && iframe.contentWindow) {
+        // 等待PDF.js完全初始化
+        setTimeout(() => {
+          this.scrollToPage(this.pageNum);
+        }, 1000); // 给PDF.js足够的加载时间
+      }
+    },
+
+    // 添加消息处理函数
+    handlePdfMessage(event) {
+      // 处理来自 PDF.js 的消息
+      if (event.data && event.data.type === "pdfLoaded") {
+        // PDF 加载完成,可以执行翻页操作
+        this.scrollToPage(this.pageNum);
+      }
+    },
+    // 监听页码变化
+    watchPageChange() {
+      const iframe = this.$refs.previewFrame;
+      if (iframe && iframe.contentWindow) {
+        try {
+          // 监听PDF.js的页码变化事件
+          iframe.contentWindow.PDFViewerApplication.eventBus.on(
+            "pagechanging",
+            (evt) => {
+              console.log("PDF页码变化:", evt.pageNumber);
+            }
+          );
+        } catch (error) {
+          console.warn("无法监听PDF页码变化:", error);
+        }
+      }
+    },
+    async initPdf() {
+      try {
+        if (this.type !== "ai") {
+          const res = await searchTaskInfo({
+            page: 1,
+            page_size: 10,
+            document_id: this.$route.query.id,
+          });
+          this.pdfUrl = { url: res.data.documentUrl };
+        } else {
+          this.pdfUrl = { url: this.fileUrl };
+        }
+        // 设置初始页码
+        this.currentPage = parseInt(this.pageNum) || 1;
+      } catch (error) {
+        console.error("PDF初始化失败:", error);
+        this.$message.error("PDF加载失败,请重试");
+      }
+    },
+
+    // PDF文档完全加载完成
+    loadCompleted() {
+      this.pdfLoadComplete = true;
+      this.loadingProgress = 100;
+
+      // 确保在PDF完全渲染后更新高亮
+      setTimeout(() => {
+        this.updateHighlightPosition();
+        // 如果有coordinate属性,添加高亮
+        if (this.coordinate) {
+          this.addHighlight(this.coordinate);
+        }
+      }, 500);
+    },
+
+    // PDF翻页控制
+    prevPage() {
+      if (this.currentPage > 1) {
+        this.currentPage--;
+      }
+    },
+
+    nextPage() {
+      if (this.currentPage < this.pageCount) {
+        this.currentPage++;
+      }
+    },
+
+    // 修改添加高亮方法
+    addHighlight(coordinates) {
+      try {
+        console.log("Adding highlight with coordinates:", coordinates);
+        let coords = JSON.parse(coordinates);
+
+        // 确保坐标数组格式正确
+        if (!Array.isArray(coords) || coords.length !== 4) {
+          console.error("Invalid coordinates format");
+          return;
+        }
+
+        // 正确获取起始点和终点坐标
+        const startX = coords[2]; // x1
+        const endY = coords[0]; // y1
+        const endX = coords[3]; // x2
+        const startY = coords[1]; // y2
+
+        // 计算矩形的位置和尺寸
+        const highlight = {
+          x: Math.min(startX, endX), // 取两个x坐标的最小值作为左边界
+          y: Math.min(startY, endY), // 取两个y坐标的最小值作为上边界
+          width: Math.abs(startX - endX), // 宽度为x坐标差的绝对值
+          height: Math.abs(startY - endY), // 高度为y坐标差的绝对值
+        };
+
+        console.log("Processed highlight:", highlight);
+        this.startX = startX;
+        this.endY = endY;
+        this.highlights = [highlight];
+
+        // 强制更新高亮位置
+        this.$nextTick(() => {
+          this.updateHighlightPosition();
+        });
+      } catch (error) {
+        console.error("Error adding highlight:", error);
+      }
+    },
+
+    // 修改更新高亮位置方法
+    updateHighlightPosition() {
+      const pdfComponent = this.$refs.pdfComponent;
+      if (!pdfComponent || !pdfComponent.$el) return;
+
+      const canvas = pdfComponent.$el.querySelector("canvas");
+      if (!canvas) return;
+
+      // 获取PDF页面的实际尺寸和缩放比例
+      const rect = canvas.getBoundingClientRect();
+      const scaleX = rect.width / canvas.width;
+      const scaleY = rect.height / canvas.height;
+
+      this.pdfScale = {
+        scaleX,
+        scaleY,
+        width: rect.width,
+        height: rect.height,
+      };
+
+      console.log("PDF scale updated:", this.pdfScale);
+    },
+
+    // 修改高亮样式计算方法
+    getHighlightStyle(highlight) {
+      if (!this.pdfScale) return {};
+
+      const { scaleX, scaleY, height } = this.pdfScale;
+
+      // PDF坐标系转换(PDF坐标系原点在左下角,需要转换为左上角)
+      return {
+        position: "absolute",
+        left: `${this.startX}px`,
+        top: `${this.endY}px`,
+        width: `${highlight.width * scaleX}px`,
+        height: `${highlight.height * scaleY}px`,
+        backgroundColor: "rgba(255, 152, 0, 0.1)", // 淡橙色半透明背景
+        border: "2px solid #FF9800", // 橙色边框
+        pointerEvents: "none",
+        zIndex: 100,
+      };
+    },
+  },
+  // 组件销毁时清理事件监听器
+  beforeDestroy() {
+    window.removeEventListener("message", this.handlePdfMessage);
+    window.removeEventListener("resize", this.updateHighlightPosition);
   },
 };
 </script>
@@ -378,8 +688,10 @@ export default {
   <style scoped>
 .file-preview {
   width: 100%;
-  height: 850px;
-  overflow: auto;
+  height: 100vh;
+  overflow: hidden;
+  display: flex;
+  flex-direction: column;
 }
 .unsupported-file {
   display: flex;
@@ -441,4 +753,122 @@ export default {
   max-height: 830px;
   padding: 20px;
 }
+
+/* 添加PDF预览相关样式 */
+.pdf-container {
+  position: relative;
+  width: 100%;
+  height: 100%;
+}
+
+.pdf-error {
+  position: absolute;
+  top: 50%;
+  left: 50%;
+  transform: translate(-50%, -50%);
+  text-align: center;
+  color: #f56c6c;
+}
+
+.pdf-loading {
+  position: absolute;
+  top: 50%;
+  left: 50%;
+  transform: translate(-50%, -50%);
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  gap: 20px;
+}
+
+.pdf-controls {
+  position: fixed;
+  bottom: 0px;
+  left: 77%;
+  transform: translateX(-50%);
+  display: flex;
+  align-items: center;
+  gap: 20px;
+  padding: 10px 20px;
+  background: rgba(255, 255, 255, 0.9);
+  border-radius: 4px;
+  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
+  z-index: 1000;
+  margin: 0 auto;
+}
+
+.page-info {
+  font-size: 14px;
+  color: #606266;
+}
+
+/* PDF页面容器样式 */
+.vuepdfiframe {
+  width: 100% !important;
+  height: 750px !important; /* 留出空间给分页控件 */
+}
+
+/* 新增PDF查看器样式 */
+.pdf-viewer {
+  position: relative;
+  z-index: 1;
+}
+
+/* PDF页面样式 */
+::v-deep .pdf-viewer canvas {
+  max-width: 771px;
+  height: 1024px !important;
+}
+
+/* 确保PDF内容居中显示 */
+:deep(.vue-pdf-embed) {
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  width: 90%;
+  height: 100%;
+}
+
+.highlight-layer {
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+  pointer-events: none;
+  z-index: 2;
+}
+
+.highlight-rect {
+  position: absolute;
+  border: 2px solid #ff9800;
+  box-shadow: 0 0 4px rgba(255, 152, 0, 0.5);
+  background-color: rgba(255, 152, 0, 0.1);
+  mix-blend-mode: multiply;
+  transition: all 0.3s ease;
+  animation: highlight-flash 2s infinite;
+}
+
+.pdf-container {
+  position: relative;
+  width: 100%;
+  height: 100%;
+}
+
+/* 添加动画效果 */
+@keyframes highlight-flash {
+  0% {
+    border-color: rgba(255, 152, 0, 0.3);
+  }
+  50% {
+    border-color: rgba(255, 152, 0, 1);
+  }
+  100% {
+    border-color: rgba(255, 152, 0, 0.3);
+  }
+}
+
+.highlight-rect {
+  animation: highlight-flash 2s infinite;
+}
 </style>

+ 33 - 14
src/views/dashboard/admin/chart.vue

@@ -639,15 +639,24 @@ export default {
           high: 85,    // 默认GPU高温阈值
           critical: 90  // 默认GPU临界温度
         }
-      }
+      },
+      isCurrentPage: false, // 添加标记当前页面状态的变量
     };
   },
   watch: {
     $route: {
       immediate: true,
       handler(newRoute) {
-        this.isOnDashboard = newRoute.path === "/dashboard";
-        this.handleRouteChange();
+        const isDashboard = newRoute.path === "/dashboard";
+        if (isDashboard && !this.isCurrentPage) {
+          // 进入dashboard页面
+          this.isCurrentPage = true;
+          this.initWebSocket();
+        } else if (!isDashboard && this.isCurrentPage) {
+          // 离开dashboard页面
+          this.isCurrentPage = false;
+          this.closeWebSocket();
+        }
       },
     },
     // 监听页面可见性
@@ -724,6 +733,11 @@ export default {
         this.ws.close();
         this.ws = null;
       }
+      // 清除重连定时器
+      if (this.wsReconnectTimer) {
+        clearTimeout(this.wsReconnectTimer);
+        this.wsReconnectTimer = null;
+      }
     },
     handleRouteChange() {
       if (this.isOnDashboard) {
@@ -734,18 +748,20 @@ export default {
     },
     /* websocket 请求 */
     initWebSocket() {
-      // 获取基础 API 地址并替换 http/https 为 ws/wss
+      // 如果不是当前页面或已经存在连接,则不建立新连接
+      if (!this.isCurrentPage || this.ws) {
+        return;
+      }
+
       const wsUrl = process.env.VUE_APP_BASE_API.replace(/^http/, "ws");
-      // 创建 WebSocket 连接
       this.ws = new WebSocket(`${wsUrl}/ws/monitoring`);
 
-      // 连接成功回调
       this.ws.onopen = () => {
         console.log("WebSocket连接成功");
       };
 
-      // 接收消息回调
       this.ws.onmessage = (event) => {
+        if (!this.isCurrentPage) return; // 如果不是当前页面,不处理消息
         try {
           const data = JSON.parse(event.data);
           // 检查数据结构是否完整
@@ -775,18 +791,20 @@ export default {
         }
       };
 
-      // 连接关闭回调
       this.ws.onclose = () => {
         console.log("WebSocket连接关闭");
-        // 可以添加重连逻辑
-        setTimeout(() => {
-          this.initWebSocket();
-        }, 3000);
+        // 只在当前页面时进行重连
+        if (this.isCurrentPage && !this.wsReconnectTimer) {
+          this.wsReconnectTimer = setTimeout(() => {
+            this.initWebSocket();
+          }, 3000);
+        }
       };
 
-      // 连接错误回调
       this.ws.onerror = (error) => {
         console.error("WebSocket连接错误:", error);
+        // 连接错误时关闭连接,触发重连
+        this.closeWebSocket();
       };
     },
 
@@ -1719,6 +1737,8 @@ export default {
   },
   // 修改beforeDestroy钩子
   beforeDestroy() {
+    this.isCurrentPage = false;
+    this.closeWebSocket();
     // 清理所有图表实例
     Object.values(this.charts).forEach((chart) => {
       if (chart) {
@@ -1729,7 +1749,6 @@ export default {
         }
       }
     });
-    this.closeWebSocket(); // 组件销毁前关闭 WebSocket
     // 移除事件监听器
     document.removeEventListener(
       "visibilitychange",

+ 36 - 7
src/views/knowledgeMenu/category/infoList.vue

@@ -10,7 +10,12 @@
       v-if="dataList.length !== 0"
     >
       <div v-for="item in dataList" :key="item.id" class="listClass">
-        <img
+        <span style="
+            
+            padding: 10px 10px 10px 0;
+            cursor: pointer;
+          ">{{ item.page_number }}</span>
+        <!--  <img
           :src="item.url"
           alt=""
           @click="openImagePreview(item.url)"
@@ -20,8 +25,12 @@
             padding: 10px 10px 10px 0;
             cursor: pointer;
           "
-        />
-        <div v-html="item.content"></div>
+        /> -->
+        <div
+          style="padding-bottom: 10px"
+          v-html="item.content"
+          @click="scrollToPage(item.page_number, item.coordinate)"
+        ></div>
       </div>
       <el-dialog
         :visible.sync="imagePreviewVisible"
@@ -34,7 +43,7 @@
         <img :src="previewImageUrl" style="width: 100%" alt="Preview" />
       </el-dialog>
       <!-- 分页控件 -->
-      <div class="pagination">
+     <!--  <div class="pagination">
         <el-pagination
           @current-change="handleCurrentChange"
           :current-page="queryForm.page"
@@ -43,7 +52,7 @@
           layout="prev, pager, next"
         >
         </el-pagination>
-      </div>
+      </div> -->
     </div>
     <div
       v-else
@@ -62,7 +71,14 @@
     </div> -->
     <div style="width: 50%">
       <!-- 文件预览组件 -->
-      <file-preview :file-url="documentUrl" :file-type="type" :type="type" />
+      <file-preview
+        :file-url="documentUrl"
+        :file-type="type"
+        :type="type"
+        ref="filePreview"
+        :pageNum="pdfPageNum"
+        :coordinate="pdfCoordinate"
+      />
     </div>
   </div>
   <div v-else>
@@ -118,7 +134,7 @@ export default {
     return {
       queryForm: {
         page: 1,
-        page_size: 10,
+        page_size: 9999,
         document_id: "",
       },
       dataList: [],
@@ -144,6 +160,8 @@ export default {
       total: 0,
       imagePreviewVisible: false,
       previewImageUrl: "",
+      pdfPageNum: "",
+      pdfCoordinate: "",
     };
   },
   mounted() {
@@ -294,6 +312,17 @@ export default {
         })
         .filter((sheet) => sheet !== null && sheet.data.length > 0);
     },
+    scrollToPage(pageNumber, coordinate) {
+      if (!pageNumber) return;
+      this.pdfPageNum = pageNumber;
+      this.pdfCoordinate = coordinate;
+      // 获取file-preview组件的引用
+      const filePreviewComponent = this.$refs.filePreview;
+
+      if (filePreviewComponent) {
+        filePreviewComponent.scrollToPage(pageNumber);
+      }
+    },
   },
 };
 </script>

+ 33 - 14
src/views/knowledgeMenu/category/knowledgeSet.vue

@@ -154,8 +154,7 @@
                 effect="dark"
                 placement="top"
                 :disabled="
-                  Number(scope.row.run) !== 1 &&
-                  Number(scope.row.run) !== 4
+                  Number(scope.row.run) !== 1 && Number(scope.row.run) !== 4
                 "
               >
                 <template #content>
@@ -171,11 +170,11 @@
                       <el-progress
                         type="circle"
                         :percentage="Math.floor(scope.row.progress) || 0"
-                        :width="35"
-                        :stroke-width="4"
+                        :width="30"
+                        :stroke-width="2"
                         :format="percentFormat"
-                       
-                      ></el-progress><!--  :status="getProgressStatus(scope.row.progress)" -->
+                      ></el-progress
+                      ><!--  :status="getProgressStatus(scope.row.progress)" -->
                     </div>
                   </template>
                   <template v-else>
@@ -374,6 +373,12 @@
             label-position="top"
             :rules="analRules"
           >
+            <el-form-item label="语言选择:" prop="language">
+              <el-radio-group v-model="analForm.language">
+                <el-radio label="zh">中文</el-radio>
+                <el-radio label="en">英文</el-radio>
+              </el-radio-group>
+            </el-form-item>
             <el-form-item label="页码范围:" prop="new_name">
               <el-input-number
                 v-model="analForm.start_page"
@@ -536,6 +541,7 @@ export default {
         start_page: 1,
         end_page: 10000,
         token_num: 0,
+        language:'zh'
       },
       analRules: {},
       selectedRows: [],
@@ -628,12 +634,12 @@ export default {
     /* 状态展示 */
     getStatusType(status) {
       const statusMap = {
-        0: "info",    // 未解析
+        0: "info", // 未解析
         1: "warning", // 解析中
         3: "success", // 成功
-        4: "danger",  // 失败
-        5: "info",    // 待解析
-        6: "danger",  // 文件异常
+        4: "danger", // 失败
+        5: "info", // 待解析
+        6: "danger", // 文件异常
       };
       return statusMap[status] || "info";
     },
@@ -1015,6 +1021,11 @@ export default {
           this.loading = true;
           analysisPro({
             document_ids: JSON.stringify(selectedIds),
+            ocr_params: {
+              language: this.analForm.language,
+              max_retries: 3,
+              timeout: [10, 180],
+            },
           }) /* { ids: JSON.stringify(selectedIds) } */
             .then((res) => {
               if (res.status === 200) {
@@ -1119,13 +1130,20 @@ export default {
         start_page: row.start_page ?? 0, // 使用空值合并运算符
         end_page: row.end_page ?? 1000, // 使用空值合并运算符
         max_tokens: row.token_num,
+        ocr_params: {
+          language: this.analForm.language, //en,zh
+          max_retries: 3,
+          timeout: [10, 180],
+        },
       };
 
       analysisPro(analysisConfig)
         .then((res) => {
           if (res.status === 200) {
             // Start checking the status immediately after successful API call
-            this.startAnalysisStatusChecker(row);
+            setTimeout(() => {
+              this.startAnalysisStatusChecker(row);
+            });
           } else {
             this.$message.error("解析请求失败");
             this.$set(row, "run", 0);
@@ -1248,6 +1266,7 @@ export default {
     submitAnal() {
       this.dataList.map((el) => {
         if (this.analForm.id == el.id) {
+          el.language=this.analForm.language
           el.start_page = this.analForm.start_page;
           el.end_page = this.analForm.end_page;
           el.token_num = this.analForm.token_num;
@@ -1660,17 +1679,17 @@ export default {
   justify-content: center;
   padding: 2px;
   transition: none !important;
-  
+
   ::v-deep .el-progress {
     line-height: 1;
     transition: none !important;
-    
+
     .el-progress__text {
       font-size: 12px !important;
       color: inherit;
       transition: none !important;
     }
-    
+
     .el-progress-circle {
       margin: 0;
       transition: none !important;

Энэ ялгаанд хэт олон файл өөрчлөгдсөн тул зарим файлыг харуулаагүй болно