Ver Fonte

修改首页数据接口

yangg há 8 meses atrás
pai
commit
de7e381686

+ 1 - 1
.env.development

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

Diff do ficheiro suprimidas por serem muito extensas
+ 0 - 0
dist/index.html


Diff do ficheiro suprimidas por serem muito extensas
+ 0 - 0
dist/static/css/chunk-043b1151.79985b25.css


+ 1 - 0
dist/static/css/chunk-17263cbd.3e79a859.css

@@ -0,0 +1 @@
+.header[data-v-f75fa77e]{margin-left:20px}.header h2[data-v-f75fa77e]{margin-bottom:0}.center[data-v-f75fa77e]{margin:10px}.center[data-v-f75fa77e] .el-form--inline .el-form-item{display:block}.center[data-v-f75fa77e] .el-input-number--medium{width:150px}.footer[data-v-f75fa77e]{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:end;-ms-flex-pack:end;justify-content:flex-end;margin:0 100px 20px}[data-v-f75fa77e] .avatar-uploader .el-upload{border:1px dashed #d9d9d9;border-radius:6px;cursor:pointer;position:relative;overflow:hidden}.avatar-uploader .el-upload[data-v-f75fa77e]:hover{border-color:#409eff}.avatar-uploader-icon[data-v-f75fa77e]{font-size:28px;color:#8c939d;width:100px;height:100px;line-height:100px;text-align:center}.avatar[data-v-f75fa77e]{width:100px;height:100px;display:block}.hint[data-v-f75fa77e]{font-size:12px;color:#c0c4cc}

+ 0 - 1
dist/static/css/chunk-260f027d.8a2c9683.css

@@ -1 +0,0 @@
-.header[data-v-5f200d82]{margin-left:20px}.header h2[data-v-5f200d82]{margin-bottom:0}.center[data-v-5f200d82]{margin:10px}.center[data-v-5f200d82] .el-form--inline .el-form-item{display:block}.center[data-v-5f200d82] .el-input-number--medium{width:150px}.footer[data-v-5f200d82]{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:end;-ms-flex-pack:end;justify-content:flex-end;margin:0 100px 20px}[data-v-5f200d82] .avatar-uploader .el-upload{border:1px dashed #d9d9d9;border-radius:6px;cursor:pointer;position:relative;overflow:hidden}.avatar-uploader .el-upload[data-v-5f200d82]:hover{border-color:#409eff}.avatar-uploader-icon[data-v-5f200d82]{font-size:28px;color:#8c939d;width:100px;height:100px;line-height:100px;text-align:center}.avatar[data-v-5f200d82]{width:100px;height:100px;display:block}.hint[data-v-5f200d82]{font-size:12px;color:#c0c4cc}

+ 0 - 1
dist/static/css/chunk-31e74231.8940e437.css

@@ -1 +0,0 @@
-.midd-page[data-v-1045dd64]{padding:20px}.el-icon-edit[data-v-1045dd64]{font-size:14px;color:#409eff}[data-v-1045dd64] .model-gen-1{background-color:#e6f3ff!important}[data-v-1045dd64] .model-gen-1.el-table__cell{background-color:#e6f3ff!important;color:#333!important}[data-v-1045dd64] .model-gen-2{background-color:#f0e6ff!important}[data-v-1045dd64] .model-gen-2.el-table__cell{background-color:#f0e6ff!important;color:#333!important}.header[data-v-1045dd64]{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;-webkit-box-align:center;-ms-flex-align:center;align-items:center;margin:15px 0}.h_left p[data-v-1045dd64]{margin-top:0}.search-container[data-v-1045dd64]{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.search-box[data-v-1045dd64]{width:350px}.custom-search-input[data-v-1045dd64] :deep(.el-input__inner){height:40px;line-height:40px;border-right:none;border-radius:4px 0 0 4px}.custom-search-input[data-v-1045dd64] :deep(.el-input-group__append){padding:0;border:none;background-color:transparent}.custom-search-input[data-v-1045dd64] :deep(.el-input-group__append .el-button){height:40px;padding:0 20px;border-radius:0 4px 4px 0;margin:0}.custom-search-input[data-v-1045dd64] :deep(.el-input__inner:hover){border-color:#dcdfe6}.custom-search-input[data-v-1045dd64] :deep(.el-input__inner:focus){border-color:#409eff}

+ 1 - 0
dist/static/css/chunk-3d8a6649.2a92bcfe.css

@@ -0,0 +1 @@
+.midd-page[data-v-bef70c24]{padding:20px}.el-icon-edit[data-v-bef70c24]{font-size:14px;color:#409eff}[data-v-bef70c24] .model-gen-1{background-color:#e6f3ff!important}[data-v-bef70c24] .model-gen-1.el-table__cell{background-color:#e6f3ff!important;color:#333!important}[data-v-bef70c24] .model-gen-2{background-color:#f0e6ff!important}[data-v-bef70c24] .model-gen-2.el-table__cell{background-color:#f0e6ff!important;color:#333!important}.header[data-v-bef70c24]{-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;-webkit-box-align:center;-ms-flex-align:center;align-items:center;margin:15px 0}.h_left[data-v-bef70c24],.header[data-v-bef70c24]{display:-webkit-box;display:-ms-flexbox;display:flex}.h_left p[data-v-bef70c24]{margin-right:45px;margin-top:0}.search-container[data-v-bef70c24]{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.search-box[data-v-bef70c24]{width:350px}.custom-search-input[data-v-bef70c24] :deep(.el-input__inner){height:40px;line-height:40px;border-right:none;border-radius:4px 0 0 4px}.custom-search-input[data-v-bef70c24] :deep(.el-input-group__append){padding:0;border:none;background-color:transparent}.custom-search-input[data-v-bef70c24] :deep(.el-input-group__append .el-button){height:40px;padding:0 20px;border-radius:0 4px 4px 0;margin:0}.custom-search-input[data-v-bef70c24] :deep(.el-input__inner:hover){border-color:#dcdfe6}.custom-search-input[data-v-bef70c24] :deep(.el-input__inner:focus){border-color:#409eff}

Diff do ficheiro suprimidas por serem muito extensas
+ 0 - 0
dist/static/css/chunk-a7d4185a.c2769c64.css


Diff do ficheiro suprimidas por serem muito extensas
+ 0 - 0
dist/static/js/app.254608f5.js


Diff do ficheiro suprimidas por serem muito extensas
+ 0 - 0
dist/static/js/chunk-043b1151.c47e440f.js


Diff do ficheiro suprimidas por serem muito extensas
+ 0 - 0
dist/static/js/chunk-0eed3357.f7d4b952.js


Diff do ficheiro suprimidas por serem muito extensas
+ 0 - 0
dist/static/js/chunk-17263cbd.903034a7.js


Diff do ficheiro suprimidas por serem muito extensas
+ 0 - 0
dist/static/js/chunk-31e74231.37b86d91.js


Diff do ficheiro suprimidas por serem muito extensas
+ 0 - 0
dist/static/js/chunk-386d37cb.e6bd6bca.js


Diff do ficheiro suprimidas por serem muito extensas
+ 0 - 0
dist/static/js/chunk-3d8a6649.444a5d66.js


Diff do ficheiro suprimidas por serem muito extensas
+ 0 - 0
dist/static/js/chunk-708604c0.b2233849.js


Diff do ficheiro suprimidas por serem muito extensas
+ 0 - 0
dist/static/js/chunk-a7d4185a.0a2bed6f.js


Diff do ficheiro suprimidas por serem muito extensas
+ 0 - 0
dist/static/js/chunk-ca61fc30.a9d2d184.js


+ 35 - 0
src/api/knowledge.js

@@ -574,3 +574,38 @@ export function get_action_types(data) {
     data
   })
 }
+
+/* 批量文献处理 */
+
+export function process_model_generation(data) {
+  return request({
+    url: 'liter-data-auto/process_model_generation',
+    method: 'post',
+    headers: {
+      'Content-Type': 'application/json'
+    },
+    data: {
+      literature_ids: data // 将传入的数据作为 literature_ids 的值
+    }
+  })
+}
+
+/* 获取文献处理内容  */
+
+export function result(data) {
+  return request({
+    url: 'literature-data/process/result',
+    method: 'post',
+    data
+  })
+}
+
+/* 获取文件解析数量 */
+
+export function doc_status(data) {
+  return request({
+    url: 'console/document-stats/',
+    method: 'get',
+    data
+  })
+}

+ 4 - 1
src/utils/request.js

@@ -31,8 +31,11 @@ service.interceptors.request.use(
        //   }
        // }
     }
+    if (config.headers['Content-Type'] !== 'application/json') {
+      config.data = qs.stringify(config.data);
+    }
     // console.log("config2",config);
-    config.data = qs.stringify(config.data);
+  /*   config.data = qs.stringify(config.data); */
     // console.log("config2",config);
     // config.headers={
     //  'Content-Type': 'multipart/form-data',

+ 51 - 53
src/views/appConfig/index.vue

@@ -387,10 +387,9 @@
               </div>
             </el-form-item>
           </el-col>
-         
         </el-row>
         <el-row :gutter="24">
-           <el-col :span="24">
+          <el-col :span="24">
             <el-form-item label="自定义提示模板:" prop="custom_prompt">
               <el-input
                 style="width: 100%"
@@ -833,10 +832,10 @@
               </div>
             </el-form-item>
           </el-col>
-          
+         
         </el-row>
         <el-row :gutter="24">
-          <el-col :span="24">
+           <el-col :span="24">
             <el-form-item label="自定义提示模板:" prop="custom_prompt">
               <el-input
                 style="width: 100%"
@@ -1300,7 +1299,6 @@
               </div>
             </el-form-item>
           </el-col>
-          
         </el-row>
         <el-row :gutter="24">
           <el-col :span="24">
@@ -1450,33 +1448,33 @@ export default {
           { required: true, message: "请选择至少一个文档", trigger: "change" },
         ],
         role_permissions: [
-        { required: true, message: "请输入角色权限", trigger: "blur" },
-        { 
-          validator: (rule, value, callback) => {
-            try {
-              JSON.parse(value);
-              callback();
-            } catch (error) {
-              callback(new Error("请输入有效的 JSON 数组"));
-            }
+          { required: true, message: "请输入角色权限", trigger: "blur" },
+          {
+            validator: (rule, value, callback) => {
+              try {
+                JSON.parse(value);
+                callback();
+              } catch (error) {
+                callback(new Error("请输入有效的 JSON 数组"));
+              }
+            },
+            trigger: "blur",
           },
-          trigger: "blur"
-        }
-      ],
-      custom_variables: [
-        { required: true, message: "请输入自定义变量", trigger: "blur" },
-        { 
-          validator: (rule, value, callback) => {
-            try {
-              JSON.parse(value);
-              callback();
-            } catch (error) {
-              callback(new Error("请输入有效的 JSON 对象"));
-            }
+        ],
+        custom_variables: [
+          { required: true, message: "请输入自定义变量", trigger: "blur" },
+          {
+            validator: (rule, value, callback) => {
+              try {
+                JSON.parse(value);
+                callback();
+              } catch (error) {
+                callback(new Error("请输入有效的 JSON 对象"));
+              }
+            },
+            trigger: "blur",
           },
-          trigger: "blur"
-        }
-      ],
+        ],
       },
       /* 配置类型列表 */
       appTypeList: [],
@@ -1635,20 +1633,20 @@ export default {
           try {
             const convertedForm = { ...this.editForm };
             // 处理 role_permissions
-          const parsedPermissions = this.validateAndParseJSON(
-            'role_permissions',
-            '角色权限格式无效'
-          );
-          if (!parsedPermissions) return;
-          convertedForm.role_permissions = parsedPermissions;
+            const parsedPermissions = this.validateAndParseJSON(
+              "role_permissions",
+              "角色权限格式无效"
+            );
+            if (!parsedPermissions) return;
+            convertedForm.role_permissions = parsedPermissions;
 
-          // 处理 custom_variables
-          const parsedVariables = this.validateAndParseJSON(
-            'custom_variables',
-            '自定义变量格式无效'
-          );
-          if (!parsedVariables) return;
-          convertedForm.custom_variables = parsedVariables;
+            // 处理 custom_variables
+            const parsedVariables = this.validateAndParseJSON(
+              "custom_variables",
+              "自定义变量格式无效"
+            );
+            if (!parsedVariables) return;
+            convertedForm.custom_variables = parsedVariables;
             // 转换知识库、文档目录和文档的ID为名称
             /*  convertedForm.knowledge_base_names = this.safeGetNamesByIds(this.editForm.knowledge_base_names, this.kneList); */
             /*  convertedForm.documents = this.safeGetNamesByIds(this.editForm.documents, this.editDocumentList); */
@@ -1875,13 +1873,13 @@ export default {
       }
     },
     validateAndParseJSON(field, errorMessage) {
-    try {
-      return JSON.parse(this.AIform[field]);
-    } catch (error) {
-      this.$message.error(`${errorMessage}: ${error.message}`);
-      return null;
-    }
-  },
+      try {
+        return JSON.parse(this.AIform[field]);
+      } catch (error) {
+        this.$message.error(`${errorMessage}: ${error.message}`);
+        return null;
+      }
+    },
     /* 新增聊天应用 */
     generateApplication() {
       this.$refs.AIformRef.validate(async (valid) => {
@@ -2076,9 +2074,9 @@ export default {
     },
     /* 获取列表 */
     init() {
-      /* 模型库 */
-      modelList({ model_type: "model" }).then((res) => {
-        this.modelNameList = res.data;
+      /* 模型库 { model_type: "model" }*/
+      modelList().then((res) => {
+        this.modelNameList = res.data.models;
       });
       /* 知识库 */
       listBuckets({ user_id: this.$store.state.user.id }).then((res) => {

+ 10 - 2
src/views/dashboard/admin/chart.vue

@@ -348,7 +348,7 @@
                           <div class="card">
                             <div class="card-body">
                               <span>文件已解析数量</span>
-                              <h3>50</h3>
+                              <h3>{{ docList.run_3 }}</h3>
                               <div
                                 ref="real6Chart"
                                 style="height: 20px; width: 100%"
@@ -362,7 +362,7 @@
                           <div class="card">
                             <div class="card-body">
                               <span>文件未解析数量</span>
-                              <h3>15</h3>
+                              <h3>{{ docList.run_0}}</h3>
                               <div
                                 ref="real1Chart"
                                 style="height: 20px; width: 100%"
@@ -437,6 +437,7 @@ import {
   structure_count,
   GET_Rbq,
   gpu_info,
+  doc_status
 } from "@/api/knowledge";
 export default {
   name: "WidgetChart",
@@ -457,6 +458,7 @@ export default {
       docTotal: 0,
       temTotal: 0,
       pageTotal: 0,
+      docList:{}
     };
   },
   watch: {
@@ -1104,6 +1106,12 @@ export default {
         if (!res) return;
         this.pageTotal = res.data.dataList.length;
       });
+      /* 获取文件解析数量 */
+      doc_status().then(res=>{
+        
+        this.docList=res.data.data.run_stats
+        console.log(this.docList.run_3);
+      })
     },
 
     /* 选择知识库 */

+ 144 - 32
src/views/middPage/index.vue

@@ -1,26 +1,30 @@
 <template>
-  <div class="midd-page">
+  <div class="midd-page" v-loading="loading" element-loading-text="加载中...">
     <div class="header">
       <div class="h_left">
         <p class="current-doc">
           <strong>当前文献</strong>:
           <span style="color: #97a8be">{{ firstForm.currentDocument }}</span>
         </p>
-        <div class="search-box">
-          <p>
-            <strong>所属标签</strong>:
+
+        <p>
+          <strong>文献编号:</strong
+          ><span style="color: #97a8be">{{ doc_identifier }}</span>
+        </p>
+        <p>
+          <strong>所属标签</strong>:
+          <template v-if="firstForm.tag && firstForm.tag.length">
             <el-tag
               v-for="(item, index) in firstForm.tag"
               :key="index"
               type=""
               :style="index !== 0 ? 'margin-left: 5px;' : ''"
             >
-              {{ item }} </el-tag
-            ><!-- <span style="color: #97a8be">{{
-              firstForm.tag || '暂无标签'
-            }}</span> -->
-          </p>
-        </div>
+              {{ item }}
+            </el-tag>
+          </template>
+          <span v-else style="color: #97a8be">暂无标签</span>
+        </p>
       </div>
     </div>
     <el-table :data="firstTableData" style="width: 100%">
@@ -64,11 +68,15 @@
       <el-table-column label="说明" prop="project_description"
         ><!-- description -->
         <template #default="scope">
-          <el-input
-            v-model="scope.row.project_description"
-            v-if="scope.row.isEdit"
-          ></el-input>
-          <span v-else>{{ scope.row.project_description }}</span>
+          <span v-if="!scope.row.isEdit">
+            {{ scope.row.project_description }}
+            <i
+              class="el-icon-edit"
+              @click="openDescriptionDialog(scope.row)"
+              style="cursor: pointer; margin-left: 5px"
+            ></i>
+          </span>
+          <el-input v-else v-model="scope.row.project_description"></el-input>
         </template>
       </el-table-column>
       <el-table-column label="范例" prop="project_example"
@@ -100,7 +108,7 @@
           ></el-input>
           <span v-else>
             {{ scope.row.generation_1 }}
-           <!--  <i
+            <!--  <i
               class="el-icon-refresh"
               @click="openModel1Dialog(scope.row)"
               style="cursor: pointer; margin-left: 5px"
@@ -120,7 +128,7 @@
           ></el-input>
           <span v-else>
             {{ scope.row.generation_2 }}
-           <!--  <i
+            <!--  <i
               class="el-icon-refresh"
               @click="openModel2Dialog(scope.row)"
               style="cursor: pointer; margin-left: 5px"
@@ -309,12 +317,21 @@
           <el-input
             v-model="firstForm.configForm.project_description"
             type="textarea"
-            :rows="2"
+            :rows="4"
             placeholder="请输入说明"
           >
           </el-input>
         </el-form-item>
-
+        <!-- 范例 -->
+        <el-form-item label="范例">
+          <el-input
+            v-model="firstForm.configForm.project_example"
+            type="textarea"
+            :rows="4"
+            placeholder="请输入范例"
+          >
+          </el-input>
+        </el-form-item>
         <!-- 提示词 -->
         <el-form-item label="提示词">
           <el-input
@@ -343,6 +360,24 @@
         </span>
       </template>
     </el-dialog>
+    <!-- 添加新的对话框 -->
+    <el-dialog
+      :visible.sync="descriptionDialogVisible"
+      title="编辑说明"
+      width="30%"
+    >
+      <el-input
+        v-model="currentDescription"
+        type="textarea"
+        :rows="4"
+      ></el-input>
+      <template #footer>
+        <span class="dialog-footer">
+          <el-button @click="descriptionDialogVisible = false">取消</el-button>
+          <el-button type="primary" @click="saveDescription">确定</el-button>
+        </span>
+      </template>
+    </el-dialog>
   </div>
 </template>
   
@@ -354,11 +389,13 @@ import {
   listProConfig,
   updateConfig,
   deleteConfig,
+  result,
 } from "@/api/knowledge";
 export default {
   name: "MiddPage",
   data() {
     return {
+      loading: false, // Add loading state
       activeName: "first",
       firstForm: {
         tableData: [
@@ -504,6 +541,12 @@ export default {
       dialogVisible: false,
       currentExample: "",
       currentRow: null,
+      doc_identifier: "",
+
+      /* 说明编辑 */
+      descriptionDialogVisible: false,
+      currentDescription: "",
+      currentDescriptionRow: null,
     };
   },
   computed: {
@@ -519,12 +562,41 @@ export default {
     },
   },
   mounted() {
+    this.doc_identifier = this.$route.query.identifier;
     this.firstForm.currentDocument = this.$route.query.name;
     this.firstForm.tag = JSON.parse(this.$route.query.tag);
     this.firstInit();
     this.updateProjectFilters();
   },
   methods: {
+    /* 说明编辑 */
+    openDescriptionDialog(row) {
+      this.descriptionDialogVisible = true;
+      this.currentDescriptionRow = row;
+      this.currentDescription = row.project_description;
+    },
+
+    saveDescription() {
+      if (this.currentDescriptionRow && this.currentDescription) {
+        // 更新当前行的说明内容
+        this.currentDescriptionRow.project_description =
+          this.currentDescription;
+
+        // 调用更新API
+        updateConfig({
+          ...this.currentDescriptionRow,
+          project_description: this.currentDescription,
+        }).then((res) => {
+          if (res.status === 200) {
+            this.$message.success("说明更新成功");
+            this.firstInit();
+          }
+        });
+      }
+      this.descriptionDialogVisible = false;
+      this.currentDescriptionRow = null;
+      this.currentDescription = "";
+    },
     /* 配置模型 */
     firstHandleConfig(index, row) {
       this.firstForm.configForm = row;
@@ -730,19 +802,55 @@ export default {
     handleClick() {},
     /* 获取详细信息 */
     async firstInit() {
-      /* 获取配置信息 */
-      listProConfig().then((res) => {
-        if (res.status !== 200) return;
-        res.data.data.map((el) => {
-          el.isEdit = false;
-        });
-        this.firstForm.tableData = res.data.data;
-      });
-      /* 应用列表 */
-      configList().then((res) => {
-        if (res.status !== 200) return;
-        this.configArr = res.data;
-      });
+      this.loading = true; // Start loading
+      try {
+        // Get config list first to ensure we have the models data
+        const [configRes, proConfigRes] = await Promise.all([
+          configList(),
+          listProConfig(),
+        ]);
+
+        if (configRes.status === 200) {
+          this.configArr = configRes.data;
+        }
+
+        if (proConfigRes.status === 200) {
+          const tableData = proConfigRes.data.data.map((el) => ({
+            ...el,
+            isEdit: false,
+            generation_1: "N/A",
+            generation_2: "N/A",
+          }));
+          this.firstForm.tableData = tableData;
+        }
+
+        // Get results only if we have a literature_id
+        if (this.$route.query.id) {
+          const resultRes = await result({
+            literature_id: this.$route.query.id,
+          });
+          if (resultRes.status === 200 && resultRes.data.data.results) {
+            this.firstForm.tableData = this.firstForm.tableData.map((row) => {
+              const fieldName = row.project_name;
+              const fieldData = resultRes.data.data.results[fieldName];
+
+              if (fieldData?.data) {
+                return {
+                  ...row,
+                  generation_1: fieldData.data.generation_A || "N/A",
+                  generation_2: fieldData.data.generation_B || "N/A",
+                };
+              }
+              return row;
+            });
+          }
+        }
+      } catch (error) {
+        console.error("Error in firstInit:", error);
+        this.$message.error("加载数据失败");
+      } finally {
+        this.loading = false; // End loading regardless of success/failure
+      }
 
       /* const res = await getDetail({ id: this.$route.query.id });
 
@@ -927,7 +1035,11 @@ export default {
   align-items: center;
   margin: 15px 0;
 }
+.h_left {
+  display: flex;
+}
 .h_left p {
+  margin-right: 45px;
   margin-top: 0px;
 }
 .search-container {

+ 172 - 38
src/views/middPage/list.vue

@@ -103,6 +103,15 @@
           </el-form>
         </div>
         <div class="batch-operations">
+          <el-button
+            type="primary"
+            @click="handleBatchProcess"
+            :loading="isProcessing"
+            :disabled="selectedRows.length === 0"
+            class="ml-15"
+          >
+            {{ isProcessing ? "处理中..." : "批量处理文献" }}
+          </el-button>
           <el-button
             type="primary"
             @click="handleBatchTag"
@@ -140,8 +149,8 @@
           <el-table-column prop="create_time" label="创建时间" width="200" />
           <el-table-column prop="status" label="处理状态" width="100">
             <template #default="{ row }">
-              <el-tag :type="getStatusType(row.status)">
-                {{ getStatusText(row.status) }}
+              <el-tag :type="getStatusType(row.processing_status)">
+                {{ getStatusText(row.processing_status) }}
               </el-tag>
             </template>
           </el-table-column>
@@ -161,16 +170,17 @@
                     <el-dropdown-item @click.native="handleNameClick(row)">
                       <i class="el-icon-view"></i> 查看
                     </el-dropdown-item>
-                    <el-dropdown-item
-                      @click.native="handlePreview(row)"
-                    >
+                    <el-dropdown-item @click.native="handlePreview(row)">
                       <i class="el-icon-tickets"></i> 预览
                     </el-dropdown-item>
-                    <el-dropdown-item
+                    <el-dropdown-item @click.native="handleSingleProcess(row)">
+                      <i class="el-icon-refresh"></i> 处理文献
+                    </el-dropdown-item>
+                    <!-- <el-dropdown-item
                       @click.native="firstHandleUpload(scope.$index, scope.row)"
                     >
                       <i class="el-icon-refresh"></i> 批量处理
-                    </el-dropdown-item>
+                    </el-dropdown-item> -->
                     <!--  <el-dropdown-item
                       @click.native="firstHandleDelete(scope.$index, scope.row)"
                     >
@@ -268,15 +278,15 @@ import {
   search_tags,
   edit_tags,
   search,
+  process_model_generation,
 } from "@/api/knowledge";
 import axios from "axios";
 // 状态映射表
 const STATUS_MAP = {
-  1: { text: "未处理", type: "info" },
-  2: { text: "已审核", type: "warning" },
-  3: { text: "已处理", type: "success" },
-  4: { text: "已作废", type: "danger" },
-  5: { text: "使用中", type: "primary" },
+  0: { text: "未处理", type: "info" },
+  1: { text: "处理中", type: "warning" },
+  2: { text: "处理完成", type: "success" },
+  3: { text: "处理失败", type: "danger" },
 };
 
 export default {
@@ -313,6 +323,8 @@ export default {
 
       searchTagOptions: [], // 搜索表单的标签选项
       searchTagsLoading: false, // 搜索表单的标签加载状态
+      isProcessing: false, // 批量处理的加载状态
+      pollingTimers: {}, // 新增:存储每个文献的轮询定时器
     };
   },
 
@@ -326,6 +338,31 @@ export default {
   },
 
   methods: {
+    // 在中添加单个处理方法
+    async handleSingleProcess(row) {
+      try {
+        await this.$confirm("确认要处理该文献吗?", "提示", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning",
+        });
+
+        const res = await process_model_generation([row.id]);
+
+        if (res.status === 200) {
+          this.$message.success("处理任务已提交");
+          await this.fetchGpuList(); // 刷新列表
+        } else {
+          throw new Error(res.message || "处理失败");
+        }
+      } catch (error) {
+        if (error === "cancel") {
+          return;
+        }
+        this.$message.error(error.message || "处理提交失败");
+        console.error("处理错误:", error);
+      }
+    },
     /* 搜索栏模糊查找 */
     /* 搜索表单的标签搜索 */
     async searchFormTags(query) {
@@ -353,6 +390,43 @@ export default {
     handleBatchTag() {
       this.tagDialogVisible = true;
     },
+    /* 批量处理文献 */
+    async handleBatchProcess() {
+      if (this.selectedRows.length === 0) {
+        this.$message.warning("请选择需要处理的文献");
+        return;
+      }
+
+      try {
+        this.isProcessing = true;
+        const ids = this.selectedRows.map((row) => row.id);
+
+        // 添加确认对话框
+        await this.$confirm("确认要批量处理选中的文献吗?", "提示", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning",
+        });
+
+        const res = await process_model_generation(ids);
+
+        if (res.status === 200) {
+          this.$message.success("批量处理已提交");
+          this.selectedRows = []; // 清空选中
+          await this.fetchGpuList(); // 刷新列表
+        } else {
+          throw new Error(res.message || "处理失败");
+        }
+      } catch (error) {
+        if (error === "cancel") {
+          return;
+        }
+        this.$message.error(error.message || "批量处理提交失败");
+        console.error("批量处理错误:", error);
+      } finally {
+        this.isProcessing = false;
+      }
+    },
 
     /* 模糊搜索 */
     async searchTags(query) {
@@ -486,11 +560,10 @@ export default {
       }
     },
 
-    // 获取GPU列表数据
+    // 修改 fetchGpuList 方法中的分页处理部分
     async fetchGpuList() {
       this.isLoading = true;
       try {
-        // 构建基础参数
         const params = {
           page: this.currentPage,
           page_size: this.pageSize,
@@ -499,15 +572,6 @@ export default {
           tag_names: this.searchForm.id,
         };
 
-        // 只有当日期范围存在且有效时才添加日期参数
-        if (
-          this.searchForm.createTimeRange &&
-          this.searchForm.createTimeRange.length === 2
-        ) {
-          params.create_time_start = this.searchForm.createTimeRange[0];
-          params.create_time_end = this.searchForm.createTimeRange[1];
-        }
-
         const response = await axios.post(
           `${process.env.VUE_APP_BASE_API}/literature-data/search/`,
           params,
@@ -520,36 +584,95 @@ export default {
 
         if (response.status !== 200) return;
 
-        this.gpuList = response.data.data.list.map((item) => {
+        // 更新数据和分页信息
+        const { list, total, current_page, page_size } = response.data.data;
+        this.gpuList = list.map((item) => {
           const nameParts = item.name.split(".");
-          return {
+          const processedItem = {
             ...item,
             name: nameParts[0],
             type: nameParts.length > 1 ? nameParts.pop() : "未知",
           };
+
+          // 检查处理状态,如果是处理中且没有设置轮询,则开始轮询
+          if (
+            processedItem.processing_status === 1 &&
+            !this.pollingTimers[processedItem.id]
+          ) {
+            this.startPolling(processedItem.id);
+          }
+          // 如果状态不是处理中,但存在轮询,则停止轮询
+          else if (
+            processedItem.processing_status !== 1 &&
+            this.pollingTimers[processedItem.id]
+          ) {
+            this.stopPolling(processedItem.id);
+          }
+
+          return processedItem;
         });
 
-        this.total = response.data.data.total;
-        this.currentPage = response.data.data.current_page;
-        this.pageSize = response.data.data.page_size;
+        // 确保这些值都是数字类型
+        this.total = parseInt(total);
+        this.currentPage = parseInt(current_page);
+        this.pageSize = parseInt(page_size);
       } catch (error) {
-        console.error("获取列表数据失败:", error); // 添加错误日志输出
+        console.error("获取列表数据失败:", error);
         this.$message.error("获取列表数据失败");
       } finally {
         this.isLoading = false;
       }
     },
+    // 新增:开始轮询
+    startPolling(id) {
+      if (this.pollingTimers[id]) return; // 如果已经在轮询,则不重复设置
 
-    // 处理每页数量变化
+      this.pollingTimers[id] = setInterval(async () => {
+        try {
+          const response = await axios.post(
+            `${process.env.VUE_APP_BASE_API}/literature-data/search/`,
+            {
+              page: this.currentPage,
+              page_size: this.pageSize,
+              doc_type_id: this.selectedType || 36,
+              keyword: this.searchForm.name,
+              tag_names: this.searchForm.id,
+            }
+          );
+
+          if (response.status === 200) {
+            const item = response.data.data.list.find((item) => item.id === id);
+            if (item && item.processing_status !== 1) {
+              // 如果状态不再是"处理中",停止轮询
+              this.stopPolling(id);
+              await this.fetchGpuList(); // 刷新列表
+            }
+          }
+        } catch (error) {
+          console.error("轮询检查状态失败:", error);
+          this.stopPolling(id); // 发生错误时停止轮询
+        }
+      }, 60000); // 每分钟检查一次
+    },
+
+    // 新增:停止轮询
+    stopPolling(id) {
+      if (this.pollingTimers[id]) {
+        clearInterval(this.pollingTimers[id]);
+        delete this.pollingTimers[id];
+      }
+    },
+
+    // 修改分页处理方法
     handleSizeChange(val) {
       this.pageSize = val;
-      this.debouncedFetchGpuList();
+      this.currentPage = 1; // 切换每页数量时重置为第一页
+      this.fetchGpuList(); // 移除防抖,直接调用
     },
 
-    // 处理页码变化
     handleCurrentChange(val) {
       this.currentPage = val;
-      this.debouncedFetchGpuList();
+      this.fetchGpuList(); // 移除防抖,直接调用
     },
     /* 预览 */
     handlePreview(row) {
@@ -567,7 +690,12 @@ export default {
         console.log('详情数据:', res) */
         this.$router.push({
           path: "/knowledge/middPage/index",
-          query: { id: row.id, name: row.name, tag: JSON.stringify(row.tags) },
+          query: {
+            id: row.id,
+            name: row.name,
+            tag: JSON.stringify(row.tags),
+            identifier: row.doc_identifier,
+          },
         });
         // 这里可以添加详情处理逻辑
       } catch (error) {
@@ -594,8 +722,8 @@ export default {
         const response = await getSotaDetails();
         this.sotaDetailsList = response.data;
       } catch (error) {
-        this.$message.error("获取SOTA详情失败");
-        console.error(error);
+        /* this.$message.error("获取SOTA详情失败");
+        console.error(error); */
       }
     },
 
@@ -606,11 +734,17 @@ export default {
         const response = await getSotaSummary();
         this.sotaSummaryList = response.data;
       } catch (error) {
-        this.$message.error("获取SOTA汇总数据失败");
-        console.error(error);
+        /*  this.$message.error("获取SOTA汇总数据失败");
+        console.error(error); */
       }
     },
   },
+  // 在组件销毁时清理所有轮询
+  beforeDestroy() {
+    Object.keys(this.pollingTimers).forEach((id) => {
+      this.stopPolling(id);
+    });
+  },
 };
 </script>
 

+ 203 - 107
src/views/templateLoca/index.vue

@@ -1,97 +1,15 @@
 <template>
   <div class="template-location-container">
-    <el-tabs v-model="activeTab" @tab-click="handleTabClick">
-      <!-- 第一个标签页 - 原有的模板位置表 -->
-      <el-tab-pane label="模板位置表" name="first">
-        <!-- 顶部操作栏 -->
-        <div class="operation-bar">
-          <el-form
-            :inline="true"
-            :model="searchForm"
-            class="search-form"
-            label-width="100px"
-          >
-            <el-form-item label="动作类型">
-              <!-- <el-input
-                v-model="searchForm.action_type"
-                placeholder="请输入动作类型"
-                clearable
-              /> -->
-              <el-select
-                v-model="searchForm.action_type"
-                placeholder="请选择动作类型"
-                clearable
-              >
-                <el-option v-for="(item,index) in typeList" :key="index" :label="item.label" :value="item.value" />
-                <!-- <el-option label="WE" value="WE" /> -->
-              </el-select>
-            </el-form-item>
-            <el-form-item label="模板位置">
-              <el-input
-                v-model="searchForm.template_location"
-                placeholder="请输入模板位置"
-                clearable
-              />
-            </el-form-item>
-            <el-form-item label="技术报告位置">
-              <el-input
-                v-model="searchForm.tech_report_location"
-                placeholder="请输入技术报告位置"
-                clearable
-              />
-            </el-form-item>
-            <el-form-item label="中间层位置">
-              <el-input
-                v-model="searchForm.middle_layer_location"
-                placeholder="请输入中间层位置"
-                clearable
-              />
-            </el-form-item>
-            <el-form-item>
-              <el-button type="primary" @click="handleSearch">搜索</el-button>
-              <el-button @click="handleReset">重置</el-button>
-            </el-form-item>
-          </el-form>
-          <el-button type="primary" @click="handleImport"
-            >导入模版位置表</el-button
-          >
-          <el-button type="primary" @click="handleExport"
-            >导出模版位置表</el-button
-          >
-        </div>
-
-        <!-- 数据列表 -->
-        <el-table :data="tableData" style="width: 100%">
-          <el-table-column prop="id" label="ID" width="80" />
-          <el-table-column prop="action_type" label="动作类型" width="100" />
-          <el-table-column prop="template_location" label="模板位置" />
-          <el-table-column prop="middle_layer_location" label="中间层位置" />
-          <el-table-column prop="tech_report_location" label="技术报告位置" />
-          <el-table-column prop="other_location" label="其他位置" />
-          <el-table-column prop="create_time" label="创建时间" width="160" />
-        </el-table>
-        <div class="pagination-container">
-          <el-pagination
-            @size-change="handleSizeChange"
-            @current-change="handleCurrentChange"
-            :current-page="pageForm.page"
-            :page-sizes="[10, 20, 30, 50]"
-            :page-size="pageForm.page_size"
-            layout="total, sizes, prev, pager, next, jumper"
-            :total="total"
-          />
-        </div>
-      </el-tab-pane>
-
-      <!-- 新增的第二个标签页 -->
-      <el-tab-pane label="文献项目输入表" name="second">
+    <el-tabs v-model="activeTab" @tab-click="handleTabClick"
+      ><!-- 新增的第二个标签页 -->
+      <el-tab-pane label="文献项目输入表" name="first">
         <div class="operation-bar">
           <el-form :inline="true" :model="gsprSearchForm" class="search-form">
             <el-form-item label="内容">
               <el-input
                 v-model="gsprSearchForm.keyword"
                 placeholder="请输入项目名称/技术报告位置"
-                style="width: 300px;"
+                style="width: 300px"
                 clearable
               />
             </el-form-item>
@@ -119,11 +37,27 @@
           <el-button type="primary" @click="handleAddGspr">新增</el-button>
         </div>
 
-        <el-table :data="gsprTableData" style="width: 100%">
-          <el-table-column prop="name" label="项目名称" />
+        <el-table
+          :data="gsprTableData"
+          style="width: 100%"
+          :default-sort="{ prop: sort_field, order: sort_order }"
+          @sort-change="handleSortChange"
+        >
+          <el-table-column prop="name" label="项目名称" sortable="custom" />
           <el-table-column prop="tech_report_location" label="技术报告位置" />
-          <el-table-column prop="department" label="部门" />
-          <el-table-column prop="content" label="内容" />
+          <el-table-column prop="department" label="部门" sortable="custom" />
+          <el-table-column prop="content" label="内容">
+            <template slot-scope="scope">
+              <div style="display: flex; align-items: center">
+                <span style="margin-right: 10px">{{ scope.row.content }}</span>
+                <i
+                  class="el-icon-edit"
+                  @click="handleEditContent(scope.row)"
+                  style="cursor: pointer; margin-left: 5px"
+                ></i>
+              </div>
+            </template>
+          </el-table-column>
           <el-table-column label="操作" width="200">
             <template slot-scope="scope">
               <el-button type="primary" @click="handleEditGspr(scope.row)"
@@ -166,9 +100,7 @@
             <el-form-item label="技术报告位置" prop="tech_report_location">
               <el-input v-model="gsprForm.tech_report_location" />
             </el-form-item>
-            <el-form-item label="技术报告位置" prop="content">
-              <el-input v-model="gsprForm.content" />
-            </el-form-item>
+
             <el-form-item label="部门" prop="department">
               <el-select v-model="gsprForm.department" placeholder="请选择状态">
                 <el-option
@@ -179,12 +111,129 @@
                 />
               </el-select>
             </el-form-item>
+            <el-form-item label="内容" prop="content">
+              <el-input
+                type="textarea"
+                v-model="gsprForm.content"
+                :rows="4"
+                placeholder="请输入内容"
+              />
+            </el-form-item>
           </el-form>
           <div slot="footer">
             <el-button @click="gsprDialogVisible = false">取消</el-button>
             <el-button type="primary" @click="handleGsprSubmit">确定</el-button>
           </div>
         </el-dialog>
+        <!-- 添加内容编辑弹窗 -->
+        <el-dialog
+          title="编辑内容"
+          :visible.sync="contentDialogVisible"
+          width="600px"
+        >
+          <el-form :model="contentForm" ref="contentForm">
+            <el-form-item label="内容" prop="content">
+              <el-input
+                type="textarea"
+                v-model="contentForm.content"
+                :rows="4"
+                placeholder="请输入内容"
+              />
+            </el-form-item>
+          </el-form>
+          <div slot="footer">
+            <el-button @click="contentDialogVisible = false">取消</el-button>
+            <el-button type="primary" @click="handleContentSubmit"
+              >确定</el-button
+            >
+          </div>
+        </el-dialog>
+      </el-tab-pane>
+      <!-- 第一个标签页 - 原有的模板位置表 -->
+      <el-tab-pane label="模板位置表" name="second">
+        <!-- 顶部操作栏 -->
+        <div class="operation-bar">
+          <el-form
+            :inline="true"
+            :model="searchForm"
+            class="search-form"
+            label-width="100px"
+          >
+            <el-form-item label="动作类型">
+              <!-- <el-input
+                v-model="searchForm.action_type"
+                placeholder="请输入动作类型"
+                clearable
+              /> -->
+              <el-select
+                v-model="searchForm.action_type"
+                placeholder="请选择动作类型"
+                clearable
+              >
+                <el-option
+                  v-for="(item, index) in typeList"
+                  :key="index"
+                  :label="item.label"
+                  :value="item.value"
+                />
+                <!-- <el-option label="WE" value="WE" /> -->
+              </el-select>
+            </el-form-item>
+            <el-form-item label="模板位置">
+              <el-input
+                v-model="searchForm.template_location"
+                placeholder="请输入模板位置"
+                clearable
+              />
+            </el-form-item>
+            <el-form-item label="技术报告位置">
+              <el-input
+                v-model="searchForm.tech_report_location"
+                placeholder="请输入技术报告位置"
+                clearable
+              />
+            </el-form-item>
+            <el-form-item label="中间层位置">
+              <el-input
+                v-model="searchForm.middle_layer_location"
+                placeholder="请输入中间层位置"
+                clearable
+              />
+            </el-form-item>
+            <el-form-item>
+              <el-button type="primary" @click="handleSearch">搜索</el-button>
+              <el-button @click="handleReset">重置</el-button>
+            </el-form-item>
+          </el-form>
+          <el-button type="primary" @click="handleImport"
+            >导入模版位置表</el-button
+          >
+          <el-button type="primary" @click="handleExport"
+            >导出模版位置表</el-button
+          >
+        </div>
+
+        <!-- 数据列表 -->
+        <el-table :data="tableData" style="width: 100%">
+          <el-table-column prop="id" label="ID" width="80" />
+          <el-table-column prop="action_type" label="动作类型" width="100" />
+          <el-table-column prop="template_location" label="模板位置" />
+          <el-table-column prop="middle_layer_location" label="中间层位置" />
+          <el-table-column prop="tech_report_location" label="技术报告位置" />
+          <el-table-column prop="other_location" label="其他位置" />
+          <el-table-column prop="create_time" label="创建时间" width="160" />
+        </el-table>
+        <div class="pagination-container">
+          <el-pagination
+            @size-change="handleSizeChange"
+            @current-change="handleCurrentChange"
+            :current-page="pageForm.page"
+            :page-sizes="[10, 20, 30, 50]"
+            :page-size="pageForm.page_size"
+            layout="total, sizes, prev, pager, next, jumper"
+            :total="total"
+          />
+        </div>
       </el-tab-pane>
     </el-tabs>
   </div>
@@ -201,7 +250,7 @@ import {
   departments,
   projectUpdate,
   projectDelete,
-  get_action_types
+  get_action_types,
 } from "@/api/knowledge";
 import axios from "axios";
 export default {
@@ -270,21 +319,53 @@ export default {
         action_type: "",
         template_location: "",
         tech_report_location: "", // 添加技术报告位置字段
-        middle_layer_location:''
+        middle_layer_location: "",
       },
       gsprSearchForm: {
         keyword: "",
         department: "",
       },
       /* 动作类型列表 */
-      typeList:[],
+      typeList: [],
+
+      contentDialogVisible: false,
+      contentForm: {
+        id: "",
+        content: "",
+        name: "",
+        department: "",
+      },
+      /* 排序 */
+      sort_field: "name", // 默认排序字段
+      sort_order: "desc", // 默认排序方向
     };
   },
   mounted() {
-    this.fetchData();
+    this.fetchGsprData();
     this.init();
   },
   methods: {
+    /* 编辑内容 */
+    handleEditContent(row) {
+      this.contentForm = {
+        id: row.id,
+        content: row.content,
+        name: row.name,
+        department: row.department,
+      };
+      this.contentDialogVisible = true;
+    },
+
+    async handleContentSubmit() {
+      try {
+        await projectUpdate(this.contentForm);
+        this.$message.success("内容更新成功");
+        this.contentDialogVisible = false;
+        this.fetchGsprData();
+      } catch (error) {
+        this.$message.error("内容更新失败");
+      }
+    },
     // 第一个表格的搜索方法
     async handleSearch() {
       this.pageForm.page = 1;
@@ -296,10 +377,11 @@ export default {
         action_type: "",
         template_location: "",
         tech_report_location: "", // 添加技术报告位置字段
-        middle_layer_location:''
+        middle_layer_location: "",
       };
       this.handleSearch();
     },
+
     // 修改 fetchData 方法,添加搜索参数
     async fetchData() {
       try {
@@ -446,11 +528,11 @@ export default {
     // 新增:处理标签页切换
     handleTabClick(tab) {
       if (tab.name === "second" && !this.isSecondTabLoaded) {
-        this.fetchGsprData();
-        this.isSecondTabLoaded = true;
-      } else {
-        this.fetchData();
+         this.fetchData();
         this.isSecondTabLoaded = false;
+      } else {
+       this.fetchGsprData();
+        this.isSecondTabLoaded = true;
       }
     },
     // 第二个表格的搜索方法
@@ -466,7 +548,19 @@ export default {
       };
       this.handleGsprSearch();
     },
-
+    /* 排序 */
+    handleSortChange({ prop, order }) {
+      this.sort_field = prop;
+      // 将 Element UI 的排序值转换为 API 需要的格式
+      this.sort_order = order === "ascending" ? "asc" : "desc";
+      // 如果排序被取消,设置默认值
+      if (!order) {
+        this.sort_field = "name";
+        this.sort_order = "desc";
+      }
+      // 这里可以调用接口重新获取排序后的数据
+      this.fetchGsprData();
+    },
     // 修改 fetchGsprData 方法,添加搜索参数
     async fetchGsprData() {
       const loading = this.$loading({
@@ -478,6 +572,8 @@ export default {
 
       try {
         const params = {
+          sort_field: this.sort_field,
+          sort_order: this.sort_order,
           ...this.gsprPageForm,
           ...this.gsprSearchForm,
         };
@@ -563,10 +659,10 @@ export default {
         if (res.status !== 200) return;
         this.departList = res.data.departments;
       });
-      get_action_types().then(res=>{
-        if(res.status!==200) return
-       this.typeList=res.data.action_types
-      })
+      get_action_types().then((res) => {
+        if (res.status !== 200) return;
+        this.typeList = res.data.action_types;
+      });
     },
   },
 };

Alguns ficheiros não foram mostrados porque muitos ficheiros mudaram neste diff