PyQt5 接入 web 登錄頁


PyQt5 接入 web 登錄頁

概述

一個桌面軟件一般都會有登錄后的操作, 用 PyQt 寫一套登錄頁面工作量還不小,出了處理登錄邏輯外,還要關心驗證碼,錯誤提示,跳轉到注冊頁面等等. 如果已經有了一個 web 版的登錄頁,那我們又何必再寫一套呢?

原理

  • 用 QWebEngineView 嵌入登錄頁;
  • 利用 QWebEngineView 的 runJavaScript 方法獲取 cookies;
  • 利用子線程掃描指定 cookie,一旦獲取到,則切換到主窗口.

流程

graph TD; 啟動-->id0(顯示登錄窗口,隱藏主窗口); id0-->id1{子線程定時檢測指定cookie}; id1-->|否|id1; id1-->|是|id2(顯示主窗口,隱藏登錄窗口); id2-->id3(需要重新登錄); id3-->id0;

代碼

main.py

import sys
import time
from threading import Thread
from PyQt5 import QtWidgets
from PyQt5.QtCore import pyqtSignal
from PyQt5.QtWidgets import QApplication, QMainWindow, QAction

import context
from content import MainContent
from login import Login


class Main(QMainWindow):
    str_signal = pyqtSignal(str)

    def __init__(self):
        super().__init__()
        self.setupUi()
        self.init_signal()
        self.connect()

    def setupUi(self):
        self.resize(1000, 700)
        self.menu = self.menuBar().addMenu('User')
        self.logout_action = QAction("&Logout", self)
        self.menu.addAction(self.logout_action)

        self.centralWidget = QtWidgets.QWidget(self)
        self.setCentralWidget(self.centralWidget)

        self.grid_layout = QtWidgets.QGridLayout(self.centralWidget)
        self.grid_layout.setContentsMargins(0, 0, 0, 0)
        self.grid_layout.setSpacing(0)

        self.login_form = Login(self)
        self.main_content = MainContent(self)
        self.grid_layout.addWidget(self.login_form, 1, 1, 1, 1)
        self.grid_layout.addWidget(self.main_content, 1, 2, 1, 1)

        self.show_login()
        self.monitor_token()

    def init_signal(self):
        def func(signal):
            getattr(self, signal)()

        self.str_signal[str].connect(func)

    def connect(self):
        self.logout_action.triggered.connect(self.show_login)

    def show_login(self):
        self.login_form.logout()
        self.login_form.show()
        self.main_content.hide()

    def show_main(self):
        self.login_form.hide()
        self.main_content.show()

    def monitor_token(self):
        def func():
            while True:
                if not context.cookies.get('_accessToken'):
                    self.login_form.load_cookies()
                    time.sleep(1)
                    if context.cookies.get('_accessToken'):
                        self.str_signal.emit("show_main")

        t = Thread(target=func)
        t.setDaemon(True)
        t.start()


if __name__ == "__main__":
    app = QApplication(sys.argv)
    ui = Main()
    ui.show()
    sys.exit(app.exec_())

login.py

# -*- encoding:utf-8 -*-
from PyQt5 import QtWebEngineWidgets
from PyQt5.QtCore import QUrl
import json
import context


class Login(QtWebEngineWidgets.QWebEngineView):

    def __init__(self, parent=None):
        super().__init__(parent=parent)
        self.setupUi()
        self.connect()

    def setupUi(self):
        self.load(QUrl('https://crm.chengfayun.com'))

    def connect(self):
        self.loadFinished.connect(self.load_cookies)

    def load_cookies(self):
        print('load cookies', self.url())

        def parse_cookies(origin):
            if origin:
                context.cookies = {item.split("=")[0]: item.split(
                    "=")[1] for item in origin.split('; ')}

        self.page().runJavaScript('document.cookie', parse_cookies)

    def logout(self):
        self.page().profile().cookieStore().deleteAllCookies()
        self.reload()

    def print_cookie(self):
        print(json.dumps(self.cookies, ensure_ascii=False, indent=2))

content.py

# -*- encoding:utf-8 -*-
from PyQt5 import QtWidgets
from PyQt5.QtWidgets import QTextEdit, QWidget, QPushButton
from login import Login
import context
import requests
import json


class MainContent(QWidget):

    def __init__(self, parent):
        super().__init__(parent=parent)
        self.setupUi()
        self.connect()

    def setupUi(self):
        self.grid_layout = QtWidgets.QGridLayout(self)
        self.grid_layout.setContentsMargins(0, 0, 0, 0)
        self.grid_layout.setSpacing(0)

        self.text_edit = QTextEdit(self)
        self.info_btn = QPushButton("get tenant info", self)
        self.meta_btn = QPushButton("get metas", self)
        self.grid_layout.addWidget(self.info_btn, 1, 1, 1, 1)
        self.grid_layout.addWidget(self.meta_btn, 1, 2, 1, 1)
        self.grid_layout.addWidget(self.text_edit, 2, 1, 1, 2)

    def connect(self):
        self.meta_btn.clicked.connect(self.get_metas)
        self.info_btn.clicked.connect(self.get_info)

    def http_get(self, url):
        return requests.get(url, headers={'x-token': context.cookies.get('_accessToken')}).json()

    def get_metas(self):
        res = self.http_get("https://crm.chengfayun.com/api/v1.0/one/all-metas")
        self.text_edit.setText(json.dumps(res, ensure_ascii=False, indent=4))

    def get_info(self):
        url = f"https://crm.chengfayun.com/api/v1.0/tenant-gateway/tenant/org/{context.cookies.get('_tenant_id')}"
        res = self.http_get(url)
        self.text_edit.setText(json.dumps(res, ensure_ascii=False, indent=4))

context.py

cookies = {}

預覽圖


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM