yangg před 21 hodinami
rodič
revize
c9cf79b376

+ 10 - 1
src/api/knowledge.js

@@ -780,4 +780,13 @@ export function getProgress(data) {
     method: 'get',
     data
   })
-}
+}
+
+/* 生成问答对 */
+export function generateQa(data) {
+  return request({
+    url: '/kbm/generate-qa',
+    method: 'post',
+    data
+  })
+}

+ 99 - 19
src/views/knowledgeMenu/category/knowledgeSet.vue

@@ -77,6 +77,9 @@
               <el-dropdown-item command="analysis">
                 <i data-feather="play" class="icons"></i> 批量解析
               </el-dropdown-item>
+              <el-dropdown-item command="generateQa">
+                <i data-feather="message-square" class="icons"></i> 生成问答对
+              </el-dropdown-item>
               <el-dropdown-item command="modifyFolder">
                 <i data-feather="folder" class="icons"></i> 批量修改目录
               </el-dropdown-item>
@@ -138,12 +141,13 @@
             :reserve-selection="true"
           ></el-table-column>
           <el-table-column prop="id" label="ID" align="center" width="80" />
-          <el-table-column prop="name" label="文件名称" sortable width="350">
+          <el-table-column prop="name" label="文件名称" sortable >
             <template #default="scope">
               <span>{{ scope.row.name }}</span>
             </template>
           </el-table-column>
           <el-table-column prop="type" label="文件类型" align="center" />
+          <el-table-column prop="qa_count" label="问答对数" align="center"></el-table-column>
           <el-table-column prop="chunk_num" label="分块数" align="center" />
           <el-table-column
             prop="create_time"
@@ -158,13 +162,13 @@
                 effect="dark"
                 placement="top"
                 :disabled="
-                 ![1, 4, 7].includes(Number(scope.row.run))
+                  ![1, 4, 7].includes(Number(scope.row.run))
                 "
               >
                 <template #content>
                   <div style="padding: 5px">
                     <div style="margin-top: 5px; font-size: 12px">
