| | |
| | | <template> |
| | | <div class="flex flex-col h100"> |
| | | <div class="mb-[10px] flex flex-shrink-0 items-center"> |
| | | <el-button style="margin-left: 8px; width: 40px" link @click="handleExitFlow"> |
| | | <el-icon style="font-size: 24px !important"> |
| | | <ArrowLeft /> |
| | | </el-icon> |
| | | </el-button> |
| | | <span class="text-[24px] text-[#26244c] font-[700]">{{ state.knowledgeInfo.knowledge_title }}</span> |
| | | </div> |
| | | <div class="set-table-height" v-show="!state.showKnowledgeForm"> |
| | | <!-- 查询、重置、排序、增加表单 --> |
| | | <el-form :inline="true" :model="graphQueryParams"> |
| | | <el-form-item label="名称" prop="title"> |
| | | <el-input v-model="graphQueryParams.title" style="width: 226.4px" placeholder="文件名称" clearable></el-input> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button type="primary" icon="ele-Search" @click="handleQueryTable"> 查询 </el-button> |
| | | <el-button icon="ele-Refresh" @click="resetQuery">重置 </el-button> |
| | | <el-button icon="ele-Plus" @click="getImportantFileTreeData()" type="primary"> 导入数据 </el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | <div class="flex-auto flex-column h-full"> |
| | | <el-table |
| | | ref="viewKnowledgeTableRef" |
| | | border |
| | | row-key="id" |
| | | class="flex-auto" |
| | | :header-cell-style="{ textAlign: 'center' }" |
| | | :data="displayTableData" |
| | | highlight-current-row |
| | | > |
| | | <el-table-column prop="name" label="文件名称" fixed="left" show-overflow-tooltip align="left" /> |
| | | <el-table-column prop="type" width="120" label="文件类型" show-overflow-tooltip align="center" /> |
| | | <el-table-column prop="time" label="上传时间" show-overflow-tooltip width="280" align="center"></el-table-column> |
| | | <el-table-column label="操作" width="80" fixed="right" show-overflow-tooltip align="center"> |
| | | <template #default="scope"> |
| | | <el-tooltip effect="dark" content="删除" placement="top"> |
| | | <i |
| | | class="ywifont ywicon-shanchu !text-[17px] text-red-400 cursor-pointer" |
| | | @click="deleteKnowledgeFileData(scope.row)" |
| | | ></i> |
| | | </el-tooltip> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | <div class="h100" v-show="!state.showKnowledgeForm"> |
| | | <div class="mb-[10px] flex flex-shrink-0 items-center"> |
| | | <el-button style="margin-left: 8px; width: 40px" link @click="handleExitFlow"> |
| | | <el-icon style="font-size: 24px !important"> |
| | | <ArrowLeft /> |
| | | </el-icon> |
| | | </el-button> |
| | | <span class="text-[24px] text-[#26244c] font-[700]">{{ state.knowledgeInfo.knowledge_title }}</span> |
| | | </div> |
| | | <div class="set-table-height"> |
| | | <!-- 查询、重置、排序、增加表单 --> |
| | | <el-form :inline="true" :model="graphQueryParams"> |
| | | <el-form-item label="名称" prop="title"> |
| | | <el-input v-model="graphQueryParams.title" style="width: 226.4px" placeholder="文件名称" clearable></el-input> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button type="primary" icon="ele-Search" @click="handleQueryTable"> 查询 </el-button> |
| | | <el-button icon="ele-Refresh" @click="resetQuery">重置 </el-button> |
| | | <el-button icon="ele-Plus" @click="importKnowledgeData()" type="primary"> 导入数据 </el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | <div class="flex-auto flex-column h-full"> |
| | | <el-table |
| | | ref="viewKnowledgeTableRef" |
| | | border |
| | | row-key="id" |
| | | class="flex-auto" |
| | | :header-cell-style="{ textAlign: 'center' }" |
| | | :data="displayTableData" |
| | | highlight-current-row |
| | | > |
| | | <el-table-column prop="name" label="文件名称" fixed="left" show-overflow-tooltip align="left" /> |
| | | <el-table-column prop="type" width="120" label="文件类型" show-overflow-tooltip align="center" /> |
| | | <el-table-column prop="time" label="上传时间" show-overflow-tooltip width="280" align="center"></el-table-column> |
| | | <el-table-column label="操作" width="120" fixed="right" show-overflow-tooltip align="center"> |
| | | <template #default="scope"> |
| | | <div class="space-x-2.5"> |
| | | <el-tooltip effect="dark" content="文本" placement="top"> |
| | | <i |
| | | class="ywifont ywicon-wendang !text-[17px] cursor-pointer text-blue-400" |
| | | @click="openOperateDemoPage(scope.row)" |
| | | ></i> |
| | | </el-tooltip> |
| | | <el-tooltip effect="dark" content="分块" placement="top"> |
| | | <i |
| | | class="ywifont ywicon-01wenjianfenkuai !text-[17px] cursor-pointer text-blue-400" |
| | | @click="handleViewKnowledgeFile(scope.row)" |
| | | ></i> |
| | | </el-tooltip> |
| | | <el-tooltip effect="dark" content="删除" placement="top"> |
| | | <i |
| | | class="ywifont ywicon-shanchu !text-[17px] text-red-400 cursor-pointer" |
| | | @click="deleteKnowledgeFileData(scope.row)" |
| | | ></i> |
| | | </el-tooltip> |
| | | </div> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div class="set-form-height" v-show="state.showKnowledgeForm"> |
| | | <el-form :model="state.knowledgeFile" label-width="120px" label-position="left" class="h100" ref="knowledgeFileRef"> |
| | | <el-divider content-position="left"><span class="text-[18px] font-[500]">选择文件</span></el-divider> |
| | | <div class="flex items-start gap-[16px] max-h-[686px] min-h-[360px] set-file-height"> |
| | | <div class="min-h-[360px] h100 set_file_left"> |
| | | <div class="font-[500] mb-2">请选择文档</div> |
| | | <div class="left_content"> |
| | | <div class="file_menu"> |
| | | <LeftTreeByMgr |
| | | title-name="类目" |
| | | ref="leftTreeRef" |
| | | :treedata="state.knowledgeBaseData" |
| | | :current-node-key="currentListID" |
| | | :defaultProps="{ |
| | | children: 'Children', |
| | | label: 'title', |
| | | id: 'id', |
| | | }" |
| | | @click="handleClickNode" |
| | | > |
| | | </LeftTreeByMgr> |
| | | </div> |
| | | <div class="file_table"> |
| | | <el-table |
| | | :data="state.fileData" |
| | | border |
| | | @select="handleSelectItem" |
| | | highlight-current-row |
| | | ref="multipleTableRef" |
| | | @select-all=" |
| | | (selection) => { |
| | | handleSelectAll(selection, state.fileData); |
| | | } |
| | | " |
| | | > |
| | | <el-table-column type="selection" width="55" /> |
| | | <el-table-column prop="name" label="文件名称" /> |
| | | </el-table> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div class="set_file_right"> |
| | | <div class="h100"> |
| | | <div class="font-[500] mb-[12px]">已选文档{{ multipleSelection.length }}/50个</div> |
| | | <div class="selected_file"> |
| | | <div v-for="(item, index) in multipleSelection" :key="index" class="set_file_item"> |
| | | <span class="set_file_name">{{ item.name }}</span> |
| | | <span class="ywifont ywicon-guanbi set_file_close" @click="handleRemoveItem(item)"></span> |
| | | <div class="h100" v-show="state.showKnowledgeForm"> |
| | | <div class="mb-[10px] flex flex-shrink-0 items-center"> |
| | | <el-button style="margin-left: 8px; width: 40px" link @click="handleShowKnowledge"> |
| | | <el-icon style="font-size: 24px !important"> |
| | | <ArrowLeft /> |
| | | </el-icon> |
| | | </el-button> |
| | | <span class="text-[24px] text-[#26244c] font-[700]">{{ state.knowledgeInfo.knowledge_import_data }}</span> |
| | | </div> |
| | | <div class="set-table-height"> |
| | | <el-form :model="state.knowledgeFile" label-width="120px" label-position="left" class="h100" ref="knowledgeFileRef"> |
| | | <el-divider content-position="left"><span class="text-[18px] font-[500]">选择文件</span></el-divider> |
| | | <div class="flex items-start gap-[16px] max-h-[686px] min-h-[360px] set-file-height"> |
| | | <div class="min-h-[360px] h100 set_file_left"> |
| | | <div class="font-[500] mb-2">请选择文档</div> |
| | | <div class="left_content"> |
| | | <div class="file_menu"> |
| | | <LeftTreeByMgr |
| | | title-name="类目" |
| | | ref="leftTreeRef" |
| | | :treedata="state.knowledgeBaseData" |
| | | :current-node-key="currentListID" |
| | | :defaultProps="{ |
| | | id: 'group_id', |
| | | label: 'group_name', |
| | | children: 'Children', |
| | | }" |
| | | @click="handleClickNode" |
| | | > |
| | | </LeftTreeByMgr> |
| | | </div> |
| | | <div class="file_table"> |
| | | <el-table |
| | | :data="state.fileData" |
| | | border |
| | | @select="handleSelectItem" |
| | | highlight-current-row |
| | | ref="multipleTableRef" |
| | | @select-all=" |
| | | (selection) => { |
| | | handleSelectAll(selection, state.fileData); |
| | | } |
| | | " |
| | | > |
| | | <el-table-column type="selection" width="55" /> |
| | | <el-table-column prop="name" label="文件名称" /> |
| | | </el-table> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <el-divider content-position="left"><span class="text-[18px]">数据处理</span></el-divider> |
| | | <el-form-item label="文档切分chunk:"> |
| | | <div class="flex-auto flex flex-col"> |
| | | <div class="flex"> |
| | | <div v-for="(item, index) in state.segmentationList" :key="index"> |
| | | <div |
| | | class="bg-[#fff] border-[1px] border-solid border-[#d8d9e6] py-[12px] w-[215px] mr-[10px] px-[16px] rounded-lg cursor-pointer" |
| | | :class="{ activeColor: state.knowledgeForm.segmentationMode === item.ID }" |
| | | @click="activeDataProcessType(item.ID)" |
| | | > |
| | | <div class="flex items-center"> |
| | | <div class="data_left"> |
| | | <img :src="item.ImageURL" class="w-[40px] h-[40px] mr-[10px]" /> |
| | | </div> |
| | | <div class="data_right"> |
| | | <el-radio v-model="state.knowledgeForm.segmentationMode" size="large" :label="item.ID"> |
| | | <span class="font-[500] text[16px]">{{ item.Name }}</span> |
| | | </el-radio> |
| | | |
| | | <el-tooltip :content="item.DemoDesc" placement="top" effect="light" popper-class="set_tooltip_demo"> |
| | | <div class="text-[#878aab] text-[12px] mx-0 mt-[2px] mb-0 set-desc"> |
| | | {{ item.DemoDesc }} |
| | | </div> |
| | | </el-tooltip> |
| | | </div> |
| | | <div class="set_file_right"> |
| | | <div class="h100"> |
| | | <div class="font-[500] mb-[12px]">已选文档{{ multipleSelection.length }}/50个</div> |
| | | <div class="selected_file"> |
| | | <div v-for="(item, index) in multipleSelection" :key="index" class="set_file_item"> |
| | | <span class="set_file_name">{{ item.name }}</span> |
| | | <span class="ywifont ywicon-guanbi set_file_close" @click="handleRemoveItem(item)"></span> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </el-form-item> |
| | | </el-form> |
| | | <el-divider content-position="left"><span class="text-[18px]">数据处理</span></el-divider> |
| | | <el-form-item label="文档切分chunk:"> |
| | | <div class="flex-auto flex flex-col"> |
| | | <div class="flex"> |
| | | <div v-for="(item, index) in state.segmentationList" :key="index"> |
| | | <div |
| | | class="bg-[#fff] border-[1px] border-solid border-[#d8d9e6] py-[12px] w-[215px] mr-[10px] px-[16px] rounded-lg cursor-pointer" |
| | | :class="{ activeColor: state.knowledgeForm.segmentationMode === item.ID }" |
| | | @click="activeDataProcessType(item.ID)" |
| | | > |
| | | <div class="flex items-center"> |
| | | <div class="data_left"> |
| | | <img :src="item.ImageURL" class="w-[40px] h-[40px] mr-[10px]" /> |
| | | </div> |
| | | <div class="data_right"> |
| | | <el-radio v-model="state.knowledgeForm.segmentationMode" size="large" :label="item.ID"> |
| | | <span class="font-[500] text[16px]">{{ item.Name }}</span> |
| | | </el-radio> |
| | | |
| | | <el-tooltip :content="item.DemoDesc" placement="top" effect="light" popper-class="set_tooltip_demo"> |
| | | <div class="text-[#878aab] text-[12px] mx-0 mt-[2px] mb-0 set-desc"> |
| | | {{ item.DemoDesc }} |
| | | </div> |
| | | </el-tooltip> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </el-form-item> |
| | | </el-form> |
| | | </div> |
| | | </div> |
| | | <div class="set-form-footer" v-show="state.showKnowledgeForm"> |
| | | <el-button @click="importCompleted" type="primary">导入完成</el-button> |
| | | <el-button @click="handleShowKnowledge">取消</el-button> |
| | | </div> |
| | | </div> |
| | | </template> |
| | |
| | | import { ElMessage, ElMessageBox } from 'element-plus'; |
| | | import { computed, nextTick, onMounted, reactive, ref } from 'vue'; |
| | | import { useRoute, useRouter } from 'vue-router'; |
| | | import { delete_docvector_file, get_docvector_file_list } from '/@/api/knowledge/docvector'; |
| | | import { add_docvector_file, delete_docvector_file, get_docvector_file_list } from '/@/api/knowledge/docvector'; |
| | | import { get_knowledge_group_list, list_knowledge_file } from '/@/api/knowledge/group'; |
| | | import LeftTreeByMgr from '/@/components/tree/leftTreeByMgr.vue'; |
| | | import { useQueryTable } from '/@/hooks/useQueryTable'; |
| | |
| | | const router = useRouter(); |
| | | const route = useRoute(); |
| | | const knowledgeTableData = ref([]); |
| | | const knowledgeFileRef = ref(); |
| | | // 定义变量内容 |
| | | const state = reactive({ |
| | | knowledgeInfo: { |
| | | knowledge_title: '', |
| | | knowledge_id: '', |
| | | knowledge_import_data: '导入数据', |
| | | } as any, |
| | | knowledgeForm: { |
| | | segmentationMode: 1, |
| | |
| | | knowledgeFile: {}, |
| | | knowledgeBaseData: [], //知识库类目 |
| | | fileData: [], //文件数据源 |
| | | isCreateIndex: false, //是否调用创建的索引的字段 |
| | | }); |
| | | //返回 |
| | | //返回到知识库列表 |
| | | const handleExitFlow = () => { |
| | | //是否显示返回 |
| | | router.back(); |
| | | state.showKnowledgeForm = true; |
| | | }; |
| | | //返回到知识库查看页面 |
| | | const handleShowKnowledge = () => { |
| | | state.showKnowledgeForm = false; |
| | | }; |
| | | //#region ====================== 搜索表格,对表格排序 ====================== |
| | | const graphQueryParams = ref({ |
| | |
| | | if (res.json_ok) { |
| | | knowledgeTableData.value = res.values; |
| | | } |
| | | }; |
| | | //查看文档 |
| | | const openOperateDemoPage = (row: any) => { |
| | | router.push({ |
| | | name: 'ViewFile', |
| | | query: { |
| | | id: row.id, |
| | | }, |
| | | }); |
| | | }; |
| | | //查看文档块 |
| | | const handleViewKnowledgeFile = (row) => { |
| | | router.push({ |
| | | name: 'ViewSegmentationFile', |
| | | query: { |
| | | id: row.id, |
| | | }, |
| | | }); |
| | | }; |
| | | //删除知识库的文件列表 |
| | | const deleteKnowledgeFileData = (row: any) => { |
| | |
| | | }); |
| | | }; |
| | | //#endregion |
| | | |
| | | //#region ====================== 导入知识库数据 ====================== |
| | | const importKnowledgeData = () => { |
| | | state.showKnowledgeForm = true; |
| | | getImportantFileTreeData(true); |
| | | }; |
| | | //导入完成 |
| | | const importCompleted = async () => { |
| | | // 上传文件 |
| | | if (multipleSelection.value.length == 0) return ElMessage.warning('请先选择文件'); |
| | | let isCreateIndex = false; |
| | | const file_id = multipleSelection.value.map((v) => v.id).join(','); |
| | | knowledgeTableData.value.forEach((element) => { |
| | | if (element.id == file_id) { |
| | | ElMessage.warning('文件已存在,请选择其他文件'); |
| | | isCreateIndex = true; |
| | | } |
| | | }); |
| | | if (isCreateIndex) return; |
| | | const res = await add_docvector_file({ |
| | | knowlg_id: state.knowledgeInfo.knowledge_id, |
| | | file_id: file_id, |
| | | }); |
| | | if (res.json_ok) { |
| | | ElMessage.success('导入数据成功'); |
| | | state.showKnowledgeForm = false; |
| | | getKnowledgeFileData(); |
| | | //清空表单 |
| | | knowledgeFileRef.value.resetFields(); |
| | | } |
| | | }; |
| | | //#endregion |
| | | //#region ====================== 知识库文件上传 ========== |
| | | const treeLoading = ref(false); |
| | | const currentTreeNode = ref(null); |
| | | const leftTreeRef = ref(null); |
| | | const currentListID = computed(() => currentTreeNode.value?.id); |
| | | const currentListID = computed(() => currentTreeNode.value?.group_id); |
| | | //获取文件列表 |
| | | const getImportantFileTreeData = async (selectFirst = false) => { |
| | | state.showKnowledgeForm = false; |
| | | treeLoading.value = true; |
| | | const res = await get_knowledge_group_list().finally(() => { |
| | | treeLoading.value = false; |
| | | }); |
| | | if (res?.json_ok) { |
| | | const resData = (res.values || []) as []; |
| | | const resData = (res.groups || []) as []; |
| | | state.knowledgeBaseData = convertListToTree(resData, { |
| | | ID: 'id', |
| | | ID: 'group_id', |
| | | Children: 'Children', |
| | | ParentID: 'parent', |
| | | ParentID: 'p_group_id', |
| | | }); |
| | | if (selectFirst) { |
| | | const firstListTreeNode = state.knowledgeBaseData[0]; |
| | |
| | | const handleClickNode = (data: any) => { |
| | | multipleSelection.value = []; |
| | | nextTick(() => { |
| | | leftTreeRef.value?.treeRef.setCurrentKey(data.id); |
| | | leftTreeRef.value?.treeRef.setCurrentKey(data.group_id); |
| | | }); |
| | | currentTreeNode.value = data; |
| | | getFileTableData(); |
| | |
| | | .set-table-height { |
| | | background: #fff; |
| | | border-radius: 16px; |
| | | height: calc(100% - 80px); |
| | | height: calc(100% - 50px); |
| | | margin-top: 12px; |
| | | overflow-y: auto; |
| | | padding: 20px 24px; |
| | | box-sizing: border-box; |
| | | } |
| | | .set-file-height { |
| | | height: calc(100% - 48px); |
| | | } |
| | | .set_file_left { |
| | | border: 1px solid #e7e8ee; |
| | | border-radius: 12px; |
| | | flex: 1; |
| | | padding: 12px 16px 16px; |
| | | box-sizing: border-box; |
| | | .left_content { |
| | | align-items: flex-start; |
| | | display: flex; |
| | | gap: 12px; |
| | | height: calc(100% - 29px); |
| | | .file_menu { |
| | | flex-shrink: 0; |
| | | height: 100%; |
| | | overflow-y: auto; |
| | | border: 1px solid #e7e8ee; |
| | | border-radius: 6px; |
| | | max-height: 627px; |
| | | padding: 20px; |
| | | width: 280px; |
| | | } |
| | | .file_table { |
| | | flex-shrink: 0; |
| | | height: 100%; |
| | | overflow-y: auto; |
| | | border-radius: 8px 8px 0 0; |
| | | flex: 1; |
| | | } |
| | | } |
| | | } |
| | | .set_file_right { |
| | | border: 1px solid #e7e8ee; |
| | | border-radius: 6px; |
| | | flex-shrink: 0; |
| | | height: 100%; |
| | | padding: 12px 16px 16px; |
| | | width: 417px; |
| | | min-height: 360px; |
| | | } |
| | | .selected_file { |
| | | max-height: calc(100% - 36px); |
| | | overflow-y: auto; |
| | | box-sizing: border-box; |
| | | .set_file_item { |
| | | align-items: center; |
| | | background: linear-gradient(0deg, #f7f8fe, #f7f8fe), #fff; |
| | | border-radius: 8px; |
| | | display: flex; |
| | | font-size: 12px; |
| | | gap: 8px; |
| | | height: 40px; |
| | | justify-content: space-between; |
| | | padding: 0 16px; |
| | | margin-bottom: 9px; |
| | | .set_file_name { |
| | | max-width: calc(100% - 22px); |
| | | } |
| | | .set_file_close { |
| | | color: #878aab; |
| | | cursor: pointer; |
| | | flex-shrink: 0; |
| | | font-size: 14px; |
| | | align-items: center; |
| | | display: inline-flex; |
| | | justify-content: center; |
| | | } |
| | | } |
| | | } |
| | | .activeColor { |
| | | border-color: #0062be; |
| | | background-color: #f6f5ff; |
| | | } |
| | | .set-desc { |
| | | -webkit-line-clamp: 2; |
| | | display: -webkit-box; |
| | | -webkit-box-orient: vertical; |
| | | overflow: hidden; |
| | | word-break: break-word; |
| | | line-height: 1.5714285714285714; |
| | | font-family: PingFangSC; |
| | | box-sizing: border-box; |
| | | } |
| | | .set-form-footer { |
| | | align-items: center; |
| | | background: #fff; |
| | | bottom: 0; |
| | | box-shadow: 4px 0 5px 1px rgba(16, 9, 65, 0.06); |
| | | display: flex; |
| | | flex-shrink: 0; |
| | | gap: 8px; |
| | | height: 64px; |
| | | padding-left: 24px; |
| | | // position: fixed; |
| | | width: 100%; |
| | | left: 220px; |
| | | } |
| | | </style> |
| | | import { get_knowledge_group_list, list_knowledge_file } from '/@/api/knowledge/group'; import { convertListToTree } from |
| | | '/@/utils/util'; |
| | | <style> |
| | | .set_tooltip_demo { |
| | | max-width: 326px; |
| | | max-height: 150px; |
| | | min-width: 32px; |
| | | min-height: 32px; |
| | | padding: 6px 8px; |
| | | color: #26244c; |
| | | text-align: start; |
| | | text-decoration: none; |
| | | word-wrap: break-word; |
| | | background-color: #fff; |
| | | border-radius: 6px; |
| | | box-shadow: 0 6px 16px 0 rgba(0, 0, 0, 0.08), 0 3px 6px -4px rgba(0, 0, 0, 0.12), 0 9px 28px 8px rgba(0, 0, 0, 0.05); |
| | | box-sizing: border-box; |
| | | } |
| | | </style> |