admin
2025-06-10 568c763084b926a6f2d632b7ac65b9ec8280752f
main.py
@@ -1,4 +1,5 @@
import base64
import ctypes
import hashlib
import json
import logging
@@ -7,26 +8,29 @@
import threading
import time
import sys
from functools import partial
from multiprocessing import Pipe, Process, freeze_support
import torch
import win32api
import win32con
import win32gui
from PyQt5.QtGui import QFont, QPalette, QColor, QTextOption
from PyQt5.QtWebChannel import QWebChannel
from PyQt5.QtWebEngineWidgets import QWebEngineView, QWebEngineSettings
from PyQt5.QtWebEngineWidgets import QWebEngineView, QWebEngineSettings, QWebEnginePage
from PyQt5.QtWidgets import QMainWindow, QApplication, QAction, QMessageBox, QLabel
from PyQt5.QtCore import Qt, pyqtSlot, QObject, pyqtSignal, QTimer, QUrl, QPoint
import constant
import gui_wx
from network_delegate_manager import LocalKanPanNetworkDelegate
from utils import network_util, xgb_api, ths_util
from utils import network_util, xgb_api, ths_util, ths_ocr_util
import setting
from utils import tool
import win32_util
from kpl.kpl_data_manager import KPLLimitUpDataManager
from utils.network_delegate_manager import LocalKanPanNetworkDelegate
URL_MSG_LIST = f"http://{constant.WEB_HOST}/kp/msg_list.html"
@@ -51,15 +55,19 @@
            result, need_delegate = LocalKanPanNetworkDelegate.http_delegate_request(url)
            if not need_delegate:
                result = network_util.http_get(url)
            print("请求结果:", result)
            print(url, "请求结果:", result)
            self.signal_request.emit(callback_info[0], callback_info[1], result)
            return result
        except Exception as e:
            logging.exception(e)
    def __socket_request(self, text, callback_info):
    def __socket_request(self, text, callback_info, port=None):
        try:
            result = network_util.socket_request(text)
            print("socket請求:", text)
            if port:
                result = network_util.socket_request(text, port=port)
            else:
                result = network_util.socket_request(text)
            print("请求结果:", result)
            self.signal_request.emit(callback_info[0], callback_info[1], result)
            return result
@@ -103,6 +111,34 @@
            pass
        callback_info = json.loads(callback_info)
        t1 = threading.Thread(target=lambda: self.__socket_request(text, callback_info))
        t1.setDaemon(True)
        t1.start()
    @pyqtSlot(str, str)
    def ls_socket_request(self, text, callback_info):
        print("ls_socket_request", text)
        try:
            text_json = json.loads(text)
            params = []
            for k in text_json:
                if k == "sign":
                    continue
                if type(text_json[k]) == dict or type(text_json[k]) == list:
                    params.append(f"{k}={json.dumps(text_json[k], separators=(',', ':'))}")
                else:
                    params.append(f"{k}={text_json[k]}")
            params.sort()
            params.append("%Yeshi2014@#.")
            params_str = "&".join(params)
            md5 = hashlib.md5()
            md5.update(params_str.encode("utf-8"))
            md5_hash = md5.hexdigest()
            text_json["sign"] = md5_hash
            text = json.dumps(text_json)
        except:
            pass
        callback_info = json.loads(callback_info)
        t1 = threading.Thread(target=lambda: self.__socket_request(text, callback_info, port=14008))
        t1.setDaemon(True)
        t1.start()
@@ -168,12 +204,12 @@
        window_height = 80
        padding = 10
        self.resize(300, 50)
        hwnds = win32_util.search_window("悬浮盯盘")
        if hwnds:
            rect = win32gui.GetWindowRect(hwnds[0])
            self.move(rect[0] + padding - 3, rect[1] - window_height - 30)
            if rect[2] - rect[0] > 0:
                self.resize((rect[2] - rect[0]) - (padding - 2) * 2, window_height)
        # hwnds = win32_util.search_window("悬浮盯盘", is_one_result=True)
        # if hwnds:
        #     rect = win32gui.GetWindowRect(hwnds[0])
        #     self.move(rect[0] + padding - 3, rect[1] - window_height - 30)
        #     if rect[2] - rect[0] > 0:
        #         self.resize((rect[2] - rect[0]) - (padding - 2) * 2, window_height)
        self.setWindowTitle("消息提示")
        self.setWindowFlag(Qt.WindowStaysOnTopHint, True)
        self.setWindowOpacity(0.9)