-                    {{ 
+                      {{ 
                         Number(scope.row.run) === 7 
                           ? (scope.row.progress_msg || "正在生成问答对...") 
                           : (scope.row.progress_msg || "正在解析中...") 
@@ -485,7 +489,8 @@
             >
           </span>
         </el-dialog>
-         <!-- 问答对弹窗 -->
+
+        <!-- 问答对弹窗 -->
         <el-dialog
           title="问答对"
           :visible.sync="qaDialogVisible"
@@ -573,11 +578,10 @@ import {
   analysisPro,
   resultTask,
   endClear,
+  generateQa,
 } from "@/api/knowledge";
-
 import { exportQaToExcel,queryDocumentContent } from "@/api/document";
 import { validateExportParams, logJSON, checkJSONSize } from "@/utils/data-validator";
-
 export default {
   components: {
     dataSearch,
@@ -660,7 +664,7 @@ export default {
       selectedRows: [], // 已选择的行
       allSelectedRows: new Map(), // 存储所有选中的行
       isAllDataSelected: false, // 是否选中所有数据
-        /* 问答对弹窗 */
+      /* 问答对弹窗 */
       qaDialogVisible: false,
       currentDocumentId: null,
       qaList: [],
@@ -680,7 +684,7 @@ export default {
     Object.values(this.analysisStatusCheckers).forEach(clearTimeout);
   },
   methods: {
-      /* 导出 */
+    /* 导出 */
     async exportData() {
       try {
         // 显示加载状态
@@ -695,6 +699,7 @@ export default {
         const exportParams = {
           kb_id: this.queryForm.bucket_id, // 知识库ID
           doc_type_id: this.queryForm.doc_type_id === 0 ? null : this.queryForm.doc_type_id, // 目录ID,0表示全部
+          export_to_local: true,
         };
 
         // 如果有选中的文档,只导出选中的
@@ -729,7 +734,7 @@ export default {
 
         // 调用导出接口
         const response = await exportQaToExcel(finalParams);
-       console.log(response);
+        console.log(response);
         
         // 检查响应格式
         if (response.status === 200) {
@@ -739,7 +744,9 @@ export default {
           // 如果有下载链接,直接使用浏览器下载
           if (exportData && exportData.download_url) {
             // 直接打开新窗口下载
-            window.open(exportData.download_url, '_blank');
+            const url=process.env.VUE_APP_BASE_API+exportData.download_url
+            console.log(url);
+            window.open(url, '_blank');
             loading.close();
             this.$message.success(message || '导出成功!');
           } else {
@@ -750,7 +757,6 @@ export default {
           loading.close();
           this.$message.error('导出请求失败');
         }
-        
       } catch (error) {
         console.error('导出失败:', error);
         this.$message.error('导出失败,请稍后重试');
@@ -842,6 +848,9 @@ export default {
         case "analysis":
           this.batchAnalysis();
           break;
+        case "generateQa":
+          this.batchGenerateQa();
+          break;
         case "modifyFolder":
           this.batchModifyFolder();
           break;
@@ -850,6 +859,44 @@ export default {
           break;
       }
     },
+
+        // 批量生成问答对
+      batchGenerateQa() {
+        if (this.selectedRows.length === 0) {
+          this.$message.warning("请选择要生成问答对的文件");
+          return;
+        }
+
+        const loading = this.$loading({
+          lock: true,
+          text: '正在生成问答对,请稍候...',
+          spinner: 'el-icon-loading',
+          background: 'rgba(0, 0, 0, 0.7)'
+        });
+
+        const selectedIds = this.selectedRows.map(row => row.id);
+        generateQa({
+          document_ids: JSON.stringify(selectedIds)
+        }).then((res) => {
+          console.log('生成问答对响应:', res);
+          if (res.status === 200) {
+            this.$message.success('问答对生成任务已提交');
+            // 更新选中文档的状态
+            this.selectedRows.forEach(row => {
+              this.$set(row, 'run', 6); // 设置状态为"待生成问答对"
+              this.startAnalysisStatusChecker(row); // 开始检查状态
+            });
+            this.clearSelection(); // 清除选择
+          } else {
+            this.$message.error(res.data?.message || '生成问答对失败');
+          }
+        }).catch(error => {
+          console.error('生成问答对时出错:', error);
+          this.$message.error('生成问答对失败,请稍后重试');
+        }).finally(() => {
+          loading.close();
+        });
+    },
     getProgressStatus(progress) {
       // el-progress 只接受 'success'/'exception'/'warning' 这几个值
       if (progress >= 100) {
@@ -1369,7 +1416,7 @@ export default {
     },
     /* 解析 */
     analysis(row) {
-      if (row.run == 1 || row.run == 5|| row.run == 6) return;
+      if (row.run == 1 || row.run == 5 || row.run == 6) return;
 
       // Set the status to "解析中" (1) immediately
       this.$set(row, "run", 1);
@@ -1406,24 +1453,25 @@ export default {
     },
     /* 任务监控 */
     startAnalysisStatusChecker(row) {
-      // Clear any existing checker for this row
+      // 清除该行已存在的检查器
       if (this.analysisStatusCheckers[row.id]) {
         clearTimeout(this.analysisStatusCheckers[row.id]);
       }
-      /* 监控任务 */
+
       const checkStatus = () => {
         resultTask(row.id)
           .then((res) => {
             if (res.status === 200) {
               const newStatus = Number(res.data.document_status);
-              const newProgress =Number(res.data.progress) === 100 ? 0 : Number(res.data.progress);
+              const newProgress = Number(res.data.progress) === 100 ? 0 : Number(res.data.progress);
               const newProgressMsg = res.data.progress_msg;
+
               // 更新状态和进度
               this.$set(row, "run", newStatus);
               this.$set(row, "progress", newProgress);
               this.$set(row, "progress_msg", newProgressMsg);
 
-            // 根据不同状态处理
+              // 根据不同状态处理
               switch (newStatus) {
                 case 3: // 解析成功
                   this.$message.success("解析成功");
@@ -1467,7 +1515,7 @@ export default {
           });
       };
 
-      // Start checking immediately
+      // 立即开始检查
       checkStatus();
     },
 
@@ -1690,7 +1738,7 @@ export default {
 
             // Initialize the analysis status for each row
             _this.dataList.forEach((row) => {
-              if (row.run == 1 || row.run == 5|| row.run == 6) {
+              if (row.run == 1 || row.run == 5 || row.run == 6) {
                 _this.startAnalysisStatusChecker(row);
               }
             });
@@ -1730,7 +1778,7 @@ export default {
 <style lang="scss" scoped>
 .project-search {
   display: flex;
-  height: calc(100vh - 100px); // 假设顶部导栏高度为60px
+  height: calc(100vh - 100px); // 假设顶部导栏高度为60px
   background-color: #f9fafb;
   .custom-tree-node {
     width: 100%;
@@ -1821,6 +1869,7 @@ export default {
     flex: 1;
     padding: 20px;
     overflow-y: auto;
+    min-width: 0;
   }
 
   .custom-tree-node {
@@ -1947,6 +1996,37 @@ export default {
     padding: 8px 16px;
   }
 }
+
+// 添加以下样式来处理表格响应式布局
+::v-deep .el-table {
+  width: 100% !important;
+  
+  // 设置表格在小屏幕时的行为
+  &__body-wrapper {
+    overflow-x: auto !important;
+  }
+  
+  // 确保表格单元格内容在空间不足时正确换行
+  .cell {
+    white-space: nowrap;
+    overflow: hidden;
+    text-overflow: ellipsis;
+  }
+
+  // 文件名称列允许换行显示
+  .el-table__row td:nth-child(3) .cell {
+    white-space: normal;
+    word-break: break-word;
+  }
+}
+
+// 确保分页区域不会造成横向滚动
+.page-info {
+  margin-top: 20px;
+  display: flex;
+  justify-content: flex-end;
+  flex-wrap: wrap;
+}
 /* 问答对弹窗样式 */
 .qa-dialog-content {
   padding: 0;