tlogin.cpp 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. #include "tlogin.h"
  2. #include "appevent.h"
  3. #include "qlabel.h"
  4. #include "qlineedit.h"
  5. #include <QGroupBox>
  6. #include <QMessageBox>
  7. #include <QMouseEvent>
  8. #include <QRegExpValidator>
  9. #include <QCheckBox>
  10. #include <QPushButton>
  11. #include "qstyle.h"
  12. #include "qwidget.h"
  13. #include "utils/layoutbuilder.h"
  14. #include "widgets/captchalabel.h"
  15. #include "api/tloginapi.h"
  16. TLogin::TLogin(QWidget *parent)
  17. : QDialog(parent)
  18. {
  19. setObjectName("Login");
  20. setWindowFlags(Qt::Window | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);
  21. setWindowTitle(tr("Login"));
  22. using namespace Layouting;
  23. info = new QLabel;
  24. info->setStyleSheet("color: #333333;");
  25. info->setText(tr("Welcome to the system"));
  26. // 创建登录组件
  27. usernameEdit = new QLineEdit();
  28. usernameEdit->setPlaceholderText(tr("Enter your user name"));
  29. usernameEdit->setMinimumWidth(200);
  30. passwordEdit = new QLineEdit();
  31. passwordEdit->setEchoMode(QLineEdit::Password);
  32. passwordEdit->setPlaceholderText(tr("Enter your ExamNo"));
  33. // 添加验证码输入框
  34. captchaEdit = new QLineEdit();
  35. captchaEdit->setPlaceholderText(tr("Enter captcha"));
  36. captchaEdit->setMaxLength(6);
  37. // 验证码图片显示
  38. captchaImage = new CaptchaLabel();
  39. captchaImage->setFixedSize(120, 40);
  40. captchaImage->setScaledContents(true);
  41. captchaImage->setCursor(Qt::PointingHandCursor); // 设置鼠标指针为手型,提示可点击
  42. captchaImage->setToolTip(tr("Click to refresh captcha")); // 添加提示文本
  43. // 添加记住用户名复选框
  44. rememberUsernameCheckBox = new QCheckBox(tr("Remember Username"));
  45. // 连接 clicked 信号到刷新验证码的槽函数
  46. connect(captchaImage, &CaptchaLabel::clicked, this, &TLogin::getCaptcha);
  47. // 创建表单布局,将captchaEdit和captchaImage放在同一行
  48. QWidget *w = Group{Column{Row{st, tr("Login"), st},
  49. Form{tr("Username:"), usernameEdit,
  50. br, tr("Password:"), passwordEdit,
  51. br, tr("Captcha:"), Row{captchaEdit, captchaImage},
  52. br, "", rememberUsernameCheckBox},
  53. Row{PushButton{bindTo(&loginPushButton),
  54. text(tr("Login")),
  55. onClicked(std::bind(&TLogin::on_login_clicked, this))},
  56. PushButton{bindTo(&offlineLoginButton),
  57. text(tr("Offline Login")),
  58. onClicked(std::bind(&TLogin::on_offline_login_clicked, this))}}
  59. }}
  60. .emerge();
  61. QPushButton *close;
  62. auto h = Row{st, PushButton{bindTo(&close), ""}};
  63. Column{h, st, Row{st, w, st}, st, info, noMargin}.attachTo(this);
  64. // 设置美观的样式表,不使用背景图片
  65. QString styleSheet = R"(
  66. QDialog#Login {
  67. background-color: #2c3e50;
  68. border: 1px solid #34495e;
  69. border-radius: 5px;
  70. }
  71. QGroupBox {
  72. background-color: #ecf0f1;
  73. border-radius: 5px;
  74. border: 1px solid #bdc3c7;
  75. padding: 10px;
  76. }
  77. QLineEdit {
  78. border: 1px solid #bdc3c7;
  79. border-radius: 3px;
  80. padding: 5px;
  81. background-color: white;
  82. }
  83. QLineEdit:focus {
  84. border: 1px solid #3498db;
  85. background-color: #f8f9fa;
  86. }
  87. QPushButton {
  88. background-color: #3498db;
  89. color: white;
  90. border: none;
  91. border-radius: 3px;
  92. padding: 8px 16px;
  93. font-weight: bold;
  94. }
  95. QPushButton:hover {
  96. background-color: #2980b9;
  97. }
  98. QPushButton:disabled {
  99. background-color: #95a5a6;
  100. }
  101. QLabel {
  102. color: #333333;
  103. }
  104. )";
  105. setStyleSheet(styleSheet);
  106. QPixmap closePix = style()->standardPixmap(QStyle::SP_TitleBarCloseButton);
  107. close->setIcon(closePix);
  108. close->setStyleSheet(R"__(
  109. QPushButton {
  110. border: none;
  111. background-color: transparent;
  112. padding: 5px;
  113. }
  114. QPushButton:hover {
  115. background-color: #e74c3c;
  116. border-radius: 3px;
  117. }
  118. )__");
  119. resize({400, 450});
  120. loginPushButton->setEnabled(true);
  121. QObject::connect(close, &QPushButton::clicked, this, &TLogin::close);
  122. // 加载保存的用户名
  123. loadSavedUsername();
  124. // 获取初始验证码
  125. getCaptcha();
  126. }
  127. // 加载保存的用户名
  128. void TLogin::loadSavedUsername()
  129. {
  130. // 从配置中读取保存的用户名
  131. QVariant savedUsername = AppEvent::instance()->configValue("savedUsername");
  132. if (!savedUsername.isNull() && savedUsername.isValid()) {
  133. usernameEdit->setText(savedUsername.toString());
  134. rememberUsernameCheckBox->setChecked(true);
  135. }
  136. QVariant savedPassword = AppEvent::instance()->configValue("savedPassword");
  137. if (!savedPassword.isNull() && savedPassword.isValid()) {
  138. passwordEdit->setText(savedPassword.toString());
  139. rememberUsernameCheckBox->setChecked(true);
  140. }
  141. }
  142. void TLogin::getCaptcha()
  143. {
  144. bool ok = false;
  145. TC::Captcha::Data captchaData = TC::Captcha().get(&ok);
  146. if (ok) {
  147. captchaId = captchaData.captchaId;
  148. // 处理Base64图片数据
  149. QString imgData = captchaData.imgPath;
  150. if (imgData.startsWith("data:image/png;base64,")) {
  151. imgData = imgData.mid(22); // 移除前缀
  152. }
  153. QByteArray imageBytes = QByteArray::fromBase64(imgData.toLatin1());
  154. QPixmap pixmap;
  155. pixmap.loadFromData(imageBytes);
  156. captchaImage->setPixmap(pixmap);
  157. } else {
  158. info->setText(tr("Failed to get captcha"));
  159. }
  160. }
  161. void TLogin::on_refresh_captcha_clicked()
  162. {
  163. getCaptcha();
  164. }
  165. void TLogin::mousePressEvent(QMouseEvent *event)
  166. {
  167. if (event->button() == Qt::LeftButton) {
  168. m_dragPosition = event->globalPos() - frameGeometry().topLeft();
  169. event->accept();
  170. }
  171. }
  172. void TLogin::mouseMoveEvent(QMouseEvent *event)
  173. {
  174. if (event->buttons() & Qt::LeftButton) {
  175. move(event->globalPos() - m_dragPosition);
  176. event->accept();
  177. }
  178. }
  179. void TLogin::on_login_clicked()
  180. {
  181. const QString userName = usernameEdit->text();
  182. const QString password = passwordEdit->text();
  183. const QString captcha = captchaEdit->text();
  184. if (userName.isEmpty() || password.isEmpty()) {
  185. QMessageBox::warning(this,
  186. tr("Login failed"),
  187. tr("User name or password cannot be empty."));
  188. return;
  189. }
  190. if (captcha.isEmpty()) {
  191. QMessageBox::warning(this,
  192. tr("Login failed"),
  193. tr("Captcha cannot be empty."));
  194. return;
  195. }
  196. // 这里需要修改Login API,添加验证码参数
  197. // 由于我们没有看到Login类的完整实现,这里假设需要修改Login构造函数
  198. // 实际实现时需要根据后端API的要求进行调整
  199. // 修改Login类构造函数,添加captchaId和captcha参数
  200. // 这里只是示例,实际实现可能需要调整
  201. bool ok = TC::Login(userName, password, captchaId, captcha).post();
  202. if (ok && AppEvent::instance()->isLogin()) {
  203. // 如果选择了记住用户名,则保存用户名到配置
  204. qDebug() << rememberUsernameCheckBox->isChecked();
  205. if (rememberUsernameCheckBox->isChecked()) {
  206. AppEvent::instance()->setConfigValue("savedUsername", userName);
  207. AppEvent::instance()->setConfigValue("savedPassword", password);
  208. AppEvent::instance()->configSave(); // 保存配置到文件
  209. } else {
  210. // 如果未选择记住用户名,则清除之前保存的用户名
  211. AppEvent::instance()->setConfigValue("savedUsername", "");
  212. AppEvent::instance()->setConfigValue("savedPassword", "");
  213. AppEvent::instance()->configSave(); // 保存配置到文件
  214. }
  215. // 登录成功,发出信号
  216. emit loginSuccessful();
  217. close();
  218. } else {
  219. // 登录失败,显示提示框并刷新验证码
  220. QMessageBox::warning(this,
  221. tr("Login failed"),
  222. tr("User name, password or captcha error, please try again."));
  223. getCaptcha(); // 刷新验证码
  224. captchaEdit->clear(); // 清空验证码输入框
  225. return;
  226. }
  227. }
  228. void TLogin::on_offline_login_clicked()
  229. {
  230. // 离线登录不需要验证用户名、密码和验证码
  231. // 直接设置一个默认用户名,表示是离线模式
  232. AppEvent::instance()->setConfigValue("offlineMode", true);
  233. AppEvent::instance()->configSave(); // 保存配置到文件
  234. // 发出登录成功信号
  235. emit loginSuccessful();
  236. close();
  237. }