import sys from pathlib import Path from PySide6.QtWidgets import QApplication, QWidget, QVBoxLayout, QHBoxLayout, QPushButton, QLabel, QTabWidget, QListWidget, QStackedWidget, QCheckBox, QSpinBox, QToolBox, QLineEdit, QTableWidget, QTreeWidget, QCalendarWidget, QMessageBox, QToolBar, QSizePolicy from PySide6.QtCore import Qt, QTime, QSize, QRect,QEvent, QThread from PySide6.QtGui import QCursor, QFont, QIcon, QImage, QPixmap, QShortcut from codes.common import clibs, db_operation from codes.common.secure_encrypt import PassCipher from codes.ui import main_ui class LoginWindow(QWidget): def __init__(self): super().__init__() self.init_ui() self.setup_slot() self.predos() self.le_username.setFocus() def init_ui(self): self.setMinimumSize(420, 200) self.setMaximumSize(500, 240) self.resize(480, 200) self.setWindowTitle("登录") self.setWindowIcon(QIcon(f"{clibs.base_path}/assets/media/icon.ico")) self.setFont(QFont("Consolas", 14)) self.layout_outter = QHBoxLayout() self.lb_logo = QLabel() self.lb_logo.setAlignment(Qt.AlignmentFlag.AlignCenter) self.lb_logo.setSizePolicy(QSizePolicy.Policy.Preferred, QSizePolicy.Policy.Preferred) self.lb_logo.setPixmap(QPixmap(f"{clibs.base_path}/assets/media/logo.png")) self.lb_logo.setFixedSize(QSize(120, 120)) self.lb_logo.setScaledContents(True) self.layout_outter.addWidget(self.lb_logo) self.tabW_login = QTabWidget() self.tab_login = QWidget() self.tabW_login.addTab(self.tab_login, "登录") self.tab_register = QWidget() self.tabW_login.addTab(self.tab_register, "注册") self.layout_outter.addWidget(self.tabW_login) # 登陆页面 self.layout_H_username = QHBoxLayout() self.lb_username = QLabel("账号") self.lb_username.setAlignment(Qt.AlignmentFlag.AlignCenter) self.layout_H_username.addWidget(self.lb_username) self.le_username = QLineEdit() self.le_username.setFocus() self.layout_H_username.addWidget(self.le_username) self.layout_H_password = QHBoxLayout() self.lb_password = QLabel("密码") self.lb_password.setAlignment(Qt.AlignmentFlag.AlignCenter) self.layout_H_password.addWidget(self.lb_password) self.le_password = QLineEdit() self.le_password.setEchoMode(QLineEdit.EchoMode.Password) self.layout_H_password.addWidget(self.le_password) self.layout_H_button = QHBoxLayout() self.btn_login = QPushButton("登录") self.btn_login.setAutoDefault(True) self.btn_cancel = QPushButton("取消") self.btn_cancel.setAutoDefault(True) self.layout_H_button.addWidget(self.btn_login) self.layout_H_button.addWidget(self.btn_cancel) self.layout_V_user_pass = QVBoxLayout() self.layout_V_user_pass.addLayout(self.layout_H_username) self.layout_V_user_pass.addLayout(self.layout_H_password) self.layout_V_user_pass.addLayout(self.layout_H_button) self.tab_login.setLayout(self.layout_V_user_pass) # 注册页面 self.layout_H_username_reg = QHBoxLayout() self.lb_username_reg = QLabel("账号设定") self.lb_username_reg.setAlignment(Qt.AlignmentFlag.AlignCenter) self.layout_H_username_reg.addWidget(self.lb_username_reg) self.le_username_reg = QLineEdit() self.le_username_reg.setFocus() self.layout_H_username_reg.addWidget(self.le_username_reg) self.layout_H_password_reg = QHBoxLayout() self.lb_password_reg = QLabel("密码设定") self.lb_password_reg.setAlignment(Qt.AlignmentFlag.AlignCenter) self.layout_H_password_reg.addWidget(self.lb_password_reg) self.le_password_reg = QLineEdit() self.le_password_reg.setEchoMode(QLineEdit.EchoMode.Password) self.layout_H_password_reg.addWidget(self.le_password_reg) self.layout_H_password_reg_confirm = QHBoxLayout() self.lb_password_reg_confirm = QLabel("密码确认") self.lb_password_reg_confirm.setAlignment(Qt.AlignmentFlag.AlignCenter) self.layout_H_password_reg_confirm.addWidget(self.lb_password_reg_confirm) self.le_password_reg_confirm = QLineEdit() self.le_password_reg_confirm.setEchoMode(QLineEdit.EchoMode.Password) self.layout_H_password_reg_confirm.addWidget(self.le_password_reg_confirm) self.layout_H_button_reg = QHBoxLayout() self.btn_login_reg = QPushButton("确认") self.btn_login_reg.setAutoDefault(True) self.btn_cancel_reg = QPushButton("取消") self.btn_cancel_reg.setAutoDefault(True) self.layout_H_button_reg.addWidget(self.btn_login_reg) self.layout_H_button_reg.addWidget(self.btn_cancel_reg) self.layout_V_user_pass_reg = QVBoxLayout() self.layout_V_user_pass_reg.addLayout(self.layout_H_username_reg) self.layout_V_user_pass_reg.addLayout(self.layout_H_password_reg) self.layout_V_user_pass_reg.addLayout(self.layout_H_password_reg_confirm) self.layout_V_user_pass_reg.addLayout(self.layout_H_button_reg) self.tab_register.setLayout(self.layout_V_user_pass_reg) self.setLayout(self.layout_outter) def setup_slot(self): self.tabW_login.currentChanged.connect(self.onChange_tabW) self.btn_login.clicked.connect(self.login_check) self.btn_cancel.clicked.connect(self.close) self.btn_login_reg.clicked.connect(self.register_check) self.btn_cancel_reg.clicked.connect(self.close) QShortcut("Esc", self).activated.connect(self.close) self.le_password.returnPressed.connect(self.login_check) self.le_password_reg_confirm.returnPressed.connect(self.register_check) def predos(self): self.m = Path(__file__).stem db_file = clibs.base_path / "assets/database/toolbox.db" if not db_file.exists(): db_operation.db_init(db_file) def onChange_tabW(self): text = self.tabW_login.tabText(self.tabW_login.currentIndex()) if text == "登录": self.le_username.clear() self.le_password.clear() self.le_username.setFocus() elif text == "注册": self.le_username_reg.clear() self.le_password_reg.clear() self.le_password_reg_confirm.clear() self.le_username_reg.setFocus() else: raise Exception(f"Unknown TabWidget Name: {text}") def login_check(self): def login_failed(exception: bool = False): self.le_username.clear() self.le_password.clear() self.le_username.setFocus() if not exception: QMessageBox.critical(self, "错误", "账号或密码错误,请重新输入!") else: QMessageBox.critical(self, "错误", "账号重复,需检查数据库,更正后再尝试登录!") def validate_login(): nonlocal username, password clibs.conn, clibs.cursor = db_operation.db_conn() record = db_operation.db_query_users(username) if len(record) == 0: login_failed() return False elif len(record) == 1: keys = ["id", "timestamp", "username", "password", "salt"] login_info = dict(zip(keys, record[0])) salt = PassCipher.gen_salt("@".join([username, password])) cipher = PassCipher(salt) try: decrypt_password = cipher.decrypt(login_info["password"]) if password != decrypt_password: login_failed() return False else: self.mainWindow = main_ui.MainWindow() self.mainWindow.show() db_operation.db_close() clibs.username = username clibs.password = password self.close() return True except ValueError: login_failed() return False else: db_operation.db_write_logs(f"username duplicated: {username}", self.m, "error") login_failed(exception=True) return False username = self.le_username.text() password = self.le_password.text() validate_login() def register_check(self): def register_failed(flag: int = 0): self.le_username_reg.clear() self.le_password_reg.clear() self.le_password_reg_confirm.clear() self.le_username_reg.setFocus() if flag == 0: QMessageBox.critical(self, "错误", "账号已存在,或两次输入密码不一致,请重新输入!") elif flag == 1: QMessageBox.critical(self, "错误", "密码长度不符合要求,请重新输入!") elif flag == 2: QMessageBox.critical(self, "错误", "账号重复,需检查数据库,更正后再尝试登录!") def validate_register(): nonlocal username, password, password_confirm clibs.conn, clibs.cursor = db_operation.db_conn() record = db_operation.db_query_users(username) if password != password_confirm: register_failed() return False if len(password) < clibs.account["minimum_password_length"]: register_failed(flag=1) return False if len(record) == 0: salt = PassCipher.gen_salt("@".join([username, password])) cipher = PassCipher(salt) password_encrypted = cipher.encrypt(password) db_operation.db_write_users(username, password_encrypted, salt) QMessageBox.information(self, "成功", "注册成功,切换至登录窗口进行登录!") self.tabW_login.setCurrentIndex(self.tabW_login.indexOf(self.tab_login)) return True elif len(record) == 1: register_failed() return False else: db_operation.db_write_logs(f"username duplicated: {username}", self.m, "error") register_failed(flag=2) return False username = self.le_username_reg.text() password = self.le_password_reg.text() password_confirm = self.le_password_reg_confirm.text() validate_register() if __name__ == '__main__': app = QApplication(sys.argv) window = LoginWindow() window.show() sys.exit(app.exec())