From b66fd499efcd8d38081f01d561c7911f296f6de0 Mon Sep 17 00:00:00 2001 From: Chenx Dust Date: Sun, 2 Aug 2026 21:03:22 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E8=BF=9E=E6=8E=A5=E6=97=B6=E6=8F=90?= =?UTF-8?q?=E7=A4=BA=E8=A1=A5=E5=85=85=E7=9F=AD=E4=BF=A1=E9=AA=8C=E8=AF=81?= =?UTF-8?q?=E6=89=8B=E6=9C=BA=E5=8F=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../coordinators/authdialogcoordinator.cpp | 84 +++++++++++++++++++ .../coordinators/authdialogcoordinator.h | 11 +++ .../coordinators/connectionuicontroller.cpp | 56 ++++++++++++- .../coordinators/connectionuicontroller.h | 6 +- 4 files changed, 155 insertions(+), 2 deletions(-) diff --git a/presentation/coordinators/authdialogcoordinator.cpp b/presentation/coordinators/authdialogcoordinator.cpp index ac62b48..775372e 100644 --- a/presentation/coordinators/authdialogcoordinator.cpp +++ b/presentation/coordinators/authdialogcoordinator.cpp @@ -4,9 +4,11 @@ #include #include #include +#include #include #include #include +#include #include #include #include @@ -53,6 +55,88 @@ void AuthDialogCoordinator::requestLogin( loginWindow->show(); } +void AuthDialogCoordinator::requestPhoneNumber( + const QString &countryCode, + const QString &phoneNumber +) +{ + if (phoneNumberDialog != nullptr) + { + phoneNumberDialog->raise(); + phoneNumberDialog->activateWindow(); + return; + } + + auto *dialog = new QDialog(parentWidget); + phoneNumberDialog = dialog; + dialog->setAttribute(Qt::WA_DeleteOnClose); + dialog->setWindowModality(Qt::WindowModal); + dialog->setWindowTitle("短信验证"); + + auto *layout = new QVBoxLayout(dialog); + layout->addWidget(new QLabel("请输入接收验证码的手机号码:", dialog)); + + auto *phoneLayout = new QHBoxLayout; + phoneLayout->addWidget(new QLabel("+", dialog)); + auto *countryCodeEdit = new QLineEdit(countryCode, dialog); + countryCodeEdit->setObjectName("countryCodeLineEdit"); + countryCodeEdit->setMaximumWidth(60); + countryCodeEdit->setPlaceholderText("国家码"); + phoneLayout->addWidget(countryCodeEdit); + phoneLayout->addWidget(new QLabel("-", dialog)); + auto *phoneNumberEdit = new QLineEdit(phoneNumber, dialog); + phoneNumberEdit->setObjectName("phoneNumberLineEdit"); + phoneNumberEdit->setPlaceholderText("手机号码"); + phoneLayout->addWidget(phoneNumberEdit); + layout->addLayout(phoneLayout); + + auto *saveCheckBox = new QCheckBox("记住手机号码(可在设置中删除)", dialog); + layout->addWidget(saveCheckBox); + + auto *buttonBox = new QDialogButtonBox( + QDialogButtonBox::Ok | QDialogButtonBox::Cancel, + dialog + ); + connect( + buttonBox, + &QDialogButtonBox::accepted, + dialog, + [this, dialog, countryCodeEdit, phoneNumberEdit, saveCheckBox]() + { + const QString submittedCountryCode = countryCodeEdit->text().trimmed(); + const QString submittedPhoneNumber = phoneNumberEdit->text().trimmed(); + if (submittedCountryCode.isEmpty() || submittedPhoneNumber.isEmpty()) + { + QMessageBox::warning( + dialog, + "警告", + "国家码或手机号码不能为空。" + ); + return; + } + + emit phoneNumberSubmitted( + submittedCountryCode, + submittedPhoneNumber, + saveCheckBox->isChecked() + ); + dialog->accept(); + } + ); + connect(buttonBox, &QDialogButtonBox::rejected, dialog, &QDialog::reject); + layout->addWidget(buttonBox); + + if (phoneNumber.isEmpty()) + { + phoneNumberEdit->setFocus(); + } + else + { + countryCodeEdit->setFocus(); + } + dialog->show(); +} + void AuthDialogCoordinator::requestSudoPassword() { if (sudoWindow != nullptr) diff --git a/presentation/coordinators/authdialogcoordinator.h b/presentation/coordinators/authdialogcoordinator.h index 853847d..e42a62c 100644 --- a/presentation/coordinators/authdialogcoordinator.h +++ b/presentation/coordinators/authdialogcoordinator.h @@ -6,6 +6,7 @@ class GraphCaptchaWindow; class LoginWindow; +class QDialog; class QSettings; class SsoLoginWebView; class SudoWindow; @@ -24,6 +25,10 @@ public: void setSettings(QSettings *settings); void requestLogin(const QString &username, const QString &password); + void requestPhoneNumber( + const QString &countryCode, + const QString &phoneNumber + ); void requestSudoPassword(); void requestGraphCaptcha(const QString &graphFile); void requestSmsCode(bool showSkipSecondaryAuthOption); @@ -32,6 +37,11 @@ public: signals: void loginSubmitted(const QString &username, const QString &password, bool saveDetails); + void phoneNumberSubmitted( + const QString &countryCode, + const QString &phoneNumber, + bool saveDetails + ); void sudoPasswordSubmitted(const QString &password, bool remember); void interactiveInputSubmitted(const QByteArray &input); @@ -39,6 +49,7 @@ private: QWidget *parentWidget; QSettings *settings; QPointer loginWindow; + QPointer phoneNumberDialog; QPointer sudoWindow; QPointer graphCaptchaWindow; QPointer ssoLoginWebView; diff --git a/presentation/coordinators/connectionuicontroller.cpp b/presentation/coordinators/connectionuicontroller.cpp index df5e862..0bf42a7 100644 --- a/presentation/coordinators/connectionuicontroller.cpp +++ b/presentation/coordinators/connectionuicontroller.cpp @@ -88,6 +88,35 @@ ConnectionUiController::ConnectionUiController( startConnection(username, password); } ); + connect( + authenticationDialogs, + &AuthDialogCoordinator::phoneNumberSubmitted, + this, + [this]( + const QString &countryCode, + const QString &phoneNumber, + bool saveDetails + ) + { + if (saveDetails) + { + settings()->setValue("ZJUConnect/PhoneCountryCode", countryCode); + settings()->setValue("ZJUConnect/PhoneNumber", phoneNumber); + settings()->sync(); + } + + const QString username = + settings()->value("Credential/Username", "").toString(); + const QString password = QByteArray::fromBase64( + settings()->value("Credential/Password", "").toString().toUtf8() + ); + startConnection( + username, + password, + countryCode + "-" + phoneNumber + ); + } + ); connect( connectionSession, &ConnectionSession::reconnectScheduled, @@ -201,6 +230,26 @@ void ConnectionUiController::handleConnectClicked() const bool passwordLogin = (protocol == "atrust" && authType == "psw") || (protocol == "easyconnect" && easyconnectAuthType != "certificate"); + if (protocol == "atrust" && authType == "smsCheckCode") + { + QString countryCode = settings() + ->value("ZJUConnect/PhoneCountryCode", "86") + .toString() + .trimmed(); + const QString phoneNumber = settings() + ->value("ZJUConnect/PhoneNumber", "") + .toString() + .trimmed(); + if (countryCode.isEmpty() || phoneNumber.isEmpty()) + { + if (countryCode.isEmpty()) + { + countryCode = "86"; + } + authenticationDialogs->requestPhoneNumber(countryCode, phoneNumber); + return; + } + } if (passwordLogin && (username.isEmpty() || password.isEmpty())) { authenticationDialogs->requestLogin(username, password); @@ -285,7 +334,8 @@ void ConnectionUiController::handleProxyClicked() void ConnectionUiController::startConnection( const QString &username, - const QString &password + const QString &password, + const QString &phone ) { ConnectionProfile profile = SettingsProfileLoader::load( @@ -294,6 +344,10 @@ void ConnectionUiController::startConnection( username, password ); + if (!phone.isNull()) + { + profile.endpoint.phone = phone; + } profile.program = CoreExecutable::path(); const ReconnectPolicy reconnectPolicy{ settings()->value("Common/AutoReconnect", false).toBool(), diff --git a/presentation/coordinators/connectionuicontroller.h b/presentation/coordinators/connectionuicontroller.h index 51fd317..e10809b 100644 --- a/presentation/coordinators/connectionuicontroller.h +++ b/presentation/coordinators/connectionuicontroller.h @@ -50,7 +50,11 @@ public: private: void handleConnectClicked(); void handleProxyClicked(); - void startConnection(const QString &username, const QString &password); + void startConnection( + const QString &username, + const QString &password, + const QString &phone = QString() + ); void showConnectionError(ZJU_ERROR error); QSettings *settings() const;