完善页面显示 #5

Merged
hnu202326010312 merged 2 commits from zyh into develop 3 months ago

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -1,4 +1,5 @@
debug/base_widget.o
debug/change_password_dialog.o
debug/login_widget.o
debug/main_window.o
debug/question_widget.o
@ -14,6 +15,7 @@ debug/logger.o
debug/problem_generator.o
debug/qrc_qmake_qmake_qm_files.o
debug/moc_base_widget.o
debug/moc_change_password_dialog.o
debug/moc_login_widget.o
debug/moc_main_window.o
debug/moc_question_widget.o

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE QtCreatorProject>
<!-- Written by QtCreator 17.0.1, 2025-10-10T00:20:53. -->
<!-- Written by QtCreator 17.0.1, 2025-10-12T15:51:50. -->
<qtcreator>
<data>
<variable>EnvironmentId</variable>
@ -162,10 +162,10 @@
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
<value type="bool" key="PE.EnvironmentAspect.PrintOnRun">false</value>
<value type="QString" key="PerfRecordArgsId">-e cpu-cycles --call-graph &quot;dwarf,4096&quot; -F 250</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">examSystem2</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4RunConfiguration:</value>
<value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey">E:/qt_project/examSystem/examSystem.pro</value>
<value type="bool" key="ProjectExplorer.RunConfiguration.Customized">false</value>
<value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey">E:/qt_project/1/examSystem.pro</value>
<value type="bool" key="ProjectExplorer.RunConfiguration.Customized">true</value>
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
<value type="bool" key="RunConfiguration.UseLibrarySearchPath">true</value>
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
@ -198,10 +198,10 @@
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
<value type="bool" key="PE.EnvironmentAspect.PrintOnRun">false</value>
<value type="QString" key="PerfRecordArgsId">-e cpu-cycles --call-graph &quot;dwarf,4096&quot; -F 250</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">examSystem2</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4RunConfiguration:</value>
<value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey">E:/qt_project/examSystem/examSystem.pro</value>
<value type="bool" key="ProjectExplorer.RunConfiguration.Customized">false</value>
<value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey">E:/qt_project/1/examSystem.pro</value>
<value type="bool" key="ProjectExplorer.RunConfiguration.Customized">true</value>
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
<value type="bool" key="RunConfiguration.UseLibrarySearchPath">true</value>
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

@ -0,0 +1,166 @@
/****************************************************************************
** Meta object code from reading C++ file 'change_password_dialog.h'
**
** Created by: The Qt Meta Object Compiler version 68 (Qt 6.5.3)
**
** WARNING! All changes made in this file will be lost!
*****************************************************************************/
#include "../src/frontend/change_password_dialog.h"
#include <QtGui/qtextcursor.h>
#include <QtCore/qmetatype.h>
#if __has_include(<QtCore/qtmochelpers.h>)
#include <QtCore/qtmochelpers.h>
#else
QT_BEGIN_MOC_NAMESPACE
#endif
#include <memory>
#if !defined(Q_MOC_OUTPUT_REVISION)
#error "The header file 'change_password_dialog.h' doesn't include <QObject>."
#elif Q_MOC_OUTPUT_REVISION != 68
#error "This file was generated using the moc from 6.5.3. It"
#error "cannot be used with the include files from this version of Qt."
#error "(The moc has changed too much.)"
#endif
#ifndef Q_CONSTINIT
#define Q_CONSTINIT
#endif
QT_WARNING_PUSH
QT_WARNING_DISABLE_DEPRECATED
QT_WARNING_DISABLE_GCC("-Wuseless-cast")
namespace {
#ifdef QT_MOC_HAS_STRINGDATA
struct qt_meta_stringdata_CLASSChangePasswordDialogENDCLASS_t {};
static constexpr auto qt_meta_stringdata_CLASSChangePasswordDialogENDCLASS = QtMocHelpers::stringData(
"ChangePasswordDialog",
"onChangePasswordClicked",
"",
"onCancelClicked",
"validatePassword"
);
#else // !QT_MOC_HAS_STRING_DATA
struct qt_meta_stringdata_CLASSChangePasswordDialogENDCLASS_t {
uint offsetsAndSizes[10];
char stringdata0[21];
char stringdata1[24];
char stringdata2[1];
char stringdata3[16];
char stringdata4[17];
};
#define QT_MOC_LITERAL(ofs, len) \
uint(sizeof(qt_meta_stringdata_CLASSChangePasswordDialogENDCLASS_t::offsetsAndSizes) + ofs), len
Q_CONSTINIT static const qt_meta_stringdata_CLASSChangePasswordDialogENDCLASS_t qt_meta_stringdata_CLASSChangePasswordDialogENDCLASS = {
{
QT_MOC_LITERAL(0, 20), // "ChangePasswordDialog"
QT_MOC_LITERAL(21, 23), // "onChangePasswordClicked"
QT_MOC_LITERAL(45, 0), // ""
QT_MOC_LITERAL(46, 15), // "onCancelClicked"
QT_MOC_LITERAL(62, 16) // "validatePassword"
},
"ChangePasswordDialog",
"onChangePasswordClicked",
"",
"onCancelClicked",
"validatePassword"
};
#undef QT_MOC_LITERAL
#endif // !QT_MOC_HAS_STRING_DATA
} // unnamed namespace
Q_CONSTINIT static const uint qt_meta_data_CLASSChangePasswordDialogENDCLASS[] = {
// content:
11, // revision
0, // classname
0, 0, // classinfo
3, 14, // methods
0, 0, // properties
0, 0, // enums/sets
0, 0, // constructors
0, // flags
0, // signalCount
// slots: name, argc, parameters, tag, flags, initial metatype offsets
1, 0, 32, 2, 0x08, 1 /* Private */,
3, 0, 33, 2, 0x08, 2 /* Private */,
4, 0, 34, 2, 0x08, 3 /* Private */,
// slots: parameters
QMetaType::Void,
QMetaType::Void,
QMetaType::Void,
0 // eod
};
Q_CONSTINIT const QMetaObject ChangePasswordDialog::staticMetaObject = { {
QMetaObject::SuperData::link<QDialog::staticMetaObject>(),
qt_meta_stringdata_CLASSChangePasswordDialogENDCLASS.offsetsAndSizes,
qt_meta_data_CLASSChangePasswordDialogENDCLASS,
qt_static_metacall,
nullptr,
qt_incomplete_metaTypeArray<qt_meta_stringdata_CLASSChangePasswordDialogENDCLASS_t,
// Q_OBJECT / Q_GADGET
QtPrivate::TypeAndForceComplete<ChangePasswordDialog, std::true_type>,
// method 'onChangePasswordClicked'
QtPrivate::TypeAndForceComplete<void, std::false_type>,
// method 'onCancelClicked'
QtPrivate::TypeAndForceComplete<void, std::false_type>,
// method 'validatePassword'
QtPrivate::TypeAndForceComplete<void, std::false_type>
>,
nullptr
} };
void ChangePasswordDialog::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
{
if (_c == QMetaObject::InvokeMetaMethod) {
auto *_t = static_cast<ChangePasswordDialog *>(_o);
(void)_t;
switch (_id) {
case 0: _t->onChangePasswordClicked(); break;
case 1: _t->onCancelClicked(); break;
case 2: _t->validatePassword(); break;
default: ;
}
}
(void)_a;
}
const QMetaObject *ChangePasswordDialog::metaObject() const
{
return QObject::d_ptr->metaObject ? QObject::d_ptr->dynamicMetaObject() : &staticMetaObject;
}
void *ChangePasswordDialog::qt_metacast(const char *_clname)
{
if (!_clname) return nullptr;
if (!strcmp(_clname, qt_meta_stringdata_CLASSChangePasswordDialogENDCLASS.stringdata0))
return static_cast<void*>(this);
return QDialog::qt_metacast(_clname);
}
int ChangePasswordDialog::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
{
_id = QDialog::qt_metacall(_c, _id, _a);
if (_id < 0)
return _id;
if (_c == QMetaObject::InvokeMetaMethod) {
if (_id < 3)
qt_static_metacall(this, _c, _id, _a);
_id -= 3;
} else if (_c == QMetaObject::RegisterMethodArgumentMetaType) {
if (_id < 3)
*reinterpret_cast<QMetaType *>(_a[0]) = QMetaType();
_id -= 3;
}
return _id;
}
QT_WARNING_POP

