Просмотр исходного кода

feat(knowledge):知识库详情页接口替换,调试

hanyang 1 год назад
Родитель
Сommit
7265b810a7

+ 7 - 2
src/apis/rgflow-dify.js

@@ -34,14 +34,19 @@ export function createRgFlow(data) {
 }
 
 // 头像上传
-export function kbdocumentupload(params) {
+export function kbdocumentupload(data) {
   const config = {
     headers: {
       'Content-Type': 'application/x-www-form-urlencoded'
       // token: token,
     }
   };
-  return axios.post('/api/v1/document/upload', params, config);
+  return request({
+    url: `/rgflow/v1/document/upload`,
+    method: 'post',
+    data,
+    headers: config.headers
+  });
 }
 // 查询模型列表
 export function queryModelList() {

+ 7 - 1
src/modules/knowledge/rgflow/MessageDetail.vue

@@ -1,11 +1,17 @@
 <template>
   <div class="message-detail">
-    <knowledgeLib></knowledgeLib>
+    <knowledgeLib :kb_id="id"></knowledgeLib>
   </div>
 </template>
 
 <script setup>
 import knowledgeLib from './knowledgeLib/index.vue';
+const props = defineProps({
+  id: {
+    type: String,
+    required: true
+  }
+});
 </script>
 <style scoped lang="css">
 .message-detail {

+ 2 - 1
src/modules/knowledge/rgflow/knowledgeLib/add.vue

@@ -64,12 +64,13 @@ const acceptNameList = computed(() => {
 // 上传文件
 const submitForm = async (done) => {
   if (files.value && files.value.length > 0) {
+    console.log(files.value, props.kbobj, 11);
     files.value.map((item) => {
       const formData = new FormData();
       formData.append('file', item.file);
       formData.append('kb_id', props.kbobj.id);
       kbdocumentupload(formData).then((res) => {
-        if (res.code == 0) {
+        if (res.retcode == 0) {
           emit('changeFetchData');
           Message.success('上传成功');
           handleCancel();

+ 1 - 1
src/modules/knowledge/rgflow/knowledgeLib/addDetails.vue

@@ -86,7 +86,7 @@ const handleSubmit = async ({ values, errors }) => {
       important_kwd: values.important_kwd,
       doc_id: props.item.id
     });
-    if (res.code === 0) {
+    if (res.retcode === 0) {
       visible.value = false;
       emit('canplaythrough');
     }

+ 1 - 1
src/modules/knowledge/rgflow/knowledgeLib/addKnow.vue

@@ -53,7 +53,7 @@ const handleSubmit = async ({ values, errors }) => {
   let data = await kbcreate({
     name: values.name
   });
-  if (data.code == 0) {
+  if (data.retcode == 0) {
     visible.value = false;
     Message.success('创建成功');
     // emit('getKbdetail',data.data.kb_id);

+ 78 - 0
src/modules/knowledge/rgflow/knowledgeLib/components/Upload.vue

@@ -0,0 +1,78 @@
+<template>
+  <a-upload
+    v-model:fileList="fileList"
+    list-type="picture-card"
+    :limit="limit"
+    :action="action"
+    @change="handleChange"
+    @before-remove="beforeRemove"
+    image-preview
+  />
+</template>
+
+<script setup>
+import { computed, ref, onMounted, watch, watchEffect } from 'vue';
+const props = defineProps({
+  limit: {
+    type: Number,
+    default: 1
+  },
+  action: String, // 上传的服务器地址
+  url: String //回显的文件地址
+});
+
+const emit = defineEmits(['update:fileList', 'success', 'handleRemove']);
+const urls = computed(() => props.url);
+const fileList = ref([]);
+
+watch(
+  () => props.url,
+  (newVal) => {
+    if (newVal) {
+      fileList.value = newVal.split(',').map((item) => ({
+        uid: item,
+        name: item,
+        status: 'done',
+        url: item
+      }));
+    }
+  },
+  {
+    deep: true // 开启深度监听
+  }
+);
+
+onMounted(() => {
+  if (urls.value) {
+    fileList.value = urls.value.split(',').map((item) => ({
+      uid: item,
+      name: item,
+      status: 'done',
+      url: item
+    }));
+  }
+
+  // console.log(
+  //   window.location.origin,
+  //   import.meta.env.VITE_API_BASE_URL,
+  //   8988
+  // );
+});
+
+// console.log(urls.value, 8988);
+const beforeRemove = (file) => {
+  emit('handleRemove');
+  fileList.value = [];
+};
+
+const handleChange = (fileList) => {
+  emit('update:fileList', fileList);
+  const successFiles = fileList.filter((item) => item.status === 'done');
+  if (successFiles.length > 0) {
+    emit(
+      'success',
+      successFiles.map((item) => item.response.data)
+    );
+  }
+};
+</script>

+ 226 - 195
src/modules/knowledge/rgflow/knowledgeLib/config.vue

@@ -1,14 +1,20 @@
 <template>
   <div ref="scrollContainer" class="main-container">
-    <div style="position: absolute;top: 0;left: 0;width: 100%;padding: 0 20px">
+    <div style="position: absolute; top: 0; left: 0; width: 100%; padding: 0 20px">
       <h4 style="margin-bottom: 10px"></h4>
-      <div style="color: #666666;">在这里更新您的知识库详细信息,尤其是解析方法。</div>
+      <div style="color: #666666">在这里更新您的知识库详细信息,尤其是解析方法。</div>
       <a-divider style="margin-top: 20px" />
     </div>
     <div class="main-container-lf">
       <div class="main-container-lf-down">
-        <a-form ref="formRef" :rules="rules" :model="form" :style="{width:'100%'}" layout="vertical"
-                @submit="handleSubmit">
+        <a-form
+          ref="formRef"
+          :rules="rules"
+          :model="form"
+          :style="{ width: '100%' }"
+          layout="vertical"
+          @submit="handleSubmit"
+        >
           <a-form-item field="name" label="知识库名称">
             <a-input v-model="form.name" placeholder="请输入" />
           </a-form-item>
@@ -25,16 +31,21 @@
             </a-space>
           </a-form-item>
           <a-form-item field="section" label="描述">
-            <a-textarea placeholder=""  v-model="form.description" allow-clear />
+            <a-textarea placeholder="" v-model="form.description" allow-clear />
           </a-form-item>
-<!--          <a-form-item field="section" label="语言" :rules="[{match:/section one/,message:'请选择'}]">-->
-<!--            <a-select v-model="form.section" placeholder="请选择" allow-clear>-->
-<!--              <a-option value="0">中文</a-option>-->
-<!--              <a-option value="1">英文</a-option>-->
-<!--            </a-select>-->
-<!--          </a-form-item>-->
+          <!--          <a-form-item field="section" label="语言" :rules="[{match:/section one/,message:'请选择'}]">-->
+          <!--            <a-select v-model="form.section" placeholder="请选择" allow-clear>-->
+          <!--              <a-option value="0">中文</a-option>-->
+          <!--              <a-option value="1">英文</a-option>-->
+          <!--            </a-select>-->
+          <!--          </a-form-item>-->
           <a-form-item field="embd_id" label="嵌入模型">
-            <a-select :size="'large'" v-model="form.embd_id" placeholder="请选择 ..." :disabled="kbObj.chunk_num && kbObj.token_num">
+            <a-select
+              :size="'large'"
+              v-model="form.embd_id"
+              placeholder="请选择 ..."
+              :disabled="kbObj.chunk_num && kbObj.token_num"
+            >
               <!-- <a-optgroup  :label="index" v-for="(item,index) in mobileData" :key=index>
                 <a-option
                   v-for="(obj) in item"
@@ -44,24 +55,20 @@
                   {{obj.llm_name}}
                 </a-option>
               </a-optgroup> -->
-              <a-option
-                  v-for="(item,index) in mobileData"
-                  :key='item.name'
-                  :value="item.name"
-                >
-                  {{item.name}}
-                </a-option>
+              <a-option v-for="(item, index) in mobileData" :key="item.name" :value="item.name">
+                {{ item.name }}
+              </a-option>
             </a-select>
           </a-form-item>
           <a-form-item field="parser_id" label="解析方法">
-            <a-select v-model="form.parser_id" placeholder="请选择" :disabled="!!(kbObj.chunk_num  && kbObj.token_num)" >
+            <a-select v-model="form.parser_id" placeholder="请选择" :disabled="!!(kbObj.chunk_num && kbObj.token_num)">
               <a-option v-for="item in parser_ids" :key="item.value" :label="item.name" :value="item.value"></a-option>
             </a-select>
           </a-form-item>
           <a-form-item field="slider" label="块Token数">
-            <a-slider v-model="form.chunk_token_num" :min="0" :max="2048"  show-input />
+            <a-slider v-model="form.chunk_token_num" :min="0" :max="2048" show-input />
           </a-form-item>
-          <a-form-item  label="布局识别" >
+          <a-form-item label="布局识别">
             <a-space direction="vertical">
               <a-switch v-model="form.layout_recognize" size="small" />
             </a-space>
@@ -73,28 +80,35 @@
             <a-form-item field="prompt" label="提示词">
               <a-textarea
                 v-model="form.prompt"
-                style="height: 10rem;border: 1px solid  var(--color-fill-3);border-radius: 4px" placeholder="请填写提示词"  />
+                style="height: 10rem; border: 1px solid var(--color-fill-3); border-radius: 4px"
+                placeholder="请填写提示词"
+              />
             </a-form-item>
             <a-form-item field="slider" label="最大token数">
-              <a-slider v-model="form.max_token" :min="0" :max="2048" show-input/>
+              <a-slider v-model="form.max_token" :min="0" :max="2048" show-input />
             </a-form-item>
-            <a-form-item field="slider" label="阈值" >
-              <a-slider v-model="form.threshold"  :step="0.01" :min="0" :max="1"  show-input/>
+            <a-form-item field="slider" label="阈值">
+              <a-slider v-model="form.threshold" :step="0.01" :min="0" :max="1" show-input />
             </a-form-item>
             <a-form-item field="slider" label="最大聚类数">
-              <a-slider v-model="form.max_cluster" :min="1" :max="1024" show-input/>
+              <a-slider v-model="form.max_cluster" :min="1" :max="1024" show-input />
             </a-form-item>
             <a-form-item field="slider" label="随机种子" v-model="form.random_seed">
-              <a-input-number v-model="form.random_seed" :style="{width:'300px',marginRight:'1rem',borderRadius:'4px'}"
-                              placeholder="请输入" class="input-demo" :min="10" :max="100" />
+              <a-input-number
+                v-model="form.random_seed"
+                :style="{ width: '300px', marginRight: '1rem', borderRadius: '4px' }"
+                placeholder="请输入"
+                class="input-demo"
+                :min="10"
+                :max="100"
+              />
               <a-button type="primary" @click="randomNumber">
                 <icon-plus />
               </a-button>
             </a-form-item>
-
           </div>
           <a-form-item>
-            <div style="width: 100%;text-align: right">
+            <div style="width: 100%; text-align: right">
               <a-space>
                 <a-button @click="cancelConfig">取消</a-button>
                 <a-button :loading="loading" type="primary" html-type="submit">保存</a-button>
@@ -105,70 +119,104 @@
       </div>
     </div>
     <div class="main-container-rt">
-      <section data-inspector-line="34" data-inspector-column="4"
-               data-inspector-relative-path="src\pages\add-knowledge\components\knowledge-setting\category-panel.tsx"
-               class="categoryPanelWrapper___yI4rY"><h4
-        class="ant-typography topTitle___tNiB9 css-dev-only-do-not-override-1wxecgq" data-inspector-line="37"
-        data-inspector-column="10"
-        data-inspector-relative-path="src\pages\add-knowledge\components\knowledge-setting\category-panel.tsx">"General"
-        分块方法说明</h4>
-        <p data-inspector-line="40" data-inspector-column="10"
-           data-inspector-relative-path="src\pages\add-knowledge\components\knowledge-setting\category-panel.tsx"><p>
-          支持的文件格式为<b>DOCX、EXCEL、PPT、IMAGE、PDF、TXT</b>。</p>
-          <p>此方法将简单的方法应用于块文件:</p>
-          <p>
-          </p>
-          <li>系统将使用视觉检测模型将连续文本分割成多个片段。</li>
-          <li>接下来,这些连续的片段被合并成Token数不超过“Token数”的块。</li>
-          <p></p></p>
-        <h4 class="ant-typography css-dev-only-do-not-override-1wxecgq" data-inspector-line="45"
-            data-inspector-column="10"
-            data-inspector-relative-path="src\pages\add-knowledge\components\knowledge-setting\category-panel.tsx">
-          "General" 示例</h4><span class="ant-typography css-dev-only-do-not-override-1wxecgq" data-inspector-line="48"
-                                   data-inspector-column="10"
-                                   data-inspector-relative-path="src\pages\add-knowledge\components\knowledge-setting\category-panel.tsx">提出以下屏幕截图以促进理解。</span>
-        <div data-inspector-line="49" data-inspector-column="10"
-             data-inspector-relative-path="src\pages\add-knowledge\components\knowledge-setting\category-panel.tsx"
-             class="ant-row imageRow___C3Xpb css-dev-only-do-not-override-1wxecgq"
-             style="margin-left: -5px; margin-right: -5px; row-gap: 10px;display: flex; margin-top: 20px;width: 100%">
+      <section
+        data-inspector-line="34"
+        data-inspector-column="4"
+        data-inspector-relative-path="src\pages\add-knowledge\components\knowledge-setting\category-panel.tsx"
+        class="categoryPanelWrapper___yI4rY"
+      >
+        <h4
+          class="ant-typography topTitle___tNiB9 css-dev-only-do-not-override-1wxecgq"
+          data-inspector-line="37"
+          data-inspector-column="10"
+          data-inspector-relative-path="src\pages\add-knowledge\components\knowledge-setting\category-panel.tsx"
+        >
+          "General" 分块方法说明
+        </h4>
+        < data-inspector-line="40" data-inspector-column="10"
+        data-inspector-relative-path="src\pages\add-knowledge\components\knowledge-setting\category-panel.tsx">
+        <p>支持的文件格式为<b>DOCX、EXCEL、PPT、IMAGE、PDF、TXT</b>。</p>
+        <p>此方法将简单的方法应用于块文件:</p>
+        <p></p>
+        <li>系统将使用视觉检测模型将连续文本分割成多个片段。</li>
+        <li>接下来,这些连续的片段被合并成Token数不超过“Token数”的块。</li>
+        <p></p>
+        <h4
+          class="ant-typography css-dev-only-do-not-override-1wxecgq"
+          data-inspector-line="45"
+          data-inspector-column="10"
+          data-inspector-relative-path="src\pages\add-knowledge\components\knowledge-setting\category-panel.tsx"
+        >
+          "General" 示例
+        </h4>
+        <span
+          class="ant-typography css-dev-only-do-not-override-1wxecgq"
+          data-inspector-line="48"
+          data-inspector-column="10"
+          data-inspector-relative-path="src\pages\add-knowledge\components\knowledge-setting\category-panel.tsx"
+          >提出以下屏幕截图以促进理解。</span
+        >
+        <div
+          data-inspector-line="49"
+          data-inspector-column="10"
+          data-inspector-relative-path="src\pages\add-knowledge\components\knowledge-setting\category-panel.tsx"
+          class="ant-row imageRow___C3Xpb css-dev-only-do-not-override-1wxecgq"
+          style="margin-left: -5px; margin-right: -5px; row-gap: 10px; display: flex; margin-top: 20px; width: 100%"
+        >
           <img
-            data-inspector-line="32" data-inspector-column="8"
-            data-inspector-relative-path="src\components\svg-icon.tsx" :src="step1" alt=""
-            width="50%">
+            data-inspector-line="32"
+            data-inspector-column="8"
+            data-inspector-relative-path="src\components\svg-icon.tsx"
+            :src="step1"
+            alt=""
+            width="50%"
+          />
           <img
-            data-inspector-line="32" data-inspector-column="8"
-            data-inspector-relative-path="src\components\svg-icon.tsx" :src="step2" alt=""
-            width="50%">
+            data-inspector-line="32"
+            data-inspector-column="8"
+            data-inspector-relative-path="src\components\svg-icon.tsx"
+            :src="step2"
+            alt=""
+            width="50%"
+          />
         </div>
-        <h4 class="ant-typography css-dev-only-do-not-override-1wxecgq" data-inspector-line="60"
-            data-inspector-column="10"
-            data-inspector-relative-path="src\pages\add-knowledge\components\knowledge-setting\category-panel.tsx">
-          General 对话示例</h4>
-        <div class="ant-divider css-dev-only-do-not-override-1wxecgq ant-divider-horizontal" data-inspector-line="63"
-             data-inspector-column="10"
-             data-inspector-relative-path="src\pages\add-knowledge\components\knowledge-setting\category-panel.tsx"
-             role="separator"></div>
+        <h4
+          class="ant-typography css-dev-only-do-not-override-1wxecgq"
+          data-inspector-line="60"
+          data-inspector-column="10"
+          data-inspector-relative-path="src\pages\add-knowledge\components\knowledge-setting\category-panel.tsx"
+        >
+          General 对话示例
+        </h4>
+        <div
+          class="ant-divider css-dev-only-do-not-override-1wxecgq ant-divider-horizontal"
+          data-inspector-line="63"
+          data-inspector-column="10"
+          data-inspector-relative-path="src\pages\add-knowledge\components\knowledge-setting\category-panel.tsx"
+          role="separator"
+        ></div>
         <a-divider style="margin-top: 20px" />
       </section>
     </div>
   </div>
 </template>
 
-<script  setup>
-import { onMounted, onBeforeMount, reactive, ref, nextTick } from "vue";
-import { Message } from "@arco-design/web-vue";
-import { queryModelList,kbUpdate,getKnowledgeBaseModel } from '../../../../apis/rgflow-dify';
-import message from "@arco-design/web-vue/es/message";
-import useLoading from "./loading";
-import step1 from "../../../../assets/image/management/step1.png";
-import step2 from "../../../../assets/image/management/step2.png";
-const { loading,setLoading } = useLoading(true);
+<script setup>
+import { onMounted, onBeforeMount, reactive, ref, nextTick } from 'vue';
+import Upload from './components/Upload.vue';
+import { Message } from '@arco-design/web-vue';
+import { queryModelList, kbUpdate, getKnowledgeBaseModel } from '../../../../apis/rgflow-dify';
+import message from '@arco-design/web-vue/es/message';
+import useLoading from './loading';
+import step1 from '../../../../assets/image/management/step1.png';
+import step2 from '../../../../assets/image/management/step2.png';
+const { loading, setLoading } = useLoading(true);
 const scrollContainer = ref();
-const props =  defineProps(['kbtenantInfo'])
-const emit =  defineEmits(['cancleConfig','saveConfig'])
+const props = defineProps(['kbtenantInfo']);
+const emit = defineEmits(['cancleConfig', 'saveConfig']);
 // 解析方法列表
-let parser_ids = props.kbtenantInfo.parser_ids.split(",").map((item) => {
-  const [value1, value2] = item.split(":");
+let parser_ids = props.kbtenantInfo.parser_ids.split(',').map((item) => {
+  const [value1, value2] = item.split(':');
   return {
     name: value2,
     value: value1
@@ -180,7 +228,7 @@ let avatarShow = ref(true);
 
 const form = reactive({
   name: '',
-  avatar: '',//头像
+  avatar: '', //头像
   max_token: 600,
   threshold: 0.32,
   max_cluster: 233,
@@ -188,13 +236,12 @@ const form = reactive({
   chunk_token_num: 384,
   use_raptor: false,
   pages: {},
-  prompt: "请总结以下段落。 小心数字,不要编造。 段落如下:\n" +
-    "      {cluster_content}\n" +
-    "以上就是你需要总结的内容。",
-  description: "",
-  language: "English",
-  permission: "",
-  embd_id: "",
+  prompt:
+    '请总结以下段落。 小心数字,不要编造。 段落如下:\n' + '      {cluster_content}\n' + '以上就是你需要总结的内容。',
+  description: '',
+  language: 'English',
+  permission: '',
+  embd_id: '',
   parser_id: '',
   layout_recognize: true
 });
@@ -203,32 +250,32 @@ const rules = {
   name: [
     {
       required: true,
-      message:'知识库名称不允许为空',
-    },
+      message: '知识库名称不允许为空'
+    }
   ],
   embd_id: [
     {
       required: true,
-      message:'请选择',
-    },
+      message: '请选择'
+    }
   ],
   parser_id: [
     {
       required: true,
-      message:'请选择',
-    },
+      message: '请选择'
+    }
   ],
   prompt: [
     {
       required: true,
-      message:'提示词不允许为空',
-    },
-  ],
-}
+      message: '提示词不允许为空'
+    }
+  ]
+};
 let visible = ref(false);
 const formRef = ref();
 const modelList = ref({});
-const mobileData= ref([])
+const mobileData = ref([]);
 const file = ref();
 
 const uploadAction = '/api/v1/llm/upload'; // 替换为你的上传API
@@ -246,59 +293,52 @@ const handleSuccess = (urls) => {
   form.avatar = urls[0];
 };
 
-
 const handleSubmit = async ({ values, errors }) => {
-  if (errors){
+  if (errors) {
     return;
   }
   let parms = {
-      name: form.name,
-      avatar: form.avatar,
-      description: form.description,
-      language: form.language,
-      permission: form.permission,
-      embd_id: form.embd_id,
-      parser_id: form.parser_id,
-      parser_config: {
-        chunk_token_num: form.chunk_token_num,
-        layout_recognize: form.layout_recognize,
-      },
-      kb_id: kbObj.id,
-   }
-   if(form.use_raptor){
-     parms.parser_config.raptor = {
-       use_raptor: form.use_raptor,
-       prompt: form.prompt,
-       max_token: form.max_token,
-       threshold: form.threshold,
-       max_cluster: form.max_cluster,
-       random_seed: form.random_seed,
-     };
-   }
-   try {
-     setLoading(true)
+    name: form.name,
+    avatar: form.avatar,
+    description: form.description,
+    language: form.language,
+    permission: form.permission,
+    embd_id: form.embd_id,
+    parser_id: form.parser_id,
+    parser_config: {
+      chunk_token_num: form.chunk_token_num,
+      layout_recognize: form.layout_recognize
+    },
+    kb_id: kbObj.id
+  };
+  if (form.use_raptor) {
+    parms.parser_config.raptor = {
+      use_raptor: form.use_raptor,
+      prompt: form.prompt,
+      max_token: form.max_token,
+      threshold: form.threshold,
+      max_cluster: form.max_cluster,
+      random_seed: form.random_seed
+    };
+  }
+  try {
+    setLoading(true);
     const data = await kbUpdate(parms);
-    if(data.code == '0'){
-      Message.success("配置成功");
+    if (data.retcode == '0') {
+      Message.success('配置成功');
       // window.location.reload();
-      emit('saveConfig')
-
+      emit('saveConfig');
     }
-    setLoading(false)
-
+    setLoading(false);
   } catch (err) {
     Message.error(err.message);
-     setLoading(false)
+    setLoading(false);
   }
-
-
-
 };
 
 const cancelConfig = () => {
-    emit('cancleConfig')
-}
-
+  emit('cancleConfig');
+};
 
 function randomNumber() {
   // 生成一个介于min和max之间的随机整数(包含min和max)
@@ -308,109 +348,97 @@ function randomNumber() {
 }
 
 const handleBeforeOk = (done) => {
-  formRef.value.validate().then(res => {
-    console.log("form:", form);
+  formRef.value.validate().then((res) => {
+    console.log('form:', form);
     if (!form.name) {
       done(false);
     } else {
-      console.log("请求数据");
-
+      console.log('请求数据');
     }
   });
 };
-const handleOpened =(el) => {
-  Object.assign(form,{
-
-  });
+const handleOpened = (el) => {
+  Object.assign(form, {});
   // formRef.value.resetFields();
-}
+};
 
 const queryModel = async (params) => {
   try {
     const data = await getKnowledgeBaseModel(params);
     // const res =await queryModelList(params)
     // console.log(data.data, '大模型列表');
-    modelList.value = data.data
-    for(let key in data.data) {
-      if (data.data.hasOwnProperty(key)) { // 确保是对象自有属性,不是原型链上的属性
-        if(data.data[key].llm.length > 0){
-          mobileData.value= data.data[key].llm.filter(item => item.type == "embedding")
+    modelList.value = data.data;
+    for (let key in data.data) {
+      if (data.data.hasOwnProperty(key)) {
+        // 确保是对象自有属性,不是原型链上的属性
+        if (data.data[key].llm.length > 0) {
+          mobileData.value = data.data[key].llm.filter((item) => item.type == 'embedding');
         }
       }
-
     }
-
-
   } catch (err) {
     // you can report use errorHandler or other
   } finally {
-
   }
 };
 
 const changekbObj = (value) => {
-
-   formRef.value.resetFields();
-  nextTick(()=>{
+  formRef.value.resetFields();
+  nextTick(() => {
     kbObj = value;
     console.log(kbObj, 'kbObj');
     let configObj = {
       name: kbObj.name,
       avatar: kbObj.avatar,
-      pages:  kbObj.parser_config.pages,
-      chunk_token_num:  kbObj.parser_config.chunk_token_num,
+      pages: kbObj.parser_config.pages,
+      chunk_token_num: kbObj.parser_config.chunk_token_num,
       description: kbObj.description,
-      language: "English",
+      language: 'English',
       permission: kbObj.permission,
       embd_id: kbObj.embd_id || props.kbtenantInfo.embd_id,
       parser_id: kbObj.parser_id,
-      layout_recognize: true,
-    }
-    let raptor = {}
-    if(kbObj.parser_config && kbObj.parser_config.raptor){
+      layout_recognize: true
+    };
+    let raptor = {};
+    if (kbObj.parser_config && kbObj.parser_config.raptor) {
       raptor = kbObj.parser_config.raptor;
-      Object.assign(form,{
+      Object.assign(form, {
         ...configObj,
         ...raptor,
-        use_raptor: kbObj.parser_config.raptor.use_raptor,
+        use_raptor: kbObj.parser_config.raptor.use_raptor
       });
-    }else{
-      Object.assign(form,{
+    } else {
+      Object.assign(form, {
         ...configObj,
-        use_raptor: false,
+        use_raptor: false
       });
     }
     imageUrls.value = [kbObj.avatar];
-    console.log(form,'配置页面表单信息');
+    console.log(form, '配置页面表单信息');
     avatarShow.value = false;
     setTimeout(() => {
       avatarShow.value = true;
-    },100);
+    }, 100);
     scrollContainer.value.scrollTop = 0;
-  })
-}
+  });
+};
 
 defineExpose({
   changekbObj
-})
-
-
-onBeforeMount(()=>{
-  setLoading(false)
-  queryModel({})
-})
-onMounted(()=>{
-
-
-})
+});
 
+onBeforeMount(() => {
+  setLoading(false);
+  queryModel({});
+});
+onMounted(() => {});
 </script>
 
-<script >
-import { IconEdit, IconPlus } from "@arco-design/web-vue/es/icon";
+<script>
+import { IconEdit, IconPlus } from '@arco-design/web-vue/es/icon';
 
 export default {
-  name: "config",
+  name: 'config',
   components: { IconPlus, IconEdit },
   methods: {}
 };
@@ -428,7 +456,7 @@ export default {
   padding-top: 80px;
 
   .main-container-lf {
-    width:calc(40% - 40px);
+    width: calc(40% - 40px);
     border-radius: 10px;
     .main-container-lf-top {
       width: 100%;
@@ -483,4 +511,7 @@ export default {
     }
   }
 }
+.arco-form .arco-slider {
+  display: flex;
+}
 </style>

+ 3 - 1
src/modules/knowledge/rgflow/knowledgeLib/edit.vue

@@ -59,10 +59,12 @@ const handleSubmit = async ({ values, errors }) => {
     doc_id: props.item.id,
     name: form.name
   });
-  if (data.code == 0) {
+  if (data.retcode == 0) {
     Message.success('操作成功');
     visible.value = false;
     emit('upTabdateItem', props.item.id, form.name);
+  } else {
+    Message.error('操作失败');
   }
 };
 

+ 1 - 1
src/modules/knowledge/rgflow/knowledgeLib/eidtDetails.vue

@@ -92,7 +92,7 @@ const handleSubmit = async ({ values, errors }) => {
       doc_id: props.item.doc_id,
       chunk_id: props.item.chunk_id
     });
-    if (res.code === 0) {
+    if (res.retcode === 0) {
       visible.value = false;
       emit('canplaythrough');
     }

+ 45 - 34
src/modules/knowledge/rgflow/knowledgeLib/index.vue

@@ -35,12 +35,14 @@
       <div class="rt-container" v-if="tabs.length > 0">
         <a-tabs :active-key="activeKey" @change="handleTabChange">
           <a-tab-pane key="1" title="数据集">
-            <a-scrollbar
-              class="rt-container-main"
-              :style="{ height: documentHeight + 70 + 'px' }"
-              style="overflow: auto"
-            >
-              <a-card ref="account" class="general-card" title="" style="padding-top: 20px">
+            <a-scrollbar class="rt-container-main" :style="{ height: documentHeight + 'px' }" style="overflow: auto">
+              <!-- <a-scrollbar class="rt-container-main" style="overflow: auto"> -->
+              <a-card
+                ref="account"
+                class="general-card"
+                title=""
+                style="height: calc(100% - 25px); overflow-y: auto; padding-top: 20px"
+              >
                 <a-row>
                   <a-col :flex="1" :span="12">
                     <a-form
@@ -341,20 +343,12 @@
             </a-scrollbar>
           </a-tab-pane>
           <a-tab-pane key="2" title="测试" v-if="getAut('/kb/test')">
-            <a-scrollbar
-              class="rt-container-main"
-              :style="{ height: documentHeight + 70 + 'px' }"
-              style="overflow: auto"
-            >
+            <a-scrollbar class="rt-container-main" :style="{ height: documentHeight + 'px' }" style="overflow: hidden">
               <test ref="testForm"></test>
             </a-scrollbar>
           </a-tab-pane>
           <a-tab-pane key="3" title="配置" v-if="getAut('/kb/update')">
-            <a-scrollbar
-              class="rt-container-main"
-              :style="{ height: documentHeight + 70 + 'px' }"
-              style="overflow: auto"
-            >
+            <a-scrollbar class="rt-container-main" :style="{ height: documentHeight + 'px' }" style="overflow: auto">
               <config
                 ref="configForm"
                 :kbtenantInfo="kbtenantInfo"
@@ -421,6 +415,12 @@ import { documentHeight, parseTime } from './utils';
 
 // let modelStore = userModelState();
 // const httpUrl = modelStore.hrefUrl;
+const props = defineProps({
+  kb_id: {
+    type: String,
+    default: ''
+  }
+});
 
 const account = ref(null);
 const generateFormModel = () => {
@@ -476,8 +476,8 @@ let kbtenantInfo = reactive({
 let tabs = ref([]);
 let timer = null; // 定时器
 
-const selectTab = (index, item) => {
-  selectedTab.value = index;
+const selectTab = (item) => {
+  // selectedTab.value = index;
   checkedArr.value = [];
   // console.log(item.id);
   kbobj = item;
@@ -489,7 +489,14 @@ const selectTab = (index, item) => {
   });
   getKbdetail(kbobj.id);
 };
-
+const toTargetKnowledge = () => {
+  if (tabs.value.length) {
+    const index = tabs.value.findIndex((item) => item.id == props.kb_id);
+    if (index !== -1) {
+      selectTab(tabs.value[index]);
+    }
+  }
+};
 const getAut = (val) => {
   // const roleData = JSON.parse(getUserResources());
   // const roleBtn = roleData.map((item: any) => item.component);
@@ -604,7 +611,8 @@ const fetchData = async (params) => {
   setLoading(true);
   try {
     const data = await queryKbDocumentList(params);
-    if (data.code == '0') {
+    console.log(data, 'data');
+    if (data.retcode == '0') {
       parser_ids = kbtenantInfo.parser_ids.split(',').reduce((acc, pair) => {
         const [key, value] = pair.split(':');
         acc[key] = value;
@@ -639,7 +647,7 @@ const fetchData = async (params) => {
 const documentList = async () => {
   let params = { ...basePagination, kb_id: kbobj.id };
   const data = await queryKbDocumentList(params);
-  if (data.code == '0') {
+  if (data.retcode == '0') {
     parser_ids = kbtenantInfo.parser_ids.split(',').reduce((acc, pair) => {
       const [key, value] = pair.split(':');
       acc[key] = value;
@@ -695,15 +703,17 @@ const knowledgeData = async (params = { page: 1, page_size: 10 }) => {
     tabs.value = data;
     // console.log(tabs.value, 'tabs');
     if (tabs.value.length > 0 && tabs.value[0]) {
-      kbobj = tabs.value[0];
-      kbId = kbobj.id;
-      activeKey.value = '1';
-      basePagination.page = 1;
+      // kbobj = tabs.value[0];
+      // kbId = kbobj.id;
+      // activeKey.value = '1';
+      // basePagination.page = 1;
       fetchData({
-        kb_id: kbobj.id,
+        kb_id: props.kb_id,
         ...basePagination
       });
-      getKbdetail(kbobj.id);
+      toTargetKnowledge();
+      // getKbdetail(kbobj.id);
+      getKbdetail(props.kb_id);
     } else {
     }
     // renderData.value = data.list;
@@ -722,6 +732,7 @@ const getKbdetail = async (kb_id) => {
   const data = await queryKbdetail({
     kb_id: kb_id
   });
+  console.log('targetID', kb_id);
   kbdetail = data.data;
   testForm.value.changekbid(kbdetail.id);
   configForm.value.changekbObj(kbdetail);
@@ -759,7 +770,7 @@ const deleteKnowledge = (id) => {
       let data = await deleteKnow({
         kb_id: id
       });
-      if (data.code == 0) {
+      if (data.retcode == 0) {
         Message.success('删除成功');
         knowledgeData();
       }
@@ -825,7 +836,7 @@ const addBlock = async (type) => {
       doc_ids: checkedArr.value,
       run: type
     });
-    if (data.code == 0) {
+    if (data.retcode == 0) {
       checkedArr.value.forEach(async (item) => {
         tabs.value.forEach(async (items) => {
           if (items.id == item) {
@@ -848,7 +859,7 @@ const addBlock = async (type) => {
       hideTitle: true,
       onOk: async () => {
         let data = await kbdocumentrm({ doc_id: checkedArr.value });
-        if (data.code == 0) {
+        if (data.retcode == 0) {
           Message.success('删除成功');
           getKbList();
         }
@@ -908,7 +919,7 @@ function upTabdateItem(id, newName) {
 const deleteItem = async (row) => {
   console.log(row);
   let data = await kbdocumentrm({ doc_id: row.id });
-  if (data.code == 0) {
+  if (data.retcode == 0) {
     Message.success('删除成功');
     // console.log(kbobj, 'kbobj');
     fetchData({
@@ -952,7 +963,7 @@ const handleChangeStatus = async (row) => {
     doc_id: row.id,
     status: row.status
   });
-  if (data.code == 0) {
+  if (data.retcode == 0) {
     Message.success('操作成功');
   }
 };
@@ -973,7 +984,7 @@ const run = async (row) => {
     doc_ids: [row.id],
     run: run
   });
-  if (data.code == 0) {
+  if (data.retcode == 0) {
     // 定时器查询当前列表
     fetchData({
       kb_id: tabs.value[selectedTab.value].id,
@@ -1091,7 +1102,7 @@ onBeforeUnmount(() => {
     .rt-container {
       position: relative;
       //background: #626aea;
-      margin-left: 20px;
+      /* margin-left: 20px; */
       /* width: calc(100% - 200px); */
       overflow: hidden;
 

+ 109 - 11
src/modules/knowledge/rgflow/knowledgeLib/test.vue

@@ -54,23 +54,52 @@
       </div>
     </div>
     <div class="main-container-rt">
-      <a-collapse style="width: 96%; margin-top: 1rem; margin-left: 2%">
-        <a-collapse-item header="0/0 选定的文件" key="3">
-          <template #extra>
-            <a-tag size="small">命中数</a-tag>
-            <a-tag size="small">看法</a-tag>
-          </template>
+      <a-collapse style="width: 96%; margin-top: 1rem; margin-left: 2%" @change="handleCollapseChange">
+        <a-collapse-item :header="check_count + '/' + doc_total + '选定的文件'" key="3">
+          <a-list :bordered="false" :pagination-props="doc_pagination_props" style="background: var(--color-bg-1)">
+            <a-list-item v-for="doc in docList" :key="doc.doc_id" style="border-left: none; border-right: none">
+              <a-list-item-meta :title="doc.doc_name">
+                <template #avatar>
+                  <a-checkbox v-model="doc.checked"></a-checkbox>
+                </template>
+              </a-list-item-meta>
+              <template #actions>
+                {{ doc.count }}
+                <icon-eye @click="handlePreview(doc.doc_id)" />
+              </template>
+            </a-list-item>
+          </a-list>
           <div>
-            <a-empty />
+            <!-- <a-empty /> -->
           </div>
         </a-collapse-item>
       </a-collapse>
+      <div
+        class="main-container-rt-down"
+        :style="collapse_status ? 'height: calc(100% - 350px);overflow-y: auto' : 'height: calc(100% - 140px)'"
+      >
+        <a-card :bordered="false" v-for="item in chunks" :key="item.chunk_id">
+          <template #title>
+            <div class="main-container-rt-down-title">
+              <div>{{ (item.similarity * 100).toFixed(2) }}&nbsp;混合相似度</div>
+              <div>{{ (item.term_similarity * 100).toFixed(2) }}&nbsp;关键词相似度</div>
+              <div>{{ (item.vector_similarity * 100).toFixed(2) }}&nbsp;向量相似度</div>
+            </div>
+          </template>
+          <div class="main-container-rt-down-content">
+            {{ item.content_with_weight }}
+          </div>
+        </a-card>
+      </div>
+      <div class="footer-page">
+        <a-pagination :total="chunk_total" show-total />
+      </div>
     </div>
   </div>
 </template>
 
 <script setup>
-import { onMounted, onBeforeMount, reactive, ref, watch } from 'vue';
+import { onMounted, onBeforeMount, reactive, ref, watch, computed } from 'vue';
 import { Message } from '@arco-design/web-vue';
 import { kbretrievalTest, queryModelList } from '../../../../apis/rgflow-dify';
 // const props = defineProps(['kbId'])
@@ -95,11 +124,28 @@ let form = reactive({
   top_k: 1024,
   vector_similarity_weight: 0.7
 });
+const chunks = ref([]);
+const all_chunks = ref([]);
+const docList = ref([]);
+
+const doc_total = ref(0);
+const chunk_total = ref(0);
+const collapse_status = ref(false);
+const check_count = computed(() => {
+  return docList.value.filter((item) => item.checked).length || 0;
+}); // 选中的文件数
+const doc_pagination_props = reactive({
+  defaultPageSize: 3,
+  total: doc_total.value
+});
 
 const formatter = (value) => {
   // return String(Math.round(value / 100))
 };
 
+const handleCollapseChange = (key) => {
+  key.length ? (collapse_status.value = true) : (collapse_status.value = false);
+};
 const handleSubmit = async ({ values, errors }) => {
   // console.log(props.kbobj, 'props.kbobj');
   if (!form.question) {
@@ -117,8 +163,20 @@ const handleSubmit = async ({ values, errors }) => {
   try {
     loading.value = true;
     const data = await kbretrievalTest(formObj);
-    if (data.code == 0) {
+    if (data.retcode == 0) {
       Message.success('测试成功');
+      all_chunks.value = data.data.chunks;
+      docList.value = data.data.doc_aggs?.map((item) => {
+        return {
+          ...item,
+          checked: false
+        };
+      });
+      docList.value[0].checked = true;
+      chunks.value = all_chunks.value.filter((item) => item.doc_id == docList.value[0].doc_id);
+
+      doc_total.value = data.data.doc_aggs.length;
+      chunk_total.value = data.data.chunks.length;
     } else {
       Message.error('测试失败');
     }
@@ -160,6 +218,11 @@ const queryModel = async (params) => {
   } finally {
   }
 };
+const handlePreview = (doc_id) => {
+  window.open(`${window.RGFLOW_BASE_URL}/document/${doc_id}?ext=docx&prefix=document`);
+};
+
+// watch(()=>)
 
 defineExpose({
   changekbid
@@ -185,10 +248,9 @@ export default {
   .main-container-lf {
     width: 30%;
     height: 100%;
-    //border: 1px solid var(--color-fill-3);
     background: var(--color-bg-2);
     border-radius: 10px;
-    overflow: auto;
+    overflow: hidden;
     .main-container-lf-top {
       width: 100%;
       height: 60px;
@@ -229,12 +291,48 @@ export default {
     }
   }
   .main-container-rt {
+    position: relative;
     width: 69%;
     height: 100%;
+    overflow: hidden;
     //background: #626aea;
     //border: 1px solid var(--color-fill-3);
     background: var(--color-bg-2);
     border-radius: 10px;
+    .main-container-rt-down {
+      padding: 25px;
+      .main-container-rt-down-title {
+        display: flex;
+        gap: 10px;
+        font-size: 14px;
+      }
+      .main-container-rt-down-content {
+        max-height: 300px;
+        position: relative;
+        padding: 20px 0;
+        font-size: 16px;
+        .footer-page {
+          position: absolute;
+          bottom: 10px;
+          left: 10px;
+        }
+      }
+    }
+    .footer-page {
+      padding-top: 10px;
+      position: absolute;
+      bottom: 20px;
+      left: 20px;
+      width: 100%;
+      background: var(--color-bg-2);
+    }
   }
 }
+
+:deep .arco-collapse-item-content {
+  padding: 0;
+}
+:deep .arco-collapse-item-content-box {
+  padding: 0;
+}
 </style>

+ 5 - 5
src/modules/knowledge/rgflow/knowledgeLib/tool.vue

@@ -365,7 +365,7 @@ const handleSubmit = async ({ values, errors }) => {
         pages: []
       }
     });
-    if (data.code == 0) {
+    if (data.retcode == 0) {
       Message.success('配置成功');
     } else {
       Message.error('配置失败');
@@ -450,7 +450,7 @@ const addBlock = (type) => {
       doc_id: props.item.id
     };
     chunkSwitch(params).then((res) => {
-      if (res.code == 0) {
+      if (res.retcode == 0) {
         Message.success('操作成功');
         getList();
         checkedAll.value = false;
@@ -488,7 +488,7 @@ const getList = async () => {
     params.available_int = available_int.value;
   }
   await queryChunkList(params).then((res) => {
-    if (res.code == 0) {
+    if (res.retcode == 0) {
       listData.value = res.data.chunks;
       isLoading.value = false;
       listData.value = listData.value.map((item) => {
@@ -512,7 +512,7 @@ const updateChunkStatus = (val) => {
   };
   chunkSwitch(params).then((res) => {
     console.log(res);
-    if (res.code == 0) {
+    if (res.retcode == 0) {
       Message.success('更新成功');
       getList();
     } else {
@@ -529,7 +529,7 @@ const deleteChunk = () => {
   };
   chunkRm(params).then((res) => {
     console.log(res);
-    if (res.code == 0) {
+    if (res.retcode == 0) {
       Message.success('删除成功');
       getList();
     } else {

+ 1 - 1
src/modules/knowledge/rgflow/knowledgeLib/utils/index.js

@@ -1,4 +1,4 @@
-export const documentHeight = window.innerHeight - 320;
+export const documentHeight = window.innerHeight - 185;
 /**
  * @description 格式化时间
  * @param time