From 7fa865b9aab629bc55667c10448cf7afe7f6ba8c Mon Sep 17 00:00:00 2001 From: hnu202326010330 <168584091@qq.com> Date: Sun, 12 Oct 2025 20:21:32 +0800 Subject: [PATCH 1/6] ADD file via upload --- src/ui/login_ui.py | 674 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 674 insertions(+) create mode 100644 src/ui/login_ui.py diff --git a/src/ui/login_ui.py b/src/ui/login_ui.py new file mode 100644 index 0000000..017c00b --- /dev/null +++ b/src/ui/login_ui.py @@ -0,0 +1,674 @@ +from PyQt5.QtWidgets import (QWidget, QVBoxLayout, QHBoxLayout, QLabel, + QLineEdit, QPushButton, QMessageBox, QFrame, QSizePolicy,QDialog) +from PyQt5.QtCore import Qt +from PyQt5.QtGui import QFont + +class LoginPage(QWidget): # 改为继承 QWidget + def __init__(self, parent=None): + super().__init__(parent) + self.parent_window = parent + self.user_system = parent.user_system if parent else None + self.setup_ui() + + def setup_ui(self): + # 移除 setWindowTitle 和 setMinimumSize,使用父窗口的尺寸 + + # 设置可爱的渐变背景 + self.setStyleSheet(""" + QWidget { + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #FFD1DC, stop:1 #B5EAD7); + } + """) + + # 主布局 + main_layout = QVBoxLayout(self) + main_layout.setContentsMargins(20, 20, 20, 20) + main_layout.setSpacing(0) + + # 添加返回按钮区域 + back_button_layout = QHBoxLayout() + back_button_layout.setContentsMargins(0, 0, 0, 10) + + self.back_btn = QPushButton("←返回") + self.back_btn.setMinimumHeight(50) + self.back_btn.setMaximumWidth(120) + self.back_btn.setStyleSheet(""" + QPushButton { + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #A0E7E5, stop:1 #6CD6D3); + color: white; + font: bold 11pt '微软雅黑'; + border-radius: 15px; + border: 2px solid #8ADBD9; + padding: 5px 15px; + } + QPushButton:hover { + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #8ADBD9, stop:1 #5AC7C4); + border: 2px solid #6CD6D3; + } + QPushButton:pressed { + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #5AC7C4, stop:1 #4BB5B2); + } + """) + self.back_btn.clicked.connect(self.go_back) + back_button_layout.addWidget(self.back_btn) + back_button_layout.addStretch() # 将按钮推到左边 + + main_layout.addLayout(back_button_layout) + + # 卡片容器 - 自适应尺寸 + card = QFrame() + card.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) + card.setStyleSheet(""" + QFrame { + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 white, stop:1 #FFF9FA); + border-radius: 20px; + border: 3px solid #FF9EBC; + } + """) + main_layout.addWidget(card) + + # 卡片布局 + card_layout = QVBoxLayout(card) + card_layout.setContentsMargins(30, 25, 30, 25) + card_layout.setSpacing(0) + + # 顶部弹性空间 + card_layout.addStretch(1) + + # 标题区域 + title_frame = QFrame() + title_frame.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) + title_frame.setStyleSheet("background: transparent; border: none;") + title_layout = QVBoxLayout(title_frame) + title_layout.setSpacing(8) + + # 装饰性emoji + emoji_label = QLabel("🔐✨🎮") + emoji_label.setStyleSheet(""" + QLabel { + font: bold 18pt 'Arial'; + color: #FF6B9C; + background: transparent; + qproperty-alignment: AlignCenter; + } + """) + emoji_label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) + title_layout.addWidget(emoji_label) + + # 主标题 + title_label = QLabel("用户登录") + title_label.setStyleSheet(""" + QLabel { + font: bold 22pt '微软雅黑'; + color: #FF6B9C; + background: transparent; + qproperty-alignment: AlignCenter; + } + """) + title_label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) + title_layout.addWidget(title_label) + + subtitle_label = QLabel("🌟 欢迎回到数学冒险岛 🌟") + subtitle_label.setStyleSheet(""" + QLabel { + font: 12pt '微软雅黑'; + color: #5A5A5A; + background: transparent; + qproperty-alignment: AlignCenter; + } + """) + subtitle_label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) + title_layout.addWidget(subtitle_label) + + card_layout.addWidget(title_frame) + card_layout.addSpacing(30) + + # 输入区域 + input_frame = QFrame() + input_frame.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) + input_frame.setStyleSheet("background: transparent; border: none;") + input_layout = QVBoxLayout(input_frame) + input_layout.setSpacing(20) + + # 用户名区域 + username_layout = QVBoxLayout() + username_layout.setSpacing(5) + + username_label = QLabel("👤 用户名:") + username_label.setStyleSheet(""" + QLabel { + font: bold 12pt '微软雅黑'; + color: #FF6B9C; + background: transparent; + } + """) + username_label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) + username_layout.addWidget(username_label) + + self.username_input = QLineEdit() + self.username_input.setMinimumHeight(40) + self.username_input.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) + self.username_input.setStyleSheet(""" + QLineEdit { + background: white; + border: 2px solid #FF9EBC; + border-radius: 15px; + font: 12pt '微软雅黑'; + color: #FF6B9C; + padding: 8px 15px; + selection-background-color: #FFE4EC; + } + QLineEdit:focus { + border: 2px solid #FF6B9C; + background: #FFF9FA; + } + QLineEdit::placeholder { + color: #CCCCCC; + font: 11pt '微软雅黑'; + } + """) + self.username_input.setPlaceholderText("请输入用户名...") + username_layout.addWidget(self.username_input) + + input_layout.addLayout(username_layout) + + # 密码区域 + password_layout = QVBoxLayout() + password_layout.setSpacing(5) + + password_label = QLabel("🔒 密码:") + password_label.setStyleSheet(""" + QLabel { + font: bold 12pt '微软雅黑'; + color: #FF6B9C; + background: transparent; + } + """) + password_label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) + password_layout.addWidget(password_label) + + self.password_input = QLineEdit() + self.password_input.setMinimumHeight(40) + self.password_input.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) + self.password_input.setStyleSheet(""" + QLineEdit { + background: white; + border: 2px solid #FF9EBC; + border-radius: 15px; + font: 12pt '微软雅黑'; + color: #FF6B9C; + padding: 8px 15px; + selection-background-color: #FFE4EC; + } + QLineEdit:focus { + border: 2px solid #FF6B9C; + background: #FFF9FA; + } + QLineEdit::placeholder { + color: #CCCCCC; + font: 11pt '微软雅黑'; + } + """) + self.password_input.setEchoMode(QLineEdit.Password) + self.password_input.setPlaceholderText("请输入密码...") + password_layout.addWidget(self.password_input) + + input_layout.addLayout(password_layout) + + card_layout.addWidget(input_frame) + card_layout.addSpacing(25) + + # 按钮区域 + button_frame = QFrame() + button_frame.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) + button_frame.setStyleSheet("background: transparent; border: none;") + button_layout = QVBoxLayout(button_frame) + button_layout.setSpacing(12) + + # 登录按钮 + self.login_btn = QPushButton("🚀 开始冒险") + self.login_btn.setMinimumHeight(45) + self.login_btn.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) + self.login_btn.setStyleSheet(""" + QPushButton { + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #FF9EBC, stop:1 #FF6B9C); + color: white; + font: bold 14pt '微软雅黑'; + border-radius: 20px; + border: 2px solid #FF85A1; + max-width: 300px; + } + QPushButton:hover { + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #FF85A1, stop:1 #FF5784); + border: 2px solid #FF6B9C; + } + QPushButton:pressed { + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #FF5784, stop:1 #FF3D6D); + } + """) + self.login_btn.clicked.connect(self.do_login) + button_layout.addWidget(self.login_btn, alignment=Qt.AlignCenter) + + # 修改密码按钮 + self.change_pwd_btn = QPushButton("🔑 修改密码") + self.change_pwd_btn.setMinimumHeight(40) + self.change_pwd_btn.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) + self.change_pwd_btn.setStyleSheet(""" + QPushButton { + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #A0E7E5, stop:1 #6CD6D3); + color: white; + font: bold 12pt '微软雅黑'; + border-radius: 18px; + border: 2px solid #8ADBD9; + max-width: 280px; + } + QPushButton:hover { + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #8ADBD9, stop:1 #5AC7C4); + border: 2px solid #6CD6D3; + } + QPushButton:pressed { + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #5AC7C4, stop:1 #4BB5B2); + } + """) + self.change_pwd_btn.clicked.connect(self.show_change_pwd) + button_layout.addWidget(self.change_pwd_btn, alignment=Qt.AlignCenter) + + card_layout.addWidget(button_frame) + card_layout.addStretch(2) + + # 装饰性底部 + decoration_label = QLabel("✨🌈🎯 数学冒险岛 🌟🎮🚀") + decoration_label.setStyleSheet(""" + QLabel { + font: bold 10pt 'Arial'; + color: #FF9EBC; + background: transparent; + qproperty-alignment: AlignCenter; + } + """) + decoration_label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) + card_layout.addWidget(decoration_label) + + # 绑定回车键 + self.username_input.returnPressed.connect(self.do_login) + self.password_input.returnPressed.connect(self.do_login) + + # 设置焦点 + self.username_input.setFocus() + + def go_back(self): + """返回上一级页面""" + if self.parent_window: + self.parent_window.show_main_page() # 返回欢迎页面 + + def do_login(self): + """执行登录""" + username = self.username_input.text().strip() + password = self.password_input.text() + + if not username: + QMessageBox.warning(self, "⚠️ 提示", "请输入用户名") + self.username_input.setFocus() + return + + if not password: + QMessageBox.warning(self, "⚠️ 提示", "请输入密码") + self.password_input.setFocus() + return + + if self.user_system.login(username, password): + QMessageBox.information(self, "🎉 登录成功", f"欢迎 {username} 回到数学冒险岛!") + # 不再使用 self.accept(),而是通知父窗口切换页面 + if self.parent_window: + self.parent_window.show_level_page() + else: + QMessageBox.warning(self, "❌ 登录失败", "用户名或密码错误,请重试") + self.password_input.clear() + self.password_input.setFocus() + + def show_change_pwd(self): + """显示修改密码界面""" + from .login_ui import ChangePasswordUI + change_pwd_ui = ChangePasswordUI(self) + change_pwd_ui.exec_() # 修改密码还是用弹窗,因为涉及敏感操作 + + def showEvent(self, event): + """显示页面时清空输入框""" + super().showEvent(event) + self.username_input.clear() + self.password_input.clear() + self.username_input.setFocus() + + +class ChangePasswordUI(QDialog): # 这个保持为 QDialog,因为是敏感操作 + def __init__(self, parent=None): + super().__init__(parent) + self.parent_window = parent + self.user_system = parent.user_system if parent else None + self.setup_ui() + + def setup_ui(self): + self.setWindowTitle("🔑 修改密码 - 数学冒险岛 🔑") + self.setMinimumSize(450, 550) + + # 设置可爱的渐变背景 + self.setStyleSheet(""" + QDialog { + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #FFD1DC, stop:1 #B5EAD7); + } + """) + + # 主布局 + main_layout = QVBoxLayout(self) + main_layout.setContentsMargins(20, 20, 20, 20) + main_layout.setSpacing(0) + + # 卡片容器 - 自适应尺寸 + card = QFrame() + card.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) + card.setStyleSheet(""" + QFrame { + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 white, stop:1 #FFF9FA); + border-radius: 20px; + border: 3px solid #FF9EBC; + } + """) + main_layout.addWidget(card) + + # 卡片布局 + card_layout = QVBoxLayout(card) + card_layout.setContentsMargins(30, 25, 30, 25) + card_layout.setSpacing(0) + + # 顶部弹性空间 + card_layout.addStretch(1) + + # 标题区域 + title_frame = QFrame() + title_frame.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) + title_frame.setStyleSheet("background: transparent; border: none;") + title_layout = QVBoxLayout(title_frame) + title_layout.setSpacing(8) + + # 装饰性emoji + emoji_label = QLabel("🔑✨🛡️") + emoji_label.setStyleSheet(""" + QLabel { + font: bold 18pt 'Arial'; + color: #FF6B9C; + background: transparent; + qproperty-alignment: AlignCenter; + } + """) + emoji_label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) + title_layout.addWidget(emoji_label) + + # 主标题 + title_label = QLabel("修改密码") + title_label.setStyleSheet(""" + QLabel { + font: bold 22pt '微软雅黑'; + color: #FF6B9C; + background: transparent; + qproperty-alignment: AlignCenter; + } + """) + title_label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) + title_layout.addWidget(title_label) + + subtitle_label = QLabel("🔒 保护你的冒险账户安全 🔒") + subtitle_label.setStyleSheet(""" + QLabel { + font: 12pt '微软雅黑'; + color: #5A5A5A; + background: transparent; + qproperty-alignment: AlignCenter; + } + """) + subtitle_label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) + title_layout.addWidget(subtitle_label) + + card_layout.addWidget(title_frame) + card_layout.addSpacing(30) + + # 输入区域 + input_frame = QFrame() + input_frame.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) + input_frame.setStyleSheet("background: transparent; border: none;") + input_layout = QVBoxLayout(input_frame) + input_layout.setSpacing(20) + + # 原密码 + old_pwd_layout = QVBoxLayout() + old_pwd_layout.setSpacing(5) + + old_pwd_label = QLabel("🔓 原密码:") + old_pwd_label.setStyleSheet(""" + QLabel { + font: bold 12pt '微软雅黑'; + color: #FF6B9C; + background: transparent; + } + """) + old_pwd_label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) + old_pwd_layout.addWidget(old_pwd_label) + + self.old_pwd_input = QLineEdit() + self.old_pwd_input.setMinimumHeight(38) + self.old_pwd_input.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) + self.old_pwd_input.setStyleSheet(""" + QLineEdit { + background: white; + border: 2px solid #FF9EBC; + border-radius: 15px; + font: 12pt '微软雅黑'; + color: #FF6B9C; + padding: 8px 15px; + selection-background-color: #FFE4EC; + } + QLineEdit:focus { + border: 2px solid #FF6B9C; + background: #FFF9FA; + } + """) + self.old_pwd_input.setEchoMode(QLineEdit.Password) + self.old_pwd_input.setPlaceholderText("请输入原密码...") + old_pwd_layout.addWidget(self.old_pwd_input) + + input_layout.addLayout(old_pwd_layout) + + # 新密码 + new_pwd_layout = QVBoxLayout() + new_pwd_layout.setSpacing(5) + + new_pwd_label = QLabel("🆕 新密码:") + new_pwd_label.setStyleSheet(""" + QLabel { + font: bold 12pt '微软雅黑'; + color: #FF6B9C; + background: transparent; + } + """) + new_pwd_label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) + new_pwd_layout.addWidget(new_pwd_label) + + self.new_pwd_input = QLineEdit() + self.new_pwd_input.setMinimumHeight(38) + self.new_pwd_input.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) + self.new_pwd_input.setStyleSheet(""" + QLineEdit { + background: white; + border: 2px solid #FF9EBC; + border-radius: 15px; + font: 12pt '微软雅黑'; + color: #FF6B9C; + padding: 8px 15px; + selection-background-color: #FFE4EC; + } + QLineEdit:focus { + border: 2px solid #FF6B9C; + background: #FFF9FA; + } + """) + self.new_pwd_input.setEchoMode(QLineEdit.Password) + self.new_pwd_input.setPlaceholderText("请输入新密码...") + new_pwd_layout.addWidget(self.new_pwd_input) + + input_layout.addLayout(new_pwd_layout) + + # 确认新密码 + confirm_pwd_layout = QVBoxLayout() + confirm_pwd_layout.setSpacing(5) + + confirm_pwd_label = QLabel("✅ 确认新密码:") + confirm_pwd_label.setStyleSheet(""" + QLabel { + font: bold 12pt '微软雅黑'; + color: #FF6B9C; + background: transparent; + } + """) + confirm_pwd_label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) + confirm_pwd_layout.addWidget(confirm_pwd_label) + + self.confirm_pwd_input = QLineEdit() + self.confirm_pwd_input.setMinimumHeight(38) + self.confirm_pwd_input.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) + self.confirm_pwd_input.setStyleSheet(""" + QLineEdit { + background: white; + border: 2px solid #FF9EBC; + border-radius: 15px; + font: 12pt '微软雅黑'; + color: #FF6B9C; + padding: 8px 15px; + selection-background-color: #FFE4EC; + } + QLineEdit:focus { + border: 2px solid #FF6B9C; + background: #FFF9FA; + } + """) + self.confirm_pwd_input.setEchoMode(QLineEdit.Password) + self.confirm_pwd_input.setPlaceholderText("请再次输入新密码...") + confirm_pwd_layout.addWidget(self.confirm_pwd_input) + + input_layout.addLayout(confirm_pwd_layout) + + card_layout.addWidget(input_frame) + card_layout.addSpacing(15) + + # 密码提示 + hint_label = QLabel("📝 密码要求:6-10位,必须包含大小写字母和数字") + hint_label.setStyleSheet(""" + QLabel { + font: 9pt '微软雅黑'; + color: #FF9EBC; + background: transparent; + qproperty-alignment: AlignCenter; + } + """) + hint_label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) + card_layout.addWidget(hint_label) + card_layout.addSpacing(25) + + # 确认按钮 + button_frame = QFrame() + button_frame.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) + button_frame.setStyleSheet("background: transparent; border: none;") + button_layout = QVBoxLayout(button_frame) + + self.confirm_btn = QPushButton("✨ 确认修改") + self.confirm_btn.setMinimumHeight(45) + self.confirm_btn.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) + self.confirm_btn.setStyleSheet(""" + QPushButton { + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #B5EAD7, stop:1 #8CD9B3); + color: white; + font: bold 14pt '微软雅黑'; + border-radius: 20px; + border: 2px solid #A0E7E5; + max-width: 300px; + } + QPushButton:hover { + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #8CD9B3, stop:1 #6CD6D3); + border: 2px solid #8CD9B3; + } + QPushButton:pressed { + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #6CD6D3, stop:1 #5AC7C4); + } + """) + self.confirm_btn.clicked.connect(self.change_password) + button_layout.addWidget(self.confirm_btn, alignment=Qt.AlignCenter) + + card_layout.addWidget(button_frame) + card_layout.addStretch(2) + + # 装饰性底部 + decoration_label = QLabel("🔐🌟🛡️ 账户安全最重要 🌈✨🎯") + decoration_label.setStyleSheet(""" + QLabel { + font: bold 10pt 'Arial'; + color: #FF9EBC; + background: transparent; + qproperty-alignment: AlignCenter; + } + """) + decoration_label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) + card_layout.addWidget(decoration_label) + + # 绑定回车键 + self.old_pwd_input.returnPressed.connect(self.change_password) + self.new_pwd_input.returnPressed.connect(self.change_password) + self.confirm_pwd_input.returnPressed.connect(self.change_password) + + # 设置焦点 + self.old_pwd_input.setFocus() + + def change_password(self): + old_password = self.old_pwd_input.text() + new_password = self.new_pwd_input.text() + confirm_password = self.confirm_pwd_input.text() + + if not old_password or not new_password or not confirm_password: + QMessageBox.warning(self, "⚠️ 提示", "请填写完整信息") + return + + if new_password != confirm_password: + QMessageBox.warning(self, "⚠️ 提示", "两次输入的新密码不一致") + self.new_pwd_input.clear() + self.confirm_pwd_input.clear() + self.new_pwd_input.setFocus() + return + + # 检查是否已登录 + if not self.user_system.current_user: + QMessageBox.warning(self, "⚠️ 提示", "请先登录后再修改密码") + self.close() + return + + if self.user_system.change_password(old_password, new_password): + QMessageBox.information(self, "🎉 修改成功", "密码修改成功!") + self.accept() + else: + QMessageBox.warning(self, "❌ 修改失败", "原密码错误或新密码不符合要求") + self.old_pwd_input.clear() + self.new_pwd_input.clear() + self.confirm_pwd_input.clear() + self.old_pwd_input.setFocus() \ No newline at end of file -- 2.34.1 From 63fcd0def4afefe836b3cf96d1a639d0ecd64bd8 Mon Sep 17 00:00:00 2001 From: hnu202326010330 <168584091@qq.com> Date: Sun, 12 Oct 2025 20:22:00 +0800 Subject: [PATCH 2/6] ADD file via upload --- src/ui/main_window.py | 764 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 764 insertions(+) create mode 100644 src/ui/main_window.py diff --git a/src/ui/main_window.py b/src/ui/main_window.py new file mode 100644 index 0000000..d703ec6 --- /dev/null +++ b/src/ui/main_window.py @@ -0,0 +1,764 @@ +import sys +from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, + QHBoxLayout, QLabel, QPushButton, QLineEdit, + QMessageBox, QFrame, QGridLayout, QSizePolicy, QStackedWidget) +from PyQt5.QtCore import Qt +from PyQt5.QtGui import QFont, QPalette, QColor + +# 导入各个页面(需要先修改这些类继承QWidget) +from .login_ui import LoginPage +from .register_ui import RegisterPage +from .question_ui import QuestionPage +from .result_ui import ResultPage + + +class MainWindow(QMainWindow): + def __init__(self,user_system): + super().__init__() + self.user_system = user_system + self.menu_bar = None + self.current_level = None + self.question_count = None + + + # 创建堆叠窗口 + self.stacked_widget = QStackedWidget() + + self.init_ui() + + def init_ui(self): + """初始化主窗口界面""" + self.setWindowTitle("🎮 数学冒险岛 🎮") + # self.setMinimumSize(900, 650) + # 设置固定大小(例如 900×650) + # self.setFixedSize(900, 1200) + # 获取字体高度来设置相对大小 + font_metrics = self.fontMetrics() + char_height = font_metrics.height() + + # 基于字符高度设置尺寸 + self.setFixedSize(40 * char_height, 55 * char_height) + + # 设置可爱的渐变背景色 + palette = self.palette() + palette.setColor(QPalette.Window, QColor(255, 240, 245)) + self.setPalette(palette) + + # 设置中央部件为堆叠窗口 + self.setCentralWidget(self.stacked_widget) + + # 初始化各个页面 + self.init_pages() + + # 显示主页面 + self.show_main_page() + + def init_pages(self): + """初始化所有页面""" + # 主页面 + self.main_page = self.create_main_page() + self.stacked_widget.addWidget(self.main_page) + + # 登录页面 + self.login_page = LoginPage(self) + self.stacked_widget.addWidget(self.login_page) + + # 注册页面 + self.register_page = RegisterPage(self) + self.stacked_widget.addWidget(self.register_page) + + # 学段选择页面 + self.level_page = self.create_level_page() + self.stacked_widget.addWidget(self.level_page) + + # 题目数量页面 + self.count_page = self.create_count_page() + self.stacked_widget.addWidget(self.count_page) + + def show_main_page(self): + """显示主页面""" + self.stacked_widget.setCurrentWidget(self.main_page) + self.clear_menu_bar() + + def show_login_page(self): + """显示登录页面""" + self.stacked_widget.setCurrentWidget(self.login_page) + self.clear_menu_bar() + + def show_register_page(self): + """显示注册页面""" + self.stacked_widget.setCurrentWidget(self.register_page) + self.clear_menu_bar() + + def show_level_page(self): + """显示学段选择页面""" + if not self.user_system or not self.user_system.current_user: + QMessageBox.warning(self, "提示", "请先登录") + return + self.stacked_widget.setCurrentWidget(self.level_page) + self.create_user_menu() + + def show_count_page(self): + """显示题目数量输入页面""" + if not self.user_system or not self.user_system.current_user: + QMessageBox.warning(self, "提示", "请先登录") + return + self.update_count_page(self.current_level) + self.stacked_widget.setCurrentWidget(self.count_page) + + def show_question_page(self, level: str, count: int): + try: + # ✅ 每次创建新页面前,清理旧的 QuestionPage(如果有) + for i in reversed(range(self.stacked_widget.count())): + widget = self.stacked_widget.widget(i) + if isinstance(widget, QuestionPage): + self.stacked_widget.removeWidget(widget) + widget.deleteLater() # 释放内存 + + # ✅ 再创建新页面 + question_page = QuestionPage(self, level, count) + self.stacked_widget.addWidget(question_page) + self.stacked_widget.setCurrentWidget(question_page) + + except Exception as e: + QMessageBox.critical(self, "❌ 程序错误", f"生成题目时发生错误:\n{str(e)}") + print(f"[ERROR] 题目生成失败: {e}") + try: + question_page = QuestionPage(self, level, count) + self.stacked_widget.addWidget(question_page) + self.stacked_widget.setCurrentWidget(question_page) + except Exception as e: + QMessageBox.critical(self, "❌ 程序错误", f"生成题目时发生错误:\n{str(e)}") + print(f"[ERROR] 题目生成失败: {e}") + + def show_result_page(self, score: int, level: str, count: int): + """显示结果页面""" + result_page = ResultPage(self, score, level, count) + self.stacked_widget.addWidget(result_page) + self.stacked_widget.setCurrentWidget(result_page) + + def remove_current_page(self): + """移除当前页面(用于答题和结果页面)""" + current_index = self.stacked_widget.currentIndex() + # 只移除动态添加的页面(索引大于固定页面数量) + if current_index >= 5: # 主页面、登录、注册、学段、题目数量 + current_widget = self.stacked_widget.currentWidget() + self.stacked_widget.removeWidget(current_widget) + + def create_main_page(self): + """创建主页面""" + widget = QWidget() + + # 主布局 - 使用弹性布局 + main_layout = QVBoxLayout(widget) + main_layout.setContentsMargins(30, 20, 30, 20) + main_layout.setSpacing(0) + + # 主容器框架 - 自适应尺寸 + container = QFrame() + container.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) + container.setStyleSheet(""" + QFrame { + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #FFD1DC, stop:1 #B5EAD7); + border-radius: 20px; + border: 3px solid #FF9EBC; + } + """) + main_layout.addWidget(container) + + # 容器布局 - 使用弹性布局 + container_layout = QVBoxLayout(container) + container_layout.setContentsMargins(40, 30, 40, 30) + container_layout.setSpacing(0) + + # 顶部弹性空间 + container_layout.addStretch(1) + + # --- 标题区域 --- + title_frame = QFrame() + title_frame.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) + title_frame.setStyleSheet("background: transparent; border: none;") + title_layout = QVBoxLayout(title_frame) + title_layout.setSpacing(10) + + # 装饰性emoji + emoji_label = QLabel("✨🎓🧮🌟") + emoji_label.setStyleSheet(""" + QLabel { + font: bold 20pt 'Arial'; + color: #FF6B9C; + background: transparent; + qproperty-alignment: AlignCenter; + } + """) + title_layout.addWidget(emoji_label) + + # 主标题 + title_label = QLabel("数学冒险岛") + title_label.setStyleSheet(""" + QLabel { + font: bold 28pt '微软雅黑'; + color: #FF6B9C; + background: transparent; + qproperty-alignment: AlignCenter; + } + """) + title_layout.addWidget(title_label) + + # 副标题 + subtitle_label = QLabel("🚀 开启你的数学冒险之旅! 🚀") + subtitle_label.setStyleSheet(""" + QLabel { + font: 14pt '微软雅黑'; + color: #5A5A5A; + background: transparent; + qproperty-alignment: AlignCenter; + } + """) + title_layout.addWidget(subtitle_label) + + container_layout.addWidget(title_frame) + container_layout.addSpacing(40) + + # --- 按钮区域 --- + button_frame = QFrame() + button_frame.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) + button_frame.setStyleSheet("background: transparent; border: none;") + button_layout = QVBoxLayout(button_frame) + button_layout.setSpacing(20) + + # 登录按钮 + login_btn = QPushButton("🎮 开始冒险") + login_btn.setMinimumSize(250, 60) + login_btn.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) + login_btn.setStyleSheet(""" + QPushButton { + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #FF9EBC, stop:1 #FF6B9C); + color: white; + font: bold 16pt '微软雅黑'; + border-radius: 30px; + border: 3px solid #FF85A1; + max-width: 300px; + } + QPushButton:hover { + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #FF85A1, stop:1 #FF5784); + border: 3px solid #FF6B9C; + } + QPushButton:pressed { + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #FF5784, stop:1 #FF3D6D); + } + """) + login_btn.clicked.connect(self.show_login_page) # 改为页面切换 + button_layout.addWidget(login_btn, alignment=Qt.AlignCenter) + + # 注册按钮 + register_btn = QPushButton("📝 注册账号") + register_btn.setMinimumSize(250, 60) + register_btn.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) + register_btn.setStyleSheet(""" + QPushButton { + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #A0E7E5, stop:1 #6CD6D3); + color: white; + font: bold 16pt '微软雅黑'; + border-radius: 30px; + border: 3px solid #8ADBD9; + max-width: 300px; + } + QPushButton:hover { + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #8ADBD9, stop:1 #5AC7C4); + border: 3px solid #6CD6D3; + } + QPushButton:pressed { + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #5AC7C4, stop:1 #4BB5B2); + } + """) + register_btn.clicked.connect(self.show_register_page) # 改为页面切换 + button_layout.addWidget(register_btn, alignment=Qt.AlignCenter) + + container_layout.addWidget(button_frame) + container_layout.addStretch(2) + + # --- 装饰性元素 --- + decoration_frame = QFrame() + decoration_frame.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) + decoration_frame.setStyleSheet("background: transparent; border: none;") + decoration_layout = QHBoxLayout(decoration_frame) + + math_symbols = QLabel("🔢 ➕ ➖ ✖️ ➗ 📐 📊 🧮") + math_symbols.setStyleSheet(""" + QLabel { + font: bold 16pt 'Arial'; + color: #FF9EBC; + background: transparent; + qproperty-alignment: AlignCenter; + } + """) + decoration_layout.addWidget(math_symbols) + + container_layout.addWidget(decoration_frame) + container_layout.addSpacing(20) + + # --- 底部信息 --- + footer_frame = QFrame() + footer_frame.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) + footer_frame.setStyleSheet("background: transparent; border: none;") + footer_layout = QHBoxLayout(footer_frame) + + footer_label = QLabel("🌈 版权所有 © 2025 数学冒险岛 🌈") + footer_label.setStyleSheet(""" + QLabel { + font: 10pt '微软雅黑'; + color: #888888; + background: transparent; + qproperty-alignment: AlignCenter; + } + """) + footer_layout.addWidget(footer_label) + + container_layout.addWidget(footer_frame) + + return widget + + def create_level_page(self): + """创建学段选择页面""" + widget = QWidget() + + # 主布局 + main_layout = QVBoxLayout(widget) + main_layout.setContentsMargins(30, 20, 30, 20) + main_layout.setSpacing(0) + + # 主容器 + frame = QFrame() + frame.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) + frame.setStyleSheet(""" + QFrame { + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #FFD1DC, stop:1 #B5EAD7); + border-radius: 20px; + border: 3px solid #FF9EBC; + } + """) + main_layout.addWidget(frame) + + frame_layout = QVBoxLayout(frame) + frame_layout.setContentsMargins(40, 30, 40, 30) + frame_layout.setSpacing(0) + + # 顶部空间 + frame_layout.addStretch(1) + + # 欢迎信息 + welcome_text = f"🎉 欢迎回来! 🎉" + self.welcome_label = QLabel(welcome_text) + self.welcome_label.setStyleSheet(""" + QLabel { + font: bold 18pt '微软雅黑'; + color: #FF6B9C; + background: transparent; + qproperty-alignment: AlignCenter; + } + """) + self.welcome_label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) + frame_layout.addWidget(self.welcome_label) + + frame_layout.addSpacing(40) + + # 学段选择标题 + select_label = QLabel("🎯 选择你的冒险地图 🎯") + select_label.setStyleSheet(""" + QLabel { + font: bold 20pt '微软雅黑'; + color: #5A5A5A; + background: transparent; + qproperty-alignment: AlignCenter; + } + """) + select_label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) + frame_layout.addWidget(select_label) + + frame_layout.addSpacing(40) + + # 按钮区域 + btn_frame = QFrame() + btn_frame.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) + btn_frame.setStyleSheet("background: transparent; border: none;") + btn_layout = QGridLayout(btn_frame) + btn_layout.setSpacing(20) + btn_layout.setVerticalSpacing(25) + + levels = [("🏫 小学乐园", "primary"), ("🏰 初中城堡", "middle"), ("🚀 高中太空", "high")] + colors = [ + ("#FF9EBC", "#FF6B9C"), # 粉色 + ("#A0E7E5", "#6CD6D3"), # 青色 + ("#B5EAD7", "#8CD9B3") # 绿色 + ] + + for i, (text, level) in enumerate(levels): + color_pair = colors[i % len(colors)] + btn = QPushButton(text) + btn.setMinimumSize(280, 70) + btn.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) + btn.setStyleSheet(f""" + QPushButton {{ + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 {color_pair[0]}, stop:1 {color_pair[1]}); + color: white; + font: bold 18pt '微软雅黑'; + border-radius: 35px; + border: 3px solid {color_pair[0]}; + max-width: 320px; + }} + QPushButton:hover {{ + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 {color_pair[1]}, stop:1 {color_pair[0]}); + }} + QPushButton:pressed {{ + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #555555, stop:1 {color_pair[1]}); + }} + """) + btn.clicked.connect(lambda checked, l=level: self.on_level_selected(l)) + btn_layout.addWidget(btn, i, 0, alignment=Qt.AlignCenter) + + frame_layout.addWidget(btn_frame) + frame_layout.addStretch(1) + + # 功能按钮区域 + func_frame = QFrame() + func_frame.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) + func_frame.setStyleSheet("background: transparent; border: none;") + func_layout = QHBoxLayout(func_frame) + func_layout.setSpacing(20) + + # 修改密码按钮 + change_pwd_btn = QPushButton("🔑 修改密码") + change_pwd_btn.setMinimumSize(180, 50) + change_pwd_btn.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) + change_pwd_btn.setStyleSheet(""" + QPushButton { + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #FFDAC1, stop:1 #FFB347); + color: white; + font: bold 14pt '微软雅黑'; + border-radius: 25px; + border: 3px solid #FFB347; + max-width: 200px; + } + QPushButton:hover { + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #FFB347, stop:1 #FF9800); + } + """) + change_pwd_btn.clicked.connect(self.open_change_password) + func_layout.addWidget(change_pwd_btn) + + # 返回上级按钮 + back_btn = QPushButton("🔙 返回主页") + back_btn.setMinimumSize(180, 50) + back_btn.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) + back_btn.setStyleSheet(""" + QPushButton { + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #C7CEEA, stop:1 #9FA8DA); + color: white; + font: bold 14pt '微软雅黑'; + border-radius: 25px; + border: 3px solid #9FA8DA; + max-width: 200px; + } + QPushButton:hover { + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #9FA8DA, stop:1 #7986CB); + } + """) + back_btn.clicked.connect(self.show_main_page) # 改为页面切换 + func_layout.addWidget(back_btn) + + frame_layout.addWidget(func_frame, alignment=Qt.AlignCenter) + frame_layout.addStretch(1) + + return widget + + def create_count_page(self): + """创建题目数量页面""" + widget = QWidget() + + # 主布局 + main_layout = QVBoxLayout(widget) + main_layout.setContentsMargins(30, 20, 30, 20) + main_layout.setSpacing(0) + + # 主容器 + frame = QFrame() + frame.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) + frame.setStyleSheet(""" + QFrame { + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #FFD1DC, stop:1 #B5EAD7); + border-radius: 20px; + border: 3px solid #FF9EBC; + } + """) + main_layout.addWidget(frame) + + frame_layout = QVBoxLayout(frame) + frame_layout.setContentsMargins(40, 30, 40, 30) + frame_layout.setSpacing(0) + + # 顶部空间 + frame_layout.addStretch(1) + + # 显示当前学段 + self.level_label = QLabel() + self.level_label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) + self.level_label.setStyleSheet(""" + QLabel { + font: bold 16pt '微软雅黑'; + color: #FF6B9C; + background: transparent; + qproperty-alignment: AlignCenter; + } + """) + frame_layout.addWidget(self.level_label) + + frame_layout.addSpacing(30) + + # 输入提示 + count_label = QLabel("🎯 请输入题目数量(10-30)") + count_label.setStyleSheet(""" + QLabel { + font: bold 18pt '微软雅黑'; + color: #5A5A5A; + background: transparent; + qproperty-alignment: AlignCenter; + } + """) + count_label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) + frame_layout.addWidget(count_label) + + # 装饰性emoji + emoji_label = QLabel("🔢 ✨ 📚 💫") + emoji_label.setStyleSheet(""" + QLabel { + font: bold 16pt 'Arial'; + color: #FF6B9C; + background: transparent; + qproperty-alignment: AlignCenter; + } + """) + emoji_label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) + frame_layout.addWidget(emoji_label) + + frame_layout.addSpacing(30) + + # 输入框 + self.count_input = QLineEdit() + self.count_input.setFont(QFont("微软雅黑", 14)) + self.count_input.setMinimumSize(200, 50) + self.count_input.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) + self.count_input.setAlignment(Qt.AlignCenter) + self.count_input.setStyleSheet(""" + QLineEdit { + background: white; + border: 3px solid #FF9EBC; + border-radius: 20px; + font: bold 14pt '微软雅黑'; + color: #FF6B9C; + padding: 5px; + selection-background-color: #FFE4EC; + } + QLineEdit:focus { + border: 3px solid #FF6B9C; + background: #FFF9FA; + } + """) + frame_layout.addWidget(self.count_input, alignment=Qt.AlignCenter) + + frame_layout.addSpacing(40) + + # 按钮区域 + btn_frame = QFrame() + btn_frame.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) + btn_frame.setStyleSheet("background: transparent; border: none;") + btn_layout = QHBoxLayout(btn_frame) + btn_layout.setSpacing(30) + + # 开始答题按钮 + start_btn = QPushButton("🚀 开始冒险") + start_btn.setMinimumSize(210, 60) + start_btn.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) + start_btn.setStyleSheet(""" + QPushButton { + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #FF9EBC, stop:1 #FF6B9C); + color: white; + font: bold 14pt '微软雅黑'; + border-radius: 30px; + border: 3px solid #FF85A1; + max-width: 220px; + } + QPushButton:hover { + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #FF85A1, stop:1 #FF5784); + } + QPushButton:pressed { + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #FF5784, stop:1 #FF3D6D); + } + """) + start_btn.clicked.connect(self.start_question) + btn_layout.addWidget(start_btn) + + # 返回按钮 + back_btn = QPushButton("🔙 返回选择") + back_btn.setMinimumSize(210, 60) + back_btn.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) + back_btn.setStyleSheet(""" + QPushButton { + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #C7CEEA, stop:1 #9FA8DA); + color: white; + font: bold 14pt '微软雅黑'; + border-radius: 30px; + border: 3px solid #9FA8DA; + max-width: 220px; + } + QPushButton:hover { + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #9FA8DA, stop:1 #7986CB); + } + """) + back_btn.clicked.connect(self.show_level_page) # 改为页面切换 + btn_layout.addWidget(back_btn) + + frame_layout.addWidget(btn_frame, alignment=Qt.AlignCenter) + frame_layout.addStretch(2) + + return widget + + def update_level_page(self): + """更新学段选择页面的欢迎信息""" + if self.user_system and self.user_system.current_user: + welcome_text = f"🎉 欢迎回来,{self.user_system.current_user}! 🎉" + self.welcome_label.setText(welcome_text) + + def update_count_page(self, level: str): + """更新题目数量页面的学段信息""" + level_text = {"primary": "🏫 小学乐园", "middle": "🏰 初中城堡", "high": "🚀 高中太空"}.get(level, level) + self.level_label.setText(f"🗺️ 当前地图:{level_text}") + self.count_input.clear() + self.count_input.setFocus() + + # 修改原有方法 + def open_login(self): + """打开登录界面 - 改为页面切换""" + self.show_login_page() + + def open_register(self): + """打开注册界面 - 改为页面切换""" + self.show_register_page() + + def on_level_selected(self, level: str): + """学段选择后进入题目数量输入""" + if self.user_system: + self.user_system.set_level(level) + self.current_level = level + self.update_count_page(level) + self.show_count_page() + + def start_question(self): + """开始答题""" + try: + count = int(self.count_input.text()) + if 10 <= count <= 30: + self.question_count = count + self.show_question_page(self.current_level, count) + else: + QMessageBox.warning(self, "⚠️ 提示", "请输入10-30之间的数字哦!") + except ValueError: + QMessageBox.warning(self, "⚠️ 提示", "请输入有效的数字!") + + # 其他方法保持不变... + def create_user_menu(self): + """创建用户菜单栏""" + if self.menu_bar: + self.menu_bar.clear() + else: + self.menu_bar = self.menuBar() + self.menu_bar.setStyleSheet(""" + QMenuBar { + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #FFD1DC, stop:1 #B5EAD7); + color: #FF6B9C; + font: bold 12pt '微软雅黑'; + border-bottom: 2px solid #FF9EBC; + } + QMenuBar::item { + background: transparent; + padding: 5px 10px; + } + QMenuBar::item:selected { + background: #FF9EBC; + border-radius: 10px; + } + """) + + # 用户菜单 + user_menu = self.menu_bar.addMenu(f"🎮 欢迎(点这里哦),{self.user_system.current_user}") + user_menu.setStyleSheet(""" + QMenu { + background: white; + border: 2px solid #FF9EBC; + border-radius: 15px; + } + QMenu::item { + padding: 8px 20px; + font: 11pt '微软雅黑'; + } + QMenu::item:selected { + background: #FFE4EC; + border-radius: 10px; + } + """) + user_menu.addAction("🔑 修改密码", self.open_change_password) + user_menu.addSeparator() + user_menu.addAction("🚪 退出登录", self.logout) + + def open_change_password(self): + """打开修改密码界面""" + if self.user_system and self.user_system.current_user: + from .login_ui import ChangePasswordUI + change_password_ui = ChangePasswordUI(self) + change_password_ui.exec_() # 这个还是弹窗,因为涉及敏感操作 + else: + QMessageBox.warning(self, "提示", "请先登录") + + def logout(self): + """退出登录""" + if self.user_system: + self.user_system.current_user = None + self.user_system.current_level = None + QMessageBox.information(self, "🎮 再见", "期待下次与你一起冒险!") + self.show_main_page() + + def clear_menu_bar(self): + """清空菜单栏""" + if self.menu_bar: + self.menu_bar.clear() + self.menu_bar = None + + +if __name__ == "__main__": + app = QApplication(sys.argv) + app.setStyle('Fusion') + window = MainWindow() + window.show() + sys.exit(app.exec_()) \ No newline at end of file -- 2.34.1 From 3cf4b9b83ec73a0a9479ec7a219f18d89abff681 Mon Sep 17 00:00:00 2001 From: hnu202326010330 <168584091@qq.com> Date: Sun, 12 Oct 2025 20:22:40 +0800 Subject: [PATCH 3/6] ADD file via upload --- src/ui/question_ui.py | 455 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 455 insertions(+) create mode 100644 src/ui/question_ui.py diff --git a/src/ui/question_ui.py b/src/ui/question_ui.py new file mode 100644 index 0000000..bdeb524 --- /dev/null +++ b/src/ui/question_ui.py @@ -0,0 +1,455 @@ +from PyQt5.QtWidgets import (QWidget, QVBoxLayout, QHBoxLayout, QLabel, + QPushButton, QMessageBox, QFrame, QRadioButton, + QButtonGroup, QScrollArea, QWidget, QProgressBar, QSizePolicy) +from PyQt5.QtCore import Qt +from PyQt5.QtGui import QFont +from .result_ui import ResultPage +from core.question_bank import QuestionBank + + +class QuestionPage(QWidget): # 改为继承 QWidget + def __init__(self, parent, level: str, count: int): + super().__init__(parent) + try: + self.parent_window = parent + self.level = level + self.count = count + self.current_idx = 0 + self.answers = [None] * count + + self.question_bank = QuestionBank() + self.paper = self.question_bank.generate_paper(level, count) + + self.setup_ui() + self.show_question() + except Exception as e: + print(f"[ERROR] QuestionPage 初始化失败: {e}") + raise e # 重新抛出,供上层捕获 + + def setup_ui(self): + """初始化界面""" + # 移除 setWindowTitle 和 setMinimumSize,使用父窗口的尺寸 + + # 设置可爱的渐变背景 + self.setStyleSheet(""" + QWidget { + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #FFD1DC, stop:1 #B5EAD7); + } + """) + + # 主布局 + main_layout = QVBoxLayout(self) + main_layout.setContentsMargins(25, 20, 25, 20) + main_layout.setSpacing(0) + + # 顶部信息区域 + top_frame = QFrame() + top_frame.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) + top_frame.setStyleSheet(""" + QFrame { + background: transparent; + border: none; + } + """) + top_layout = QVBoxLayout(top_frame) + top_layout.setSpacing(15) + + # 标题 + title_label = QLabel("🧮 数学冒险岛 - 答题挑战 🧮") + title_label.setStyleSheet(""" + QLabel { + font: bold 24pt '微软雅黑'; + color: #FF6B9C; + background: transparent; + qproperty-alignment: AlignCenter; + } + """) + title_label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) + top_layout.addWidget(title_label) + + # 进度显示 + self.progress_label = QLabel() + self.progress_label.setStyleSheet(""" + QLabel { + font: bold 16pt '微软雅黑'; + color: #5A5A5A; + background: transparent; + qproperty-alignment: AlignCenter; + } + """) + self.progress_label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) + top_layout.addWidget(self.progress_label) + + # 进度条 + self.progress_bar = QProgressBar() + self.progress_bar.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) + self.progress_bar.setFixedHeight(25) + self.progress_bar.setStyleSheet(""" + QProgressBar { + border: 3px solid #FF9EBC; + border-radius: 12px; + background-color: white; + text-align: center; + font: bold 12pt '微软雅黑'; + color: #FF6B9C; + } + QProgressBar::chunk { + background: qlineargradient(x1:0, y1:0, x2:1, y2:0, + stop:0 #FF9EBC, stop:0.5 #FF6B9C, stop:1 #FF3D6D); + border-radius: 8px; + } + """) + top_layout.addWidget(self.progress_bar) + + main_layout.addWidget(top_frame) + main_layout.addSpacing(20) + + # 题目内容框架(可滚动) + scroll_area = QScrollArea() + scroll_area.setWidgetResizable(True) + scroll_area.setStyleSheet(""" + QScrollArea { + border: none; + background: transparent; + } + QScrollBar:vertical { + background: white; + width: 15px; + margin: 0px; + } + QScrollBar::handle:vertical { + background: #FF9EBC; + border-radius: 7px; + min-height: 20px; + } + QScrollBar::handle:vertical:hover { + background: #FF6B9C; + } + """) + main_layout.addWidget(scroll_area) + + # 滚动区域的内容部件 + scroll_content = QWidget() + scroll_area.setWidget(scroll_content) + + content_layout = QVBoxLayout(scroll_content) + content_layout.setContentsMargins(0, 0, 0, 0) + + # 题目卡片 + question_card = QFrame() + question_card.setStyleSheet(""" + QFrame { + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 white, stop:1 #FFF9FA); + border-radius: 20px; + border: 3px solid #FF9EBC; + } + """) + question_layout = QVBoxLayout(question_card) + question_layout.setContentsMargins(30, 25, 30, 25) + question_layout.setSpacing(20) + + # 题干 + self.question_label = QLabel() + self.question_label.setStyleSheet(""" + QLabel { + font: bold 18pt '微软雅黑'; + color: #5A5A5A; + background: transparent; + line-height: 1.5; + } + """) + self.question_label.setWordWrap(True) + self.question_label.setAlignment(Qt.AlignLeft | Qt.AlignTop) + question_layout.addWidget(self.question_label) + + # 选项框架 + self.options_frame = QFrame() + self.options_frame.setStyleSheet(""" + QFrame { + background: transparent; + border: none; + } + """) + self.options_layout = QVBoxLayout(self.options_frame) + self.options_layout.setSpacing(12) + question_layout.addWidget(self.options_frame) + + content_layout.addWidget(question_card) + + main_layout.addSpacing(20) + + # 底部按钮框架 + button_frame = QFrame() + button_frame.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) + button_frame.setStyleSheet("background: transparent; border: none;") + button_layout = QHBoxLayout(button_frame) + button_layout.setSpacing(20) + + # 上一题按钮 + self.prev_btn = QPushButton("⬅️ 上一题") + self.prev_btn.setMinimumSize(120, 50) + self.prev_btn.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) + self.prev_btn.setStyleSheet(""" + QPushButton { + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #C7CEEA, stop:1 #9FA8DA); + color: white; + font: bold 14pt '微软雅黑'; + border-radius: 25px; + border: 3px solid #9FA8DA; + } + QPushButton:hover { + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #9FA8DA, stop:1 #7986CB); + border: 3px solid #7986CB; + } + QPushButton:pressed { + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #7986CB, stop:1 #5C6BC0); + } + QPushButton:disabled { + background: #E0E0E0; + color: #9E9E9E; + border: 3px solid #CCCCCC; + } + """) + self.prev_btn.clicked.connect(self.prev_question) + button_layout.addWidget(self.prev_btn) + + button_layout.addStretch(1) + + # 下一题按钮 + self.next_btn = QPushButton("下一题 ➡️") + self.next_btn.setMinimumSize(120, 50) + self.next_btn.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) + self.next_btn.setStyleSheet(""" + QPushButton { + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #A0E7E5, stop:1 #6CD6D3); + color: white; + font: bold 14pt '微软雅黑'; + border-radius: 25px; + border: 3px solid #8ADBD9; + } + QPushButton:hover { + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #8ADBD9, stop:1 #5AC7C4); + border: 3px solid #6CD6D3; + } + QPushButton:pressed { + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #5AC7C4, stop:1 #4BB5B2); + } + """) + self.next_btn.clicked.connect(self.next_question) + button_layout.addWidget(self.next_btn) + + button_layout.addStretch(1) + + # 提交按钮 + self.submit_btn = QPushButton("🎯 提交试卷") + self.submit_btn.setMinimumSize(140, 50) + self.submit_btn.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) + self.submit_btn.setStyleSheet(""" + QPushButton { + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #FF9EBC, stop:1 #FF6B9C); + color: white; + font: bold 14pt '微软雅黑'; + border-radius: 25px; + border: 3px solid #FF85A1; + } + QPushButton:hover { + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #FF85A1, stop:1 #FF5784); + border: 3px solid #FF6B9C; + } + QPushButton:pressed { + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #FF5784, stop:1 #FF3D6D); + } + """) + self.submit_btn.clicked.connect(self.submit_paper) + button_layout.addWidget(self.submit_btn) + + main_layout.addWidget(button_frame) + + # 选项按钮组 + self.option_group = QButtonGroup(self) + self.option_group.buttonClicked.connect(self.on_option_selected) + + def show_question(self): + """显示当前题目""" + if self.current_idx >= len(self.paper): + return + + question = self.paper[self.current_idx] + + # 更新进度 + progress_text = f"📊 第 {self.current_idx + 1} 题 / 共 {self.count} 题" + self.progress_label.setText(progress_text) + + # 更新进度条 + progress_percent = int((self.current_idx + 1) / self.count * 100) + self.progress_bar.setValue(progress_percent) + self.progress_bar.setFormat(f"🚀 进度: {progress_percent}%") + + # 显示题干 + self.question_label.setText(question.content) + + # 清空选项框架 + for i in reversed(range(self.options_layout.count())): + widget = self.options_layout.itemAt(i).widget() + if widget: + widget.deleteLater() + + # 移除所有按钮 + self.option_group = QButtonGroup(self) + self.option_group.buttonClicked.connect(self.on_option_selected) + + # 创建选项按钮 + option_labels = ["A", "B", "C", "D"] + option_emojis = ["🔸", "🔹", "🔸", "🔹"] + + for i, option_text in enumerate(question.options): + # 选项卡片 + option_card = QFrame() + option_card.setStyleSheet(""" + QFrame { + background: white; + border: 2px solid #FFD1DC; + border-radius: 15px; + } + QFrame:hover { + background: #FFF9FA; + border: 2px solid #FF9EBC; + } + """) + option_card.setFixedHeight(60) + option_layout = QHBoxLayout(option_card) + option_layout.setContentsMargins(20, 10, 20, 10) + + # 单选按钮 + radio_btn = QRadioButton(f"{option_emojis[i]} {option_labels[i]}. {option_text}") + radio_btn.setStyleSheet(""" + QRadioButton { + font: 16pt '微软雅黑'; + color: #5A5A5A; + background: transparent; + spacing: 15px; + } + QRadioButton::indicator { + width: 24px; + height: 24px; + } + QRadioButton::indicator:unchecked { + border: 3px solid #FF9EBC; + border-radius: 12px; + background-color: white; + } + QRadioButton::indicator:checked { + border: 3px solid #FF6B9C; + border-radius: 12px; + background-color: #FF6B9C; + } + QRadioButton:hover { + color: #FF6B9C; + } + """) + + self.option_group.addButton(radio_btn, i) + option_layout.addWidget(radio_btn) + option_layout.addStretch(1) + + self.options_layout.addWidget(option_card) + + # 恢复已选答案 + if self.answers[self.current_idx] is not None: + button = self.option_group.button(self.answers[self.current_idx]) + if button: + button.setChecked(True) + + # 更新按钮状态 + self.update_button_states() + + def on_option_selected(self, button): + """选项被选择时的处理""" + self.save_current_answer() + + def update_button_states(self): + """更新按钮状态""" + # 上一题按钮 + self.prev_btn.setEnabled(self.current_idx > 0) + + # 下一题按钮 + if self.current_idx == self.count - 1: + self.next_btn.setText("最后一题 🏁") + else: + self.next_btn.setText("下一题 ➡️") + + def save_current_answer(self): + """保存当前题目的答案""" + selected_button = self.option_group.checkedButton() + if selected_button: + self.answers[self.current_idx] = self.option_group.id(selected_button) + + def prev_question(self): + """上一题""" + self.save_current_answer() + if self.current_idx > 0: + self.current_idx -= 1 + self.show_question() + + def next_question(self): + """下一题""" + self.save_current_answer() + if self.current_idx < self.count - 1: + self.current_idx += 1 + self.show_question() + else: + # 如果是最后一题,提示提交 + QMessageBox.information(self, "🎉 完成", "太棒了!你已经完成了所有题目,请提交试卷查看成绩!") + + def submit_paper(self): + """提交试卷""" + self.save_current_answer() + + # 检查是否所有题目都已作答 + unanswered = [i+1 for i, answer in enumerate(self.answers) if answer is None] + if unanswered: + reply = QMessageBox.question( + self, + "🤔 确认提交", + f"还有 {len(unanswered)} 题未作答(题号:{unanswered}),确定要提交吗?", + QMessageBox.Yes | QMessageBox.No, + QMessageBox.No + ) + if reply != QMessageBox.Yes: + return + + # 计算得分 + correct_answers = [] + for i, question in enumerate(self.paper): + selected_index = self.answers[i] + if selected_index is not None: + selected_answer = question.options[selected_index] + is_correct = (selected_answer == question.answer) + correct_answers.append(is_correct) + else: + correct_answers.append(False) + + score = self.question_bank.calculate_score(correct_answers) + + # 显示结果页面 + if self.parent_window: + self.parent_window.show_result_page(score, self.level, self.count) + + def showEvent(self, event): + """显示页面时重置状态""" + super().showEvent(event) + # 重置答题状态 + self.current_idx = 0 + self.answers = [None] * self.count + self.show_question() \ No newline at end of file -- 2.34.1 From a8716b76c357e9ea09bd09ac4c74fc9a4d418a50 Mon Sep 17 00:00:00 2001 From: hnu202326010330 <168584091@qq.com> Date: Sun, 12 Oct 2025 20:23:02 +0800 Subject: [PATCH 4/6] ADD file via upload --- src/ui/register_ui.py | 589 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 589 insertions(+) create mode 100644 src/ui/register_ui.py diff --git a/src/ui/register_ui.py b/src/ui/register_ui.py new file mode 100644 index 0000000..48ddf4f --- /dev/null +++ b/src/ui/register_ui.py @@ -0,0 +1,589 @@ +# 标准库 +import sys + +# 第三方库 +from PyQt5.QtWidgets import ( + QWidget, QVBoxLayout, QHBoxLayout, QLabel, QLineEdit, + QPushButton, QMessageBox, QFrame, QGridLayout, QSizePolicy +) +from PyQt5.QtCore import Qt, QTimer +from PyQt5.QtGui import QFont + +class RegisterPage(QWidget): # 改为继承 QWidget + def __init__(self, parent=None): + super().__init__(parent) + self.parent_window = parent + self.user_system = parent.user_system if parent else None + self.countdown_active = False + self.countdown_seconds = 60 + self.countdown_timer = QTimer() + self.countdown_timer.timeout.connect(self.update_countdown) + + self.setup_ui() + + def setup_ui(self): + """初始化注册界面""" + # 移除 setWindowTitle 和 setMinimumSize,使用父窗口的尺寸 + + # 设置可爱的渐变背景 + self.setStyleSheet(""" + QWidget { + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #FFD1DC, stop:1 #B5EAD7); + } + """) + + # 主布局 + main_layout = QVBoxLayout(self) + main_layout.setContentsMargins(25, 20, 25, 20) + main_layout.setSpacing(0) + + # 卡片容器 + card = QFrame() + card.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) + card.setStyleSheet(""" + QFrame { + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 white, stop:1 #FFF9FA); + border-radius: 20px; + border: 3px solid #FF9EBC; + } + """) + main_layout.addWidget(card) + + # 卡片布局 + card_layout = QVBoxLayout(card) + card_layout.setContentsMargins(35, 30, 35, 30) + card_layout.setSpacing(0) + + # 顶部按钮栏 + top_button_layout = QHBoxLayout() + top_button_layout.setAlignment(Qt.AlignLeft) + + # 返回主页按钮 + self.back_button = QPushButton("← 返回主页") + self.back_button.setMinimumSize(100, 35) + self.back_button.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) + self.back_button.setStyleSheet(""" + QPushButton { + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #B5EAD7, stop:1 #8CD9C7); + color: white; + font: bold 11pt '微软雅黑'; + border-radius: 15px; + border: 2px solid #A0E7E5; + } + QPushButton:hover { + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #A0E7E5, stop:1 #7BCFBD); + border: 2px solid #8CD9C7; + } + QPushButton:pressed { + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #7BCFBD, stop:1 #6AC0AE); + } + """) + self.back_button.clicked.connect(self.go_back_to_main) + top_button_layout.addWidget(self.back_button) + top_button_layout.addStretch(1) # 将按钮推到左侧 + + card_layout.addLayout(top_button_layout) + card_layout.addSpacing(10) + + # 顶部弹性空间 + card_layout.addStretch(1) + + # 标题区域 + title_frame = QFrame() + title_frame.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) + title_frame.setStyleSheet("background: transparent; border: none;") + title_layout = QVBoxLayout(title_frame) + title_layout.setSpacing(10) + + # 装饰性emoji + emoji_label = QLabel("🎉✨📝") + emoji_label.setStyleSheet(""" + QLabel { + font: bold 20pt 'Arial'; + color: #FF6B9C; + background: transparent; + qproperty-alignment: AlignCenter; + } + """) + title_layout.addWidget(emoji_label) + + # 主标题 + title_label = QLabel("用户注册") + title_label.setStyleSheet(""" + QLabel { + font: bold 24pt '微软雅黑'; + color: #FF6B9C; + background: transparent; + qproperty-alignment: AlignCenter; + } + """) + title_layout.addWidget(title_label) + + subtitle_label = QLabel("🚀 加入数学冒险岛大家庭 🚀") + subtitle_label.setStyleSheet(""" + QLabel { + font: 12pt '微软雅黑'; + color: #5A5A5A; + background: transparent; + qproperty-alignment: AlignCenter; + } + """) + title_layout.addWidget(subtitle_label) + + card_layout.addWidget(title_frame) + card_layout.addSpacing(30) + + # 表单区域 - 使用垂直布局包装网格布局 + form_container = QFrame() + form_container.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) + form_container.setStyleSheet("background: transparent; border: none;") + form_container_layout = QVBoxLayout(form_container) + + # 网格布局 + form_layout = QGridLayout() + form_layout.setVerticalSpacing(15) # 减少垂直间距 + form_layout.setHorizontalSpacing(15) + form_layout.setColumnStretch(1, 1) + + # 用户名输入 + username_label = QLabel("👤 用户名:") + username_label.setStyleSheet(""" + QLabel { + font: bold 12pt '微软雅黑'; + color: #FF6B9C; + background: transparent; + } + """) + form_layout.addWidget(username_label, 0, 0, Qt.AlignLeft) + + self.username_input = QLineEdit() + self.username_input.setMinimumHeight(40) + self.username_input.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) + self.username_input.setStyleSheet(""" + QLineEdit { + background: white; + border: 2px solid #FF9EBC; + border-radius: 15px; + font: 12pt '微软雅黑'; + color: #FF6B9C; + padding: 8px 15px; + selection-background-color: #FFE4EC; + } + QLineEdit:focus { + border: 2px solid #FF6B9C; + background: #FFF9FA; + } + QLineEdit::placeholder { + color: #CCCCCC; + font: 11pt '微软雅黑'; + } + """) + self.username_input.setPlaceholderText("请输入用户名...") + form_layout.addWidget(self.username_input, 0, 1) + + # 用户名提示 + username_hint = QLabel("📝 用户名要求:2-10位中文、字母或数字") + username_hint.setStyleSheet(""" + QLabel { + font: 9pt '微软雅黑'; + color: #FF9EBC; + background: transparent; + } + """) + form_layout.addWidget(username_hint, 1, 1, Qt.AlignLeft) + + # 添加间距行 + form_layout.addWidget(QLabel(""), 2, 0, 1, 2) # 空行作为间距 + + # 邮箱输入 + email_label = QLabel("📧 邮箱:") + email_label.setStyleSheet(""" + QLabel { + font: bold 12pt '微软雅黑'; + color: #FF6B9C; + background: transparent; + } + """) + form_layout.addWidget(email_label, 3, 0, Qt.AlignLeft) + + self.email_input = QLineEdit() + self.email_input.setMinimumHeight(40) + self.email_input.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) + self.email_input.setStyleSheet(""" + QLineEdit { + background: white; + border: 2px solid #FF9EBC; + border-radius: 15px; + font: 12pt '微软雅黑'; + color: #FF6B9C; + padding: 8px 15px; + selection-background-color: #FFE4EC; + } + QLineEdit:focus { + border: 2px solid #FF6B9C; + background: #FFF9FA; + } + QLineEdit::placeholder { + color: #CCCCCC; + font: 11pt '微软雅黑'; + } + """) + self.email_input.setPlaceholderText("请输入邮箱...") + form_layout.addWidget(self.email_input, 3, 1) + + # 添加间距行 + form_layout.addWidget(QLabel(""), 4, 0, 1, 2) # 空行作为间距 + + # 注册码 + code_label = QLabel("🔐 注册码:") + code_label.setStyleSheet(""" + QLabel { + font: bold 12pt '微软雅黑'; + color: #FF6B9C; + background: transparent; + } + """) + form_layout.addWidget(code_label, 5, 0, Qt.AlignLeft) + + code_input_layout = QHBoxLayout() + code_input_layout.setSpacing(10) + + self.code_input = QLineEdit() + self.code_input.setMinimumHeight(55) + self.code_input.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) + self.code_input.setStyleSheet(""" + QLineEdit { + background: white; + border: 2px solid #FF9EBC; + border-radius: 15px; + font: 12pt '微软雅黑'; + color: #FF6B9C; + padding: 8px 15px; + selection-background-color: #FFE4EC; + } + QLineEdit:focus { + border: 2px solid #FF6B9C; + background: #FFF9FA; + } + QLineEdit::placeholder { + color: #CCCCCC; + font: 11pt '微软雅黑'; + } + """) + self.code_input.setPlaceholderText("请输入注册码...") + code_input_layout.addWidget(self.code_input) + + self.code_btn = QPushButton("获取注册码") + self.code_btn.setMinimumSize(120, 40) + self.code_btn.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) + self.code_btn.setStyleSheet(""" + QPushButton { + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #A0E7E5, stop:1 #6CD6D3); + color: white; + font: bold 11pt '微软雅黑'; + border-radius: 15px; + border: 2px solid #8ADBD9; + } + QPushButton:hover { + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #8ADBD9, stop:1 #5AC7C4); + border: 2px solid #6CD6D3; + } + QPushButton:pressed { + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #5AC7C4, stop:1 #4BB5B2); + } + QPushButton:disabled { + background: #E0E0E0; + color: #9E9E9E; + border: 2px solid #CCCCCC; + } + """) + self.code_btn.clicked.connect(self.send_code) + code_input_layout.addWidget(self.code_btn) + + form_layout.addLayout(code_input_layout, 5, 1) + + # 添加间距行 + form_layout.addWidget(QLabel(""), 6, 0, 1, 2) # 空行作为间距 + + # 密码 + pwd_label = QLabel("🔒 密码:") + pwd_label.setStyleSheet(""" + QLabel { + font: bold 12pt '微软雅黑'; + color: #FF6B9C; + background: transparent; + } + """) + form_layout.addWidget(pwd_label, 7, 0, Qt.AlignLeft) + + self.pwd_input = QLineEdit() + self.pwd_input.setMinimumHeight(40) + self.pwd_input.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) + self.pwd_input.setStyleSheet(""" + QLineEdit { + background: white; + border: 2px solid #FF9EBC; + border-radius: 15px; + font: 12pt '微软雅黑'; + color: #FF6B9C; + padding: 8px 15px; + selection-background-color: #FFE4EC; + } + QLineEdit:focus { + border: 2px solid #FF6B9C; + background: #FFF9FA; + } + QLineEdit::placeholder { + color: #CCCCCC; + font: 11pt '微软雅黑'; + } + """) + self.pwd_input.setEchoMode(QLineEdit.Password) + self.pwd_input.setPlaceholderText("请输入密码...") + form_layout.addWidget(self.pwd_input, 7, 1) + + # 密码提示 + pwd_hint = QLabel("📝 密码要求:6-10位,必须包含大小写字母和数字") + pwd_hint.setStyleSheet(""" + QLabel { + font: 9pt '微软雅黑'; + color: #FF9EBC; + background: transparent; + } + """) + form_layout.addWidget(pwd_hint, 8, 1, Qt.AlignLeft) + + # 添加间距行 + form_layout.addWidget(QLabel(""), 9, 0, 1, 2) # 空行作为间距 + + # 确认密码 + confirm_pwd_label = QLabel("✅ 确认密码:") + confirm_pwd_label.setStyleSheet(""" + QLabel { + font: bold 12pt '微软雅黑'; + color: #FF6B9C; + background: transparent; + } + """) + form_layout.addWidget(confirm_pwd_label, 10, 0, Qt.AlignLeft) + + self.confirm_pwd_input = QLineEdit() + self.confirm_pwd_input.setMinimumHeight(40) + self.confirm_pwd_input.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) + self.confirm_pwd_input.setStyleSheet(""" + QLineEdit { + background: white; + border: 2px solid #FF9EBC; + border-radius: 15px; + font: 12pt '微软雅黑'; + color: #FF6B9C; + padding: 8px 15px; + selection-background-color: #FFE4EC; + } + QLineEdit:focus { + border: 2px solid #FF6B9C; + background: #FFF9FA; + } + QLineEdit::placeholder { + color: #CCCCCC; + font: 11pt '微软雅黑'; + } + """) + self.confirm_pwd_input.setEchoMode(QLineEdit.Password) + self.confirm_pwd_input.setPlaceholderText("请再次输入密码...") + form_layout.addWidget(self.confirm_pwd_input, 10, 1) + + form_container_layout.addLayout(form_layout) + form_container_layout.addStretch(1) + + card_layout.addWidget(form_container) + card_layout.addStretch(1) + + # 按钮布局 + button_layout = QHBoxLayout() + button_layout.setSpacing(20) + button_layout.setAlignment(Qt.AlignCenter) + + # 返回主页按钮(底部) + back_button_bottom = QPushButton("🔙 返回主页") + back_button_bottom.setMinimumSize(120, 45) + back_button_bottom.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) + back_button_bottom.setStyleSheet(""" + QPushButton { + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #C9C9C9, stop:1 #A8A8A8); + color: white; + font: bold 12pt '微软雅黑'; + border-radius: 20px; + border: 2px solid #B8B8B8; + } + QPushButton:hover { + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #B8B8B8, stop:1 #989898); + border: 2px solid #A8A8A8; + } + QPushButton:pressed { + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #989898, stop:1 #888888); + } + """) + back_button_bottom.clicked.connect(self.go_back_to_main) + button_layout.addWidget(back_button_bottom) + + # 注册按钮 + register_btn = QPushButton("🎉 立即注册") + register_btn.setMinimumSize(150, 50) + register_btn.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) + register_btn.setStyleSheet(""" + QPushButton { + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #FF9EBC, stop:1 #FF6B9C); + color: white; + font: bold 14pt '微软雅黑'; + border-radius: 25px; + border: 3px solid #FF85A1; + } + QPushButton:hover { + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #FF85A1, stop:1 #FF5784); + border: 3px solid #FF6B9C; + } + QPushButton:pressed { + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #FF5784, stop:1 #FF3D6D); + } + """) + register_btn.clicked.connect(self.do_register) + button_layout.addWidget(register_btn) + + card_layout.addLayout(button_layout) + card_layout.addSpacing(10) + + # 装饰性底部 + decoration_label = QLabel("✨🌈🎮 开启你的数学冒险之旅 🌟📚🚀") + decoration_label.setStyleSheet(""" + QLabel { + font: bold 10pt 'Arial'; + color: #FF9EBC; + background: transparent; + qproperty-alignment: AlignCenter; + } + """) + card_layout.addWidget(decoration_label) + + # 设置焦点 + self.username_input.setFocus() + + def go_back_to_main(self): + """返回主页""" + if self.parent_window: + self.parent_window.show_main_page() + + def send_code(self): + """发送注册码""" + if self.countdown_active: + return + + email = self.email_input.text().strip() + username = self.username_input.text().strip() or "用户" + + if not email: + QMessageBox.warning(self, "⚠️ 提示", "请输入邮箱地址") + self.email_input.setFocus() + return + + if not self.user_system.is_valid_email(email): + QMessageBox.warning(self, "⚠️ 提示", "请输入有效的邮箱地址") + self.email_input.setFocus() + return + + if self.user_system.send_verification(email, username): + QMessageBox.information(self, "📧 发送成功", "注册码已发送到您的邮箱,请查收!") + self.start_countdown() + else: + QMessageBox.warning(self, "❌ 发送失败", "邮箱已被使用或发送失败,请重试") + + def start_countdown(self): + """注册码按钮倒计时""" + print("开始倒计时") # 调试信息 + self.countdown_active = True + self.code_btn.setEnabled(False) + self.countdown_seconds = 60 + self.countdown_timer.start(1000) + self.update_countdown() + + def update_countdown(self): + """更新倒计时显示""" + print(f"倒计时更新: {self.countdown_seconds}秒") # 调试信息 + + if self.countdown_seconds > 0: + self.code_btn.setText(f"重新发送({self.countdown_seconds}s)") + self.countdown_seconds -= 1 + # 强制更新UI + self.code_btn.repaint() + else: + self.countdown_timer.stop() + self.code_btn.setText("获取注册码") + self.code_btn.setEnabled(True) + self.countdown_active = False + print("倒计时结束") # 调试信息 + + def do_register(self): + """执行注册""" + username = self.username_input.text().strip() + email = self.email_input.text().strip() + code = self.code_input.text().strip() + pwd = self.pwd_input.text() + confirm_pwd = self.confirm_pwd_input.text() + + if not username or not email or not code or not pwd or not confirm_pwd: + QMessageBox.warning(self, "⚠️ 提示", "请填写完整信息") + return + + if pwd != confirm_pwd: + QMessageBox.warning(self, "⚠️ 提示", "两次输入的密码不一致") + self.pwd_input.clear() + self.confirm_pwd_input.clear() + self.pwd_input.setFocus() + return + + if self.user_system.register(username, email, code, pwd): + QMessageBox.information(self, "🎉 注册成功", + "注册成功!现在可以使用用户名登录,开始你的数学冒险之旅!") + # 不再使用 self.accept(),而是通知父窗口切换页面 + if self.parent_window: + self.parent_window.show_main_page() # 注册成功后回到主页面 + else: + QMessageBox.warning(self, "❌ 注册失败", + "注册失败:注册码错误、用户名已存在或信息不符合要求") + + def showEvent(self, event): + """显示页面时清空输入框""" + super().showEvent(event) + self.username_input.clear() + self.email_input.clear() + self.code_input.clear() + self.pwd_input.clear() + self.confirm_pwd_input.clear() + self.username_input.setFocus() + + # 重置倒计时 + if self.countdown_timer.isActive(): + self.countdown_timer.stop() + self.code_btn.setText("获取注册码") + self.code_btn.setEnabled(True) + self.countdown_active = False + + def closeEvent(self, event): + """关闭事件处理""" + if self.countdown_timer.isActive(): + self.countdown_timer.stop() + event.accept() \ No newline at end of file -- 2.34.1 From b22b0ac225e16467c2f48d39f9289f2c77d0c5e4 Mon Sep 17 00:00:00 2001 From: hnu202326010330 <168584091@qq.com> Date: Sun, 12 Oct 2025 20:23:41 +0800 Subject: [PATCH 5/6] ADD file via upload --- src/ui/result_ui.py | 296 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 296 insertions(+) create mode 100644 src/ui/result_ui.py diff --git a/src/ui/result_ui.py b/src/ui/result_ui.py new file mode 100644 index 0000000..7c942ef --- /dev/null +++ b/src/ui/result_ui.py @@ -0,0 +1,296 @@ +from PyQt5.QtWidgets import (QWidget, QVBoxLayout, QHBoxLayout, QLabel, + QPushButton, QFrame, QMessageBox) +from PyQt5.QtCore import Qt +from PyQt5.QtGui import QFont + +class ResultPage(QWidget): # 改为继承 QWidget + def __init__(self, parent, score: int, level: str, count: int): + super().__init__(parent) + self.parent_window = parent + self.level = level + self.count = count + self.score = score + self.setup_ui() + + def setup_ui(self): + """初始化界面""" + # 移除 setWindowTitle 和 setMinimumSize,使用父窗口的尺寸 + + # 设置可爱的渐变背景 + self.setStyleSheet(""" + QWidget { + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #FFD1DC, stop:1 #B5EAD7); + } + """) + + # 主布局 + main_layout = QVBoxLayout(self) + main_layout.setContentsMargins(30, 30, 30, 30) + main_layout.setSpacing(0) + + # 卡片容器 + card = QFrame() + card.setStyleSheet(""" + QFrame { + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 white, stop:1 #FFF9FA); + border-radius: 25px; + border: 3px solid #FF9EBC; + } + """) + main_layout.addWidget(card) + + # 卡片布局 + card_layout = QVBoxLayout(card) + card_layout.setContentsMargins(40, 40, 40, 40) + card_layout.setSpacing(0) + + # 顶部弹性空间 + card_layout.addStretch(1) + + # 标题区域 + title_frame = QFrame() + title_frame.setStyleSheet("background: transparent; border: none;") + title_layout = QVBoxLayout(title_frame) + title_layout.setSpacing(15) + + # 装饰性emoji + emoji_label = QLabel("🎊✨🏆") + emoji_label.setStyleSheet(""" + QLabel { + font: bold 28pt 'Arial'; + color: #FF6B9C; + background: transparent; + qproperty-alignment: AlignCenter; + } + """) + title_layout.addWidget(emoji_label) + + # 主标题 + title_label = QLabel("冒险完成!") + title_label.setStyleSheet(""" + QLabel { + font: bold 32pt '微软雅黑'; + color: #FF6B9C; + background: transparent; + qproperty-alignment: AlignCenter; + } + """) + title_layout.addWidget(title_label) + + # 副标题 + level_text = {"primary": "小学乐园", "middle": "初中城堡", "high": "高中太空"}.get(self.level, self.level) + subtitle_label = QLabel(f"🎯 你在 {level_text} 完成了 {self.count} 道题目 🎯") + subtitle_label.setStyleSheet(""" + QLabel { + font: 16pt '微软雅黑'; + color: #5A5A5A; + background: transparent; + qproperty-alignment: AlignCenter; + } + """) + title_layout.addWidget(subtitle_label) + + card_layout.addWidget(title_frame) + card_layout.addSpacing(40) + + # 得分区域 + score_frame = QFrame() + score_frame.setStyleSheet("background: transparent; border: none;") + score_layout = QVBoxLayout(score_frame) + score_layout.setSpacing(10) + + # 得分标题 + score_title_label = QLabel("你的冒险得分") + score_title_label.setStyleSheet(""" + QLabel { + font: bold 18pt '微软雅黑'; + color: #5A5A5A; + background: transparent; + qproperty-alignment: AlignCenter; + } + """) + score_layout.addWidget(score_title_label) + + # 得分显示 - 根据分数显示不同颜色和评价 + if self.score >= 90: + score_color = "#FF6B9C" + score_emoji = "🎉" + evaluation = "太棒了!你是数学小天才!" + elif self.score >= 80: + score_color = "#FF9EBC" + score_emoji = "🌟" + evaluation = "优秀!继续加油!" + elif self.score >= 70: + score_color = "#A0E7E5" + score_emoji = "👍" + evaluation = "良好!表现不错!" + elif self.score >= 60: + score_color = "#B5EAD7" + score_emoji = "💪" + evaluation = "及格!还有进步空间!" + else: + score_color = "#C7CEEA" + score_emoji = "📚" + evaluation = "加油!多练习会更好!" + + score_display_frame = QFrame() + score_display_frame.setStyleSheet(f""" + QFrame {{ + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 white, stop:1 #FFF9FA); + border-radius: 20px; + border: 3px solid {score_color}; + }} + """) + score_display_layout = QVBoxLayout(score_display_frame) + score_display_layout.setContentsMargins(30, 20, 30, 20) + + # 得分数字 + score_value_label = QLabel(f"{score_emoji} {self.score}分 {score_emoji}") + score_value_label.setStyleSheet(f""" + QLabel {{ + font: bold 48pt '微软雅黑'; + color: {score_color}; + background: transparent; + qproperty-alignment: AlignCenter; + }} + """) + score_display_layout.addWidget(score_value_label) + + # 评价 + evaluation_label = QLabel(evaluation) + evaluation_label.setStyleSheet(f""" + QLabel {{ + font: bold 16pt '微软雅黑'; + color: {score_color}; + background: transparent; + qproperty-alignment: AlignCenter; + }} + """) + score_display_layout.addWidget(evaluation_label) + + score_layout.addWidget(score_display_frame) + card_layout.addWidget(score_frame) + card_layout.addSpacing(40) + + # 按钮框架 + button_frame = QFrame() + button_frame.setStyleSheet("background: transparent; border: none;") + button_layout = QHBoxLayout(button_frame) + button_layout.setSpacing(20) + + # 按钮样式 + button_style = """ + QPushButton { + font: bold 14pt '微软雅黑'; + border-radius: 25px; + min-width: 140px; + min-height: 50px; + border: 3px solid; + } + """ + + # 再做一套按钮 + again_btn = QPushButton("🔄 再来一次") + again_btn.setStyleSheet(button_style + """ + QPushButton { + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #A0E7E5, stop:1 #6CD6D3); + color: white; + border-color: #8ADBD9; + } + QPushButton:hover { + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #8ADBD9, stop:1 #5AC7C4); + border-color: #6CD6D3; + } + QPushButton:pressed { + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #5AC7C4, stop:1 #4BB5B2); + } + """) + again_btn.clicked.connect(self.do_again) + button_layout.addWidget(again_btn) + + # 返回学段按钮 + level_btn = QPushButton("🗺️ 选择地图") + level_btn.setStyleSheet(button_style + """ + QPushButton { + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #FFDAC1, stop:1 #FFB347); + color: white; + border-color: #FFB347; + } + QPushButton:hover { + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #FFB347, stop:1 #FF9800); + border-color: #FF9800; + } + QPushButton:pressed { + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #FF9800, stop:1 #F57C00); + } + """) + level_btn.clicked.connect(self.exit_to_level) + button_layout.addWidget(level_btn) + + # 退出程序按钮 + quit_btn = QPushButton("🚪 结束冒险") + quit_btn.setStyleSheet(button_style + """ + QPushButton { + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #C7CEEA, stop:1 #9FA8DA); + color: white; + border-color: #9FA8DA; + } + QPushButton:hover { + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #9FA8DA, stop:1 #7986CB); + border-color: #7986CB; + } + QPushButton:pressed { + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #7986CB, stop:1 #5C6BC0); + } + """) + quit_btn.clicked.connect(self.quit_app) + button_layout.addWidget(quit_btn) + + card_layout.addWidget(button_frame) + card_layout.addStretch(1) + + # 装饰性底部 + decoration_label = QLabel("✨🌈🎮 数学冒险岛 - 学数学,真有趣! 🌟📚🚀") + decoration_label.setStyleSheet(""" + QLabel { + font: bold 12pt 'Arial'; + color: #FF9EBC; + background: transparent; + qproperty-alignment: AlignCenter; + } + """) + card_layout.addWidget(decoration_label) + + def quit_app(self): + """退出程序""" + reply = QMessageBox.question(self, "🎮 结束冒险", + "确定要结束数学冒险吗?", + QMessageBox.Yes | QMessageBox.No, + QMessageBox.No) + if reply == QMessageBox.Yes: + if self.parent_window: + self.parent_window.close() + + def do_again(self): + """重新做题""" + if self.parent_window: + self.parent_window.remove_current_page() # 移除结果页面 + self.parent_window.show_count_page() # 回到题目数量页面 + + def exit_to_level(self): + """返回学段选择""" + if self.parent_window: + self.parent_window.remove_current_page() # 移除结果页面 + self.parent_window.show_level_page() # 回到学段选择页面 \ No newline at end of file -- 2.34.1 From d532bc131972f400e473a3c6c8d137dbdc826289 Mon Sep 17 00:00:00 2001 From: hnu202326010330 <168584091@qq.com> Date: Sun, 12 Oct 2025 20:24:19 +0800 Subject: [PATCH 6/6] ADD file via upload --- src/ui/user_management_ui.py | 297 +++++++++++++++++++++++++++++++++++ 1 file changed, 297 insertions(+) create mode 100644 src/ui/user_management_ui.py diff --git a/src/ui/user_management_ui.py b/src/ui/user_management_ui.py new file mode 100644 index 0000000..46ff5f7 --- /dev/null +++ b/src/ui/user_management_ui.py @@ -0,0 +1,297 @@ +from PyQt5.QtWidgets import (QWidget, QVBoxLayout, QHBoxLayout, QLabel, + QLineEdit, QPushButton, QMessageBox, QFrame, QSizePolicy) +from PyQt5.QtCore import Qt +from PyQt5.QtGui import QFont + +class ChangeUsernamePage(QWidget): # 改为继承 QWidget + def __init__(self, parent=None): + super().__init__(parent) + self.parent_window = parent + self.user_system = parent.user_system if parent and hasattr(parent, 'user_system') else None + self.setup_ui() + + def setup_ui(self): + """初始化界面""" + # 移除 setWindowTitle 和 setMinimumSize,使用父窗口的尺寸 + + # 设置可爱的渐变背景 + self.setStyleSheet(""" + QWidget { + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #FFD1DC, stop:1 #B5EAD7); + } + """) + + # 主布局 + main_layout = QVBoxLayout(self) + main_layout.setContentsMargins(25, 20, 25, 20) + main_layout.setSpacing(0) + + # 卡片容器 + card = QFrame() + card.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) + card.setStyleSheet(""" + QFrame { + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 white, stop:1 #FFF9FA); + border-radius: 20px; + border: 3px solid #FF9EBC; + } + """) + main_layout.addWidget(card) + + # 卡片布局 + card_layout = QVBoxLayout(card) + card_layout.setContentsMargins(35, 30, 35, 30) + card_layout.setSpacing(0) + + # 顶部弹性空间 + card_layout.addStretch(1) + + # 标题区域 + title_frame = QFrame() + title_frame.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) + title_frame.setStyleSheet("background: transparent; border: none;") + title_layout = QVBoxLayout(title_frame) + title_layout.setSpacing(10) + + # 装饰性emoji + emoji_label = QLabel("👤✨🆕") + emoji_label.setStyleSheet(""" + QLabel { + font: bold 20pt 'Arial'; + color: #FF6B9C; + background: transparent; + qproperty-alignment: AlignCenter; + } + """) + title_layout.addWidget(emoji_label) + + # 主标题 + title_label = QLabel("修改用户名") + title_label.setStyleSheet(""" + QLabel { + font: bold 24pt '微软雅黑'; + color: #FF6B9C; + background: transparent; + qproperty-alignment: AlignCenter; + } + """) + title_layout.addWidget(title_label) + + subtitle_label = QLabel("🎯 给你的冒险角色换个新名字吧! 🎯") + subtitle_label.setStyleSheet(""" + QLabel { + font: 12pt '微软雅黑'; + color: #5A5A5A; + background: transparent; + qproperty-alignment: AlignCenter; + } + """) + title_layout.addWidget(subtitle_label) + + card_layout.addWidget(title_frame) + card_layout.addSpacing(30) + + # 当前用户名显示 + current_user_frame = QFrame() + current_user_frame.setStyleSheet(""" + QFrame { + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #FFF9FA, stop:1 #FFE4EC); + border-radius: 15px; + border: 2px solid #FFD1DC; + } + """) + current_user_layout = QVBoxLayout(current_user_frame) + current_user_layout.setContentsMargins(20, 15, 20, 15) + + current_title_label = QLabel("🎮 当前冒险者") + current_title_label.setStyleSheet(""" + QLabel { + font: bold 14pt '微软雅黑'; + color: #FF6B9C; + background: transparent; + qproperty-alignment: AlignCenter; + } + """) + current_user_layout.addWidget(current_title_label) + + # 检查用户系统是否存在 + if self.user_system and self.user_system.current_user: + current_username = self.user_system.current_user + else: + current_username = "未登录" + + current_user_label = QLabel(f"✨ {current_username} ✨") + current_user_label.setStyleSheet(""" + QLabel { + font: bold 18pt '微软雅黑'; + color: #FF6B9C; + background: transparent; + qproperty-alignment: AlignCenter; + } + """) + current_user_layout.addWidget(current_user_label) + + card_layout.addWidget(current_user_frame) + card_layout.addSpacing(25) + + # 新用户名输入区域 + input_frame = QFrame() + input_frame.setStyleSheet("background: transparent; border: none;") + input_layout = QVBoxLayout(input_frame) + input_layout.setSpacing(8) + + # 新用户名标签 + new_username_label = QLabel("🆕 新用户名:") + new_username_label.setStyleSheet(""" + QLabel { + font: bold 14pt '微软雅黑'; + color: #FF6B9C; + background: transparent; + } + """) + input_layout.addWidget(new_username_label) + + # 新用户名输入框 + self.new_username_input = QLineEdit() + self.new_username_input.setMinimumHeight(45) + self.new_username_input.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) + self.new_username_input.setStyleSheet(""" + QLineEdit { + background: white; + border: 2px solid #FF9EBC; + border-radius: 18px; + font: 14pt '微软雅黑'; + color: #FF6B9C; + padding: 8px 20px; + selection-background-color: #FFE4EC; + } + QLineEdit:focus { + border: 2px solid #FF6B9C; + background: #FFF9FA; + } + QLineEdit::placeholder { + color: #CCCCCC; + font: 12pt '微软雅黑'; + } + """) + self.new_username_input.setPlaceholderText("请输入新的冒险者名字...") + input_layout.addWidget(self.new_username_input) + + # 用户名提示 + hint_label = QLabel("📝 用户名要求:2-10位中文、字母或数字") + hint_label.setStyleSheet(""" + QLabel { + font: 10pt '微软雅黑'; + color: #FF9EBC; + background: transparent; + } + """) + input_layout.addWidget(hint_label) + + card_layout.addWidget(input_frame) + card_layout.addSpacing(30) + + # 确认按钮 + button_frame = QFrame() + button_frame.setStyleSheet("background: transparent; border: none;") + button_layout = QVBoxLayout(button_frame) + + self.confirm_btn = QPushButton("✨ 确认修改") + self.confirm_btn.setMinimumSize(200, 50) + self.confirm_btn.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) + self.confirm_btn.setStyleSheet(""" + QPushButton { + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #B5EAD7, stop:1 #8CD9B3); + color: white; + font: bold 16pt '微软雅黑'; + border-radius: 25px; + border: 3px solid #A0E7E5; + } + QPushButton:hover { + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #8CD9B3, stop:1 #6CD6D3); + border: 3px solid #8CD9B3; + } + QPushButton:pressed { + background: qlineargradient(x1:0, y1:0, x2:0, y2:1, + stop:0 #6CD6D3, stop:1 #5AC7C4); + } + """) + self.confirm_btn.clicked.connect(self.change_username) + button_layout.addWidget(self.confirm_btn, alignment=Qt.AlignCenter) + + card_layout.addWidget(button_frame) + card_layout.addStretch(1) + + # 装饰性底部 + decoration_label = QLabel("🌟🌈🎮 换个名字,开启新的冒险! 📚✨🚀") + decoration_label.setStyleSheet(""" + QLabel { + font: bold 10pt 'Arial'; + color: #FF9EBC; + background: transparent; + qproperty-alignment: AlignCenter; + } + """) + card_layout.addWidget(decoration_label) + + # 绑定回车键 + self.new_username_input.returnPressed.connect(self.change_username) + + # 设置焦点 + self.new_username_input.setFocus() + + def change_username(self): + """修改用户名""" + if not self.user_system: + QMessageBox.warning(self, "❌ 错误", "用户系统未初始化") + return + + if not self.user_system.current_user: + QMessageBox.warning(self, "⚠️ 提示", "请先登录") + if self.parent_window: + self.parent_window.show_main_page() # 回到主页面 + return + + new_username = self.new_username_input.text().strip() + + if not new_username: + QMessageBox.warning(self, "⚠️ 提示", "请输入新用户名") + self.new_username_input.setFocus() + return + + if new_username == self.user_system.current_user: + QMessageBox.warning(self, "⚠️ 提示", "新用户名与当前用户名相同,请换个不同的名字吧!") + self.new_username_input.clear() + self.new_username_input.setFocus() + return + + if self.user_system.set_username(new_username): + QMessageBox.information(self, "🎉 修改成功", + f"用户名修改成功!\n\n" + f"从现在开始,你就是勇敢的冒险者:\n" + f"✨ {new_username} ✨") + # 不再使用 self.accept(),而是通知父窗口切换页面 + if self.parent_window: + self.parent_window.show_level_page() # 回到学段选择页面 + else: + QMessageBox.warning(self, "❌ 修改失败", + "用户名修改失败:\n" + "• 用户名不符合要求(2-10位中文、字母或数字)\n" + "• 或用户名已被其他冒险者使用") + self.new_username_input.clear() + self.new_username_input.setFocus() + + def showEvent(self, event): + """显示页面时重置状态""" + super().showEvent(event) + self.new_username_input.clear() + self.new_username_input.setFocus() + + # 更新当前用户名显示 + if hasattr(self, 'current_user_label') and self.user_system and self.user_system.current_user: + self.current_user_label.setText(f"✨ {self.user_system.current_user} ✨") \ No newline at end of file -- 2.34.1