@ -42,6 +42,7 @@ static constexpr auto qt_meta_stringdata_CLASSLoginWidgetENDCLASS = QtMocHelpers
"LoginWidget",
"loginSuccess",
"",
"userName",
"registerSuccess",
"onLoginClicked",
"showRegisterPage",
@ -51,16 +52,17 @@ static constexpr auto qt_meta_stringdata_CLASSLoginWidgetENDCLASS = QtMocHelpers
);
#else // !QT_MOC_HAS_STRING_DATA
struct qt_meta_stringdata_CLASSLoginWidgetENDCLASS_t {
uint offsetsAndSizes[18];
uint offsetsAndSizes[20];
char stringdata0[12];
char stringdata1[13];
char stringdata2[1];
char stringdata3[16];
char stringdata4[15];
char stringdata5[17];
char stringdata6[14];
char stringdata7[18];
char stringdata3[9];
char stringdata4[16];
char stringdata5[15];
char stringdata6[17];
char stringdata7[14];
char stringdata8[18];
char stringdata9[18];
};
#define QT_MOC_LITERAL(ofs, len) \
uint(sizeof(qt_meta_stringdata_CLASSLoginWidgetENDCLASS_t::offsetsAndSizes) + ofs), len
@ -69,16 +71,18 @@ Q_CONSTINIT static const qt_meta_stringdata_CLASSLoginWidgetENDCLASS_t qt_meta_s
QT_MOC_LITERAL(0, 11), // "LoginWidget"
QT_MOC_LITERAL(12, 12), // "loginSuccess"
QT_MOC_LITERAL(25, 0), // ""
QT_MOC_LITERAL(26, 15), // "registerSuccess"
QT_MOC_LITERAL(42, 14), // "onLoginClicked"
QT_MOC_LITERAL(57, 16), // "showRegisterPage"
QT_MOC_LITERAL(74, 13), // "showLoginPage"
QT_MOC_LITERAL(88, 17), // "onRegisterClicked"
QT_MOC_LITERAL(106, 17) // "onSendCodeClicked"
QT_MOC_LITERAL(26, 8), // "userName"
QT_MOC_LITERAL(35, 15), // "registerSuccess"
QT_MOC_LITERAL(51, 14), // "onLoginClicked"
QT_MOC_LITERAL(66, 16), // "showRegisterPage"
QT_MOC_LITERAL(83, 13), // "showLoginPage"
QT_MOC_LITERAL(97, 17), // "onRegisterClicked"
QT_MOC_LITERAL(115, 17) // "onSendCodeClicked"
},
"LoginWidget",
"loginSuccess",
"",
"userName",
"registerSuccess",
"onLoginClicked",
"showRegisterPage",
@ -104,19 +108,19 @@ Q_CONSTINIT static const uint qt_meta_data_CLASSLoginWidgetENDCLASS[] = {
2, // signalCount
// signals: name, argc, parameters, tag, flags, initial metatype offsets
1, 0, 56, 2, 0x06, 1 /* Public */,
3, 0, 57, 2, 0x06, 2 /* Public */,
1, 1, 56, 2, 0x06, 1 /* Public */,
4, 1, 59, 2, 0x06, 3 /* Public */,
// slots: name, argc, parameters, tag, flags, initial metatype offsets
4, 0, 58, 2, 0x08, 3 /* Private */,
5, 0, 59, 2, 0x08, 4 /* Private */,
6, 0, 60, 2, 0x08, 5 /* Private */,
7, 0, 61, 2, 0x08, 6 /* Private */,
8, 0, 62, 2, 0x08, 7 /* Private */,
5, 0, 62, 2, 0x08, 5 /* Private */,
6, 0, 63, 2, 0x08, 6 /* Private */,
7, 0, 64, 2, 0x08, 7 /* Private */,
8, 0, 65, 2, 0x08, 8 /* Private */,
9, 0, 66, 2, 0x08, 9 /* Private */,
// signals: parameters
QMetaType::Void,
QMetaType::Void,
QMetaType::Void, QMetaType::QString, 3,
QMetaType::Void, QMetaType::QString, 3,
// slots: parameters
QMetaType::Void,
@ -139,8 +143,10 @@ Q_CONSTINIT const QMetaObject LoginWidget::staticMetaObject = { {
QtPrivate::TypeAndForceComplete<LoginWidget, std::true_type>,
// method 'loginSuccess'
QtPrivate::TypeAndForceComplete<void, std::false_type>,
QtPrivate::TypeAndForceComplete<const QString &, std::false_type>,
// method 'registerSuccess'
QtPrivate::TypeAndForceComplete<void, std::false_type>,
QtPrivate::TypeAndForceComplete<const QString &, std::false_type>,
// method 'onLoginClicked'
QtPrivate::TypeAndForceComplete<void, std::false_type>,
// method 'showRegisterPage'
@ -161,8 +167,8 @@ void LoginWidget::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id,
auto *_t = static_cast<LoginWidget *>(_o);
(void)_t;
switch (_id) {
case 0: _t->loginSuccess(); break;
case 1: _t->registerSuccess(); break;
case 0: _t->loginSuccess((*reinterpret_cast< std::add_pointer_t<QString>>(_a[1]))); break;
case 1: _t->registerSuccess((*reinterpret_cast< std::add_pointer_t<QString>>(_a[1]))); break;
case 2: _t->onLoginClicked(); break;
case 3: _t->showRegisterPage(); break;
case 4: _t->showLoginPage(); break;
@ -173,21 +179,20 @@ void LoginWidget::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id,
} else if (_c == QMetaObject::IndexOfMethod) {
int *result = reinterpret_cast<int *>(_a[0]);
{
using _t = void (LoginWidget::*)();
using _t = void (LoginWidget::*)(const QString & );
if (_t _q_method = &LoginWidget::loginSuccess; *reinterpret_cast<_t *>(_a[1]) == _q_method) {
*result = 0;
return;
}
}
{
using _t = void (LoginWidget::*)();
using _t = void (LoginWidget::*)(const QString & );
if (_t _q_method = &LoginWidget::registerSuccess; *reinterpret_cast<_t *>(_a[1]) == _q_method) {
*result = 1;
return;
}
}
}
(void)_a;
}
const QMetaObject *LoginWidget::metaObject() const
@ -221,14 +226,16 @@ int LoginWidget::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
}
// SIGNAL 0
void LoginWidget::loginSuccess()
void LoginWidget::loginSuccess(const QString & _t1)
{
QMetaObject::activate(this, &staticMetaObject, 0, nullptr);
void *_a[] = { nullptr, const_cast<void*>(reinterpret_cast<const void*>(std::addressof(_t1))) };
QMetaObject::activate(this, &staticMetaObject, 0, _a);
}
// SIGNAL 1
void LoginWidget::registerSuccess()
void LoginWidget::registerSuccess(const QString & _t1)
{
QMetaObject::activate(this, &staticMetaObject, 1, nullptr);
void *_a[] = { nullptr, const_cast<void*>(reinterpret_cast<const void*>(std::addressof(_t1))) };
QMetaObject::activate(this, &staticMetaObject, 1, _a);
}
QT_WARNING_POP

Binary file not shown.

@ -42,27 +42,33 @@ static constexpr auto qt_meta_stringdata_CLASSMainWindowENDCLASS = QtMocHelpers:
"MainWindow",
"showSelection",
"",
"userName",
"showQuestions",
"difficulty",
"count",
"showResult",
"exam_system::TestResult",
"result",
"restartFromResult"
"restartFromResult",
"logout",
"onExitTest"
);
#else // !QT_MOC_HAS_STRING_DATA
struct qt_meta_stringdata_CLASSMainWindowENDCLASS_t {
uint offsetsAndSizes[20];
uint offsetsAndSizes[26];
char stringdata0[11];
char stringdata1[14];
char stringdata2[1];
char stringdata3[14];
char stringdata4[11];
char stringdata5[6];
char stringdata6[11];
char stringdata7[24];
char stringdata8[7];
char stringdata9[18];
char stringdata3[9];
char stringdata4[14];
char stringdata5[11];
char stringdata6[6];
char stringdata7[11];
char stringdata8[24];
char stringdata9[7];
char stringdata10[18];
char stringdata11[7];
char stringdata12[11];
};
#define QT_MOC_LITERAL(ofs, len) \
uint(sizeof(qt_meta_stringdata_CLASSMainWindowENDCLASS_t::offsetsAndSizes) + ofs), len
@ -71,24 +77,30 @@ Q_CONSTINIT static const qt_meta_stringdata_CLASSMainWindowENDCLASS_t qt_meta_st
QT_MOC_LITERAL(0, 10), // "MainWindow"
QT_MOC_LITERAL(11, 13), // "showSelection"
QT_MOC_LITERAL(25, 0), // ""
QT_MOC_LITERAL(26, 13), // "showQuestions"
QT_MOC_LITERAL(40, 10), // "difficulty"
QT_MOC_LITERAL(51, 5), // "count"
QT_MOC_LITERAL(57, 10), // "showResult"
QT_MOC_LITERAL(68, 23), // "exam_system::TestResult"
QT_MOC_LITERAL(92, 6), // "result"
QT_MOC_LITERAL(99, 17) // "restartFromResult"
QT_MOC_LITERAL(26, 8), // "userName"
QT_MOC_LITERAL(35, 13), // "showQuestions"
QT_MOC_LITERAL(49, 10), // "difficulty"
QT_MOC_LITERAL(60, 5), // "count"
QT_MOC_LITERAL(66, 10), // "showResult"
QT_MOC_LITERAL(77, 23), // "exam_system::TestResult"
QT_MOC_LITERAL(101, 6), // "result"
QT_MOC_LITERAL(108, 17), // "restartFromResult"
QT_MOC_LITERAL(126, 6), // "logout"
QT_MOC_LITERAL(133, 10) // "onExitTest"
},
"MainWindow",
"showSelection",
"",
"userName",
"showQuestions",
"difficulty",
"count",
"showResult",
"exam_system::TestResult",
"result",
"restartFromResult"
"restartFromResult",
"logout",
"onExitTest"
};
#undef QT_MOC_LITERAL
#endif // !QT_MOC_HAS_STRING_DATA
@ -100,7 +112,7 @@ Q_CONSTINIT static const uint qt_meta_data_CLASSMainWindowENDCLASS[] = {
11, // revision
0, // classname
0, 0, // classinfo
4, 14, // methods
6, 14, // methods
0, 0, // properties
0, 0, // enums/sets
0, 0, // constructors
@ -108,15 +120,19 @@ Q_CONSTINIT static const uint qt_meta_data_CLASSMainWindowENDCLASS[] = {
0, // signalCount
// slots: name, argc, parameters, tag, flags, initial metatype offsets
1, 0, 38, 2, 0x08, 1 /* Private */,
3, 2, 39, 2, 0x08, 2 /* Private */,
6, 1, 44, 2, 0x08, 5 /* Private */,
9, 0, 47, 2, 0x08, 7 /* Private */,
1, 1, 50, 2, 0x08, 1 /* Private */,
4, 2, 53, 2, 0x08, 3 /* Private */,
7, 1, 58, 2, 0x08, 6 /* Private */,
10, 0, 61, 2, 0x08, 8 /* Private */,
11, 0, 62, 2, 0x08, 9 /* Private */,
12, 0, 63, 2, 0x08, 10 /* Private */,
// slots: parameters
QMetaType::Void, QMetaType::QString, 3,
QMetaType::Void, QMetaType::QString, QMetaType::Int, 5, 6,
QMetaType::Void, 0x80000000 | 8, 9,
QMetaType::Void,
QMetaType::Void,
QMetaType::Void, QMetaType::QString, QMetaType::Int, 4, 5,
QMetaType::Void, 0x80000000 | 7, 8,
QMetaType::Void,
0 // eod
@ -133,6 +149,7 @@ Q_CONSTINIT const QMetaObject MainWindow::staticMetaObject = { {
QtPrivate::TypeAndForceComplete<MainWindow, std::true_type>,
// method 'showSelection'
QtPrivate::TypeAndForceComplete<void, std::false_type>,
QtPrivate::TypeAndForceComplete<const QString &, std::false_type>,
// method 'showQuestions'
QtPrivate::TypeAndForceComplete<void, std::false_type>,
QtPrivate::TypeAndForceComplete<const QString &, std::false_type>,
@ -141,6 +158,10 @@ Q_CONSTINIT const QMetaObject MainWindow::staticMetaObject = { {
QtPrivate::TypeAndForceComplete<void, std::false_type>,
QtPrivate::TypeAndForceComplete<const exam_system::TestResult &, std::false_type>,
// method 'restartFromResult'
QtPrivate::TypeAndForceComplete<void, std::false_type>,
// method 'logout'
QtPrivate::TypeAndForceComplete<void, std::false_type>,
// method 'onExitTest'
QtPrivate::TypeAndForceComplete<void, std::false_type>
>,
nullptr
@ -152,10 +173,12 @@ void MainWindow::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id,
auto *_t = static_cast<MainWindow *>(_o);
(void)_t;
switch (_id) {
case 0: _t->showSelection(); break;
case 0: _t->showSelection((*reinterpret_cast< std::add_pointer_t<QString>>(_a[1]))); break;
case 1: _t->showQuestions((*reinterpret_cast< std::add_pointer_t<QString>>(_a[1])),(*reinterpret_cast< std::add_pointer_t<int>>(_a[2]))); break;
case 2: _t->showResult((*reinterpret_cast< std::add_pointer_t<exam_system::TestResult>>(_a[1]))); break;
case 3: _t->restartFromResult(); break;
case 4: _t->logout(); break;
case 5: _t->onExitTest(); break;
default: ;
}
}
@ -180,13 +203,13 @@ int MainWindow::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
if (_id < 0)
return _id;
if (_c == QMetaObject::InvokeMetaMethod) {
if (_id < 4)
if (_id < 6)
qt_static_metacall(this, _c, _id, _a);
_id -= 4;
_id -= 6;
} else if (_c == QMetaObject::RegisterMethodArgumentMetaType) {
if (_id < 4)
if (_id < 6)
*reinterpret_cast<QMetaType *>(_a[0]) = QMetaType();
_id -= 4;
_id -= 6;
}
return _id;
}

Binary file not shown.

@ -45,11 +45,13 @@ static constexpr auto qt_meta_stringdata_CLASSQuestionWidgetENDCLASS = QtMocHelp
"exam_system::TestResult",
"result",
"onNextClicked",
"onSubmitClicked"
"onSubmitClicked",
"onPrevClicked",
"onOptionSelected"
);
#else // !QT_MOC_HAS_STRING_DATA
struct qt_meta_stringdata_CLASSQuestionWidgetENDCLASS_t {
uint offsetsAndSizes[14];
uint offsetsAndSizes[18];
char stringdata0[15];
char stringdata1[14];
char stringdata2[1];
@ -57,6 +59,8 @@ struct qt_meta_stringdata_CLASSQuestionWidgetENDCLASS_t {
char stringdata4[7];
char stringdata5[14];
char stringdata6[16];
char stringdata7[14];
char stringdata8[17];
};
#define QT_MOC_LITERAL(ofs, len) \
uint(sizeof(qt_meta_stringdata_CLASSQuestionWidgetENDCLASS_t::offsetsAndSizes) + ofs), len
@ -68,7 +72,9 @@ Q_CONSTINIT static const qt_meta_stringdata_CLASSQuestionWidgetENDCLASS_t qt_met
QT_MOC_LITERAL(30, 23), // "exam_system::TestResult"
QT_MOC_LITERAL(54, 6), // "result"
QT_MOC_LITERAL(61, 13), // "onNextClicked"
QT_MOC_LITERAL(75, 15) // "onSubmitClicked"
QT_MOC_LITERAL(75, 15), // "onSubmitClicked"
QT_MOC_LITERAL(91, 13), // "onPrevClicked"
QT_MOC_LITERAL(105, 16) // "onOptionSelected"
},
"QuestionWidget",
"testCompleted",
@ -76,7 +82,9 @@ Q_CONSTINIT static const qt_meta_stringdata_CLASSQuestionWidgetENDCLASS_t qt_met
"exam_system::TestResult",
"result",
"onNextClicked",
"onSubmitClicked"
"onSubmitClicked",
"onPrevClicked",
"onOptionSelected"
};
#undef QT_MOC_LITERAL
#endif // !QT_MOC_HAS_STRING_DATA
@ -88,7 +96,7 @@ Q_CONSTINIT static const uint qt_meta_data_CLASSQuestionWidgetENDCLASS[] = {
11, // revision
0, // classname
0, 0, // classinfo
3, 14, // methods
5, 14, // methods
0, 0, // properties
0, 0, // enums/sets
0, 0, // constructors
@ -96,16 +104,20 @@ Q_CONSTINIT static const uint qt_meta_data_CLASSQuestionWidgetENDCLASS[] = {
1, // signalCount
// signals: name, argc, parameters, tag, flags, initial metatype offsets
1, 1, 32, 2, 0x06, 1 /* Public */,
1, 1, 44, 2, 0x06, 1 /* Public */,
// slots: name, argc, parameters, tag, flags, initial metatype offsets
5, 0, 35, 2, 0x08, 3 /* Private */,
6, 0, 36, 2, 0x08, 4 /* Private */,
5, 0, 47, 2, 0x08, 3 /* Private */,
6, 0, 48, 2, 0x08, 4 /* Private */,
7, 0, 49, 2, 0x08, 5 /* Private */,
8, 0, 50, 2, 0x08, 6 /* Private */,
// signals: parameters
QMetaType::Void, 0x80000000 | 3, 4,
// slots: parameters
QMetaType::Void,
QMetaType::Void,
QMetaType::Void,
QMetaType::Void,
@ -127,6 +139,10 @@ Q_CONSTINIT const QMetaObject QuestionWidget::staticMetaObject = { {
// method 'onNextClicked'
QtPrivate::TypeAndForceComplete<void, std::false_type>,
// method 'onSubmitClicked'
QtPrivate::TypeAndForceComplete<void, std::false_type>,
// method 'onPrevClicked'
QtPrivate::TypeAndForceComplete<void, std::false_type>,
// method 'onOptionSelected'
QtPrivate::TypeAndForceComplete<void, std::false_type>
>,
nullptr
@ -141,6 +157,8 @@ void QuestionWidget::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _
case 0: _t->testCompleted((*reinterpret_cast< std::add_pointer_t<exam_system::TestResult>>(_a[1]))); break;
case 1: _t->onNextClicked(); break;
case 2: _t->onSubmitClicked(); break;
case 3: _t->onPrevClicked(); break;
case 4: _t->onOptionSelected(); break;
default: ;
}
} else if (_c == QMetaObject::IndexOfMethod) {
@ -174,13 +192,13 @@ int QuestionWidget::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
if (_id < 0)
return _id;
if (_c == QMetaObject::InvokeMetaMethod) {
if (_id < 3)
if (_id < 5)
qt_static_metacall(this, _c, _id, _a);
_id -= 3;
_id -= 5;
} else if (_c == QMetaObject::RegisterMethodArgumentMetaType) {
if (_id < 3)
if (_id < 5)
*reinterpret_cast<QMetaType *>(_a[0]) = QMetaType();
_id -= 3;
_id -= 5;
}
return _id;
}

Binary file not shown.

@ -44,23 +44,33 @@ static constexpr auto qt_meta_stringdata_CLASSSelectionWidgetENDCLASS = QtMocHel
"",
"difficulty",
"questionCount",
"logoutRequested",
"onPrimaryClicked",
"onJuniorClicked",
"onSeniorClicked",
"onStartClicked"
"onStartClicked",
"onChangePasswordClicked",
"onLogoutClicked",
"onExitClicked",
"showUserInfo"
);
#else // !QT_MOC_HAS_STRING_DATA
struct qt_meta_stringdata_CLASSSelectionWidgetENDCLASS_t {
uint offsetsAndSizes[18];
uint offsetsAndSizes[28];
char stringdata0[16];
char stringdata1[13];
char stringdata2[1];
char stringdata3[11];
char stringdata4[14];
char stringdata5[17];
char stringdata6[16];
char stringdata5[16];
char stringdata6[17];
char stringdata7[16];
char stringdata8[15];
char stringdata8[16];
char stringdata9[15];
char stringdata10[24];
char stringdata11[16];
char stringdata12[14];
char stringdata13[13];
};
#define QT_MOC_LITERAL(ofs, len) \
uint(sizeof(qt_meta_stringdata_CLASSSelectionWidgetENDCLASS_t::offsetsAndSizes) + ofs), len
@ -71,20 +81,30 @@ Q_CONSTINIT static const qt_meta_stringdata_CLASSSelectionWidgetENDCLASS_t qt_me
QT_MOC_LITERAL(29, 0), // ""
QT_MOC_LITERAL(30, 10), // "difficulty"
QT_MOC_LITERAL(41, 13), // "questionCount"
QT_MOC_LITERAL(55, 16), // "onPrimaryClicked"
QT_MOC_LITERAL(72, 15), // "onJuniorClicked"
QT_MOC_LITERAL(88, 15), // "onSeniorClicked"
QT_MOC_LITERAL(104, 14) // "onStartClicked"
QT_MOC_LITERAL(55, 15), // "logoutRequested"
QT_MOC_LITERAL(71, 16), // "onPrimaryClicked"
QT_MOC_LITERAL(88, 15), // "onJuniorClicked"
QT_MOC_LITERAL(104, 15), // "onSeniorClicked"
QT_MOC_LITERAL(120, 14), // "onStartClicked"
QT_MOC_LITERAL(135, 23), // "onChangePasswordClicked"
QT_MOC_LITERAL(159, 15), // "onLogoutClicked"
QT_MOC_LITERAL(175, 13), // "onExitClicked"
QT_MOC_LITERAL(189, 12) // "showUserInfo"
},
"SelectionWidget",
"startRequest",
"",
"difficulty",
"questionCount",
"logoutRequested",
"onPrimaryClicked",
"onJuniorClicked",
"onSeniorClicked",
"onStartClicked"
"onStartClicked",
"onChangePasswordClicked",
"onLogoutClicked",
"onExitClicked",
"showUserInfo"
};
#undef QT_MOC_LITERAL
#endif // !QT_MOC_HAS_STRING_DATA
@ -96,26 +116,36 @@ Q_CONSTINIT static const uint qt_meta_data_CLASSSelectionWidgetENDCLASS[] = {
11, // revision
0, // classname
0, 0, // classinfo
5, 14, // methods
10, 14, // methods
0, 0, // properties
0, 0, // enums/sets
0, 0, // constructors
0, // flags
1, // signalCount
2, // signalCount
// signals: name, argc, parameters, tag, flags, initial metatype offsets
1, 2, 44, 2, 0x06, 1 /* Public */,
1, 2, 74, 2, 0x06, 1 /* Public */,
5, 0, 79, 2, 0x06, 4 /* Public */,
// slots: name, argc, parameters, tag, flags, initial metatype offsets
5, 0, 49, 2, 0x08, 4 /* Private */,
6, 0, 50, 2, 0x08, 5 /* Private */,
7, 0, 51, 2, 0x08, 6 /* Private */,
8, 0, 52, 2, 0x08, 7 /* Private */,
6, 0, 80, 2, 0x08, 5 /* Private */,
7, 0, 81, 2, 0x08, 6 /* Private */,
8, 0, 82, 2, 0x08, 7 /* Private */,
9, 0, 83, 2, 0x08, 8 /* Private */,
10, 0, 84, 2, 0x08, 9 /* Private */,
11, 0, 85, 2, 0x08, 10 /* Private */,
12, 0, 86, 2, 0x08, 11 /* Private */,
13, 0, 87, 2, 0x08, 12 /* Private */,
// signals: parameters
QMetaType::Void, QMetaType::QString, QMetaType::Int, 3, 4,
QMetaType::Void,
// slots: parameters
QMetaType::Void,
QMetaType::Void,
QMetaType::Void,
QMetaType::Void,
QMetaType::Void,
QMetaType::Void,
QMetaType::Void,
@ -137,6 +167,8 @@ Q_CONSTINIT const QMetaObject SelectionWidget::staticMetaObject = { {
QtPrivate::TypeAndForceComplete<void, std::false_type>,
QtPrivate::TypeAndForceComplete<const QString &, std::false_type>,
QtPrivate::TypeAndForceComplete<int, std::false_type>,
// method 'logoutRequested'
QtPrivate::TypeAndForceComplete<void, std::false_type>,
// method 'onPrimaryClicked'
QtPrivate::TypeAndForceComplete<void, std::false_type>,
// method 'onJuniorClicked'
@ -144,6 +176,14 @@ Q_CONSTINIT const QMetaObject SelectionWidget::staticMetaObject = { {
// method 'onSeniorClicked'
QtPrivate::TypeAndForceComplete<void, std::false_type>,
// method 'onStartClicked'
QtPrivate::TypeAndForceComplete<void, std::false_type>,
// method 'onChangePasswordClicked'
QtPrivate::TypeAndForceComplete<void, std::false_type>,
// method 'onLogoutClicked'
QtPrivate::TypeAndForceComplete<void, std::false_type>,
// method 'onExitClicked'
QtPrivate::TypeAndForceComplete<void, std::false_type>,
// method 'showUserInfo'
QtPrivate::TypeAndForceComplete<void, std::false_type>
>,
nullptr
@ -156,10 +196,15 @@ void SelectionWidget::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int
(void)_t;
switch (_id) {
case 0: _t->startRequest((*reinterpret_cast< std::add_pointer_t<QString>>(_a[1])),(*reinterpret_cast< std::add_pointer_t<int>>(_a[2]))); break;
case 1: _t->onPrimaryClicked(); break;
case 2: _t->onJuniorClicked(); break;
case 3: _t->onSeniorClicked(); break;
case 4: _t->onStartClicked(); break;
case 1: _t->logoutRequested(); break;
case 2: _t->onPrimaryClicked(); break;
case 3: _t->onJuniorClicked(); break;
case 4: _t->onSeniorClicked(); break;
case 5: _t->onStartClicked(); break;
case 6: _t->onChangePasswordClicked(); break;
case 7: _t->onLogoutClicked(); break;
case 8: _t->onExitClicked(); break;
case 9: _t->showUserInfo(); break;
default: ;
}
} else if (_c == QMetaObject::IndexOfMethod) {
@ -171,6 +216,13 @@ void SelectionWidget::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int
return;
}
}
{
using _t = void (SelectionWidget::*)();
if (_t _q_method = &SelectionWidget::logoutRequested; *reinterpret_cast<_t *>(_a[1]) == _q_method) {
*result = 1;
return;
}
}
}
}
@ -193,13 +245,13 @@ int SelectionWidget::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
if (_id < 0)
return _id;
if (_c == QMetaObject::InvokeMetaMethod) {
if (_id < 5)
if (_id < 10)
qt_static_metacall(this, _c, _id, _a);
_id -= 5;
_id -= 10;
} else if (_c == QMetaObject::RegisterMethodArgumentMetaType) {
if (_id < 5)
if (_id < 10)
*reinterpret_cast<QMetaType *>(_a[0]) = QMetaType();
_id -= 5;
_id -= 10;
}
return _id;
}
@ -210,4 +262,10 @@ void SelectionWidget::startRequest(const QString & _t1, int _t2)
void *_a[] = { nullptr, const_cast<void*>(reinterpret_cast<const void*>(std::addressof(_t1))), const_cast<void*>(reinterpret_cast<const void*>(std::addressof(_t2))) };
QMetaObject::activate(this, &staticMetaObject, 0, _a);
}
// SIGNAL 1
void SelectionWidget::logoutRequested()
{
QMetaObject::activate(this, &staticMetaObject, 1, nullptr);
}
QT_WARNING_POP

