yangyin
2024-11-12 bdba8fa1c5b2d8223e5ad26ebc9dbe6b9a5579b2
src/views/project/yw/dataManage/knowledge/Knowledge.vue
@@ -1,68 +1,95 @@
<template>
   <div class="h100 overflow-y-auto p-[16px]">
   <div class="h100 overflow-y-auto">
      <div class="flex flex-col h100">
         <div class="text-[16px] font-[500] h-[22px]">知识库管理</div>
         <div class="mx-0 mt-[12px] mb-[16px] flex justify-between items-center">
            <div class="flex-col">
               <el-input
                  v-model="knowledgeBaseForm.title"
                  style="width: 230px; margin-right: 10px; background: #ffffff; border-radius: 6px; transition: all 0.2s"
                  placeholder="搜索知识库名称"
                  clearable
               ></el-input>
               <el-button type="primary" icon="ele-Search" @click="handleQueryTable"> 查询 </el-button>
               <el-button icon="ele-Refresh" @click="resetQuery">重置 </el-button>
            </div>
            <el-button icon="ele-Plus" @click="createKnowledgeBase()" type="primary"> 创建知识库 </el-button>
         </div>
         <div class="flex flex-wrap gap-[12px]">
            <div class="flex flex-wrap gap-3 overflow-x-auto set_item_jel" v-for="item in displayTableData" :key="item.id">
               <img :src="knowledgeLeft" class="set_item_img" />
               <div class="set_item_content">
                  <div class="flex items-center">
                     <div class="mr-[10px] text-[14px] font-[500] h-[22px]">{{ item.title }}</div>
                     <span class="set_desc_text">
                        <span class="set_desc_icon ywifont ywicon-wendang"> </span>
                        1个知识
                     </span>
                     <span class="set_desc_text">
                        <span class="set_desc_icon ywifont ywicon-fenshu_an"> </span>
                        {{ item.scope }}
                     </span>
                     <span class="set_desc_text">
                        <span class="set_desc_icon ywifont ywicon-cshy-shizhong"> </span>
                        {{ item.create_time }}更新
                     </span>
                     <span
                        :class="{
                           'text-orange-500': item.publish === SupervisorPublished.N,
                           'text-green-500': item.publish === SupervisorPublished.Y,
                        }"
                        class="text-[12px]"
                     >
                        {{ supervisorPublishedMap[item.publish] }}
                     </span>
         <el-row class="h100">
            <el-col :span="4" class="h100 px-[10px]">
               <LeftTreeByMgr
                  v-loading="treeLoading"
                  class="h100 p-[20px]"
                  ref="leftTreeRef"
                  :defaultProps="{
                     id: 'group_id',
                     label: 'group_name',
                     children: 'children',
                  }"
                  :treedata="listTreeData"
                  title-name="分组列表"
                  :show-more-operate="false"
                  :show-add="false"
                  defaultExpandAll
                  :current-node-key="currentListID"
                  :node-icon="() => 'ele-Document'"
                  @click="handleClickNode"
               >
               </LeftTreeByMgr>
            </el-col>
            <el-col :span="20" class="h100 p-[10px]">
               <div class="text-[16px] font-[500] h-[22px]">知识库管理</div>
               <div class="mx-0 mt-[12px] mb-[16px] flex justify-between items-center">
                  <div class="flex-col">
                     <el-input
                        v-model="knowledgeBaseForm.title"
                        style="width: 230px; margin-right: 10px; background: #ffffff; border-radius: 6px; transition: all 0.2s"
                        placeholder="搜索知识库名称"
                        clearable
                     ></el-input>
                     <el-button type="primary" icon="ele-Search" @click="handleQueryTable"> 查询 </el-button>
                     <el-button icon="ele-Refresh" @click="resetQuery">重置 </el-button>
                  </div>
                  <el-button icon="ele-Plus" @click="createKnowledgeBase()" type="primary"> 创建知识库 </el-button>
               </div>
               <div class="flex flex-wrap gap-[12px]">
                  <div class="flex flex-wrap gap-3 overflow-x-auto set_item_jel" v-for="item in displayTableData" :key="item.id">
                     <img :src="knowledgeLeft" class="set_item_img" />
                     <div class="set_item_content">
                        <div class="flex items-center">
                           <div class="mr-[10px] text-[14px] font-[500] w-[100px]">{{ item.title }}</div>
                           <div class="flex flex-wrap gap-1">
                              <span class="set_desc_text">
                                 <span class="set_desc_icon ywifont ywicon-wendang"> </span>
                                 1个知识
                              </span>
                              <span class="set_desc_text">
                                 <span class="set_desc_icon ywifont ywicon-fenshu_an"> </span>
                                 {{ item.scope }}
                              </span>
                              <span class="set_desc_text">
                                 <span class="set_desc_icon ywifont ywicon-cshy-shizhong"> </span>
                                 {{ item.create_time }}更新
                              </span>
                              <span
                                 :class="{
                                    'text-orange-500': item.publish === SupervisorPublished.N,
                                    'text-green-500': item.publish === SupervisorPublished.Y,
                                 }"
                                 class="text-[12px]"
                              >
                                 {{ supervisorPublishedMap[item.publish] }}
                              </span>
                           </div>
                        </div>
                     </div>
                     <div class="set_btn_group">
                        <el-button
                           link
                           class="text-[12px]"
                           @click="publishKnowledgeBase(item)"
                           :style="{ color: item.publish === SupervisorPublished.Y ? '#f97316' : '#22c55e' }"
                           >{{ item.publish === SupervisorPublished.Y ? '下架' : '发布' }}
                        </el-button>
                        <el-divider direction="vertical" />
                        <el-button link class="text-[12px] text-[#686682]" @click="viewKnowledgeBase(item)">查看 </el-button>
                        <el-divider direction="vertical" />
                        <el-button link class="text-[12px] text-[#686682]" @click="openChatTest(item)">对话测试 </el-button>
                        <el-divider direction="vertical" />
                        <el-button link class="text-[12px] text-[#686682]" @click="editKnowledgeBase(item)">编辑 </el-button>
                        <el-divider direction="vertical" />
                        <el-button link class="text-[12px]" @click="deleteKnowledgeBase(item)" style="color: #f00">删除 </el-button>
                     </div>
                  </div>
               </div>
               <div class="set_btn_group">
                  <el-button
                     link
                     class="text-[12px]"
                     @click="publishKnowledgeBase(item)"
                     :style="{ color: item.publish === SupervisorPublished.Y ? '#f97316' : '#22c55e' }"
                     >{{ item.publish === SupervisorPublished.Y ? '下架' : '发布' }}
                  </el-button>
                  <el-divider direction="vertical" />
                  <el-button link class="text-[12px] text-[#686682]" @click="viewKnowledgeBase(item)">查看 </el-button>
                  <el-divider direction="vertical" />
                  <el-button link class="text-[12px] text-[#686682]" @click="openChatTest(item)">对话测试 </el-button>
                  <el-divider direction="vertical" />
                  <el-button link class="text-[12px] text-[#686682]" @click="editKnowledgeBase(item)">编辑 </el-button>
                  <el-divider direction="vertical" />
                  <el-button link class="text-[12px]" @click="deleteKnowledgeBase(item)" style="color: #f00">删除 </el-button>
               </div>
            </div>
         </div>
            </el-col>
         </el-row>
      </div>
      <div
         v-if="chatTestIsShow"
