|
@@ -1,9 +1,11 @@
|
|
|
<template>
|
|
|
<el-container style="height: 100vh;">
|
|
|
<!-- 上方的 Header -->
|
|
|
- <el-header style="height: 50px; background: linear-gradient(to right, #6db3f2, #1e69e8); color: white; display: flex; align-items: center; padding: 0 20px;">
|
|
|
+ <el-header
|
|
|
+ style="height: 50px; background: linear-gradient(to right, #6db3f2, #1e69e8); color: white; display: flex; align-items: center; padding: 0 20px;">
|
|
|
<!-- 返回按钮 -->
|
|
|
- <el-button @click="goBack" style="margin-right: 20px; background-color: #fff; color: #409EFF; border: 1px solid #409EFF;">
|
|
|
+ <el-button @click="goBack"
|
|
|
+ style="margin-right: 20px; background-color: #fff; color: #409EFF; border: 1px solid #409EFF;">
|
|
|
返回
|
|
|
</el-button>
|
|
|
|
|
@@ -13,25 +15,56 @@
|
|
|
</div>
|
|
|
|
|
|
<!-- 添加新知识按钮 -->
|
|
|
- <el-button @click="openDialog" style="border-radius: 20px; background-color: #fff; color: #409EFF; border: 1px solid #409EFF;">
|
|
|
+ <el-button @click="openDialog"
|
|
|
+ style="border-radius: 20px; background-color: #fff; color: #409EFF; border: 1px solid #409EFF;">
|
|
|
添加新知识
|
|
|
</el-button>
|
|
|
</el-header>
|
|
|
|
|
|
<el-container>
|
|
|
<!-- 左侧菜单栏 -->
|
|
|
- <el-aside width="330px" style="background-color: #f4f4f4; padding: 10px; display: flex; flex-direction: column; overflow-y: auto; height: calc(100vh - 60px);">
|
|
|
+ <el-aside
|
|
|
+ width="330px"
|
|
|
+ style="background-color: #f4f4f4; padding: 10px; display: flex; flex-direction: column; overflow-y: auto; height: calc(100vh - 60px);"
|
|
|
+ >
|
|
|
<!-- 左侧标题,居中显示 -->
|
|
|
- <div style="font-size: 18px; font-weight: bold; margin-bottom: 10px; text-align: center; width: 100%;">
|
|
|
+ <div
|
|
|
+ style="font-size: 18px; font-weight: bold; margin-bottom: 10px; text-align: center; width: 100%;"
|
|
|
+ >
|
|
|
内容列表
|
|
|
</div>
|
|
|
|
|
|
- <el-menu :default-active="activeItem" @select="handleSelect" style="border-right: none; flex-grow: 1;">
|
|
|
- <el-menu-item v-for="item in currentPageItems" :key="item.doc_id" :index="item.doc_id">
|
|
|
- {{ item.text.substring(0, 20) + '...' }}
|
|
|
+ <!-- 菜单,只有在有数据时才渲染 -->
|
|
|
+ <el-menu
|
|
|
+ v-if="currentPageItems && currentPageItems.length > 0"
|
|
|
+ :default-active="activeItem"
|
|
|
+ @select="handleSelect"
|
|
|
+ style="border-right: none; flex-grow: 1;"
|
|
|
+ >
|
|
|
+ <el-menu-item
|
|
|
+ v-for="item in currentPageItems"
|
|
|
+ :key="item.doc_id"
|
|
|
+ :index="String(item.doc_id)"
|
|
|
+ style="display: flex; justify-content: space-between; align-items: center;"
|
|
|
+ >
|
|
|
+ <!-- 左边文字:固定宽度 + 超出省略号 -->
|
|
|
+ <span class="menu-text">{{ item.title || item.text }}</span>
|
|
|
+
|
|
|
+ <!-- 删除按钮 -->
|
|
|
+ <el-icon
|
|
|
+ style="cursor: pointer; font-size: 18px; color: #f56c6c; display: flex; align-items: center; justify-content: center;"
|
|
|
+ @click.stop="confirmDelete(item.doc_id, item.title)"
|
|
|
+ >
|
|
|
+ <Delete/>
|
|
|
+ </el-icon>
|
|
|
</el-menu-item>
|
|
|
</el-menu>
|
|
|
|
|
|
+ <!-- 没有数据时的占位 -->
|
|
|
+ <div v-else style="text-align: center; color: #999; padding: 20px;">
|
|
|
+ 暂无内容
|
|
|
+ </div>
|
|
|
+
|
|
|
<!-- 分页 -->
|
|
|
<el-pagination
|
|
|
v-model:current-page="pageIndex"
|
|
@@ -45,10 +78,61 @@
|
|
|
</el-aside>
|
|
|
|
|
|
<!-- 右侧内容区域 -->
|
|
|
- <el-main style="padding: 20px; overflow-y: auto; height: calc(100vh - 60px);">
|
|
|
+ <el-main style="padding: 20px; overflow-y: auto; height: calc(100vh - 60px); position: relative;">
|
|
|
+ <!-- 右上角按钮 -->
|
|
|
+ <!-- 右上角按钮:有内容时才显示 -->
|
|
|
+ <el-button
|
|
|
+ v-if="selectedContent"
|
|
|
+ size="small"
|
|
|
+ type="primary"
|
|
|
+ style="position: absolute; top: 10px; right: 10px;"
|
|
|
+ @click="openChunkDialog"
|
|
|
+ >
|
|
|
+ 展示分段
|
|
|
+ </el-button>
|
|
|
+
|
|
|
<h2>{{ selectedTitle }}</h2>
|
|
|
<p>{{ selectedContent }}</p>
|
|
|
</el-main>
|
|
|
+
|
|
|
+ <!-- 分段展示弹窗 -->
|
|
|
+ <el-dialog
|
|
|
+ title="文档分段"
|
|
|
+ v-model="chunkDialogVisible"
|
|
|
+ width="80%"
|
|
|
+ :destroy-on-close="true"
|
|
|
+ :top="'5vh'"
|
|
|
+ >
|
|
|
+ <div style="max-height: 80%; overflow-y: auto;">
|
|
|
+ <!-- 延迟渲染,避免动画阶段触发 ResizeObserver -->
|
|
|
+ <el-table
|
|
|
+ v-if="chunkDialogVisible && chunkList.length > 0"
|
|
|
+ :data="chunkList"
|
|
|
+ style="width: 100%; min-height: 100px;"
|
|
|
+ >
|
|
|
+ <el-table-column prop="chunk_id" label="分段ID" width="100" header-align="center" align="center"/>
|
|
|
+ <el-table-column prop="summary" label="总结" width="300" header-align="center"/>
|
|
|
+ <el-table-column prop="text" label="内容" header-align="center"/>
|
|
|
+ </el-table>
|
|
|
+
|
|
|
+
|
|
|
+ <!-- 分页器 -->
|
|
|
+ <div style="margin-top: 10px; text-align: center;">
|
|
|
+ <el-pagination
|
|
|
+ v-model:current-page="chunkPage"
|
|
|
+ :page-size="chunkPageSize"
|
|
|
+ :total="chunkTotal"
|
|
|
+ layout="prev, pager, next"
|
|
|
+ @current-change="fetchChunks"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </el-dialog>
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
</el-container>
|
|
|
|
|
|
<!-- 弹窗 -->
|
|
@@ -73,11 +157,11 @@
|
|
|
</template>
|
|
|
|
|
|
<script lang="ts">
|
|
|
-import { defineComponent, onMounted, ref, computed } from 'vue';
|
|
|
-import { useRouter } from 'vue-router'; // 引入 vue-router 用于路由跳转
|
|
|
+import {defineComponent, onMounted, ref, computed} from 'vue';
|
|
|
+import {useRouter} from 'vue-router'; // 引入 vue-router 用于路由跳转
|
|
|
import axios from 'axios';
|
|
|
-import { ElMessage } from 'element-plus'; // 导入 ElMessage
|
|
|
-
|
|
|
+import {ElMessage, ElMessageBox} from 'element-plus';
|
|
|
+import {Delete} from '@element-plus/icons-vue';
|
|
|
|
|
|
// 定义接口类型
|
|
|
interface Item {
|
|
@@ -114,6 +198,13 @@ export default defineComponent({
|
|
|
|
|
|
const dialogVisible = ref(false); // 控制弹窗的显示和隐藏
|
|
|
|
|
|
+ // 分段弹窗
|
|
|
+ const chunkDialogVisible = ref(false);
|
|
|
+ const chunkList = ref<any[]>([]);
|
|
|
+ const chunkPage = ref(1);
|
|
|
+ const chunkPageSize = ref(10);
|
|
|
+ const chunkTotal = ref(0);
|
|
|
+
|
|
|
// 获取API数据并填充项
|
|
|
const fetchData = async (datasetId: number) => {
|
|
|
console.log(datasetId);
|
|
@@ -226,6 +317,71 @@ export default defineComponent({
|
|
|
}
|
|
|
};
|
|
|
|
|
|
+ // 确认删除
|
|
|
+ const confirmDelete = (doc_id: string, title: string | null) => {
|
|
|
+ ElMessageBox.confirm(
|
|
|
+ `确定要删除文档 "${title || doc_id}" 吗?`,
|
|
|
+ '删除确认',
|
|
|
+ {
|
|
|
+ confirmButtonText: '删除',
|
|
|
+ cancelButtonText: '取消',
|
|
|
+ type: 'warning',
|
|
|
+ }
|
|
|
+ ).then(() => {
|
|
|
+ deleteDoc(doc_id);
|
|
|
+ }).catch(() => {
|
|
|
+ // 用户取消,不处理
|
|
|
+ });
|
|
|
+ };
|
|
|
+
|
|
|
+ // 删除文档方法
|
|
|
+ const deleteDoc = async (doc_id: string) => {
|
|
|
+ try {
|
|
|
+ await axios.post('http://192.168.100.31:8001/api/delete', {
|
|
|
+ level: 'doc',
|
|
|
+ params: {doc_id}
|
|
|
+ });
|
|
|
+ ElMessage.success('删除成功');
|
|
|
+ if (datasetId.value !== null) {
|
|
|
+ fetchData(datasetId.value); // 刷新列表
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error(error);
|
|
|
+ ElMessage.error('删除失败');
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ // 打开分段弹窗
|
|
|
+ const openChunkDialog = async () => {
|
|
|
+ if (!activeItem.value) {
|
|
|
+ ElMessage.warning("请先选择一个文档");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ chunkDialogVisible.value = true;
|
|
|
+ await fetchChunks(chunkPage.value);
|
|
|
+ };
|
|
|
+
|
|
|
+// 获取分段数据
|
|
|
+ const fetchChunks = async (page: number) => {
|
|
|
+ if (!activeItem.value) return;
|
|
|
+ try {
|
|
|
+ const response = await axios.get('http://61.48.133.26:8001/api/chunk/list', {
|
|
|
+ params: {
|
|
|
+ page,
|
|
|
+ pageSize: chunkPageSize.value,
|
|
|
+ docId: activeItem.value,
|
|
|
+ }
|
|
|
+ });
|
|
|
+ const data = response.data.data;
|
|
|
+ chunkList.value = data.entities;
|
|
|
+ chunkTotal.value = data.total_count;
|
|
|
+ chunkPage.value = data.page;
|
|
|
+ } catch (err) {
|
|
|
+ console.error(err);
|
|
|
+ ElMessage.error("获取分段失败");
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
return {
|
|
|
activeItem,
|
|
|
selectedTitle,
|
|
@@ -243,6 +399,16 @@ export default defineComponent({
|
|
|
openDialog,
|
|
|
submitData,
|
|
|
resetForm,
|
|
|
+ confirmDelete,
|
|
|
+ deleteDoc,
|
|
|
+ Delete,
|
|
|
+ chunkDialogVisible,
|
|
|
+ chunkList,
|
|
|
+ chunkPage,
|
|
|
+ chunkPageSize,
|
|
|
+ chunkTotal,
|
|
|
+ openChunkDialog,
|
|
|
+ fetchChunks,
|
|
|
};
|
|
|
},
|
|
|
});
|
|
@@ -274,4 +440,13 @@ export default defineComponent({
|
|
|
overflow: hidden; /* 超出部分隐藏 */
|
|
|
text-overflow: ellipsis; /* 使用省略号代替超出的文本 */
|
|
|
}
|
|
|
+
|
|
|
+.menu-text {
|
|
|
+ max-width: 200px; /* 固定宽度 */
|
|
|
+ display: inline-block;
|
|
|
+ white-space: nowrap; /* 不换行 */
|
|
|
+ overflow: hidden; /* 超出隐藏 */
|
|
|
+ text-overflow: ellipsis; /* 显示省略号 */
|
|
|
+}
|
|
|
+
|
|
|
</style>
|