Binary file not shown.

@ -1,4 +1,5 @@
release/base_widget.o
release/change_password_dialog.o
release/login_widget.o
release/main_window.o
release/question_widget.o
@ -14,6 +15,7 @@ release/logger.o
release/problem_generator.o
release/qrc_qmake_qmake_qm_files.o
release/moc_base_widget.o
release/moc_change_password_dialog.o
release/moc_login_widget.o
release/moc_main_window.o
release/moc_question_widget.o

Binary file not shown.

Binary file not shown.

@ -0,0 +1,212 @@
#include "change_password_dialog.h"
ChangePasswordDialog::ChangePasswordDialog(exam_system::BackendInterface* backend, QWidget* parent)
: QDialog(parent), backend(backend)
{
setupUI();
setWindowTitle("修改密码");
setModal(true);
setFixedSize(400, 300);
}
void ChangePasswordDialog::setupUI()
{
auto* mainLayout = new QVBoxLayout(this);
mainLayout->setContentsMargins(20, 20, 20, 20);
mainLayout->setSpacing(15);
// 标题
auto* titleLabel = new QLabel("修改密码");
titleLabel->setStyleSheet("font-size: 18px; font-weight: bold;");
titleLabel->setAlignment(Qt::AlignCenter);
mainLayout->addWidget(titleLabel);
// 表单布局
auto* formLayout = new QFormLayout();
formLayout->setSpacing(10);
// 原密码输入
oldPasswordEdit = new QLineEdit();
oldPasswordEdit->setEchoMode(QLineEdit::Password);
oldPasswordEdit->setPlaceholderText("请输入当前密码");
formLayout->addRow("原密码:", oldPasswordEdit);
// 新密码输入
newPasswordEdit = new QLineEdit();
newPasswordEdit->setEchoMode(QLineEdit::Password);
newPasswordEdit->setPlaceholderText("6-10位包含大小写字母和数字");
formLayout->addRow("新密码:", newPasswordEdit);
// 确认密码输入
confirmPasswordEdit = new QLineEdit();
confirmPasswordEdit->setEchoMode(QLineEdit::Password);
confirmPasswordEdit->setPlaceholderText("请再次输入新密码");
formLayout->addRow("确认密码:", confirmPasswordEdit);
// 密码强度提示
strengthLabel = new QLabel();
strengthLabel->setStyleSheet("font-size: 12px; color: #666;");
strengthLabel->setWordWrap(true);
formLayout->addRow("", strengthLabel);
mainLayout->addLayout(formLayout);
// 按钮布局
auto* buttonLayout = new QHBoxLayout();
changeBtn = new QPushButton("确认修改");
cancelBtn = new QPushButton("取消");
changeBtn->setStyleSheet("QPushButton { padding: 8px 16px; }");
cancelBtn->setStyleSheet("QPushButton { padding: 8px 16px; }");
buttonLayout->addStretch();
buttonLayout->addWidget(changeBtn);
buttonLayout->addWidget(cancelBtn);
mainLayout->addLayout(buttonLayout);
// 连接信号槽
connect(changeBtn, &QPushButton::clicked, this, &ChangePasswordDialog::onChangePasswordClicked);
connect(cancelBtn, &QPushButton::clicked, this, &ChangePasswordDialog::onCancelClicked);
// 实时验证密码
connect(newPasswordEdit, &QLineEdit::textChanged, this, &ChangePasswordDialog::validatePassword);
connect(confirmPasswordEdit, &QLineEdit::textChanged, this, &ChangePasswordDialog::validatePassword);
}
void ChangePasswordDialog::validatePassword()
{
QString newPassword = newPasswordEdit->text();
QString confirmPassword = confirmPasswordEdit->text();
// 更新密码强度提示
updatePasswordStrength(newPassword);
// 验证密码匹配
if (!newPassword.isEmpty() && !confirmPassword.isEmpty()) {
if (newPassword != confirmPassword) {
strengthLabel->setText("❌ 两次输入的密码不一致");
strengthLabel->setStyleSheet("font-size: 12px; color: #e74c3c;");
changeBtn->setEnabled(false);
return;
}
}
// 验证密码格式
if (!newPassword.isEmpty() && !validatePasswordFormat(newPassword)) {
changeBtn->setEnabled(false);
return;
}
// 所有验证通过
if (!newPassword.isEmpty() && !confirmPassword.isEmpty() &&
validatePasswordFormat(newPassword) && newPassword == confirmPassword) {
strengthLabel->setText("✅ 密码格式正确");
strengthLabel->setStyleSheet("font-size: 12px; color: #27ae60;");
changeBtn->setEnabled(true);
} else {
changeBtn->setEnabled(false);
}
}
void ChangePasswordDialog::updatePasswordStrength(const QString& password)
{
if (password.isEmpty()) {
strengthLabel->setText("密码要求: 6-10位包含大小写字母和数字");
strengthLabel->setStyleSheet("font-size: 12px; color: #666;");
return;
}
// 检查各项条件
bool hasLength = password.length() >= 6 && password.length() <= 10;
bool hasLower = password.contains(QRegularExpression("[a-z]"));
bool hasUpper = password.contains(QRegularExpression("[A-Z]"));
bool hasDigit = password.contains(QRegularExpression("[0-9]"));
QStringList conditions;
if (!hasLength) conditions << "长度6-10位";
if (!hasLower) conditions << "小写字母";
if (!hasUpper) conditions << "大写字母";
if (!hasDigit) conditions << "数字";
if (conditions.isEmpty()) {
strengthLabel->setText("✅ 密码格式正确");
strengthLabel->setStyleSheet("font-size: 12px; color: #27ae60;");
} else {
strengthLabel->setText("❌ 缺少: " + conditions.join(", "));
strengthLabel->setStyleSheet("font-size: 12px; color: #e74c3c;");
}
}
bool ChangePasswordDialog::validatePasswordFormat(const QString& password)
{
// 检查长度
if (password.length() < 6 || password.length() > 10) {
return false;
}
// 检查是否包含大小写字母和数字
QRegularExpression regex("^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d).+$");
return regex.match(password).hasMatch();
}
void ChangePasswordDialog::onChangePasswordClicked()
{
QString oldPassword = oldPasswordEdit->text();
QString newPassword = newPasswordEdit->text();
QString confirmPassword = confirmPasswordEdit->text();
// 验证输入是否完整
if (oldPassword.isEmpty()) {
QMessageBox::warning(this, "输入错误", "请输入原密码");
oldPasswordEdit->setFocus();
return;
}
if (newPassword.isEmpty()) {
QMessageBox::warning(this, "输入错误", "请输入新密码");
newPasswordEdit->setFocus();
return;
}
if (confirmPassword.isEmpty()) {
QMessageBox::warning(this, "输入错误", "请确认新密码");
confirmPasswordEdit->setFocus();
return;
}
// 验证密码格式
if (!validatePasswordFormat(newPassword)) {
QMessageBox::warning(this, "密码格式错误",
"密码必须满足以下要求:\n"
"• 长度6-10位\n"
"• 包含大小写字母\n"
"• 包含数字");
newPasswordEdit->setFocus();
return;
}
// 验证密码匹配
if (newPassword != confirmPassword) {
QMessageBox::warning(this, "密码不匹配", "两次输入的新密码不一致");
confirmPasswordEdit->setFocus();
return;
}
// 调用后端接口修改密码
bool success = backend->ChangePassword(oldPassword.toStdString(), newPassword.toStdString());
if (success) {
QMessageBox::information(this, "修改成功", "密码修改成功!");
accept(); // 关闭对话框并返回 Accepted
} else {
QMessageBox::warning(this, "修改失败", "密码修改失败,请检查原密码是否正确");
oldPasswordEdit->setFocus();
oldPasswordEdit->selectAll();
}
}
void ChangePasswordDialog::onCancelClicked()
{
reject(); // 关闭对话框并返回 Rejected
}