@@ -83,13 +110,13 @@
      </div>
   </div>
</template>
<script setup lang="ts">
import { useDraggable } from '@vueuse/core';
import axios, { CancelTokenSource } from 'axios';
import { ElMessage, ElMessageBox } from 'element-plus';
import { nextTick, onMounted, ref } from 'vue';
import { computed, nextTick, onMounted, ref } from 'vue';
import { useRouter } from 'vue-router';
import * as agentGroupApi from '/@/api/ai/agentGroup';
import {
   check_docvector_validate,
   delete_docvector_name,
@@ -97,18 +124,64 @@
   publish_docvector_name,
} from '/@/api/knowledge/docvector';
import Chat from '/@/components/chat/Chat.vue';
import LeftTreeByMgr from '/@/components/tree/leftTreeByMgr.vue';
import { useQueryTable } from '/@/hooks/useQueryTable';
import mittBus from '/@/utils/mitt';
import { useCompRef } from '/@/utils/types';
import { convertListToTree } from '/@/utils/util';
import { SupervisorPublished, supervisorPublishedMap } from '/@/views/project/yw/lowCode/sqlAmis/types';
import { OptClassificationMap, classificationEnum } from '/@/views/types/metrics';
import knowledgeLeft from '/static/images/knowledge/data_type_1.png';
const router = useRouter();
//#region ====================== 左侧树数据,tree init ======================
const leftTreeRef = useCompRef(LeftTreeByMgr);
const treeLoading = ref(false);
const listData = ref([]);
const currentListID = computed(() => currentNode.value?.group_id);
const currentNode = ref(null);
const listTreeData = computed(() => {
   const byParentData = convertListToTree(listData.value, {
      ID: 'group_id',
      ParentID: 'p_group_id',
      Children: 'children',
   });
   const result = [];
   byParentData.forEach((item) => {
      if (item.group_type == OptClassificationMap[classificationEnum.Knowledge]) {
         result.push(item);
      }
   });
   return result;
});
const handleClickNode = (data) => {
   nextTick(() => {
      leftTreeRef.value?.treeRef.setCurrentKey(data.group_id);
   });
   currentNode.value = data;
   docvectorList();
};
const getListTreeData = async () => {
   const res = await agentGroupApi.getSceneGroupTreeByPost();
   listData.value = res.groups || [];
   const firstListTreeNode = listTreeData.value[0];
   if (firstListTreeNode) {
      handleClickNode(firstListTreeNode);
   } else {
      knowledgeBaseList.value = [];
      currentNode.value = null;
   }
};
//#endregion
//#region ====================== 获取知识库sheet列表 ======================
const knowledgeBaseList = ref([]);
//创建知识库
const createKnowledgeBase = () => {
   router.push({
      name: 'AddKnowledge',
      query: {
         group_id: currentListID.value,
      },
   });
};
//获取知识库列表
@@ -118,7 +191,8 @@
      res.values.forEach((item) => {
         item.create_time = new Date(item.create_time).toLocaleString();
      });
      knowledgeBaseList.value = res.values;
      const filterDocData = res.values.filter((item) => item.group_id === currentListID.value);
      knowledgeBaseList.value = filterDocData;
   } else {
      return ElMessage.error('获取列表索引失败' + (res?.json_msg ? `,${JSON.stringify(res.json_msg)}` : ''));
   }
