189 lines
5.9 KiB
C++
189 lines
5.9 KiB
C++
#include "bootpassword.h"
|
|
#include "numpaddialog.h"
|
|
#include <QKeyEvent>
|
|
#include <QVBoxLayout>
|
|
#include <QHBoxLayout>
|
|
#include <QLineEdit>
|
|
#include <QLabel>
|
|
#include <QPushButton>
|
|
#include <QTimer>
|
|
#include "global.h"
|
|
|
|
BootPasswordPage::BootPasswordPage(AppContext* ctx, QWidget* parent)
|
|
: BasePage(ctx, parent)
|
|
{
|
|
QVBoxLayout* root = new QVBoxLayout(this);
|
|
root->setContentsMargins(0, 0, 0, 0);
|
|
root->addStretch(1);
|
|
|
|
QWidget* col = new QWidget(this);
|
|
col->setFixedWidth(600);
|
|
col->setProperty("card", true); // 登录主体框体背景(面板色 + 圆角边框)
|
|
QVBoxLayout* lay = new QVBoxLayout(col);
|
|
lay->setContentsMargins(40, 40, 40, 40); // 框体内边距
|
|
lay->setSpacing(50);
|
|
lay->setAlignment(Qt::AlignHCenter);
|
|
|
|
|
|
// 标题
|
|
QLabel* title = label("请输入开机密码", 60, C::TEXT, true, col);
|
|
title->setAlignment(Qt::AlignCenter);
|
|
lay->addWidget(title);
|
|
lay->addSpacing(30);
|
|
|
|
// 密码输入框(只读回显,点击弹出数字键盘)
|
|
m_input = new QLineEdit(col);
|
|
m_input->setReadOnly(true);
|
|
m_input->setEchoMode(QLineEdit::Password);
|
|
m_input->setAlignment(Qt::AlignCenter);
|
|
m_input->setFixedSize(450, 120);
|
|
m_input->setStyleSheet("font-size:80px");
|
|
m_input->setProperty("clickable", true);
|
|
lay->addWidget(m_input, 0, Qt::AlignHCenter);
|
|
lay->addSpacing(40);
|
|
m_input->installEventFilter(this);
|
|
m_input->setFocusPolicy(Qt::StrongFocus);
|
|
|
|
// 错误提示(默认隐藏)
|
|
m_error = label("密码输入有误,请重新输入", 80, C::DANGER, true, col);
|
|
m_error->setAlignment(Qt::AlignCenter);
|
|
m_error->setStyleSheet("font-size:80px");
|
|
m_error->hide();
|
|
lay->addWidget(m_error);
|
|
|
|
// 确认 / 取消
|
|
QHBoxLayout* btnRow = new QHBoxLayout();
|
|
btnRow->setSpacing(80);
|
|
btnRow->addStretch(1);
|
|
QPushButton* ok = button("确认", "", col);
|
|
ok->setFixedSize(160, 140);
|
|
ok->setStyleSheet("font-size:60px;");
|
|
connect(ok, &QPushButton::clicked, this, &BootPasswordPage::onConfirm);
|
|
QPushButton* cancel = button("取消", "", col);
|
|
cancel->setFixedSize(160, 140);
|
|
// 取消语义:选中时红底白字(内联 :focus,确保覆盖全局蓝色选中态)
|
|
cancel->setStyleSheet("font-size:60px;QPushButton:focus{background-color:#E5484D;color:#FFFFFF;border:2px solid #FFA6A9;}");
|
|
connect(cancel, &QPushButton::clicked, this, &BootPasswordPage::onCancel);
|
|
btnRow->addWidget(ok);
|
|
btnRow->addWidget(cancel);
|
|
btnRow->addStretch(1);
|
|
lay->addLayout(btnRow);
|
|
|
|
// 忘记密码 / 修改密码(平时红字透明底,按下红底白字)
|
|
const QString linkBtnStyle =
|
|
"QPushButton{color:#E5484D;background:transparent;border:1px solid transparent;border-radius:6px;font-size:30px;}"
|
|
"QPushButton:hover,QPushButton:pressed,QPushButton:focus{background-color:#E5484D;color:#FFFFFF;border:1px solid #FFA6A9;}";
|
|
QHBoxLayout* forgetRow = new QHBoxLayout();
|
|
forgetRow->setSpacing(80);
|
|
forgetRow->addStretch(1);
|
|
QPushButton* forget = button("忘记密码", "", col);
|
|
forget->setFixedSize(130, 60);
|
|
forget->setStyleSheet(linkBtnStyle);
|
|
connect(forget, &QPushButton::clicked, this, &BootPasswordPage::onForget);
|
|
QPushButton* modify = button("修改密码", "", col);
|
|
modify->setFixedSize(130, 60);
|
|
modify->setStyleSheet(linkBtnStyle);
|
|
connect(modify, &QPushButton::clicked, this, &BootPasswordPage::onForget);
|
|
forgetRow->addWidget(forget);
|
|
forgetRow->addWidget(modify);
|
|
forgetRow->addStretch(1);
|
|
lay->addLayout(forgetRow);
|
|
|
|
root->addWidget(col, 0, Qt::AlignHCenter);
|
|
root->addStretch(1);
|
|
|
|
refreshInput();
|
|
}
|
|
|
|
// 点击密码输入框 → 弹出数字键盘(拦截鼠标点击)
|
|
bool BootPasswordPage::eventFilter(QObject* obj, QEvent* ev)
|
|
{
|
|
if (obj == m_input) {
|
|
if (ev->type() == QEvent::MouseButtonPress) {
|
|
onInputClicked();
|
|
return true;
|
|
}
|
|
if (ev->type() == QEvent::KeyPress) {
|
|
QKeyEvent* ke = static_cast<QKeyEvent*>(ev);
|
|
if (ke->key() == Qt::Key_Return || ke->key() == Qt::Key_Enter) {
|
|
onInputClicked();
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return BasePage::eventFilter(obj, ev);
|
|
}
|
|
|
|
void BootPasswordPage::onInputClicked()
|
|
{
|
|
if (m_locked)
|
|
return;
|
|
NumPadDialog dlg(this);
|
|
dlg.setMaxLen(4);
|
|
dlg.setValue(m_value);
|
|
if (dlg.exec() == QDialog::Accepted) {
|
|
m_value = dlg.value();
|
|
m_error->hide();
|
|
refreshInput();
|
|
}
|
|
}
|
|
|
|
void BootPasswordPage::onConfirm()
|
|
{
|
|
if (m_locked)
|
|
return;
|
|
|
|
if (m_value == ctx()->password()) {
|
|
m_wrongCount = 0;
|
|
clearInput();
|
|
emit navigate(PageSelfCheck);
|
|
} else {
|
|
m_wrongCount++;
|
|
clearInput();
|
|
if (m_wrongCount >= 5) {
|
|
// 【设计建议】连续 5 次错误锁定 30s
|
|
m_locked = true;
|
|
m_error->setText("连续输入错误,已锁定 30 秒");
|
|
m_error->show();
|
|
QTimer::singleShot(30000, this, [this]() {
|
|
m_locked = false;
|
|
m_wrongCount = 0;
|
|
m_error->hide();
|
|
});
|
|
} else {
|
|
emit navigate(PageWarning);
|
|
}
|
|
}
|
|
}
|
|
|
|
void BootPasswordPage::onCancel()
|
|
{
|
|
clearInput();
|
|
}
|
|
|
|
void BootPasswordPage::onForget()
|
|
{
|
|
clearInput();
|
|
emit navigate(PageMgmtLogin);
|
|
}
|
|
|
|
void BootPasswordPage::clearInput()
|
|
{
|
|
m_value.clear();
|
|
refreshInput();
|
|
}
|
|
|
|
void BootPasswordPage::focusInput()
|
|
{
|
|
onInputClicked();
|
|
}
|
|
|
|
void BootPasswordPage::refreshInput()
|
|
{
|
|
const bool empty = m_value.isEmpty();
|
|
// 空态:无论是否被选中都显示提示文字(灰字);有内容:显示密码圆点
|
|
m_input->setEchoMode(empty ? QLineEdit::Normal : QLineEdit::Password);
|
|
m_input->setText(empty ? "点击输入密码" : m_value);
|
|
m_input->setStyleSheet(empty ? "font-size:50px;color:#9AA7B4;" : "font-size:80px;");
|
|
}
|