@ -0,0 +1,44 @@
#ifndef CHANGEPASSWORDDIALOG_H
#define CHANGEPASSWORDDIALOG_H
#include <QDialog>
#include <QLineEdit>
#include <QPushButton>
#include <QLabel>
#include <QFormLayout>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QMessageBox>
#include <QRegularExpression>
#include "../shared/backend_interface.h"
class ChangePasswordDialog : public QDialog
{
Q_OBJECT
public:
explicit ChangePasswordDialog(exam_system::BackendInterface* backend, QWidget* parent = nullptr);
private slots:
void onChangePasswordClicked();
void onCancelClicked();
void validatePassword();
private:
void setupUI();
bool validatePasswordFormat(const QString& password);
void updatePasswordStrength(const QString& password);
exam_system::BackendInterface* backend;
QLineEdit* oldPasswordEdit;
QLineEdit* newPasswordEdit;
QLineEdit* confirmPasswordEdit;
QPushButton* changeBtn;
QPushButton* cancelBtn;
QLabel* strengthLabel;
};
#endif

@ -175,7 +175,7 @@ void LoginWidget::onLoginClicked()
if (result) {
showMessage("登录成功!");
emit loginSuccess(); // 发射登录成功信号,通知槽函数
emit loginSuccess(user_name); // 发射登录成功信号,通知槽函数
} else {
showMessage("登录失败,请检查用户名和密码");
}
@ -197,29 +197,42 @@ void LoginWidget::onSendCodeClicked()
return;
}
backend->SendVerificationCode(email.toStdString());
showMessage("验证码已发送到您的邮箱,请查收");
// 如果已经在倒计时,直接返回
if (countdownTimer && countdownTimer->isActive()) {
showMessage("请等待倒计时结束");
return;
}
bool result = backend->SendVerificationCode(email.toStdString());
if(result){
showMessage("验证码已发送到您的邮箱,请查收");
} else{
showMessage("邮箱已被注册");
}
// 初始化或重置计时器
if (!countdownTimer) {
countdownTimer = new QTimer(this);
connect(countdownTimer, &QTimer::timeout, this, &LoginWidget::onCountdownTimeout);
}
// 禁用发送按钮60秒防止重复发送
// 开始倒计时
sendCodeBtn->setEnabled(false);
sendCodeBtn->setText("60秒后重发");
QTimer *timer = new QTimer(this);
int countdown = 60;
connect(timer, &QTimer::timeout, this, [this, timer, &countdown]() {
countdown--;
if (countdown > 0) {
sendCodeBtn->setText(QString("%1秒后重发").arg(countdown));
} else {
sendCodeBtn->setEnabled(true);
sendCodeBtn->setText("发送验证码");
timer->stop();
timer->deleteLater();
}
});
timer->start(1000);
countdown_seconds_ = 60;
sendCodeBtn->setText(QString("%1秒后重发").arg(countdown_seconds_));
countdownTimer->start(1000);
}
void LoginWidget::onCountdownTimeout() {
countdown_seconds_--;
if (countdown_seconds_ > 0) {
sendCodeBtn->setText(QString("%1秒后重发").arg(countdown_seconds_));
} else {
sendCodeBtn->setEnabled(true);
sendCodeBtn->setText("发送验证码");
countdownTimer->stop();
}
}
void LoginWidget::onRegisterClicked()
@ -252,7 +265,7 @@ void LoginWidget::onRegisterClicked()
if (result) {
showMessage("注册成功!");
emit registerSuccess(); // 发射注册成功信号
emit registerSuccess(user_name); // 发射注册成功信号
} else {
showMessage("注册失败,验证码错误或邮箱已被注册");
}
@ -296,3 +309,19 @@ void LoginWidget::showLoginPage()
stackedWidget->setCurrentWidget(loginPage);
}
void LoginWidget::clearInputs()
{
// 清空登录页面
loginUserNameEdit->clear();
loginPasswordEdit->clear();
// 清空注册页面
registerEmailEdit->clear();
registerUserNameEdit->clear();
codeEdit->clear();
registerPasswordEdit->clear();
confirmPasswordEdit->clear();
// 确保显示登录页面
stackedWidget->setCurrentWidget(loginPage);
}

