123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249 |
- <template>
- <el-container style="height: 100vh; padding: 20px;">
- <!-- 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;"
- :loading="loading.create"
- >
- 创建知识库
- </el-button>
- </el-header>
- <!-- 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', position: 'relative' }"
- class="box-card"
- >
- <!-- 美观的删除按钮 -->
- <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>
- </el-card>
- </div>
- </el-main>
- <!-- 创建知识库弹窗 -->
- <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;" :disabled="loading.create">
- 取消
- </el-button>
- <el-button
- type="primary"
- @click="createKnowledgeBase"
- style="border-radius: 20px; background-color: #409EFF; border-color: #409EFF;"
- :loading="loading.create"
- >
- 创建
- </el-button>
- </template>
- </el-dialog>
- </el-container>
- </template>
- <script lang="ts">
- import { API_BASE_URL } from "@/config";
- import {defineComponent, ref, reactive} from 'vue';
- import axios from 'axios';
- 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;
- created_at: string;
- }
- export default defineComponent({
- name: 'KnowledgeBase',
- components: {CloseBold},
- // components: { CloseBold },
- setup() {
- 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 res = await axios.get(`${API_BASE_URL}/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(`${API_BASE_URL}/dataset/add`, {
- name: newKnowledgeBaseTitle.value
- });
- ElMessage.success('知识库创建成功');
- createModalVisible.value = false;
- 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(`${API_BASE_URL}/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) => {
- router.push({
- path: '/knowledge/content',
- query: {datasetId: datasetId.toString(), datasetName}
- });
- };
- // 初始化加载
- fetchKnowledgeBaseList();
- return {
- knowledgeBaseList,
- newKnowledgeBaseTitle,
- createModalVisible,
- loading,
- showCreateModal,
- createKnowledgeBase,
- confirmDelete,
- goToDetailPage,
- };
- }
- });
- </script>
- <style scoped>
- .el-card {
- cursor: pointer;
- transition: transform 0.3s ease;
- box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
- border-radius: 12px;
- background-color: #fff;
- width: 250px;
- margin-top: 20px;
- }
- .el-card:hover {
- transform: translateY(-10px);
- }
- .el-dialog {
- z-index: 9999;
- border-radius: 12px;
- }
- .el-button {
- border-radius: 20px;
- }
- .el-input {
- border-radius: 10px;
- }
- .knowledge-base-grid {
- display: flex;
- flex-wrap: wrap;
- gap: 20px;
- justify-content: flex-start;
- }
- @media (max-width: 768px) {
- .el-card {
- width: 230px;
- }
- }
- @media (max-width: 480px) {
- .el-card {
- width: 100%;
- }
- }
- </style>
|