#include "tlogin.h" #include "appevent.h" #include "qlabel.h" #include "qlineedit.h" #include #include #include #include #include #include #include "qstyle.h" #include "qwidget.h" #include "utils/layoutbuilder.h" #include "widgets/captchalabel.h" #include "api/tloginapi.h" TLogin::TLogin(QWidget *parent) : QDialog(parent) { setObjectName("Login"); setWindowFlags(Qt::Window | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint); setWindowTitle(tr("Login")); using namespace Layouting; info = new QLabel; info->setStyleSheet("color: #333333;"); info->setText(tr("Welcome to the system")); // 创建登录组件 usernameEdit = new QLineEdit(); usernameEdit->setPlaceholderText(tr("Enter your user name")); usernameEdit->setMinimumWidth(200); passwordEdit = new QLineEdit(); passwordEdit->setEchoMode(QLineEdit::Password); passwordEdit->setPlaceholderText(tr("Enter your ExamNo")); // 添加验证码输入框 captchaEdit = new QLineEdit(); captchaEdit->setPlaceholderText(tr("Enter captcha")); captchaEdit->setMaxLength(6); // 验证码图片显示 captchaImage = new CaptchaLabel(); captchaImage->setFixedSize(120, 40); captchaImage->setScaledContents(true); captchaImage->setCursor(Qt::PointingHandCursor); // 设置鼠标指针为手型,提示可点击 captchaImage->setToolTip(tr("Click to refresh captcha")); // 添加提示文本 // 添加记住用户名复选框 rememberUsernameCheckBox = new QCheckBox(tr("Remember Username")); // 连接 clicked 信号到刷新验证码的槽函数 connect(captchaImage, &CaptchaLabel::clicked, this, &TLogin::getCaptcha); // 创建表单布局,将captchaEdit和captchaImage放在同一行 QWidget *w = Group{Column{Row{st, tr("Login"), st}, Form{tr("Username:"), usernameEdit, br, tr("Password:"), passwordEdit, br, tr("Captcha:"), Row{captchaEdit, captchaImage}, br, "", rememberUsernameCheckBox}, Row{PushButton{bindTo(&loginPushButton), text(tr("Login")), onClicked(std::bind(&TLogin::on_login_clicked, this))}, PushButton{bindTo(&offlineLoginButton), text(tr("Offline Login")), onClicked(std::bind(&TLogin::on_offline_login_clicked, this))}} }} .emerge(); QPushButton *close; auto h = Row{st, PushButton{bindTo(&close), ""}}; Column{h, st, Row{st, w, st}, st, info, noMargin}.attachTo(this); // 设置美观的样式表,不使用背景图片 QString styleSheet = R"( QDialog#Login { background-color: #2c3e50; border: 1px solid #34495e; border-radius: 5px; } QGroupBox { background-color: #ecf0f1; border-radius: 5px; border: 1px solid #bdc3c7; padding: 10px; } QLineEdit { border: 1px solid #bdc3c7; border-radius: 3px; padding: 5px; background-color: white; } QLineEdit:focus { border: 1px solid #3498db; background-color: #f8f9fa; } QPushButton { background-color: #3498db; color: white; border: none; border-radius: 3px; padding: 8px 16px; font-weight: bold; } QPushButton:hover { background-color: #2980b9; } QPushButton:disabled { background-color: #95a5a6; } QLabel { color: #333333; } )"; setStyleSheet(styleSheet); QPixmap closePix = style()->standardPixmap(QStyle::SP_TitleBarCloseButton); close->setIcon(closePix); close->setStyleSheet(R"__( QPushButton { border: none; background-color: transparent; padding: 5px; } QPushButton:hover { background-color: #e74c3c; border-radius: 3px; } )__"); resize({400, 450}); loginPushButton->setEnabled(true); QObject::connect(close, &QPushButton::clicked, this, &TLogin::close); // 加载保存的用户名 loadSavedUsername(); // 获取初始验证码 getCaptcha(); } // 加载保存的用户名 void TLogin::loadSavedUsername() { // 从配置中读取保存的用户名 QVariant savedUsername = AppEvent::instance()->configValue("savedUsername"); if (!savedUsername.isNull() && savedUsername.isValid()) { usernameEdit->setText(savedUsername.toString()); rememberUsernameCheckBox->setChecked(true); } QVariant savedPassword = AppEvent::instance()->configValue("savedPassword"); if (!savedPassword.isNull() && savedPassword.isValid()) { passwordEdit->setText(savedPassword.toString()); rememberUsernameCheckBox->setChecked(true); } } void TLogin::getCaptcha() { bool ok = false; TC::Captcha::Data captchaData = TC::Captcha().get(&ok); if (ok) { captchaId = captchaData.captchaId; // 处理Base64图片数据 QString imgData = captchaData.imgPath; if (imgData.startsWith("data:image/png;base64,")) { imgData = imgData.mid(22); // 移除前缀 } QByteArray imageBytes = QByteArray::fromBase64(imgData.toLatin1()); QPixmap pixmap; pixmap.loadFromData(imageBytes); captchaImage->setPixmap(pixmap); } else { info->setText(tr("Failed to get captcha")); } } void TLogin::on_refresh_captcha_clicked() { getCaptcha(); } void TLogin::mousePressEvent(QMouseEvent *event) { if (event->button() == Qt::LeftButton) { m_dragPosition = event->globalPos() - frameGeometry().topLeft(); event->accept(); } } void TLogin::mouseMoveEvent(QMouseEvent *event) { if (event->buttons() & Qt::LeftButton) { move(event->globalPos() - m_dragPosition); event->accept(); } } void TLogin::on_login_clicked() { const QString userName = usernameEdit->text(); const QString password = passwordEdit->text(); const QString captcha = captchaEdit->text(); if (userName.isEmpty() || password.isEmpty()) { QMessageBox::warning(this, tr("Login failed"), tr("User name or password cannot be empty.")); return; } if (captcha.isEmpty()) { QMessageBox::warning(this, tr("Login failed"), tr("Captcha cannot be empty.")); return; } // 这里需要修改Login API,添加验证码参数 // 由于我们没有看到Login类的完整实现,这里假设需要修改Login构造函数 // 实际实现时需要根据后端API的要求进行调整 // 修改Login类构造函数,添加captchaId和captcha参数 // 这里只是示例,实际实现可能需要调整 bool ok = TC::Login(userName, password, captchaId, captcha).post(); if (ok && AppEvent::instance()->isLogin()) { // 如果选择了记住用户名,则保存用户名到配置 qDebug() << rememberUsernameCheckBox->isChecked(); if (rememberUsernameCheckBox->isChecked()) { AppEvent::instance()->setConfigValue("savedUsername", userName); AppEvent::instance()->setConfigValue("savedPassword", password); AppEvent::instance()->configSave(); // 保存配置到文件 } else { // 如果未选择记住用户名,则清除之前保存的用户名 AppEvent::instance()->setConfigValue("savedUsername", ""); AppEvent::instance()->setConfigValue("savedPassword", ""); AppEvent::instance()->configSave(); // 保存配置到文件 } // 登录成功,发出信号 emit loginSuccessful(); close(); } else { // 登录失败,显示提示框并刷新验证码 QMessageBox::warning(this, tr("Login failed"), tr("User name, password or captcha error, please try again.")); getCaptcha(); // 刷新验证码 captchaEdit->clear(); // 清空验证码输入框 return; } } void TLogin::on_offline_login_clicked() { // 离线登录不需要验证用户名、密码和验证码 // 直接设置一个默认用户名,表示是离线模式 AppEvent::instance()->setConfigValue("offlineMode", true); AppEvent::instance()->configSave(); // 保存配置到文件 // 发出登录成功信号 emit loginSuccessful(); close(); }