@@ -257,11 +293,29 @@
        self.python_bridge = SecondWindowBridgeClass(self.webview)
        channel.registerObject("Bridge", self.python_bridge)
        # win32gui.SetWindowLong(self.winId(), win32con.GWL_WNDPROC, self.handleCustomMessage)
        # self.signal_update_kpl.connect(self.set_kpl_data)
        # t1 = threading.Thread(target=self.update_kpl_func)
        # t1.setDaemon(True)
        # t1.start()
    # 自定义消息处理函数
    def handleCustomMessage(self, hwnd, msg, wparam, lparam):
        if msg == win32con.WM_USER + 1024:
            # 解析数据
            # try:
            #     code = ctypes.cast(lparam, ctypes.py_object).value
            #     print(code)
            # except:
            #     pass
            pass
            # 处理数据
            # self.dataReceived.emit(intValue, stringValue)
        return win32gui.DefWindowProc(hwnd, msg, wparam, lparam)
    def loadUrl(self, url):
        self.webview.load(QUrl(url))
@@ -297,6 +351,16 @@
                (self.pos().x(), self.pos().y(), self.size().width(), self.size().height()))
        except Exception as e:
            print("")
class WebEnginePage(QWebEnginePage):
    def javaScriptConsoleMessage(self, level, message, lineNumber, sourceID):
        """处理 JavaScript 控制台消息"""
        print(f"JavaScript Console Error: {message} at line {lineNumber} of {sourceID}")
    def onLoadFailed(self, errorCode, failingUrl, errorDescription):
        """处理加载失败的情况"""
        print(f"Failed to load URL: {failingUrl}, Error: {errorDescription}, Code: {errorCode}")
class MainWindow(QMainWindow):
@@ -347,6 +411,13 @@
        def __juejin_tick_download():
            self.wx_pipe.send(json.dumps({"type": "juejin_tick_download"}))
        def __ths_ocr_code():
            try:
                code = ths_ocr_util.ocr_ths_code(always_save=True)
                self.show_info(f"识别到的代码:{code}")
            except Exception as e:
                self.show_warning(f"识别出错:{str(e)}")
        def __download_codes():
            try:
                result = self.__request("", 72)
@@ -372,16 +443,13 @@
            size = (self.width(), self.height())
            self.wx_pipe.send(json.dumps({"type": "codes_setting", "pos": (ps[0] + size[0] / 2, ps[1] + size[1] / 2)}))
        def __show_dead_hwnds():
            self.wx_pipe.send(json.dumps({"type": "show_dead_hwnds"}))
        def __manage_ths_pos():
            ps = (self.x(), self.y())
            size = (self.width(), self.height())
            self.wx_pipe.send(json.dumps({"type": "manage_ths_pos", "pos": (ps[0] + size[0] / 2, ps[1] + size[1] / 2)}))
        def __show_float_callback():
            self.wx_pipe.send(json.dumps({"type": "show_float_callback"}))
        def __show_main_callback():
            self.wx_pipe.send(json.dumps({"type": "show_main_callback"}))
        def __show_second_window():
            self.secondWindow.show()
