import json import random import sys from typing import Callable, Any from PySide6.QtWidgets import QApplication, QWidget, QMessageBox, QMainWindow, QHBoxLayout, QVBoxLayout, QLineEdit, QLabel from PySide6.QtGui import QIcon, QPixmap, QShortcut, QResizeEvent, QFont, QKeySequence from PySide6.QtCore import Qt,QSize from codes.ui.login import Ui_login from codes.ui.app import Ui_App from codes.common.worker import Worker from codes.common import clibs from codes.common.secure_encrypt import PassCipher from codes.common import db_operation class LoginWindow(QWidget, Ui_login): def __init__(self): super().__init__() self.setupUi(self) self.pre_dos() def pre_dos(self): self.setWindowIcon(QIcon(f"{clibs.base_path}/assets/media/icon.ico")) self.lb_logo.setPixmap(QPixmap(f"{clibs.base_path}/assets/media/avatar.png")) self.lb_logo.setScaledContents(True) # bindings QShortcut("Esc", self).activated.connect(self.close) self.pb_login.clicked.connect(self.login) self.pb_cancel.clicked.connect(self.close) self.le_password.returnPressed.connect(self.login) def login(self): def login_failed(): QMessageBox.warning(self, "告警", "\n用户名或密码不正确,请重新输入!") self.le_username.setText("") self.le_password.setText("") def validate_login(): nonlocal username, password with open(f"{clibs.base_path}/assets/conf/config.json", mode="rt", encoding="utf-8") as f_conf: clibs.account = json.load(f_conf) if username != clibs.account["username"] or len(password) < clibs.account["minimum_password_length"]: login_failed() return False salt = PassCipher.gen_salt(password) cipher = PassCipher(salt) # password_encrypt = cipher.encrypt(password) # print(f"password_encrypt = {password_encrypt}") # exit() try: decrypt_password = cipher.decrypt(clibs.account["login_password"]) except ValueError: login_failed() return False if password != decrypt_password: login_failed() return False self.mainWindow = MainWindow() self.mainWindow.show() self.deleteLater() return True username = self.le_username.text() password = self.le_password.text() validate_login() class MainWindow(QMainWindow, Ui_App): def __init__(self): super().__init__() self.conn = None self.cursor = None self.thread = None self.setupUi(self) self.pre_dos() self.lock_overlay = None def pre_dos(self): self.setWindowIcon(QIcon(f"{clibs.base_path}/assets/media/icon.ico")) db_operation.db_backup() self.conn, self.cursor = db_operation.db_conn() # bindings self.ac_quit.triggered.connect(self.close) self.ac_caging.triggered.connect(self.lock_window) self.ac_logs.triggered.connect(lambda : print("test ac log")) def launch(self, func, on_anything: Callable[..., Any] = print, *args, **kwargs): self.thread = Worker(func, *args, **kwargs) self.thread.started.connect(lambda: on_anything({"started": True})) self.thread.result.connect(on_anything) self.thread.error.connect(on_anything) self.thread.finished.connect(lambda: on_anything({"finished": True})) self.thread.start() def lock_window(self): def unlock(): def check_failed(): QMessageBox.warning(self, "错误", "\n密码错误,请重新输入!") le_password.clear() le_password.setFocus() password = le_password.text() if len(password) < clibs.account["minimum_password_length"]: check_failed() return False salt = PassCipher.gen_salt(password) cipher = PassCipher(salt) try: decrypt_password = cipher.decrypt(clibs.account["unlock_password"]) except ValueError: check_failed() return False if password != decrypt_password: check_failed() return False self.lock_overlay.deleteLater() self.lock_overlay = None self.set_shortcuts(True) return True def gen_lock_screen(): # generate lock screen v_layout = QVBoxLayout(self.lock_overlay) # v layout v_layout.setObjectName(u"v_layout") h_layout = QHBoxLayout() # h layout h_layout.setObjectName(u"h_layout") h_layout.setContentsMargins(-1, -1, 10, 50) lb_e_1 = QLabel(self.lock_overlay) lb_e_1.setObjectName(u"lb_e_1") h_layout.addWidget(lb_e_1) lb_password = QLabel(self.lock_overlay) lb_password.setObjectName(u"lb_password") lb_password.setMinimumSize(QSize(100, 0)) lb_password.setMaximumSize(QSize(100, 16777215)) font = QFont() font.setFamilies([u"Consolas"]) font.setPointSize(14) font.setBold(True) font.setItalic(True) lb_password.setFont(font) lb_password.setAlignment(Qt.AlignmentFlag.AlignCenter) lb_password.setText("Password") h_layout.addWidget(lb_password) le_password = QLineEdit(self.lock_overlay) le_password.setObjectName(u"le_password") le_password.setMinimumSize(QSize(200, 0)) le_password.setFont(font) le_password.setEchoMode(QLineEdit.EchoMode.Password) h_layout.addWidget(le_password) lb_e_2 = QLabel(self.lock_overlay) lb_e_2.setObjectName(u"lb_e_2") h_layout.addWidget(lb_e_2) h_layout.setStretch(0, 5) h_layout.setStretch(1, 2) h_layout.setStretch(2, 3) h_layout.setStretch(3, 5) v_layout.addLayout(h_layout) return le_password self.set_shortcuts(False) if not self.lock_overlay: self.lock_overlay = QWidget(self) self.lock_overlay.setObjectName("w_overlay") cx = random.random() cy = random.random() stop1 = random.random() stop2 = random.random() angle = random.randint(0, 360) self.lock_overlay.setStyleSheet(f"""background: qconicalgradient(cx:{cx}, cy:{cy}, angle:{angle}, stop:0 #f6f8fa, stop:{stop1} #eef1f5, stop:{stop2} #dce1e8);""") # self.lock_overlay.setStyleSheet("""background: qconicalgradient(cx:0.5, cy:0.5, angle:45, stop:0 #f6f8fa, stop:0.5 #eef1f5, stop:1 #dce1e8);""") le_password = gen_lock_screen() le_password.returnPressed.connect(unlock) self.lock_overlay.setGeometry(self.rect()) self.lock_overlay.show() le_password.setFocus() def set_shortcuts(self, stat: bool = True): if stat: self.ac_homepage.setShortcut(QKeySequence("Ctrl+Alt+H")) self.ac_settings.setShortcut(QKeySequence("Ctrl+Alt+S")) self.ac_logs.setShortcut(QKeySequence("Ctrl+Alt+L")) self.ac_about.setShortcut(QKeySequence("Ctrl+Alt+A")) self.ac_caging.setShortcut(QKeySequence("Ctrl+Alt+C")) self.ac_quit.setShortcut(QKeySequence("Ctrl+Alt+Q")) else: self.ac_homepage.setShortcut(QKeySequence()) self.ac_settings.setShortcut(QKeySequence()) self.ac_logs.setShortcut(QKeySequence()) self.ac_about.setShortcut(QKeySequence()) self.ac_caging.setShortcut(QKeySequence()) self.ac_quit.setShortcut(QKeySequence()) def resizeEvent(self, event: QResizeEvent): super().resizeEvent(event) if self.lock_overlay: self.lock_overlay.setGeometry(self.rect()) def closeEvent(self, event): reply = QMessageBox.question(self, "退出", "\n程序可能在运行,确定要退出吗?") if reply == QMessageBox.StandardButton.Yes: db_operation.db_close(self.conn, self.cursor) event.accept() else: event.ignore() if __name__ == '__main__': app = QApplication(sys.argv) login = LoginWindow() login.show() sys.exit(app.exec())