diff --git a/dsRag/Dao/KbDao.py b/dsRag/Dao/KbDao.py
index 68b0c2a4..fa7439f9 100644
--- a/dsRag/Dao/KbDao.py
+++ b/dsRag/Dao/KbDao.py
@@ -101,4 +101,11 @@ class KbDao:
async with conn.cursor(DictCursor) as cur:
await cur.execute(
"SELECT * FROM t_ai_kb_files WHERE state = 0")
+ return await cur.fetchall()
+
+ async def list_kbs(self) -> List[Dict]:
+ """获取所有知识库列表"""
+ async with self.mysql_pool.acquire() as conn:
+ async with conn.cursor(DictCursor) as cur:
+ await cur.execute("SELECT * FROM t_ai_kb")
return await cur.fetchall()
\ No newline at end of file
diff --git a/dsRag/Dao/__pycache__/KbDao.cpython-310.pyc b/dsRag/Dao/__pycache__/KbDao.cpython-310.pyc
index 575a5666..773e58a4 100644
Binary files a/dsRag/Dao/__pycache__/KbDao.cpython-310.pyc and b/dsRag/Dao/__pycache__/KbDao.cpython-310.pyc differ
diff --git a/dsRag/Doc/7、启动.txt b/dsRag/Doc/7、启动.txt
new file mode 100644
index 00000000..93e34ea6
--- /dev/null
+++ b/dsRag/Doc/7、启动.txt
@@ -0,0 +1 @@
+http://localhost:8000/static/index.html
\ No newline at end of file
diff --git a/dsRag/Start.py b/dsRag/Start.py
index 5100a2a2..667df41f 100644
--- a/dsRag/Start.py
+++ b/dsRag/Start.py
@@ -9,6 +9,8 @@ from fastapi import FastAPI, UploadFile, File
from Dao.KbDao import KbDao
from Util.MySQLUtil import init_mysql_pool
+from fastapi.staticfiles import StaticFiles
+
# 初始化日志
logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)
@@ -43,6 +45,11 @@ async def lifespan(app: FastAPI):
app = FastAPI(lifespan=lifespan)
# 知识库CRUD接口
+@app.get("/kb")
+async def list_kbs():
+ """获取所有知识库列表"""
+ return await app.state.kb_dao.list_kbs()
+
@app.post("/kb")
async def create_kb(kb: dict):
"""创建知识库"""
@@ -90,5 +97,7 @@ async def upload_file(kb_id: int, file: UploadFile = File(...)):
"""文件上传接口"""
return await app.state.kb_dao.handle_upload(kb_id, file)
+app.mount("/static", StaticFiles(directory="Static"), name="static")
+
if __name__ == "__main__":
uvicorn.run(app, host="0.0.0.0", port=8000)
\ No newline at end of file
diff --git a/dsRag/Static/css/style.css b/dsRag/Static/css/style.css
new file mode 100644
index 00000000..e2d47410
--- /dev/null
+++ b/dsRag/Static/css/style.css
@@ -0,0 +1,30 @@
+body {
+ font-size: .875rem;
+}
+
+.sidebar {
+ position: fixed;
+ top: 0;
+ bottom: 0;
+ left: 0;
+ z-index: 100;
+ padding: 48px 0 0;
+ box-shadow: inset -1px 0 0 rgba(0, 0, 0, .1);
+}
+
+.sidebar .nav-link {
+ font-weight: 500;
+ color: #adb5bd;
+}
+
+.sidebar .nav-link.active {
+ color: #fff;
+}
+
+.sidebar .nav-link:hover {
+ color: rgba(255, 255, 255, .75);
+}
+
+main {
+ padding-top: 1.5rem;
+}
\ No newline at end of file
diff --git a/dsRag/Static/index.html b/dsRag/Static/index.html
new file mode 100644
index 00000000..3b649828
--- /dev/null
+++ b/dsRag/Static/index.html
@@ -0,0 +1,102 @@
+
+
+
+
+ 知识库管理系统
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
知识库管理
+
+
+
+
+
+
+ ID |
+ 名称 |
+ 描述 |
+ 创建时间 |
+ 操作 |
+
+
+
+
+
+
+
+
+
+
+
文件管理
+
+
+
+
+
+
+
+
+
+ ID |
+ 文件名 |
+ 大小 |
+ 类型 |
+ 状态 |
+ 上传时间 |
+ 操作 |
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/dsRag/Static/js/app.js b/dsRag/Static/js/app.js
new file mode 100644
index 00000000..37824957
--- /dev/null
+++ b/dsRag/Static/js/app.js
@@ -0,0 +1,171 @@
+// API基础URL
+const API_BASE_URL = 'http://localhost:8000';
+
+// 初始化页面
+document.addEventListener('DOMContentLoaded', function() {
+ loadKbList();
+ setupEventListeners();
+});
+
+// 设置事件监听器
+function setupEventListeners() {
+ // 添加知识库按钮
+ document.getElementById('add-kb-btn').addEventListener('click', showKbModal);
+
+ // 上传文件按钮
+ document.getElementById('upload-file-btn').addEventListener('click', showFileModal);
+
+ // 知识库选择器变化
+ document.getElementById('kb-selector').addEventListener('change', function() {
+ loadFileList(this.value);
+ });
+}
+
+// 加载知识库列表
+async function loadKbList() {
+ try {
+ const response = await axios.get(`${API_BASE_URL}/kb`);
+ const kbList = response.data;
+
+ const tbody = document.getElementById('kb-table-body');
+ tbody.innerHTML = '';
+
+ const kbSelector = document.getElementById('kb-selector');
+ kbSelector.innerHTML = '';
+
+ kbList.forEach(kb => {
+ // 填充知识库表格
+ const row = document.createElement('tr');
+ row.innerHTML = `
+ ${kb.id} |
+ ${kb.name} |
+ ${kb.description || '-'} |
+ ${new Date(kb.create_time).toLocaleString()} |
+
+
+
+ |
+ `;
+ tbody.appendChild(row);
+
+ // 填充知识库选择器
+ const option = document.createElement('option');
+ option.value = kb.id;
+ option.textContent = kb.name;
+ kbSelector.appendChild(option);
+ });
+
+ // 添加编辑和删除按钮的事件
+ document.querySelectorAll('.edit-kb').forEach(btn => {
+ btn.addEventListener('click', function() {
+ showKbModal(this.getAttribute('data-id'));
+ });
+ });
+
+ document.querySelectorAll('.delete-kb').forEach(btn => {
+ btn.addEventListener('click', function() {
+ deleteKb(this.getAttribute('data-id'));
+ });
+ });
+ } catch (error) {
+ console.error('加载知识库列表失败:', error);
+ alert('加载知识库列表失败');
+ }
+}
+
+// 加载文件列表
+async function loadFileList(kbId) {
+ if (!kbId) return;
+
+ try {
+ const response = await axios.get(`${API_BASE_URL}/kb_files?kb_id=${kbId}`);
+ const fileList = response.data;
+
+ const tbody = document.getElementById('file-table-body');
+ tbody.innerHTML = '';
+
+ fileList.forEach(file => {
+ const row = document.createElement('tr');
+ row.innerHTML = `
+ ${file.id} |
+ ${file.file_name} |
+ ${formatFileSize(file.file_size)} |
+ ${file.file_type} |
+ ${getFileStatusText(file.state)} |
+ ${new Date(file.create_time).toLocaleString()} |
+
+
+ |
+ `;
+ tbody.appendChild(row);
+ });
+
+ // 添加删除按钮的事件
+ document.querySelectorAll('.delete-file').forEach(btn => {
+ btn.addEventListener('click', function() {
+ deleteFile(this.getAttribute('data-id'));
+ });
+ });
+ } catch (error) {
+ console.error('加载文件列表失败:', error);
+ alert('加载文件列表失败');
+ }
+}
+
+// 辅助函数:格式化文件大小
+function formatFileSize(bytes) {
+ if (bytes === 0) return '0 Bytes';
+ const k = 1024;
+ const sizes = ['Bytes', 'KB', 'MB', 'GB'];
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
+ return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
+}
+
+// 辅助函数:获取文件状态文本
+function getFileStatusText(state) {
+ switch (state) {
+ case 0: return '待处理';
+ case 1: return '已处理';
+ case 2: return '处理失败';
+ default: return '未知状态';
+ }
+}
+
+// 显示知识库模态框
+function showKbModal(kbId = null) {
+ // 实现知识库添加/编辑模态框逻辑
+}
+
+// 显示文件上传模态框
+function showFileModal() {
+ // 实现文件上传模态框逻辑
+}
+
+// 删除知识库
+async function deleteKb(kbId) {
+ if (!confirm('确定要删除这个知识库吗?')) return;
+
+ try {
+ await axios.delete(`${API_BASE_URL}/kb/${kbId}`);
+ alert('删除成功');
+ loadKbList();
+ } catch (error) {
+ console.error('删除知识库失败:', error);
+ alert('删除知识库失败');
+ }
+}
+
+// 删除文件
+async function deleteFile(fileId) {
+ if (!confirm('确定要删除这个文件吗?')) return;
+
+ try {
+ await axios.delete(`${API_BASE_URL}/kb_files/${fileId}`);
+ alert('删除成功');
+ const kbId = document.getElementById('kb-selector').value;
+ if (kbId) loadFileList(kbId);
+ } catch (error) {
+ console.error('删除文件失败:', error);
+ alert('删除文件失败');
+ }
+}
\ No newline at end of file