@@ -394,21 +462,16 @@
        def __clear_webview_cache():
            self.webview.page().profile().clearHttpCache()
        def __show_ths_flash_trade():
            hwnds = ths_util.get_flash_trade_hwnds()
            for hwnd in hwnds:
                if not win32gui.IsWindowVisible(hwnd):
                    win32gui.BringWindowToTop(hwnd)
                win32_util.move_window(hwnd, 0, 0)
        menubar = self.menuBar()
        setting_ = menubar.addMenu('&设置')
        juejin_action = QAction("&掘金参数配置", self)
        juejin_action.triggered.connect(__set_juejin_params)
        setting_.addAction(juejin_action)
        action = QAction("&代码管理", self)
        action.triggered.connect(__manage_code)
        setting_.addAction(action)
        action = QAction("&下载涨停代码", self)
        action.triggered.connect(__download_codes)
        setting_.addAction(action)
        action = QAction("&GPU检测", self)
        action.triggered.connect(__gpu_is_avaiable)
@@ -418,33 +481,25 @@
        action.triggered.connect(__clear_webview_cache)
        setting_.addAction(action)
        action = QAction("&掘金分时数据下载", self)
        action.triggered.connect(__juejin_tick_download)
        action = QAction("&同花顺代码识别", self)
        action.triggered.connect(__ths_ocr_code)
        setting_.addAction(action)
        auto_ = menubar.addMenu('&自动化')
        action = QAction("&同花顺设置", self)
        action.triggered.connect(__manage_ths_pos)
        auto_.addAction(action)
        action = QAction("&死句柄管理", self)
        action.triggered.connect(__show_dead_hwnds)
        setting_.addAction(action)
        view_ = menubar.addMenu('&视图')
        action = QAction("&打开副屏", self)
        action.triggered.connect(__show_second_window)
        view_.addAction(action)
        action = QAction("&打开悬浮盯盘", self)
        action.triggered.connect(__show_float_callback)
        view_.addAction(action)
        action = QAction("&打开历史消息", self)
        action.triggered.connect(__show_his_msg_window)
        view_.addAction(action)
        view_ = menubar.addMenu('&代码管理')
        view_.aboutToShow.connect(__manage_code)
        view_ = menubar.addMenu('&打开分时')
        view_.aboutToShow.connect(__show_main_callback)
        view_ = menubar.addMenu('&显示一键卖出')
        view_.aboutToShow.connect(__show_ths_flash_trade)
    def __init__(self, wx_pipe):
        super().__init__()
@@ -459,6 +514,7 @@
            self.center()
        self.setWindowFlag(Qt.WindowStaysOnTopHint, True)
        self.webview = QWebEngineView()
        self.webview.setPage(WebEnginePage())
        self.webview.settings().setAttribute(QWebEngineSettings.JavascriptEnabled, True)
        self.__menu()
        # JS桥设置
@@ -476,11 +532,12 @@
        else:
            self.webview.load(QUrl("http://127.0.0.1:8848/kp/index23-05-04.html"))
        self.secondWindow.show()
        if not constant.IS_TEST:
            self.secondWindow.loadUrl(f"http://{constant.WEB_HOST}/kp/codes_list.html")
        else:
            self.secondWindow.loadUrl("http://127.0.0.1:8848/kp/codes_list.html")
        if not setting.is_only_convertible_bonds():
            self.secondWindow.show()
            if not constant.IS_TEST:
                self.secondWindow.loadUrl(f"http://{constant.WEB_HOST}/kp/codes_list.html")
            else:
                self.secondWindow.loadUrl("http://127.0.0.1:8848/kp/codes_list.html")
        # 绑定槽函数
        self.signal_update_code.connect(self.set_target_code)
@@ -500,6 +557,8 @@
        except Exception as e:
            print("")
        self.wx_pipe.send(json.dumps({"type": "exit"}))
        wxGuiProcess.terminate()
        wxGuiProcess.join()
        sys.exit(0)
    # 读取消息
@@ -535,6 +594,7 @@
        except Exception as e:
            logging.exception(e)
# 打包命令
# cd D:\workspace\GP\trade_desk
# D:\workspace\GP\trade_desk\dist\env\pk_env\Scripts\pyinstaller.exe main.spec
@@ -543,6 +603,7 @@
if __name__ == "__main__":
    freeze_support()
    p1, p2 = multiprocessing.Pipe()
    global wxGuiProcess
    wxGuiProcess = Process(target=gui_wx.run, args=(p1,))
    wxGuiProcess.start()