Browse Source

增加删除功能

xueyiming 2 weeks ago
parent
commit
7df14baac9
7 changed files with 137 additions and 61 deletions
  1. 2 1
      package-lock.json
  2. 1 0
      package.json
  3. 9 3
      src/main.ts
  4. 117 49
      src/views/KnowledgeBase.vue
  5. 2 2
      src/views/KnowledgeContent.vue
  6. 3 3
      src/views/QAndA.vue
  7. 3 3
      src/views/SearchPage.vue

+ 2 - 1
package-lock.json

@@ -8,6 +8,7 @@
       "name": "rag-web",
       "version": "0.1.0",
       "dependencies": {
+        "@element-plus/icons-vue": "^2.3.2",
         "axios": "^1.12.0",
         "core-js": "^3.8.3",
         "element-plus": "^2.11.2",
@@ -1774,7 +1775,7 @@
     },
     "node_modules/@element-plus/icons-vue": {
       "version": "2.3.2",
-      "resolved": "https://registry.npmjs.org/@element-plus/icons-vue/-/icons-vue-2.3.2.tgz",
+      "resolved": "https://registry.npmmirror.com/@element-plus/icons-vue/-/icons-vue-2.3.2.tgz",
       "integrity": "sha512-OzIuTaIfC8QXEPmJvB4Y4kw34rSXdCJzxcD1kFStBvr8bK6X1zQAYDo0CNMjojnfTqRQCJ0I7prlErcoRiET2A==",
       "license": "MIT",
       "peerDependencies": {

+ 1 - 0
package.json

@@ -8,6 +8,7 @@
     "lint": "vue-cli-service lint"
   },
   "dependencies": {
+    "@element-plus/icons-vue": "^2.3.2",
     "axios": "^1.12.0",
     "core-js": "^3.8.3",
     "element-plus": "^2.11.2",

+ 9 - 3
src/main.ts

@@ -1,13 +1,19 @@
-import { createApp } from 'vue'
+import {createApp} from 'vue'
 import App from './App.vue'
 import router from './router'
 import store from './store'
 
 import ElementPlus from 'element-plus';
 import 'element-plus/dist/index.css'; // 引入 Element Plus 样式
+import * as ElementPlusIconsVue from '@element-plus/icons-vue'
 
-createApp(App)
-    .use(store)
+const app = createApp(App)
+
+app.use(store)
     .use(router)
     .use(ElementPlus)
     .mount('#app')
+
+for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
+    app.component(key, component)
+}

+ 117 - 49
src/views/KnowledgeBase.vue

@@ -1,48 +1,76 @@
 <template>
   <el-container style="height: 100vh; padding: 20px;">
-    <!-- Header: Knowledge Base title + Create button -->
+    <!-- Header -->
     <el-header style="display: flex; justify-content: space-between; align-items: center; padding: 20px;">
       <div style="font-size: 28px; font-weight: bold; color: #333;">知识库</div>
-      <el-button type="primary" @click="showCreateModal" style="border-radius: 20px;">创建知识库</el-button>
+      <el-button
+          type="primary"
+          @click="showCreateModal"
+          style="border-radius: 20px;"
+          :loading="loading.create"
+      >
+        创建知识库
+      </el-button>
     </el-header>
 
-    <!-- Content Area: Display Knowledge Base List -->
+    <!-- Content Area -->
     <el-main style="padding: 20px;">
       <div class="knowledge-base-grid">
         <el-card
             v-for="item in knowledgeBaseList"
             :key="item.dataset_id"
-            :body-style="{ padding: '20px', borderRadius: '12px' }"
+            :body-style="{ padding: '20px', borderRadius: '12px', position: 'relative' }"
             class="box-card"
-            @click="goToDetailPage(item.dataset_id, item.name)"
         >
-          <div style="font-size: 18px; font-weight: bold; margin-bottom: 10px; color: #2c3e50;">
-            {{ item.name }}
+          <!-- 美观的删除按钮 -->
+          <el-button
+              circle
+              size="small"
+              style="position: absolute; top: 10px; right: 10px; width: 28px; height: 28px;"
+              @click.stop="confirmDelete(item.dataset_id, item.name)"
+          >
+            <el-icon><CloseBold /></el-icon>
+          </el-button>
+
+          <!-- 点击卡片跳转详情 -->
+          <div
+              style="cursor: pointer"
+              @click="goToDetailPage(item.dataset_id, item.name)"
+          >
+            <div style="font-size: 18px; font-weight: bold; margin-bottom: 10px; color: #2c3e50;">
+              {{ item.name }}
+            </div>
+            <div style="color: #7f8c8d;">文档数量:{{ item.count }}</div>
+            <div style="color: #7f8c8d;">创建时间:{{ item.created_at }}</div>
           </div>
-          <div style="color: #7f8c8d;">文档数量:{{ item.count }}</div>
-          <div style="color: #7f8c8d;">创建时间:{{ item.created_at }}</div>
         </el-card>
+
+
       </div>
     </el-main>
 
-    <!-- Modal for Creating Knowledge Base -->
+    <!-- 创建知识库弹窗 -->
     <el-dialog v-model="createModalVisible" title="创建知识库" width="400px" style="border-radius: 12px;">
       <el-input
           v-model="newKnowledgeBaseTitle"
           placeholder="请输入知识库名称"
           maxlength="64"
           style="border-radius: 10px; padding: 10px;"
+          :disabled="loading.create"
       />
-      <!-- 显示已输入字符数/最大字符数 -->
       <div style="text-align: right; margin-top: 5px; font-size: 12px; color: #999;">
         {{ newKnowledgeBaseTitle.length }}/64
       </div>
       <template #footer>
-        <el-button @click="createModalVisible = false" style="border-radius: 20px;">取消</el-button>
+        <el-button @click="createModalVisible = false" style="border-radius: 20px;" :disabled="loading.create">
+          取消
+        </el-button>
         <el-button
             type="primary"
             @click="createKnowledgeBase"
-            style="border-radius: 20px; background-color: #409EFF; border-color: #409EFF;">
+            style="border-radius: 20px; background-color: #409EFF; border-color: #409EFF;"
+            :loading="loading.create"
+        >
           创建
         </el-button>
       </template>
@@ -51,76 +79,120 @@
 </template>
 
 <script lang="ts">
-import {defineComponent, ref} from 'vue';
+import {defineComponent, ref, reactive} from 'vue';
 import axios from 'axios';
-import {ElMessage} from 'element-plus';
-import {useRouter} from 'vue-router'; // 导入 useRouter
+import {ElMessage, ElMessageBox} from 'element-plus';
+import { CloseBold } from '@element-plus/icons-vue';
+import {useRouter} from 'vue-router';
 
 interface KnowledgeBaseItem {
   dataset_id: number;
   name: string;
   count: number;
-  create_at: string;
+  created_at: string;
 }
 
 export default defineComponent({
   name: 'KnowledgeBase',
+  components: {CloseBold},
+  // components: { CloseBold },
   setup() {
-    const router = useRouter(); // 获取 router 实例
+    const router = useRouter();
     const knowledgeBaseList = ref<KnowledgeBaseItem[]>([]);
     const newKnowledgeBaseTitle = ref('');
     const createModalVisible = ref(false);
 
-    // 获取知识库列表
+    // loading 状态
+    const loading = reactive({
+      create: false,
+      delete: {} as Record<number, boolean>
+    });
+
     const fetchKnowledgeBaseList = async () => {
       try {
-        const response = await axios.get('http://127.0.0.1:8001/api/dataset/list');
-        knowledgeBaseList.value = response.data.data;
+        const res = await axios.get('http://61.48.133.26:8001/api/dataset/list');
+        knowledgeBaseList.value = res.data.data;
       } catch (error) {
         ElMessage.error('获取知识库列表失败');
       }
     };
 
-    // 显示创建知识库的弹窗
     const showCreateModal = () => {
       createModalVisible.value = true;
     };
 
-    // 创建新的知识库
     const createKnowledgeBase = async () => {
       if (!newKnowledgeBaseTitle.value.trim()) {
         ElMessage.warning('请输入知识库名称');
         return;
       }
-
+      loading.create = true;
       try {
-        await axios.post('http://127.0.0.1:8001/api/dataset/add', {
+        await axios.post('http://61.48.133.26:8001/api/dataset/add', {
           name: newKnowledgeBaseTitle.value
         });
         ElMessage.success('知识库创建成功');
         createModalVisible.value = false;
-        newKnowledgeBaseTitle.value = ''; // 清空输入框
-        fetchKnowledgeBaseList(); // 重新获取知识库列表
-      } catch (error) {
-        ElMessage.error('创建知识库失败');
+        newKnowledgeBaseTitle.value = '';
+        await fetchKnowledgeBaseList();
+      } catch (error: any) {
+        ElMessage.error(error?.response?.data?.detail || '创建知识库失败');
+      } finally {
+        loading.create = false;
+      }
+    };
+
+    const confirmDelete = async (datasetId: number, datasetName: string) => {
+      try {
+        await ElMessageBox.confirm(
+            `确定要删除知识库 "${datasetName}" 吗?`,
+            '删除确认',
+            {
+              confirmButtonText: '删除',
+              cancelButtonText: '取消',
+              type: 'warning',
+            }
+        );
+        await deleteKnowledgeBase(datasetId);
+      } catch {
+        // 用户取消,不做任何操作
+      }
+    };
+
+    const deleteKnowledgeBase = async (datasetId: number) => {
+      loading.delete[datasetId] = true;
+      try {
+        await axios.post('http://192.168.100.31:8001/api/delete', {
+          level: 'dataset',
+          params: {dataset_id: datasetId}
+        });
+        ElMessage.success('知识库删除成功');
+        await fetchKnowledgeBaseList();
+      } catch (error: any) {
+        ElMessage.error(error?.response?.data?.detail || '删除知识库失败');
+      } finally {
+        loading.delete[datasetId] = false;
       }
     };
 
-    // 跳转到知识库详情页面
     const goToDetailPage = (datasetId: number, datasetName: string) => {
-      console.log(`跳转到知识库 ${datasetId} 的详情页`);
-      router.push({path: `/knowledge/content`, query: {datasetId: datasetId.toString(), datasetName: datasetName}});
+      router.push({
+        path: '/knowledge/content',
+        query: {datasetId: datasetId.toString(), datasetName}
+      });
     };
 
-    // 初始化加载知识库列表
+    // 初始化加载
     fetchKnowledgeBaseList();
 
     return {
       knowledgeBaseList,
       newKnowledgeBaseTitle,
       createModalVisible,
+      loading,
       showCreateModal,
       createKnowledgeBase,
+      confirmDelete,
       goToDetailPage,
     };
   }
@@ -131,50 +203,46 @@ export default defineComponent({
 .el-card {
   cursor: pointer;
   transition: transform 0.3s ease;
-  box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1); /* 添加阴影效果 */
-  border-radius: 12px; /* 添加圆角 */
+  box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
+  border-radius: 12px;
   background-color: #fff;
-  width: 250px; /* 设置卡片的固定宽度 */
+  width: 250px;
+  margin-top: 20px;
 }
 
 .el-card:hover {
-  transform: translateY(-10px); /* 鼠标悬停时,卡片上升 */
+  transform: translateY(-10px);
 }
 
 .el-dialog {
   z-index: 9999;
-  border-radius: 12px; /* 弹窗圆角 */
+  border-radius: 12px;
 }
 
 .el-button {
-  border-radius: 20px; /* 按钮圆角 */
+  border-radius: 20px;
 }
 
 .el-input {
-  border-radius: 10px; /* 输入框圆角 */
+  border-radius: 10px;
 }
 
 .knowledge-base-grid {
   display: flex;
   flex-wrap: wrap;
-  gap: 20px; /* 设置每个卡片之间的间距 */
-  justify-content: flex-start; /* 默认从左侧对齐 */
-}
-
-.el-card {
-  margin-top: 20px; /* 设置上边距为20px */
+  gap: 20px;
+  justify-content: flex-start;
 }
 
-/* 适配小屏幕 */
 @media (max-width: 768px) {
   .el-card {
-    width: 230px; /* 在小屏幕下调整卡片宽度 */
+    width: 230px;
   }
 }
 
 @media (max-width: 480px) {
   .el-card {
-    width: 100%; /* 屏幕宽度小于480px时,每行展示1个卡片 */
+    width: 100%;
   }
 }
 </style>

+ 2 - 2
src/views/KnowledgeContent.vue

@@ -118,7 +118,7 @@ export default defineComponent({
     const fetchData = async (datasetId: number) => {
       console.log(datasetId);
       try {
-        const response = await axios.get('http://127.0.0.1:8001/api/content/list', {
+        const response = await axios.get('http://61.48.133.26:8001/api/content/list', {
           params: {
             page: pageIndex.value,
             pageSize: pageSize.value,
@@ -200,7 +200,7 @@ export default defineComponent({
       }
 
       try {
-        const response = await axios.post('http://127.0.0.1:8001/api/chunk', {
+        const response = await axios.post('http://61.48.133.26:8001/api/chunk', {
           dataset_id: datasetId.value,
           title: formData.value.title,
           text: formData.value.text,

+ 3 - 3
src/views/QAndA.vue

@@ -107,7 +107,7 @@ const loading = ref(false);
 // 请求知识库列表
 const getKnowledgeBaseList = async () => {
   try {
-    const response = await fetch('http://127.0.0.1:8001/api/dataset/list');
+    const response = await fetch('http://61.48.133.26:8001/api/dataset/list');
     const data = await response.json();
     knowledgeBaseList.value = data.data;
   } catch (error) {
@@ -140,7 +140,7 @@ const chat = async () => {
   loading.value = true; // 开始搜索时显示加载提示
   const datasetIds = selectedDatasetIds.value.join(',');
   try {
-    const response = await fetch(`http://127.0.0.1:8001/api/chat?query=${query.value}&datasetIds=${datasetIds}`);
+    const response = await fetch(`http://61.48.133.26:8001/api/chat?query=${query.value}&datasetIds=${datasetIds}`);
     const data = await response.json();
     searchResults.value = data.data.results.map((item) => ({
       ...item,
@@ -165,7 +165,7 @@ const handleDetails = async (result) => {
 
   // 请求完整内容
   try {
-    const response = await fetch(`http://127.0.0.1:8001/api/content/get?docId=${result.docId}`);
+    const response = await fetch(`http://61.48.133.26:8001/api/content/get?docId=${result.docId}`);
     const data = await response.json();
     if (data.status_code === 200) {
       originalContent.value = data.data.text; // 显示原文内容

+ 3 - 3
src/views/SearchPage.vue

@@ -91,7 +91,7 @@ const loading = ref(false);
 // 请求知识库列表
 const getKnowledgeBaseList = async () => {
   try {
-    const response = await fetch('http://127.0.0.1:8001/api/dataset/list');
+    const response = await fetch('http://61.48.133.26:8001/api/dataset/list');
     const data = await response.json();
     knowledgeBaseList.value = data.data;
   } catch (error) {
@@ -124,7 +124,7 @@ const search = async () => {
   loading.value = true; // 开始搜索时显示加载提示
   const datasetIds = selectedDatasetIds.value.join(',');
   try {
-    const response = await fetch(`http://127.0.0.1:8001/api/query?query=${query.value}&datasetIds=${datasetIds}`);
+    const response = await fetch(`http://61.48.133.26:8001/api/query?query=${query.value}&datasetIds=${datasetIds}`);
     const data = await response.json();
     searchResults.value = data.data.results.map((item) => ({
       ...item,
@@ -144,7 +144,7 @@ const handleDetails = async (result) => {
 
   // 请求完整内容
   try {
-    const response = await fetch(`http://127.0.0.1:8001/api/content/get?docId=${result.docId}`);
+    const response = await fetch(`http://61.48.133.26:8001/api/content/get?docId=${result.docId}`);
     const data = await response.json();
     if (data.status_code === 200) {
       originalContent.value = data.data.text; // 显示原文内容