@@ -184,7 +258,6 @@
});
//#endregion
//#region ====================== Chat 测试 ======================
const chatRef = useCompRef(Chat);
const chatTestMapRow = ref(null);
const chatTestIsShow = ref(false);
@@ -193,22 +266,15 @@
   chatTestIsShow.value = true;
   nextTick(() => {
      chatRef.value.clear();
      // setTimeout(() => {
      //    chatRef.value.autoSend(row.title);
      // }, 30);
   });
};
const closeChatTest = () => {
   chatTestMapRow.value = null;
   chatTestIsShow.value = false;
};
const draggableChatRef = ref<HTMLElement | null>(null);
const chatDragHandlerRef = ref<HTMLDivElement>(null);
const chatDragContainerRef = ref<HTMLDivElement>(null);
// `style` will be a helper computed for `left: ?px; top: ?px;`
const { x, y, style } = useDraggable(draggableChatRef, {
   handle: chatDragHandlerRef,
   initialValue: {
@@ -216,7 +282,6 @@
      y: document.body.clientHeight / 2 - 400,
   },
});
const questionAi = async (text, sourceObj: { source: CancelTokenSource }) => {
   const currentSource = axios.CancelToken.source();
   sourceObj.source = currentSource;
@@ -232,11 +297,21 @@
   );
   return res;
};
//#endregion
onMounted(() => {
   docvectorList();
   getListTreeData();
   mittBus.on('addKnowledgeBaseObj', (obj) => {
      knowledgeBaseList.value.push(obj);
   });
   mittBus.on('updateKnowledgeBaseObj', (formValue) => {
      const foundIndex = knowledgeBaseList.value.findIndex((item) => item.id === formValue.id);
      if (foundIndex > -1) {
         knowledgeBaseList.value[foundIndex] = {
            ...knowledgeBaseList.value[foundIndex],
            ...formValue,
         };
      }
   });
});
</script>
<style scoped lang="scss">