@ -16,12 +16,15 @@ class LoginWidget : public BaseWidget
public:
//禁止隐式类型转换
explicit LoginWidget(exam_system::BackendInterface* backend, QWidget* parent = nullptr);
//清空输入
void clearInputs();
signals:
// 登录成功信号
void loginSuccess();
void loginSuccess(const QString& userName);
// 注册成功信号
void registerSuccess();
void registerSuccess(const QString& userName);
private slots:
// 登录按钮点击
@ -44,7 +47,7 @@ private:
void setupRegisterPage();
// 验证密码格式
bool validatePassword(const QString &password);
void onCountdownTimeout();
// 登录页面组件
QWidget *loginPage;
QLineEdit *loginUserNameEdit;
@ -65,6 +68,8 @@ private:
//BackendInterface* backend;
QStackedWidget *stackedWidget; // 页面堆栈
QTimer *countdownTimer;
int countdown_seconds_;
};
#endif

@ -26,17 +26,19 @@ MainWindow::MainWindow(exam_system::BackendInterface* backend, QWidget* parent)
connect(loginWidget, &LoginWidget::registerSuccess, this, &MainWindow::showSelection);
connect(selectionWidget, &SelectionWidget::startRequest, this, &MainWindow::showQuestions);
connect(selectionWidget, &SelectionWidget::logoutRequested, this, &MainWindow::logout);
connect(questionWidget, &QuestionWidget::testCompleted, this, &MainWindow::showResult);
connect(resultWidget, &ResultWidget::restartTest, this, &MainWindow::restartFromResult);
connect(resultWidget, &ResultWidget::exitTest, this, &MainWindow::showSelection);
connect(resultWidget, &ResultWidget::exitTest, this, &MainWindow::onExitTest);
// 显示登录页面
stackedWidget->setCurrentWidget(loginWidget);
}
void MainWindow::showSelection() {
void MainWindow::showSelection(const QString& userName) {
selectionWidget->setCurrentUserName(userName);
stackedWidget->setCurrentWidget(selectionWidget);
}
@ -52,4 +54,16 @@ void MainWindow::showResult(const exam_system::TestResult& result) {
void MainWindow::restartFromResult() {
stackedWidget->setCurrentWidget(selectionWidget);
}
void MainWindow::logout(){
backend->UserLogout();
selectionWidget->setCurrentUserName("");
loginWidget->clearInputs();
stackedWidget->setCurrentWidget(loginWidget);
}
void MainWindow::onExitTest(){
backend->UserExit();
QApplication::quit();
}

@ -16,11 +16,12 @@ public:
explicit MainWindow(exam_system::BackendInterface* backend, QWidget* parent = nullptr);
private slots:
void showSelection();
void showSelection(const QString& userName);
void showQuestions(const QString& difficulty, int count);
void showResult(const exam_system::TestResult& result);
void restartFromResult();
void logout();
void onExitTest();
private:
exam_system::BackendInterface* backend;
QStackedWidget* stackedWidget;

@ -2,6 +2,7 @@
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QGroupBox>
#include <QMessageBox>
QuestionWidget::QuestionWidget(exam_system::BackendInterface* backend, QWidget* parent)
: BaseWidget(backend, parent) {
@ -36,10 +37,12 @@ void QuestionWidget::setupUI() {
questionLayout->addLayout(optionsLayout);
auto* buttonLayout = new QHBoxLayout;
prevBtn = new QPushButton("上一题");
nextBtn = new QPushButton("下一题");
submitBtn = new QPushButton("提交试卷");
submitBtn->setVisible(false);
buttonLayout->addWidget(prevBtn);
buttonLayout->addStretch();
buttonLayout->addWidget(nextBtn);
buttonLayout->addWidget(submitBtn);
@ -48,8 +51,10 @@ void QuestionWidget::setupUI() {
mainLayout->addWidget(questionGroup);
mainLayout->addLayout(buttonLayout);
connect(prevBtn, &QPushButton::clicked, this, &QuestionWidget::onPrevClicked);
connect(nextBtn, &QPushButton::clicked, this, &QuestionWidget::onNextClicked);
connect(submitBtn, &QPushButton::clicked, this, &QuestionWidget::onSubmitClicked);
connect(optionGroup, &QButtonGroup::buttonClicked, this, &QuestionWidget::onOptionSelected);
}
void QuestionWidget::startTest(const QString& difficulty, int questionCount) {
@ -60,30 +65,95 @@ void QuestionWidget::startTest(const QString& difficulty, int questionCount) {
}
void QuestionWidget::showQuestion(int index) {
if (index < 0 || index >= questions_.size()) return;
if (index < 0 || index >= questions_.size()) return;
const auto& question = questions_[index];
questionLabel->setText(QString::number(index + 1) + ". " +
QString::fromStdString(question.content));
optionGroup->setExclusive(false);
for (int i = 0; i < 4; ++i) {
optionButtons[i]->setChecked(false);
}
optionGroup->setExclusive(true);
// 然后根据保存的答案设置选中状态
int savedAnswer = user_answers_[index];
if (savedAnswer != -1 && savedAnswer >= 0 && savedAnswer < 4) {
optionButtons[savedAnswer]->setChecked(true);
}
for (int i = 0; i < 4; ++i) {
optionButtons[i]->setText(QString("%1. %2").arg(char('A' + i))
.arg(QString::fromStdString(question.options[i])));
optionButtons[i]->setChecked(user_answers_[index] == i);
}
updateProgress();
// 更新按钮状态
submitBtn->setVisible(index == questions_.size() - 1);
nextBtn->setVisible(index < questions_.size() - 1);
updateButtonStates();
}
void QuestionWidget::updateProgress() {
progressLabel->setText(QString("进度: %1/%2").arg(current_question_ + 1).arg(questions_.size()));
}
void QuestionWidget::updateButtonStates() {
// 更新上一题按钮状态
prevBtn->setEnabled(current_question_ > 0);
// 更新下一题按钮状态
nextBtn->setEnabled(isCurrentQuestionAnswered() && current_question_ < questions_.size() - 1);
// 更新提交按钮状态和可见性
bool isLastQuestion = current_question_ == questions_.size() - 1;
submitBtn->setVisible(isLastQuestion);
if (isLastQuestion) {
submitBtn->setEnabled(isCurrentQuestionAnswered());
}
// 更新按钮文本
if (current_question_ == questions_.size() - 1) {
nextBtn->setVisible(false);
} else {
nextBtn->setVisible(true);
}
}
bool QuestionWidget::isCurrentQuestionAnswered() {
return user_answers_[current_question_] != -1;
}
void QuestionWidget::onOptionSelected() {
// 保存当前选择的答案
int selected = optionGroup->checkedId();
if (selected != -1) {
user_answers_[current_question_] = selected;
}
// 更新按钮状态
updateButtonStates();
}
void QuestionWidget::onPrevClicked() {
// 保存当前答案
int selected = optionGroup->checkedId();
if (selected != -1) {
user_answers_[current_question_] = selected;
}
// 显示上一题
if (current_question_ > 0) {
current_question_--;
showQuestion(current_question_);
}
}
void QuestionWidget::onNextClicked() {
// 检查当前题目是否已回答
if (!isCurrentQuestionAnswered()) {
QMessageBox::warning(this, "未选择答案", "请先选择当前题目的答案!");
return;
}
// 保存当前答案
int selected = optionGroup->checkedId();
if (selected != -1) {
@ -98,12 +168,36 @@ void QuestionWidget::onNextClicked() {
}
void QuestionWidget::onSubmitClicked() {
// 检查最后一题是否已回答
if (!isCurrentQuestionAnswered()) {
QMessageBox::warning(this, "未选择答案", "请先选择当前题目的答案!");
return;
}
// 保存最后一题的答案
int selected = optionGroup->checkedId();
if (selected != -1) {
user_answers_[current_question_] = selected;
}
// 检查是否有未回答的题目
int unansweredCount = 0;
for (int answer : user_answers_) {
if (answer == -1) {
unansweredCount++;
}
}
if (unansweredCount > 0) {
QMessageBox::StandardButton reply;
reply = QMessageBox::question(this, "确认提交",
QString("还有 %1 道题目未回答,确定要提交吗?").arg(unansweredCount),
QMessageBox::Yes | QMessageBox::No);
if (reply == QMessageBox::No) {
return;
}
}
// 提交答案并获取结果
exam_system::TestResult result = backend->SubmitAnswers(user_answers_);
emit testCompleted(result);

@ -24,11 +24,15 @@ signals:
private slots:
void onNextClicked();
void onSubmitClicked();
void onPrevClicked();
void onOptionSelected();
private:
void setupUI() override;
void showQuestion(int index);
void updateProgress();
void updateButtonStates();
bool isCurrentQuestionAnswered();
std::vector<exam_system::QuestionInfo> questions_;
std::vector<int> user_answers_;
@ -39,6 +43,7 @@ private:
QButtonGroup* optionGroup;
QRadioButton* optionButtons[4];
QPushButton* nextBtn;
QPushButton* prevBtn;
QPushButton* submitBtn;
};

@ -1,62 +1,125 @@
#include "selection_widget.h"
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QButtonGroup>
#include <QGroupBox>
#include <QApplication>
SelectionWidget::SelectionWidget(exam_system::BackendInterface* backend, QWidget* parent)
: BaseWidget(backend, parent) {
setupUI();
}
void SelectionWidget::setupUI() {
void SelectionWidget::setupUI()
{
auto* mainLayout = new QVBoxLayout(this);
auto* titleLabel = new QLabel("请选择学习阶段");
titleLabel->setAlignment(Qt::AlignCenter);
titleLabel->setStyleSheet("font-size: 18px; font-weight: bold; margin: 20px;");
auto* buttonLayout = new QHBoxLayout;
auto* primaryBtn = new QPushButton("小学");
auto* juniorBtn = new QPushButton("初中");
auto* seniorBtn = new QPushButton("高中");
// 设置按钮样式
QString buttonStyle = "QPushButton { font-size: 16px; padding: 15px; min-width: 100px; }";
mainLayout->setContentsMargins(20, 10, 20, 20);
mainLayout->setSpacing(15);
// 创建菜单栏
createMenuBar();
mainLayout->setMenuBar(menuBar);
// 欢迎标签
welcomeLabel = new QLabel("欢迎使用数学学习软件");
welcomeLabel->setAlignment(Qt::AlignCenter);
welcomeLabel->setStyleSheet("font-size: 24px; font-weight: bold; margin: 20px;");
mainLayout->addWidget(welcomeLabel);
// 用户信息标签
userInfoLabel = new QLabel();
userInfoLabel->setAlignment(Qt::AlignCenter);
userInfoLabel->setStyleSheet("font-size: 14px; margin-bottom: 30px;");
mainLayout->addWidget(userInfoLabel);
// 难度选择区域
auto* difficultyLabel = new QLabel("选择学习阶段:");
difficultyLabel->setStyleSheet("font-size: 16px;");
mainLayout->addWidget(difficultyLabel);
auto* buttonLayout = new QHBoxLayout();
primaryBtn = new QPushButton("小学");
juniorBtn = new QPushButton("初中");
seniorBtn = new QPushButton("高中");
// 难度选择按钮
QString buttonStyle = "QPushButton { font-size: 14px; padding: 10px 20px; min-width: 100px; }";
primaryBtn->setStyleSheet(buttonStyle);
juniorBtn->setStyleSheet(buttonStyle);
seniorBtn->setStyleSheet(buttonStyle);
buttonLayout->addWidget(primaryBtn);
buttonLayout->addWidget(juniorBtn);
buttonLayout->addWidget(seniorBtn);
mainLayout->addLayout(buttonLayout);
// 题目数量选择
auto* countLayout = new QHBoxLayout;
auto* countLayout = new QHBoxLayout();
auto* countLabel = new QLabel("题目数量:");
countLabel->setStyleSheet("font-size: 14px;");
countSpinBox = new QSpinBox;
countSpinBox->setRange(10, 30);
countSpinBox->setRange(5, 50);
countSpinBox->setValue(10);
countLayout->addWidget(countLabel);
countLayout->addWidget(countSpinBox);
countLayout->addStretch();
mainLayout->addLayout(countLayout);
// 开始测试按钮
startBtn = new QPushButton("开始测试");
startBtn->setEnabled(false);
startBtn->setStyleSheet("QPushButton { font-size: 16px; padding: 10px; background-color: #fefefeff; color: black; }");
mainLayout->addWidget(titleLabel);
mainLayout->addLayout(buttonLayout);
mainLayout->addLayout(countLayout);
mainLayout->addWidget(startBtn);
startBtn->setStyleSheet("QPushButton { font-size: 16px; padding: 10px 20px; background-color: #4CAF50; color: white; }");
auto* startLayout = new QHBoxLayout();
startLayout->addStretch();
startLayout->addWidget(startBtn);
startLayout->addStretch();
mainLayout->addLayout(startLayout);
mainLayout->addStretch();
// 连接信号槽
connect(primaryBtn, &QPushButton::clicked, this, &SelectionWidget::onPrimaryClicked);
connect(juniorBtn, &QPushButton::clicked, this, &SelectionWidget::onJuniorClicked);
connect(seniorBtn, &QPushButton::clicked, this, &SelectionWidget::onSeniorClicked);
connect(startBtn, &QPushButton::clicked, this, &SelectionWidget::onStartClicked);
}
void SelectionWidget::createMenuBar()
{
menuBar = new QMenuBar(this);
// 用户菜单
userMenu = menuBar->addMenu("用户");
userInfoAction = new QAction("个人信息", this);
changePasswordAction = new QAction("修改密码", this);
logoutAction = new QAction("退出登录", this);
userMenu->addAction(userInfoAction);
userMenu->addAction(changePasswordAction);
userMenu->addSeparator();
userMenu->addAction(logoutAction);
// 系统菜单
systemMenu = menuBar->addMenu("系统");
exitAction = new QAction("退出程序", this);
systemMenu->addAction(exitAction);
// 连接菜单动作
connect(userInfoAction, &QAction::triggered, this, &SelectionWidget::showUserInfo);
connect(changePasswordAction, &QAction::triggered, this, &SelectionWidget::onChangePasswordClicked);
connect(logoutAction, &QAction::triggered, this, &SelectionWidget::onLogoutClicked);
connect(exitAction, &QAction::triggered, this, &SelectionWidget::onExitClicked);
}
void SelectionWidget::setCurrentUserName(const QString& userName)
{
currentUserName = userName;
userInfoLabel->setText(QString("当前用户: %1").arg(userName));
}
void SelectionWidget::onPrimaryClicked() {
selectedDifficulty = "primary";
showMessage("您已选择小学难度");
@ -80,3 +143,38 @@ void SelectionWidget::onStartClicked() {
emit startRequest(selectedDifficulty, countSpinBox->value());
}
}
void SelectionWidget::onChangePasswordClicked()
{
ChangePasswordDialog dialog(backend, this);
if (dialog.exec() == QDialog::Accepted) {
QMessageBox::information(this, "成功", "密码修改成功!");
}
}
void SelectionWidget::onLogoutClicked()
{
QMessageBox::StandardButton reply;
reply = QMessageBox::question(this, "确认退出", "确定要退出登录吗?",
QMessageBox::Yes | QMessageBox::No);
if (reply == QMessageBox::Yes) {
emit logoutRequested();
}
}
void SelectionWidget::onExitClicked()
{
QMessageBox::StandardButton reply;
reply = QMessageBox::question(this, "退出程序", "确定要退出程序吗?",
QMessageBox::Yes | QMessageBox::No);
if (reply == QMessageBox::Yes) {
QApplication::quit();
}
}
void SelectionWidget::showUserInfo()
{
QMessageBox::information(this, "个人信息",
QString("用户名: %1\n\n欢迎使用数学学习软件!").arg(currentUserName));
}

@ -6,7 +6,14 @@
#include <QPushButton>
#include <QSpinBox>
#include <QLabel>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QMenuBar>
#include <QMenu>
#include <QAction>
#include <QMessageBox>
#include "../shared/backend_interface.h"
#include "change_password_dialog.h"
class SelectionWidget : public BaseWidget {
Q_OBJECT
@ -14,22 +21,47 @@ class SelectionWidget : public BaseWidget {
public:
//禁止隐式类型转换
explicit SelectionWidget(exam_system::BackendInterface* backend, QWidget* parent = nullptr);
// 设置当前用户名
void setCurrentUserName(const QString& userName);
signals:
void startRequest(const QString& difficulty, int questionCount);
void logoutRequested();
private slots:
void onPrimaryClicked();
void onJuniorClicked();
void onSeniorClicked();
void onStartClicked();
void onChangePasswordClicked();
void onLogoutClicked();
void onExitClicked();
void showUserInfo();
private:
void setupUI() override;
void setupUI() override;
void createMenuBar();
QString selectedDifficulty;
QString currentUserName;
// UI 组件
QSpinBox* countSpinBox;
QPushButton* startBtn;
QPushButton* primaryBtn;
QPushButton* juniorBtn;
QPushButton* seniorBtn;
// 菜单栏
QMenuBar* menuBar;
QMenu* userMenu;
QMenu* systemMenu;
QAction* changePasswordAction;
QAction* logoutAction;
QAction* exitAction;
QAction* userInfoAction;
QLabel* welcomeLabel;
QLabel* userInfoLabel;
};
#endif

@ -0,0 +1,13 @@
# 用户数据文件格式: username,password,user_type,email
# 用户类型: 小学, 初中, 高中
# 自动生成 - 请勿手动编辑
zhangsan1,Erp91637,小学,zhangsan1@example.com
zhangsan2,123,小学,zhangsan2@example.com
zhangsan3,123,小学,zhangsan3@example.com
lisi1,123,初中,lisi1@example.com
lisi2,123,初中,lisi2@example.com
lisi3,123,初中,lisi3@example.com
wangwu1,123,高中,wangwu1@example.com
wangwu2,123,高中,wangwu2@example.com
wangwu3,123,高中,wangwu3@example.com
1 # 用户数据文件格式: username,password,user_type,email
2 # 用户类型: 小学, 初中, 高中
3 # 自动生成 - 请勿手动编辑
4 zhangsan1,Erp91637,小学,zhangsan1@example.com
5 zhangsan2,123,小学,zhangsan2@example.com
6 zhangsan3,123,小学,zhangsan3@example.com
7 lisi1,123,初中,lisi1@example.com
8 lisi2,123,初中,lisi2@example.com
9 lisi3,123,初中,lisi3@example.com
10 wangwu1,123,高中,wangwu1@example.com
11 wangwu2,123,高中,wangwu2@example.com
12 wangwu3,123,高中,wangwu3@example.com

@ -0,0 +1,19 @@
1. 21 * 13 + 54 / 98
2. 44 - 6
3. 73 + 90 * 73 / 36 - 23
4. 28 / 39 * 46
5. 92 * 55
6. 32 / 50
7. 73 * 74 + 71 / 73
8. 90 * 28 + 14 - 78 - 5
9. 2 / 57
10. 95 + 99 * 85 / 92 - 33

@ -0,0 +1,19 @@
1. 68 - 43 / 84 / 9 + 9
2. 15 / 92 / 46 * 60 * 88
3. 78 - 62 + 89 / 49
4. 61 * 93 / 1
5. 51 * 3 * 18
6. 57 + 62 - 12 / 82
7. 2 / 6 + 73 - 25
8. 99 - 68 / 45 - 10 + 46
9. 66 + 72 * 92 / 85
10. 20 / 9 * 35
Loading…
Cancel
Save