前端代码2.0 #2

Merged
hnu202326010112 merged 1 commits from liumuxue_branch into develop 3 months ago

@ -2,6 +2,7 @@
#include <QMessageBox>
#include <random>
#include <QGroupBox>
#include <QTimer>
ExamWidget::ExamWidget(QWidget *parent) : QWidget(parent), currentQuestion(0), totalQuestions(0)
{
@ -127,13 +128,9 @@ void ExamWidget::startExam(Grade grade, int questionCount)
userAnswers.clear();
correctAnswers.clear();
// 生成正确答案(随机)
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<> dis(0, 3);
// 为每个题目生成正确答案
for (int i = 0; i < totalQuestions; ++i) {
correctAnswers.push_back(dis(gen));
correctAnswers.push_back(i % 4); // 简单实现,实际应该计算
}
showQuestion(0);
@ -159,6 +156,14 @@ void ExamWidget::showQuestion(int index)
}
optionGroup->setExclusive(true);
// 恢复之前的选择(如果有)
if (static_cast<size_t>(index) < userAnswers.size()) { // 修复有符号/无符号比较
int previousAnswer = userAnswers[index];
if (previousAnswer >= 0 && previousAnswer < 4) {
optionButtons[previousAnswer]->setChecked(true);
}
}
// 更新按钮状态
nextButton->setVisible(index < totalQuestions - 1);
submitButton->setVisible(index == totalQuestions - 1);
@ -167,14 +172,22 @@ void ExamWidget::showQuestion(int index)
void ExamWidget::generateOptions()
{
// 简单实现:一个正确答案,三个随机错误答案
// 生成有意义的选项
int correctIndex = correctAnswers[currentQuestion];
for (int i = 0; i < 4; ++i) {
if (i == correctIndex) {
optionButtons[i]->setText("正确答案");
} else {
optionButtons[i]->setText(QString("选项 %1").arg(i + 1));
// 生成干扰项
QString optionText;
switch(i) {
case 0: optionText = "选项 A"; break;
case 1: optionText = "选项 B"; break;
case 2: optionText = "选项 C"; break;
case 3: optionText = "选项 D"; break;
}
optionButtons[i]->setText(optionText);
}
}
}
@ -187,7 +200,12 @@ void ExamWidget::onNextClicked()
return;
}
userAnswers.push_back(selected);
// 保存当前答案
if (static_cast<size_t>(currentQuestion) >= userAnswers.size()) { // 修复有符号/无符号比较
userAnswers.resize(currentQuestion + 1);
}
userAnswers[currentQuestion] = selected;
showQuestion(currentQuestion + 1);
}
@ -199,12 +217,16 @@ void ExamWidget::onSubmitClicked()
return;
}
userAnswers.push_back(selected);
// 保存最后一题的答案
if (static_cast<size_t>(currentQuestion) >= userAnswers.size()) { // 修复有符号/无符号比较
userAnswers.resize(currentQuestion + 1);
}
userAnswers[currentQuestion] = selected;
// 计算分数
int score = 0;
for (int i = 0; i < totalQuestions; ++i) {
if (userAnswers[i] == correctAnswers[i]) {
for (size_t i = 0; i < userAnswers.size(); ++i) { // 使用size_t
if (i < correctAnswers.size() && userAnswers[i] == correctAnswers[i]) {
score++;
}
}

@ -2,32 +2,72 @@
LoginWidget::LoginWidget(QWidget *parent) : QWidget(parent)
{
// 设置最小尺寸
setMinimumSize(400, 400);
QVBoxLayout *layout = new QVBoxLayout(this);
layout->setSpacing(20);
layout->setContentsMargins(50, 50, 50, 50);
// 标题
QLabel *titleLabel = new QLabel("数学学习软件 - 登录");
titleLabel->setAlignment(Qt::AlignCenter);
titleLabel->setStyleSheet("font-size: 20px; font-weight: bold; margin: 20px;");
titleLabel->setStyleSheet("font-size: 24px; font-weight: bold; margin: 20px; color: #2c3e50;");
// 用户名输入
QLabel *usernameLabel = new QLabel("用户名:");
usernameLabel->setStyleSheet("font-size: 14px; font-weight: bold;");
usernameEdit = new QLineEdit();
usernameEdit->setPlaceholderText("请输入用户名");
usernameEdit->setMinimumHeight(35);
usernameEdit->setStyleSheet("QLineEdit { padding: 8px; font-size: 14px; border: 1px solid #bdc3c7; border-radius: 4px; }");
// 密码输入
QLabel *passwordLabel = new QLabel("密码:");
passwordLabel->setStyleSheet("font-size: 14px; font-weight: bold;");
passwordEdit = new QLineEdit();
passwordEdit->setEchoMode(QLineEdit::Password);
passwordEdit->setPlaceholderText("请输入密码");
passwordEdit->setMinimumHeight(35);
passwordEdit->setStyleSheet("QLineEdit { padding: 8px; font-size: 14px; border: 1px solid #bdc3c7; border-radius: 4px; }");
// 按钮
loginButton = new QPushButton("登录");
loginButton->setMinimumHeight(40);
loginButton->setStyleSheet("QPushButton {"
"background-color: #3498db;"
"color: white;"
"border: none;"
"font-size: 16px;"
"font-weight: bold;"
"border-radius: 5px;"
"}"
"QPushButton:hover {"
"background-color: #2980b9;"
"}");
registerButton = new QPushButton("注册新账号");
registerButton->setMinimumHeight(40);
registerButton->setStyleSheet("QPushButton {"
"background-color: #95a5a6;"
"color: white;"
"border: none;"
"font-size: 16px;"
"font-weight: bold;"
"border-radius: 5px;"
"}"
"QPushButton:hover {"
"background-color: #7f8c8d;"
"}");
// 添加到布局
layout->addWidget(titleLabel);
layout->addSpacing(30);
layout->addWidget(usernameLabel);
layout->addWidget(usernameEdit);
layout->addWidget(passwordLabel);
layout->addWidget(passwordEdit);
layout->addSpacing(30);
layout->addWidget(loginButton);
layout->addWidget(registerButton);
@ -38,7 +78,7 @@ LoginWidget::LoginWidget(QWidget *parent) : QWidget(parent)
void LoginWidget::onLoginClicked()
{
QString username = usernameEdit->text();
QString username = usernameEdit->text().trimmed();
QString password = passwordEdit->text();
if (username.isEmpty() || password.isEmpty()) {

@ -1,7 +1,6 @@
#ifndef LOGINWIDGET_H
#define LOGINWIDGET_H
#include <QWidget>
#include <QLineEdit>
#include <QPushButton>
@ -26,7 +25,7 @@ private slots:
void onRegisterClicked();
private:
QLineEdit *usernameEdit;
QLineEdit *usernameEdit; // 改为用户名输入
QLineEdit *passwordEdit;
QPushButton *loginButton;
QPushButton *registerButton;

@ -1,10 +1,12 @@
#include "mainwindow.h"
#include <QMessageBox>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent), currentUser(nullptr)
{
setWindowTitle("中小学数学学习软件");
setFixedSize(600, 400);
setMinimumSize(600, 700);
resize(600, 700);
// 创建堆叠窗口
stackedWidget = new QStackedWidget(this);
@ -28,7 +30,7 @@ MainWindow::MainWindow(QWidget *parent)
connect(loginWidget, &LoginWidget::loginSuccess, this, &MainWindow::onUserLoggedIn);
connect(loginWidget, &LoginWidget::showRegister, this, &MainWindow::showRegister);
connect(registerWidget, &RegisterWidget::showLogin, this, &MainWindow::showLogin);
connect(registerWidget, &RegisterWidget::registerSuccess, this, &MainWindow::onUserLoggedIn);
connect(registerWidget, &RegisterWidget::registerSuccess, this, &MainWindow::onRegisterSuccess);
connect(mainMenuWidget, &MainMenuWidget::startExam, this, &MainWindow::showExam);
connect(examWidget, &ExamWidget::examFinished, this, &MainWindow::showResult);
connect(resultWidget, &ResultWidget::backToMenu, this, &MainWindow::showMainMenu);
@ -73,6 +75,14 @@ void MainWindow::showResult(int score, int total)
{
resultWidget->setResult(score, total);
stackedWidget->setCurrentWidget(resultWidget);
// 保存考试记录
if (currentUser) {
FileSaver::saveExamRecord(currentUser->getUsername(),
currentUser->getGradeString(),
score, total,
FileSaver::getCurrentTime());
}
}
void MainWindow::onUserLoggedIn(User* user)
@ -80,3 +90,10 @@ void MainWindow::onUserLoggedIn(User* user)
currentUser = user;
showMainMenu();
}
void MainWindow::onRegisterSuccess()
{
// 注册成功后显示登录界面
QMessageBox::information(this, "注册成功", "注册成功,请登录");
showLogin();
}

@ -9,6 +9,7 @@
#include "examwidget.h"
#include "resultwidget.h"
#include "usermanage.h"
#include "filesaver.h"
class MainWindow : public QMainWindow
{
@ -25,6 +26,7 @@ private slots:
void showExam(int questionCount);
void showResult(int score, int total);
void onUserLoggedIn(User* user);
void onRegisterSuccess();
private:
QStackedWidget *stackedWidget;

@ -1,70 +1,260 @@
#include "registerwidget.h"
#include "usermanage.h"
#include <QHBoxLayout>
#include <QGridLayout>
#include <QRandomGenerator>
#include <QTime>
RegisterWidget::RegisterWidget(QWidget *parent) : QWidget(parent)
RegisterWidget::RegisterWidget(QWidget *parent) : QWidget(parent), countdownSeconds(0)
{
QVBoxLayout *layout = new QVBoxLayout(this);
// 设置最小尺寸
setMinimumSize(500, 600);
QVBoxLayout *mainLayout = new QVBoxLayout(this);
mainLayout->setSpacing(20);
mainLayout->setContentsMargins(40, 30, 40, 30);
// 标题
QLabel *titleLabel = new QLabel("用户注册");
titleLabel->setAlignment(Qt::AlignCenter);
titleLabel->setStyleSheet("font-size: 20px; font-weight: bold; margin: 20px;");
titleLabel->setStyleSheet("font-size: 28px; font-weight: bold; margin: 20px; color: #2c3e50;");
// 创建网格布局用于表单
QGridLayout *formLayout = new QGridLayout();
formLayout->setSpacing(15);
formLayout->setColumnMinimumWidth(0, 100);
formLayout->setColumnStretch(1, 1);
// 邮箱输入
QLabel *emailLabel = new QLabel("邮箱:");
emailLabel->setStyleSheet("font-size: 14px; font-weight: bold;");
emailEdit = new QLineEdit();
emailEdit->setPlaceholderText("请输入您的邮箱");
emailEdit->setMinimumHeight(35);
emailEdit->setStyleSheet("QLineEdit { padding: 8px; font-size: 14px; border: 1px solid #bdc3c7; border-radius: 4px; }");
// 发送验证码按钮
sendCodeButton = new QPushButton("发送验证码");
sendCodeButton->setFixedWidth(120);
sendCodeButton->setMinimumHeight(35);
sendCodeButton->setStyleSheet("QPushButton {"
"background-color: #3498db;"
"color: white;"
"border: none;"
"font-size: 12px;"
"border-radius: 4px;"
"}"
"QPushButton:hover {"
"background-color: #2980b9;"
"}"
"QPushButton:disabled {"
"background-color: #bdc3c7;"
"}");
// 验证码输入
QLabel *codeLabel = new QLabel("验证码:");
codeLabel->setStyleSheet("font-size: 14px; font-weight: bold;");
verificationCodeEdit = new QLineEdit();
verificationCodeEdit->setPlaceholderText("请输入收到的验证码");
verificationCodeEdit->setMinimumHeight(35);
verificationCodeEdit->setStyleSheet("QLineEdit { padding: 8px; font-size: 14px; border: 1px solid #bdc3c7; border-radius: 4px; }");
// 注册码
QLabel *codeLabel = new QLabel("注册码:");
registerCodeEdit = new QLineEdit();
registerCodeEdit->setText(generateRegisterCode());
registerCodeEdit->setReadOnly(true);
// 计时器标签
timerLabel = new QLabel();
timerLabel->setStyleSheet("color: #e74c3c; font-size: 14px; font-weight: bold;");
timerLabel->setFixedWidth(60);
timerLabel->setAlignment(Qt::AlignCenter);
// 用户名输入
QLabel *usernameLabel = new QLabel("用户名:");
usernameLabel->setStyleSheet("font-size: 14px; font-weight: bold;");
usernameEdit = new QLineEdit();
usernameEdit->setPlaceholderText("请输入用户名2-20个字符");
usernameEdit->setMinimumHeight(35);
usernameEdit->setStyleSheet("QLineEdit { padding: 8px; font-size: 14px; border: 1px solid #bdc3c7; border-radius: 4px; }");
// 年级选择
QLabel *gradeLabel = new QLabel("选择年级:");
gradeLabel->setStyleSheet("font-size: 14px; font-weight: bold;");
gradeComboBox = new QComboBox();
gradeComboBox->addItem("小学");
gradeComboBox->addItem("初中");
gradeComboBox->addItem("高中");
gradeComboBox->setMinimumHeight(35);
gradeComboBox->setStyleSheet("QComboBox { padding: 8px; font-size: 14px; border: 1px solid #bdc3c7; border-radius: 4px; }");
// 密码输入
QLabel *passwordLabel = new QLabel("密码 (6-10位包含大小写字母和数字):");
QLabel *passwordLabel = new QLabel("密码:");
passwordLabel->setStyleSheet("font-size: 14px; font-weight: bold;");
passwordEdit = new QLineEdit();
passwordEdit->setEchoMode(QLineEdit::Password);
passwordEdit->setPlaceholderText("6-10位包含大小写字母和数字");
passwordEdit->setMinimumHeight(35);
passwordEdit->setStyleSheet("QLineEdit { padding: 8px; font-size: 14px; border: 1px solid #bdc3c7; border-radius: 4px; }");
// 确认密码
QLabel *confirmPasswordLabel = new QLabel("确认密码:");
confirmPasswordLabel->setStyleSheet("font-size: 14px; font-weight: bold;");
confirmPasswordEdit = new QLineEdit();
confirmPasswordEdit->setEchoMode(QLineEdit::Password);
confirmPasswordEdit->setPlaceholderText("请再次输入密码");
confirmPasswordEdit->setMinimumHeight(35);
confirmPasswordEdit->setStyleSheet("QLineEdit { padding: 8px; font-size: 14px; border: 1px solid #bdc3c7; border-radius: 4px; }");
// 设置表单布局
int row = 0;
// 邮箱行
formLayout->addWidget(emailLabel, row, 0, Qt::AlignRight | Qt::AlignVCenter);
QHBoxLayout *emailLayout = new QHBoxLayout();
emailLayout->setSpacing(10);
emailLayout->addWidget(emailEdit);
emailLayout->addWidget(sendCodeButton);
formLayout->addLayout(emailLayout, row, 1);
row++;
// 验证码行
formLayout->addWidget(codeLabel, row, 0, Qt::AlignRight | Qt::AlignVCenter);
QHBoxLayout *codeLayout = new QHBoxLayout();
codeLayout->setSpacing(10);
codeLayout->addWidget(verificationCodeEdit);
codeLayout->addWidget(timerLabel);
formLayout->addLayout(codeLayout, row, 1);
row++;
// 用户名行
formLayout->addWidget(usernameLabel, row, 0, Qt::AlignRight | Qt::AlignVCenter);
formLayout->addWidget(usernameEdit, row, 1);
row++;
// 年级行
formLayout->addWidget(gradeLabel, row, 0, Qt::AlignRight | Qt::AlignVCenter);
formLayout->addWidget(gradeComboBox, row, 1);
row++;
// 密码行
formLayout->addWidget(passwordLabel, row, 0, Qt::AlignRight | Qt::AlignVCenter);
formLayout->addWidget(passwordEdit, row, 1);
row++;
// 确认密码行
formLayout->addWidget(confirmPasswordLabel, row, 0, Qt::AlignRight | Qt::AlignVCenter);
formLayout->addWidget(confirmPasswordEdit, row, 1);
row++;
// 按钮区域
QWidget *buttonWidget = new QWidget();
QHBoxLayout *buttonLayout = new QHBoxLayout(buttonWidget);
buttonLayout->setSpacing(30);
buttonLayout->setContentsMargins(0, 30, 0, 0);
// 按钮
registerButton = new QPushButton("注册");
registerButton->setFixedSize(140, 45);
registerButton->setStyleSheet("QPushButton {"
"background-color: #27ae60;"
"color: white;"
"border: none;"
"font-size: 16px;"
"font-weight: bold;"
"border-radius: 6px;"
"}"
"QPushButton:hover {"
"background-color: #229954;"
"}");
backButton = new QPushButton("返回登录");
backButton->setFixedSize(140, 45);
backButton->setStyleSheet("QPushButton {"
"background-color: #95a5a6;"
"color: white;"
"border: none;"
"font-size: 16px;"
"font-weight: bold;"
"border-radius: 6px;"
"}"
"QPushButton:hover {"
"background-color: #7f8c8d;"
"}");
// 添加到布局
layout->addWidget(titleLabel);
layout->addWidget(emailLabel);
layout->addWidget(emailEdit);
layout->addWidget(codeLabel);
layout->addWidget(registerCodeEdit);
layout->addWidget(passwordLabel);
layout->addWidget(passwordEdit);
layout->addWidget(confirmPasswordLabel);
layout->addWidget(confirmPasswordEdit);
layout->addWidget(registerButton);
layout->addWidget(backButton);
buttonLayout->addStretch();
buttonLayout->addWidget(registerButton);
buttonLayout->addWidget(backButton);
buttonLayout->addStretch();
// 添加到主布局
mainLayout->addWidget(titleLabel);
mainLayout->addLayout(formLayout);
mainLayout->addStretch();
mainLayout->addWidget(buttonWidget);
// 初始化计时器
countdownTimer = new QTimer(this);
countdownTimer->setInterval(1000);
// 连接信号槽
connect(sendCodeButton, &QPushButton::clicked, this, &RegisterWidget::onSendCodeClicked);
connect(registerButton, &QPushButton::clicked, this, &RegisterWidget::onRegisterClicked);
connect(backButton, &QPushButton::clicked, this, &RegisterWidget::onBackClicked);
connect(countdownTimer, &QTimer::timeout, this, &RegisterWidget::updateTimer);
// 初始状态
resetCountdown();
}
void RegisterWidget::onSendCodeClicked()
{
QString email = emailEdit->text().trimmed();
if (!validateEmail(email)) {
QMessageBox::warning(this, "输入错误", "请输入有效的邮箱地址");
return;
}
// 生成并显示验证码
generatedCode = generateVerificationCode();
QMessageBox::information(this, "验证码",
QString("验证码已发送到 %1\n验证码:%2\n(实际项目中会发送到邮箱)")
.arg(email).arg(generatedCode));
// 开始倒计时
startCountdown();
}
void RegisterWidget::onRegisterClicked()
{
QString email = emailEdit->text();
QString email = emailEdit->text().trimmed();
QString username = usernameEdit->text().trimmed();
QString verificationCode = verificationCodeEdit->text().trimmed();
QString password = passwordEdit->text();
QString confirmPassword = confirmPasswordEdit->text();
QString grade = gradeComboBox->currentText();
// 邮箱格式验证
QRegularExpression emailRegex(R"(^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$)");
if (!emailRegex.match(email).hasMatch()) {
// 验证输入
if (email.isEmpty() || username.isEmpty() || verificationCode.isEmpty() ||
password.isEmpty() || confirmPassword.isEmpty()) {
QMessageBox::warning(this, "输入错误", "请填写所有字段");
return;
}
if (!validateEmail(email)) {
QMessageBox::warning(this, "输入错误", "请输入有效的邮箱地址");
return;
}
// 密码验证
// 验证验证码
if (verificationCode != generatedCode) {
QMessageBox::warning(this, "验证错误", "验证码错误");
return;
}
// 检查验证码是否过期
if (countdownSeconds <= 0) {
QMessageBox::warning(this, "验证错误", "验证码已过期,请重新获取");
return;
}
// 验证密码
if (password != confirmPassword) {
QMessageBox::warning(this, "输入错误", "两次输入的密码不一致");
return;
@ -76,12 +266,35 @@ void RegisterWidget::onRegisterClicked()
return;
}
QMessageBox::information(this, "注册成功", "注册成功!");
emit registerSuccess();
if (username.length() < 2 || username.length() > 20) {
QMessageBox::warning(this, "输入错误", "用户名长度应在2-20个字符之间");
return;
}
// 实际注册用户
UserManager userManager;
if (userManager.registerUser(username.toStdWString(),
password.toStdWString(),
grade.toStdWString())) {
QMessageBox::information(this, "注册成功", "注册成功!");
// 重置表单
emailEdit->clear();
usernameEdit->clear();
verificationCodeEdit->clear();
passwordEdit->clear();
confirmPasswordEdit->clear();
resetCountdown();
emit registerSuccess();
} else {
QMessageBox::warning(this, "注册失败", "用户名已存在,请选择其他用户名");
}
}
void RegisterWidget::onBackClicked()
{
resetCountdown();
emit showLogin();
}
@ -101,13 +314,54 @@ bool RegisterWidget::validatePassword(const QString &password)
return hasUpper && hasLower && hasDigit;
}
QString RegisterWidget::generateRegisterCode()
bool RegisterWidget::validateEmail(const QString &email)
{
QRegularExpression emailRegex(R"(^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$)");
return emailRegex.match(email).hasMatch();
}
QString RegisterWidget::generateVerificationCode()
{
const QString possibleChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
const QString possibleChars = "0123456789";
QString code;
for (int i = 0; i < 8; ++i) {
// 使用传统的随机数生成
qsrand(QTime::currentTime().msec());
for (int i = 0; i < 6; ++i) {
int index = qrand() % possibleChars.length();
code.append(possibleChars.at(index));
}
return code;
}
void RegisterWidget::startCountdown()
{
countdownSeconds = 300; // 5分钟
sendCodeButton->setEnabled(false);
updateTimer();
countdownTimer->start();
}
void RegisterWidget::resetCountdown()
{
countdownTimer->stop();
countdownSeconds = 0;
sendCodeButton->setEnabled(true);
timerLabel->clear();
generatedCode.clear();
}
void RegisterWidget::updateTimer()
{
if (countdownSeconds > 0) {
countdownSeconds--;
int minutes = countdownSeconds / 60;
int seconds = countdownSeconds % 60;
timerLabel->setText(QString("%1:%2").arg(minutes, 2, 10, QLatin1Char('0'))
.arg(seconds, 2, 10, QLatin1Char('0')));
} else {
resetCountdown();
QMessageBox::information(this, "提示", "验证码已过期,请重新获取");
}
}

@ -8,7 +8,11 @@
#include <QVBoxLayout>
#include <QMessageBox>
#include <QRegularExpression>
#include <QRegularExpressionValidator>
#include <QComboBox>
#include <QTimer>
#include <QRandomGenerator>
#include <QHBoxLayout>
#include <QGridLayout>
class RegisterWidget : public QWidget
{
@ -22,19 +26,32 @@ signals:
void showLogin();
private slots:
void onSendCodeClicked();
void onRegisterClicked();
void onBackClicked();
void updateTimer();
private:
QLineEdit *emailEdit;
QLineEdit *registerCodeEdit;
QLineEdit *usernameEdit;
QLineEdit *verificationCodeEdit;
QLineEdit *passwordEdit;
QLineEdit *confirmPasswordEdit;
QComboBox *gradeComboBox;
QPushButton *sendCodeButton;
QPushButton *registerButton;
QPushButton *backButton;
QLabel *timerLabel;
QTimer *countdownTimer;
int countdownSeconds;
QString generatedCode;
bool validatePassword(const QString &password);
QString generateRegisterCode();
bool validateEmail(const QString &email);
QString generateVerificationCode();
void startCountdown();
void resetCountdown();
};
#endif

Loading…
Cancel
Save