Initial commit: 知识库管理器应用
- 实现基于 PySide6 的 GUI 界面 - 集成 FastAPI 知识库服务器 API - 支持查看、编辑、提交 Markdown 文件 - 包含完整的 pytest-qt 测试套件 - 添加功能列表文档
This commit is contained in:
203
main_window.py
Normal file
203
main_window.py
Normal file
@@ -0,0 +1,203 @@
|
||||
import sys
|
||||
from PySide6.QtWidgets import (
|
||||
QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout,
|
||||
QLabel, QLineEdit, QPushButton, QListWidget, QTextEdit,
|
||||
QMessageBox, QSplitter, QFileDialog
|
||||
)
|
||||
from PySide6.QtCore import Qt
|
||||
from api_client import KnowledgeBaseAPI
|
||||
|
||||
|
||||
class KnowledgeBaseApp(QMainWindow):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.api: Optional[KnowledgeBaseAPI] = None
|
||||
self.current_filename: Optional[str] = None
|
||||
self.init_ui()
|
||||
|
||||
def init_ui(self):
|
||||
self.setWindowTitle('知识库管理器')
|
||||
self.setGeometry(100, 100, 1200, 800)
|
||||
|
||||
central_widget = QWidget()
|
||||
self.setCentralWidget(central_widget)
|
||||
|
||||
main_layout = QVBoxLayout(central_widget)
|
||||
|
||||
# 服务器地址配置区域
|
||||
server_layout = QHBoxLayout()
|
||||
server_label = QLabel('服务器地址:')
|
||||
self.server_input = QLineEdit('http://43.134.1.17:8800/')
|
||||
self.server_input.setMinimumWidth(300)
|
||||
self.config_button = QPushButton('配置')
|
||||
self.config_button.clicked.connect(self.configure_server)
|
||||
self.refresh_button = QPushButton('刷新列表')
|
||||
self.refresh_button.clicked.connect(self.refresh_file_list)
|
||||
|
||||
server_layout.addWidget(server_label)
|
||||
server_layout.addWidget(self.server_input)
|
||||
server_layout.addWidget(self.config_button)
|
||||
server_layout.addWidget(self.refresh_button)
|
||||
server_layout.addStretch()
|
||||
|
||||
main_layout.addLayout(server_layout)
|
||||
|
||||
# 主内容区域(使用分割器)
|
||||
splitter = QSplitter(Qt.Horizontal)
|
||||
|
||||
# 左侧:文件列表
|
||||
left_widget = QWidget()
|
||||
left_layout = QVBoxLayout(left_widget)
|
||||
|
||||
list_label = QLabel('文件列表 (.md):')
|
||||
self.file_list = QListWidget()
|
||||
self.file_list.itemClicked.connect(self.load_file)
|
||||
|
||||
left_layout.addWidget(list_label)
|
||||
left_layout.addWidget(self.file_list)
|
||||
|
||||
# 右侧:编辑区域
|
||||
right_widget = QWidget()
|
||||
right_layout = QVBoxLayout(right_widget)
|
||||
|
||||
filename_layout = QHBoxLayout()
|
||||
filename_label = QLabel('文件名:')
|
||||
self.filename_input = QLineEdit()
|
||||
self.filename_input.setPlaceholderText('输入文件名(例如:example.md)')
|
||||
|
||||
filename_layout.addWidget(filename_label)
|
||||
filename_layout.addWidget(self.filename_input)
|
||||
|
||||
self.text_editor = QTextEdit()
|
||||
self.text_editor.setPlaceholderText('在此编辑 Markdown 内容...')
|
||||
|
||||
button_layout = QHBoxLayout()
|
||||
self.save_button = QPushButton('保存到服务器')
|
||||
self.save_button.clicked.connect(self.save_file)
|
||||
self.post_button = QPushButton('提交新文件')
|
||||
self.post_button.clicked.connect(self.post_new_file)
|
||||
|
||||
button_layout.addWidget(self.save_button)
|
||||
button_layout.addWidget(self.post_button)
|
||||
|
||||
right_layout.addLayout(filename_layout)
|
||||
right_layout.addWidget(self.text_editor)
|
||||
right_layout.addLayout(button_layout)
|
||||
|
||||
splitter.addWidget(left_widget)
|
||||
splitter.addWidget(right_widget)
|
||||
splitter.setSizes([300, 900])
|
||||
|
||||
main_layout.addWidget(splitter)
|
||||
|
||||
# 状态栏
|
||||
self.status_label = QLabel('就绪')
|
||||
self.statusBar().addWidget(self.status_label)
|
||||
|
||||
def configure_server(self):
|
||||
server_url = self.server_input.text().strip()
|
||||
if not server_url:
|
||||
QMessageBox.warning(self, '警告', '请输入服务器地址')
|
||||
return
|
||||
|
||||
self.api = KnowledgeBaseAPI(server_url)
|
||||
|
||||
if self.api.test_connection():
|
||||
self.status_label.setText(f'已连接到服务器: {server_url}')
|
||||
QMessageBox.information(self, '成功', '服务器配置成功!')
|
||||
self.refresh_file_list()
|
||||
else:
|
||||
QMessageBox.critical(self, '错误', '无法连接到服务器,请检查地址是否正确')
|
||||
self.status_label.setText('连接失败')
|
||||
|
||||
def refresh_file_list(self):
|
||||
if not self.api:
|
||||
QMessageBox.warning(self, '警告', '请先配置服务器')
|
||||
return
|
||||
|
||||
try:
|
||||
files = self.api.get_file_list()
|
||||
self.file_list.clear()
|
||||
|
||||
# 只显示 .md 文件
|
||||
md_files = [f for f in files if f.endswith('.md')]
|
||||
self.file_list.addItems(md_files)
|
||||
|
||||
self.status_label.setText(f'已加载 {len(md_files)} 个文件')
|
||||
except Exception as e:
|
||||
QMessageBox.critical(self, '错误', str(e))
|
||||
self.status_label.setText('加载文件列表失败')
|
||||
|
||||
def load_file(self, item):
|
||||
filename = item.text()
|
||||
self.current_filename = filename
|
||||
self.filename_input.setText(filename)
|
||||
|
||||
try:
|
||||
content = self.api.get_file(filename)
|
||||
self.text_editor.setPlainText(content)
|
||||
self.status_label.setText(f'已加载文件: {filename}')
|
||||
except Exception as e:
|
||||
QMessageBox.critical(self, '错误', str(e))
|
||||
self.status_label.setText('加载文件失败')
|
||||
|
||||
def save_file(self):
|
||||
if not self.api:
|
||||
QMessageBox.warning(self, '警告', '请先配置服务器')
|
||||
return
|
||||
|
||||
if not self.current_filename:
|
||||
QMessageBox.warning(self, '警告', '请先选择一个文件')
|
||||
return
|
||||
|
||||
content = self.text_editor.toPlainText()
|
||||
|
||||
try:
|
||||
self.api.post_file(self.current_filename, content)
|
||||
QMessageBox.information(self, '成功', f'文件 {self.current_filename} 保存成功!')
|
||||
self.status_label.setText(f'已保存文件: {self.current_filename}')
|
||||
except Exception as e:
|
||||
QMessageBox.critical(self, '错误', str(e))
|
||||
self.status_label.setText('保存文件失败')
|
||||
|
||||
def post_new_file(self):
|
||||
if not self.api:
|
||||
QMessageBox.warning(self, '警告', '请先配置服务器')
|
||||
return
|
||||
|
||||
filename = self.filename_input.text().strip()
|
||||
|
||||
if not filename:
|
||||
QMessageBox.warning(self, '警告', '请输入文件名')
|
||||
return
|
||||
|
||||
if not filename.endswith('.md'):
|
||||
filename += '.md'
|
||||
self.filename_input.setText(filename)
|
||||
|
||||
content = self.text_editor.toPlainText()
|
||||
|
||||
if not content:
|
||||
QMessageBox.warning(self, '警告', '请输入文件内容')
|
||||
return
|
||||
|
||||
try:
|
||||
self.api.post_file(filename, content)
|
||||
QMessageBox.information(self, '成功', f'文件 {filename} 提交成功!')
|
||||
self.current_filename = filename
|
||||
self.status_label.setText(f'已提交文件: {filename}')
|
||||
self.refresh_file_list()
|
||||
except Exception as e:
|
||||
QMessageBox.critical(self, '错误', str(e))
|
||||
self.status_label.setText('提交文件失败')
|
||||
|
||||
|
||||
def main():
|
||||
app = QApplication(sys.argv)
|
||||
window = KnowledgeBaseApp()
|
||||
window.show()
|
||||
sys.exit(app.exec())
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
Reference in New Issue
Block a user