From ec060ce444cdd1c48a54686cadbc8950478eedcf Mon Sep 17 00:00:00 2001
From: admin <weikou2014>
Date: 星期五, 22 八月 2025 16:27:34 +0800
Subject: [PATCH] 网页内容修改

---
 main.py | 1965 +++++++++++++++++++++++------------------------------------
 1 files changed, 759 insertions(+), 1,206 deletions(-)

diff --git a/main.py b/main.py
index 00c292f..ddc3348 100644
--- a/main.py
+++ b/main.py
@@ -1,1247 +1,800 @@
+import base64
+import ctypes
+import hashlib
 import json
-import socket
-import sys
-import time
-from multiprocessing import freeze_support
-
-import win32con
-import win32gui
-
-import ocr_util
-import opencv_util
-import setting
-import ths_util
-import win32_util
-
-freeze_support()
 import logging
 import multiprocessing
+import queue
 import threading
+import time
+import sys
+from functools import partial
+from multiprocessing import Pipe, Process, freeze_support
 
-import matplotlib.pyplot as plt
-from matplotlib.widgets import Button
+import torch
+import win32api
+import win32con
+import win32gui
+from PyQt5.QtGui import QFont, QPalette, QColor, QTextOption
 
-import wx
-from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
-from matplotlib.figure import Figure
+from PyQt5.QtWebChannel import QWebChannel
+from PyQt5.QtWebEngineWidgets import QWebEngineView, QWebEngineSettings, QWebEnginePage
+from PyQt5.QtWidgets import QMainWindow, QApplication, QAction, QMessageBox, QLabel
 
-import code_data_manager
-import juejin_core
-import tool
-import dateutil
+from PyQt5.QtCore import Qt, pyqtSlot, QObject, pyqtSignal, QTimer, QUrl, QPoint
 
-APP_TITLE = "鍗栫エ鐪嬫澘"
-APP_ICON = ""
+import constant
+import gui_wx
+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"
+
+window_msg_queue = queue.Queue()
 
 
-def show_warning(content, click):
-    toastone = wx.MessageDialog(None, content, "鎻愮ず", wx.YES_DEFAULT | wx.ICON_WARNING)
-    if toastone.ShowModal() == wx.ID_YES:  # 濡傛灉鐐瑰嚮浜嗘彁绀烘鐨勭‘瀹氭寜閽�
-        if click is not None:
-            click()
-        toastone.Destroy()
+class BaseBridgeClass(QObject):
+    signal_request = pyqtSignal(str, str, str)
 
+    def __request_result_callback(self, method, key, result):
+        base64_str = base64.b64encode(result.encode('utf-8')).decode('utf-8')
+        self.__webview.page().runJavaScript(f"{method}('{key}','{base64_str}')")
 
-def show_info(content, click):
-    toastone = wx.MessageDialog(None, content, "鎻愮ず", wx.YES_DEFAULT | wx.ICON_INFORMATION)
-    if toastone.ShowModal() == wx.ID_YES:  # 濡傛灉鐐瑰嚮浜嗘彁绀烘鐨勭‘瀹氭寜閽�
-        click()
-        toastone.Destroy()
+    def __init__(self, webview):
+        super().__init__()
+        self.__webview = webview
+        self.signal_request.connect(self.__request_result_callback)
 
-
-class JueJinSettingFrame(wx.Frame):
-    def __init__(self, position):
-        wx.Frame.__init__(self, None, -1, "鎺橀噾鍙傛暟璁剧疆", style=wx.SYSTEM_MENU ^ wx.CLOSE_BOX ^ wx.CAPTION ^ wx.STAY_ON_TOP,
-                          size=(450, 200))
-
-        self.SetBackgroundColour(wx.Colour(224, 224, 224))
-        self.SetPosition(wx.Point(position[0] - self.GetSize()[0] / 2, position[1] - self.GetSize()[1] / 2))
-        boxsier = wx.BoxSizer()
-        flex = wx.FlexGridSizer(rows=3, cols=2, vgap=10, hgap=10)
-        # 绛栫暐
-        label = wx.StaticText(self, label="绛栫暐ID锛�")
-        flex.Add(label, flag=wx.ALIGN_RIGHT)
-        self.edit_celue = wx.TextCtrl(self, size=(300, -1))
-        flex.Add(self.edit_celue, flag=wx.EXPAND)
-
-        # token
-        label = wx.StaticText(self, label="Token锛�")
-        flex.Add(label)
-        self.edit_token = wx.TextCtrl(self, size=(300, -1), style=wx.TE_MULTILINE)
-        flex.Add(self.edit_token)
-
-        # 鍗犱綅
-        flex.Add(wx.StaticText(self, label=""))
-        # 纭畾鎸夐挳
-        ID_SURE = wx.NewId()
-        self.btn_sure = wx.Button(self, label='纭畾', id=ID_SURE)
-        self.btn_sure.Bind(wx.EVT_BUTTON, self.__sure_btn)
-        flex.Add(self.btn_sure, 1, wx.TOP | wx.LEFT, 20)
-
-        boxsier.Add(flex, 1, wx.TOP | wx.LEFT, 20)
-        self.SetSizer(boxsier)
-
-        # 鍒濆鍖栨暟鎹�
-        self.__init_data()
-
-    def __init_data(self):
-        strategy_id, token = setting.get_juejin_params()
-        self.edit_celue.SetLabelText(strategy_id)
-        self.edit_token.SetLabelText(token)
-        pass
-
-    def __sure_btn(self, event):
-        strategy_id = self.edit_celue.GetValue()
-        token = self.edit_token.GetValue()
-        setting.set_juejin_params(strategy_id, token)
-        toastone = wx.MessageDialog(None, "鏇存敼鎴愬姛", "鎻愮ず", wx.YES_DEFAULT | wx.ICON_INFORMATION)
-        if toastone.ShowModal() == wx.ID_YES:  # 濡傛灉鐐瑰嚮浜嗘彁绀烘鐨勭‘瀹氭寜閽�
-            self.Close()
-            toastone.Destroy()
-
-
-class CodesSettingFrame(wx.Frame):
-    def __init__(self, position, callback):
-        wx.Frame.__init__(self, None, -1, "浠g爜璁剧疆", style=wx.SYSTEM_MENU ^ wx.CLOSE_BOX ^ wx.CAPTION ^ wx.STAY_ON_TOP,
-                          size=(170, 300))
-        self.SetBackgroundColour(wx.Colour(224, 224, 224))
-        self.SetPosition(wx.Point(position[0] - self.GetSize()[0] / 2, position[1] - self.GetSize()[1] / 2))
-        boxsier = wx.BoxSizer(wx.VERTICAL)
-        # 浠g爜
-        label = wx.StaticText(self, label="鐩爣浠g爜锛�")
-        boxsier.Add(label)
-        self.edit_codes = wx.TextCtrl(self, size=(150, 200), style=wx.TE_MULTILINE)
-        boxsier.Add(self.edit_codes)
-
-        # 纭畾鎸夐挳
-        ID_SURE = wx.NewId()
-        self.btn_sure = wx.Button(self, label='纭畾', id=ID_SURE)
-        self.btn_sure.Bind(wx.EVT_BUTTON, self.__sure_btn)
-        boxsier.Add(self.btn_sure)
-        root_boxsier = wx.BoxSizer(wx.HORIZONTAL)
-        root_boxsier.Add(boxsier, 1, wx.TOP | wx.TOP, 10)
-        self.SetSizer(root_boxsier)
-
-        # 鍒濆鍖栨暟鎹�
-        self.__init_data()
-        self.callback = callback
-
-    def __init_data(self):
-        codes = juejin_core.GPCodeManager().get_codes()
-        self.edit_codes.SetValue("\n".join(codes))
-        pass
-
-    def __sure_btn(self, event):
-        codes_str = self.edit_codes.GetValue()
-        codes = codes_str.split("\n")
-        codes_result = []
-        for code in codes:
-            if code.strip():
-                codes_result.append(code.strip())
-        juejin_core.GPCodeManager().set_codes(codes_result)
-        # 閲嶆柊璁㈤槄
-        self.callback()
-        toastone = wx.MessageDialog(None, "鏇存敼鎴愬姛", "鎻愮ず", wx.YES_DEFAULT | wx.ICON_INFORMATION)
-        if toastone.ShowModal() == wx.ID_YES:  # 濡傛灉鐐瑰嚮浜嗘彁绀烘鐨勭‘瀹氭寜閽�
-            self.Close()
-            toastone.Destroy()
-
-
-class FobiddenCodesFrame(wx.Frame):
-    def __init__(self, position):
-        wx.Frame.__init__(self, None, -1, "娣诲姞绂佹浜ゆ槗浠g爜", style=wx.SYSTEM_MENU ^ wx.CLOSE_BOX ^ wx.CAPTION ^ wx.STAY_ON_TOP,
-                          size=(170, 200))
-        self.SetBackgroundColour(wx.Colour(224, 224, 224))
-        self.SetPosition(wx.Point(position[0] - self.GetSize()[0] / 2, position[1] - self.GetSize()[1] / 2))
-        boxsier = wx.BoxSizer(wx.VERTICAL)
-        # 浠g爜
-        label = wx.StaticText(self, label="浠g爜锛�")
-        boxsier.Add(label, flag=wx.ALIGN_LEFT, border=10)
-        self.edit_codes = wx.TextCtrl(self, size=(150, 100), style=wx.TE_MULTILINE)
-        boxsier.Add(self.edit_codes)
-
-        # 纭畾鎸夐挳
-        ID_SURE = wx.NewId()
-        self.btn_sure = wx.Button(self, label='纭畾', id=ID_SURE)
-        self.btn_sure.Bind(wx.EVT_BUTTON, self.__sure_btn)
-        boxsier.Add(self.btn_sure)
-        root_boxsier = wx.BoxSizer(wx.HORIZONTAL)
-        root_boxsier.Add(boxsier, 1, wx.TOP | wx.TOP, 10)
-        self.SetSizer(root_boxsier)
-
-    def __request(self, codes):
-        client = socket.socket()  # 鐢熸垚socket锛岃繛鎺erver
-        ip_port = ("192.168.3.252", 9001)  # server鍦板潃鍜岀鍙e彿锛堟渶濂芥槸10000浠ュ悗锛�
-        client.connect(ip_port)
-        data = {"type": 201, "data": {"codes": codes}}
-        client.send(json.dumps(data).encode("utf-8"))
-        client.close()
-
-    def __sure_btn(self, event):
-        codes_str = self.edit_codes.GetValue()
-        if codes_str:
-            codes_str = codes_str.strip()
-
-        codes = codes_str.split("\n")
-        codes_result = []
-        for code in codes:
-            if code.strip() and len(code.strip()) == 6:
-                codes_result.append(code.strip())
-        if len(codes_result) == 0:
-            show_warning("璇峰~鍐欐纭殑浠g爜锛�", self.Close)
-            return
+    def __http_request(self, url, callback_info):
         try:
-            self.__request(codes_result)
+            # 浠g悊璇锋眰缁撴灉
+            result, need_delegate = LocalKanPanNetworkDelegate.http_delegate_request(url)
+            if not need_delegate:
+                result = network_util.http_get(url)
+            print(url, f"璇锋眰缁撴灉锛歿len(result.encode('utf-8'))}", result)
+            self.signal_request.emit(callback_info[0], callback_info[1], result)
+            return result
         except Exception as e:
-            show_warning("娣诲姞鍑洪敊锛�" + str(e), None)
-            return
+            logging.exception(e)
 
-        toastone = wx.MessageDialog(None, "娣诲姞鎴愬姛", "鎻愮ず", wx.YES_DEFAULT | wx.ICON_INFORMATION)
-        if toastone.ShowModal() == wx.ID_YES:  # 濡傛灉鐐瑰嚮浜嗘彁绀烘鐨勭‘瀹氭寜閽�
-            self.Close()
-            toastone.Destroy()
-
-
-class THSPositionSettingFrame(wx.Frame):
-    def __init__(self, position):
-        wx.Frame.__init__(self, None, -1, "鍚岃姳椤哄潗鏍囪缃�", style=wx.SYSTEM_MENU ^ wx.CLOSE_BOX ^ wx.CAPTION ^ wx.STAY_ON_TOP,
-                          size=(170, 400))
-        self.SetBackgroundColour(wx.Colour(224, 224, 224))
-        self.SetPosition(wx.Point(position[0] - self.GetSize()[0] / 2, position[1] - self.GetSize()[1] / 2))
-        boxsier = wx.BoxSizer(wx.VERTICAL)
-
-        label = wx.StaticText(self, label="浜ゆ槗鍒锋柊浜嬩欢闂撮殧(ms)锛�")
-        boxsier.Add(label)
-        self.edit_refresh_time_space = wx.TextCtrl(self, size=(150, -1))
-        boxsier.Add(self.edit_refresh_time_space)
-
-        label = wx.StaticText(self, label="鐐瑰嚮鏃堕棿闂撮殧(ms)锛�")
-        boxsier.Add(label)
-        self.edit_time_space = wx.TextCtrl(self, size=(150, -1))
-        boxsier.Add(self.edit_time_space)
-
-        # 浠g爜
-        label = wx.StaticText(self, label="鍧愭爣锛�")
-        boxsier.Add(label)
-        self.edit_codes = wx.TextCtrl(self, size=(150, 200), style=wx.TE_MULTILINE)
-        boxsier.Add(self.edit_codes)
-
-        # 纭畾鎸夐挳
-        ID_SURE = wx.NewId()
-        self.btn_sure = wx.Button(self, label='纭畾', id=ID_SURE)
-        self.btn_sure.Bind(wx.EVT_BUTTON, self.__sure_btn)
-        boxsier.Add(self.btn_sure)
-        root_boxsier = wx.BoxSizer(wx.HORIZONTAL)
-        root_boxsier.Add(boxsier, 1, wx.TOP | wx.TOP, 10)
-        self.SetSizer(root_boxsier)
-
-        # 鍒濆鍖栨暟鎹�
-        self.__init_data()
-
-    def __init_data(self):
-        pos = setting.get_ths_auto_click_positions()
-        self.edit_codes.SetValue("\n".join(pos))
-        space = setting.get_ths_auto_click_time_space()
-        if space is None:
-            space = 500
-        self.edit_time_space.SetValue(f"{space}")
-
-        space = setting.get_ths_auto_refresh_time_space()
-        if space is None:
-            space = 500
-        self.edit_refresh_time_space.SetValue(f"{space}")
-
-    def __sure_btn(self, event):
-        codes_str = self.edit_codes.GetValue()
-        ps = codes_str.split("\n")
-        result = []
-        for p in ps:
-            if p.strip():
-                result.append(p.strip())
-        setting.set_ths_auto_click_positions(result)
-
-        time_space = self.edit_time_space.GetValue()
-        if len(time_space) == 0:
-            show_warning("鐐瑰嚮鏃堕棿闂撮殧涓嶆纭�", None)
-            return
-
-        refresh_time_space = self.edit_refresh_time_space.GetValue()
-        if len(refresh_time_space) == 0:
-            show_warning("鍒锋柊鏃堕棿闂撮殧涓嶆纭�", None)
-            return
-
-        setting.set_ths_auto_click_time_space(time_space)
-        setting.set_ths_auto_refresh_time_space(refresh_time_space)
-
-        toastone = wx.MessageDialog(None, "鏇存敼鎴愬姛", "鎻愮ず", wx.YES_DEFAULT | wx.ICON_INFORMATION)
-        if toastone.ShowModal() == wx.ID_YES:  # 濡傛灉鐐瑰嚮浜嗘彁绀烘鐨勭‘瀹氭寜閽�
-            self.Close()
-            toastone.Destroy()
-
-
-def ocr_ths_code():
-    hwnd = ths_util.get_ths_main_content_hwnd()
-    if not hwnd:
-        raise Exception("鐪嬬洏椤甸潰鍙ユ焺鏈幏鍙栧埌")
-    # 鍙ユ焺鎴浘
-    rect = win32gui.GetWindowRect(hwnd)
-    # hwnd_width = (rect[2] - rect[0]) * 15 // 10
-    rect_ = setting.get_ths_auto_code_rect()
-    img = win32_util.window_capture(hwnd, (0, rect_[0], rect_[1], rect_[0] + rect_[2]))
-    code = ocr_util.recognize_code(opencv_util.clip_ths_code_area(img))
-    return code
-
-
-# 鎮诞妗�
-class FloatFrame(wx.Frame):
-    def __init__(self, position):
-        wx.Frame.__init__(self, None, -1, "鎮诞鐩洏", style=wx.CAPTION ^ wx.STAY_ON_TOP,
-                          size=(320, 195))
-        self.SetBackgroundColour(wx.Colour(224, 224, 224))
-        self.SetTransparent(230)
-        if position:
-            self.SetPosition(wx.Point(position[0], position[1]))
-        boxsier = wx.FlexGridSizer(5, 2, 2, 20)
-
-        self.btn_remove_black = wx.Button(self, label="绉婚櫎榛戝悕鍗�", size=(70, 30))
-        boxsier.Add(self.btn_remove_black, 0, wx.TOP, 5)
-
-        bs1 = wx.BoxSizer(wx.HORIZONTAL)
-
-        self.btn_remove_white = wx.Button(self, label="绉婚櫎鐧藉悕鍗�", size=(70, 30))
-        bs1.Add(self.btn_remove_white, 0, wx.TOP, 5)
-        boxsier.Add(bs1, 0, wx.LEFT, 80)
-
-        label = wx.StaticText(self, label="浜ゆ槗鍒锋柊锛�")
-        bs1 = wx.BoxSizer(wx.HORIZONTAL)
-        bs1.Add(label)
-        self.check_auto_refresh = wx.CheckBox(self, size=(-1, -1))
-        bs1.Add(self.check_auto_refresh, 0, wx.LEFT, 10)
-        boxsier.Add(bs1, 0, wx.TOP, 5)
-
-        bs1 = wx.BoxSizer(wx.HORIZONTAL)
-        self.want_list = wx.Button(self, label="鎯充拱鍗�", size=(45, 20))
-        bs1.Add(self.want_list, 0, wx.TOP, 2)
-        self.btn_want_buy = wx.Button(self, label="鍔犲叆鎯充拱鍗�", size=(70, 25))
-        bs1.Add(self.btn_want_buy)
-
-        boxsier.Add(bs1, 0, wx.LEFT, 35)
-
-        label = wx.StaticText(self, label="鍒嗙粍鍒锋柊锛�")
-        bs1 = wx.BoxSizer(wx.HORIZONTAL)
-        bs1.Add(label)
-        self.check_auto_click = wx.CheckBox(self, size=(-1, -1))
-        bs1.Add(self.check_auto_click, 0, wx.LEFT, 10)
-        boxsier.Add(bs1)
-
-        self.btn_want_buy_remove = wx.Button(self, label="绉婚櫎鎯充拱鍗�", size=(70, 25))
-        boxsier.Add(self.btn_want_buy_remove, 0, wx.LEFT, 80)
-
-        self.edit_code = wx.TextCtrl(self, size=(80, -1))
-        boxsier.Add(self.edit_code)
-
-        self.notify_text = wx.StaticText(self, label="", size=(80, -1))
-        boxsier.Add(self.notify_text)
-
-        # 浠g爜
-        bs1 = wx.BoxSizer(wx.HORIZONTAL)
-        self.btn_black = wx.Button(self, label="鍔犲叆榛戝悕鍗�", size=(70, 30))
-        bs1.Add(self.btn_black)
-        self.black_list = wx.Button(self, label="榛戝悕鍗�", size=(45, 20))
-        self.black_list.SetForegroundColour("#00e600")
-        bs1.Add(self.black_list, 0, wx.CENTER | wx.ALL, 0)
-        boxsier.Add(bs1, 0, wx.LEFT, 0)
-
-        bs1 = wx.BoxSizer(wx.HORIZONTAL)
-        self.btn_white = wx.Button(self, label="鍔犲叆鐧藉悕鍗�", size=(70, 30))
-        self.white_list = wx.Button(self, label="鐧藉悕鍗�", size=(45, 20))
-        self.white_list.SetForegroundColour("#FF3232")
-        bs1.Add(self.white_list, 0, wx.CENTER | wx.ALL, 0)
-        bs1.Add(self.btn_white, 0, wx.LEFT, 2)
-
-        boxsier.Add(bs1, 0, wx.LEFT, 32)
-
-        # 缁戝畾
-        self.btn_black.Bind(wx.EVT_BUTTON, self.add_black)
-        self.btn_white.Bind(wx.EVT_BUTTON, self.add_white)
-        self.btn_remove_black.Bind(wx.EVT_BUTTON, self.remove_from_black)
-        self.btn_remove_white.Bind(wx.EVT_BUTTON, self.remove_from_white)
-
-        self.btn_want_buy.Bind(wx.EVT_BUTTON, self.add_want)
-        self.btn_want_buy_remove.Bind(wx.EVT_BUTTON, self.remove_from_want)
-
-        self.check_auto_click.Bind(wx.EVT_CHECKBOX, self.__auto_click_check)
-        self.check_auto_refresh.Bind(wx.EVT_CHECKBOX, self.__auto_refresh_check)
-        self.white_list.Bind(wx.EVT_BUTTON, lambda e: self.show_list(e, "鐧藉悕鍗曞垪琛�", 302))
-        self.black_list.Bind(wx.EVT_BUTTON, lambda e: self.show_list(e, "榛戝悕鍗曞垪琛�", 301))
-        self.want_list.Bind(wx.EVT_BUTTON, lambda e: self.show_list(e, "鎯宠涔板垪琛�", 403))
-
-        root_boxsier = wx.BoxSizer(wx.HORIZONTAL)
-        root_boxsier.Add(boxsier, 1, wx.LEFT, 10)
-        self.SetSizer(root_boxsier)
-
-        self.__bind_hot_keys()
-        # 鍒濆鍖栨暟鎹�
-        self.__init_data()
-
-        self.timer = wx.Timer(self)  # 鍒涘缓瀹氭椂鍣�
-        self.Bind(wx.EVT_TIMER, self.clear_msg, self.timer)
-
-    def clear_msg(self, event):
-        self.notify_text.SetLabelText("")
-
-    def __ocr_code(self):
-        code = self.edit_code.GetValue()
-        if code is not None and len(code.strip()) == 0:
-            code = None
-        if code is not None:
-            if len(code) != 6:
-                self.show_warning("璇峰~鍐欐纭殑浠g爜")
-                return
+    def __socket_request(self, text, callback_info, port=None):
+        try:
+            print("socket璜嬫眰锛�", text)
+            if port:
+                result = network_util.socket_request(text, port=port)
             else:
-                return
-
-        code = ocr_ths_code()
-        if code is None:
-            raise Exception("浠g爜璇嗗埆鍑洪敊")
-        self.edit_code.SetValue(code)
-
-    def show_warning(self, content):
-        self.notify_text.SetLabel(content)
-        self.notify_text.SetForegroundColour("#FF7F27")
-        self.timer.Stop()
-        self.timer.StartOnce(20000)
-
-    def show_info(self, content):
-        self.notify_text.SetLabel(content)
-        self.notify_text.SetForegroundColour("#008000")
-        self.timer.Stop()
-        self.timer.StartOnce(20000)
-
-    def __get_code(self):
-        self.__ocr_code()
-        code = self.edit_code.GetValue()
-        if code is None or len(code) != 6:
-            raise Exception("璇峰~鍐欐纭殑浠g爜")
-        return code
-
-    def add_black(self, event):
-        try:
-            code = self.__get_code()
-            print("鍔犲叆榛戝悕鍗�", code)
-            self.__request([code], 201)
-            self.show_info(f"{code}鍔犲叆榛戝悕鍗曟垚鍔�")
-            self.edit_code.SetValue("")
+                result = network_util.socket_request(text)
+            print(f"璇锋眰缁撴灉锛歿len(result.encode('utf-8'))}", result)
+            self.signal_request.emit(callback_info[0], callback_info[1], result)
+            return result
         except Exception as e:
-            self.show_warning(str(e))
-            return
+            logging.exception(e)
 
-    def add_white(self, event):
-        try:
-            code = self.__get_code()
-            print("鍔犲叆鐧藉悕鍗�", code)
-            self.__request([code], 202)
-            self.show_info(f"{code}鍔犲叆鐧藉悕鍗曟垚鍔�")
-            self.edit_code.SetValue("")
-        except Exception as e:
-            self.show_warning(str(e))
-            return
-
-    def add_want(self, event):
-        try:
-            code = self.__get_code()
-            print("鍔犲叆鎯宠涔�", code)
-            self.__request([code], 401)
-            self.show_info(f"{code}鍔犲叆鎯宠涔板悕鍗曟垚鍔�")
-            self.edit_code.SetValue("")
-        except Exception as e:
-            self.show_warning(str(e))
-            return
-
-    def remove_from_black(self, event):
-        try:
-            code = self.__get_code()
-            print("绉婚櫎榛戝悕鍗�", code)
-            self.__request([code], 203)
-            self.show_info(f"{code}绉婚櫎榛戝悕鍗曟垚鍔�")
-            self.edit_code.SetValue("")
-        except Exception as e:
-            self.show_warning(str(e))
-            return
-
-    def remove_from_white(self, event):
-        try:
-            code = self.__get_code()
-            print("绉婚櫎鐧藉悕鍗�", code)
-            self.__request([code], 204)
-            self.show_info(f"{code}绉婚櫎鐧藉悕鍗曟垚鍔�")
-            self.edit_code.SetValue("")
-        except Exception as e:
-            self.show_warning(str(e))
-            return
-
-    def remove_from_want(self, event):
-        try:
-            code = self.__get_code()
-            print("绉婚櫎鎯宠涔板悕鍗�", code)
-            self.__request([code], 402)
-            self.show_info(f"{code}绉婚櫎鎯宠涔板悕鍗曟垚鍔�")
-            self.edit_code.SetValue("")
-        except Exception as e:
-            self.show_warning(str(e))
-            return
-
-    def show_list(self, event, title, type):
-        try:
-            result = self.__request_list(type)
-            result = json.loads(result)
-            self.__show_list(title, result["data"])
-        except Exception as e:
-            show_warning(str(e), None)
-
-    def __show_list(self, title, datas):
-        st = ""
-        for i in range(0, len(datas)):
-            st += datas[i]
-            if i % 2 == 1 and i != len(datas) - 1:
-                st += "\n"
-            elif i != len(datas) - 1:
-                st += " , "
-
-        toastone = wx.MessageDialog(None, st, title)
-        if toastone.ShowModal() == wx.ID_YES:  # 濡傛灉鐐瑰嚮浜嗘彁绀烘鐨勭‘瀹氭寜閽�
-            toastone.Destroy()
-
-    def __bind_hot_keys(self):
-        # 蹇嵎閿�
-        setting_ = wx.Menu()
-        m_black = wx.MenuItem(setting_, id=101, text='&E', kind=wx.ITEM_NORMAL)
-        m_white = wx.MenuItem(setting_, id=102, text='&E', kind=wx.ITEM_NORMAL)
-        self.Bind(wx.EVT_MENU, self.add_black, m_black)
-        self.Bind(wx.EVT_MENU, self.add_white, m_white)
-        entries = [wx.AcceleratorEntry() for i in range(2)]
-        entries[0].Set(wx.ACCEL_CTRL, wx.WXK_F4, 101)
-        entries[1].Set(wx.ACCEL_CTRL, wx.WXK_F5, 102)
-        accel = wx.AcceleratorTable(entries)
-        self.SetAcceleratorTable(accel)
-
-    def __init_data(self):
-        auto_click = setting.is_ths_auto_click()
-        if auto_click:
-            self.check_auto_click.SetValue(True)
-        else:
-            self.check_auto_click.SetValue(False)
-
-        auto_refresh = setting.is_ths_trade_auto_refresh()
-        if auto_refresh:
-            self.check_auto_refresh.SetValue(True)
-        else:
-            self.check_auto_refresh.SetValue(False)
-
-    def __auto_click_check(self, event):
-        if event.Selection:
-            setting.set_ths_auto_click(True)
-        else:
-            setting.set_ths_auto_click(False)
-
-    def __auto_refresh_check(self, event):
-        if event.Selection:
-            setting.set_ths_trade_auto_refresh(True)
-        else:
-            setting.set_ths_trade_auto_refresh(False)
-
-    def __request(self, codes, type):
-        client = socket.socket()  # 鐢熸垚socket锛岃繛鎺erver
-        ip_port = ("192.168.3.252", 9001)  # server鍦板潃鍜岀鍙e彿锛堟渶濂芥槸10000浠ュ悗锛�
-        client.connect(ip_port)
-        data = {"type": type, "data": {"codes": codes}}
-        client.send(json.dumps(data).encode("utf-8"))
-        client.close()
-
-    def __request_list(self, type):
-        client = socket.socket()  # 鐢熸垚socket锛岃繛鎺erver
-        ip_port = ("192.168.3.252", 9001)  # server鍦板潃鍜岀鍙e彿锛堟渶濂芥槸10000浠ュ悗锛�
-        client.connect(ip_port)
-        data = {"type": type, "data": {}}
-        client.send(json.dumps(data).encode("utf-8"))
-        # 璇诲彇鍐呭
-        result = client.recv(10240)
-        client.close()
-        return result.decode("gbk")
-
-
-class mainFrame(wx.Frame):
-    def __init__(self):
-        '''鏋勯�犲嚱鏁�'''
-        wx.Frame.__init__(self, None, -1, APP_TITLE, style=wx.DEFAULT_FRAME_STYLE,
-                          size=(800, 500))
-        # ^ wx.RESIZE_BORDER ^ wx.STAY_ON_TOP
-        # 榛樿style鏄笅鍒楅」鐨勭粍鍚堬細wx.MINIMIZE_BOX | wx.MAXIMIZE_BOX | wx.RESIZE_BORDER | wx.SYSTEM_MENU | wx.CAPTION | wx.CLOSE_BOX | wx.CLIP_CHILDREN
-        self.SetBackgroundColour(wx.Colour(0, 0, 0))
-        self.Center()
-        self.__menu()
-        # 浠ヤ笅浠g爜澶勭悊鍥炬爣
-        # if hasattr(sys, "frozen") and getattr(sys, "frozen") == "windows_exe":
-        #     exeName = win32api.GetModuleFileName(win32api.GetModuleHandle(None))
-        #     icon = wx.Icon(exeName, wx.BITMAP_TYPE_ICO)
-        # else:
-        #     icon = wx.Icon(APP_ICON, wx.BITMAP_TYPE_ICO)
-        # self.SetIcon(icon)
-        # 瀹氫箟绐楀彛鍏抽棴
-        self.Bind(wx.EVT_CLOSE, self.OnExit)
-        self.Bind(wx.EVT_SIZE, self.OnResize)
-        self.panels = []
-        self.scroll = None
-        self.mark_lines = {}
-        self.col = 1
-        self.__re_draw()
-
-        self.timer = wx.Timer(self)  # 鍒涘缓瀹氭椂鍣�
-        self.Bind(wx.EVT_TIMER, self.post_redraw, self.timer)  # 缁戝畾涓�涓畾鏃跺櫒浜嬩欢
-        self.last_size = (self.Size[0], self.Size[1])
-
-        # self.scroll.Layout()
-        # self.boxsier.Fit(self.scroll)
-
-        # boxsier.Add(mainBoxsier, 1, wx.EXPAND | wx.ALL, 5)
-        # self.SetSizer(boxsier)
-        # mainBoxsier.Fit(self)
-
-        window_info = setting.get_window_info()
-        float_pos = None
-        if window_info:
-            float_pos = window_info[1]
-            self.SetPosition(wx.Point(window_info[0][0], window_info[0][1]))
-            self.Size = wx.Size(window_info[0][2], window_info[0][3])
-        self.floatFrame = FloatFrame(float_pos)
-        self.floatFrame.Show()
-        if setting.is_stay_on_top():
-            self.WindowStyle = wx.MINIMIZE_BOX | wx.MAXIMIZE_BOX | wx.RESIZE_BORDER | wx.SYSTEM_MENU | wx.CAPTION | wx.CLOSE_BOX | wx.CLIP_CHILDREN | wx.STAY_ON_TOP
-
-    def scrollTo(self, pos):
-        self.scroll.Scroll(0, pos)
-
-    def __re_draw(self):
-        codes_name = juejin_core.GPCodeManager().get_codes_with_names()
-        rows = len(codes_name)
-        if rows % self.col == 0:
-            rows = rows / self.col
-        else:
-            rows = rows / self.col + 1
-        space = 0
-        if self.scroll is None:
-            self.scroll = wx.ScrolledWindow(self, -1, size=(800, 1000))
-            self.boxsier = wx.FlexGridSizer(rows, self.col, space, space)
-            self.scroll.SetSizer(self.boxsier)
-        self.scroll.EnableScrolling(False, True)
-        if self.panels:
-            for p in self.panels:
-                p.Destroy()
-        self.boxsier.Clear()
-        pannel_height = round((self.Size[0] - (self.col - 1) * space) / self.col * (450 / 800))
-
-        self.scroll.SetScrollbars(1, 1, 0, pannel_height * rows)
-        self.scroll.SetScrollRate(0, pannel_height)
-        global drawManager
-        axes_list = []
-        self.panels = []
-        for i in range(0, len(codes_name)):
-            # pos=(0, i * pannel_height)
-            pannel = wx.Panel(self.scroll, size=(-1, pannel_height))
-            pannel.BackgroundColour = wx.Colour(0, 0, 0)
-            self.panels.append(pannel)
-            self.boxsier.Add(pannel)
-            axes = self.__create_canvas(pannel, "{}({})".format(codes_name[i][0], codes_name[i][1]), codes_name[i][1],
-                                        codes_name[i][2])
-            axes_list.append(axes)
-
-        self.scroll.Layout()
-        # self.boxsier.Fit(self.scroll)
-        #
-        # 鍒濆鍖栨暟鎹�
-        drawManager = DrawManager(axes_list, codes_name)
-        drawManager.init_code_datas()
-
-    def __create_canvas(self, pannel, title, name, price, close_callback=None):
-        def show_mouse_line(event):
-            # 鍒犻櫎涔嬪墠鐨勭嚎
-            if title in self.mark_lines:
-                if self.mark_lines.get(title):
-                    line = self.mark_lines.get(title).get("mouse")
-                    if line is not None:
-                        line.remove()
-                        self.mark_lines.get(title).pop("mouse")
-            else:
-                self.mark_lines[title] = {}
-            try:
-                line = axes2.axhline(event.ydata, linestyle='-', color='white', lw=0.5)
-                self.mark_lines[title]["mouse"] = line
-                axes2.figure.canvas.draw()
-            except:
-                pass
-
-        def clear_mouse_line(event):
-            print("clear_mouse_line")
-            if title in self.mark_lines:
-                if self.mark_lines.get(title):
-                    line = self.mark_lines.get(title).get("mouse")
-                    if line is not None:
-                        line.remove()
-                        self.mark_lines.get(title).pop("mouse")
-                        axes2.figure.canvas.draw()
-
-        def close_canvas(event):
-            print("鍏抽棴", title)
-            close_callback(title)
-
-        width_dpi = self.Size[0] / (100 * self.col)
-        figure_score = Figure(figsize=(width_dpi, round(width_dpi * (4.5 / 7.8), 2)))
-        # 璁剧疆澶栬竟璺�
-        figure_score.subplots_adjust(left=0.01, bottom=0.15, right=0.85)
-        # 璁剧疆瀛椾綋棰滆壊
-        plt.rcParams["text.color"] = "red"
-        plt.rcParams["axes.labelcolor"] = "red"
-        # 璁剧疆鍧愭爣杞存暟瀛楅鑹�
-        plt.rcParams["xtick.color"] = "white"
-        plt.rcParams["ytick.color"] = "white"
-        # 璁剧疆鍧愭爣杞撮鑹�
-        plt.rcParams["axes.edgecolor"] = "firebrick"
-
-        # 瑙e喅涓枃涔辩爜闂
-        plt.rcParams["font.sans-serif"] = ["SimHei"]  # 璁剧疆瀛椾綋
-        plt.rcParams["font.serif"] = ["SimHei"]
-        plt.rcParams["axes.unicode_minus"] = False  # 璇ヨ鍙ヨВ鍐冲浘鍍忎腑鐨勨��-鈥濊礋鍙风殑涔辩爜闂
-
-        # 娴嬭瘯
-        buttonaxe = plt.axes([0.94, 0.5, 0.1, 0.1])
-        button1 = Button(buttonaxe, '鍏抽棴', color='white', hovercolor='yellow')
-
-        axes = figure_score.add_subplot(1, 1, 1)
-        axes.autoscale(True)
-
-        # axes_score.plot(t_score, s_score, 'ro', t_score, s_score, 'k')
-        axes.set_title(title)
-        axes.grid(color='firebrick', ls='-', lw=0.5)
-        axes.set_xlabel(f'鏃堕棿锛坽name}锛�')
-        axes.dist = 0
-
-        # axes.set_ylabel(u'浠锋牸')
-        # 鑾峰彇骞冲紑浠�
-        extra = 0  # (tool.get_limit_up_price(price)-decimal.Decimal(price))*decimal.Decimal(0.02)
-
-        axes.set_ylim(tool.get_limit_down_price(price) - extra, tool.get_limit_up_price(price) + extra)
-        axes.patch.set_facecolor('black')
-        figure_score.patch.set_facecolor('black')
-
-        axes2 = axes.twinx()
-        # axes2.grid(color='firebrick', ls='-', lw=0.5)
-        # axes2.grid(color='firebrick', ls='-', lw=0.5)
-        axes2.grid(False)
-        # 榧犳爣鍦ㄧ敾甯冪Щ鍔�
-        axes2.figure.canvas.mpl_connect('motion_notify_event', show_mouse_line)
-        # 榧犳爣绂诲紑鐢诲竷
-        axes2.figure.canvas.mpl_connect('axes_leave_event', clear_mouse_line)
-
-        # 璁剧疆绾靛潗鏍囪酱
-        limit_up_price = float(tool.get_limit_up_price(price))
-        max_rate = round((limit_up_price - price) / price, 4) * 100
-        print("娑ㄥ仠鏈�澶ф瘮渚�", max_rate)
-        yticks2 = []
-        for i in range(0, 21):
-            if i >= 10:
-                yticks2.append(0 - round(max_rate * (10 - i) / 10, 4))
-            else:
-                yticks2.append(round(max_rate * (i - 10) / 10, 4))
-        yticks2_labels = []
-        yticks = []
-        yticks_labels = []
-        for i in range(0, len(yticks2)):
-            if i % 2 == 0:
-                yticks2_labels.append("{}%".format(abs(round(yticks2[i], 2))))
-            else:
-                yticks2_labels.append("")
-            price_ = round((1 + yticks2[i] / 100) * price, 2)
-            yticks.append(price_)
-            if i % 2 == 0:
-                yticks_labels.append("")
-                # yticks_labels.append(round(yticks[i], 2))
-                if i == 10:
-                    axes2.axhline(yticks2[i], linestyle='-', color='firebrick', lw=2)
-                else:
-                    axes2.axhline(yticks2[i], linestyle='-', color='firebrick', lw=1.2)
-            else:
-                # axes2.axhline(yticks2[i], linestyle='-', color='firebrick', lw=0.5)
-                yticks_labels.append("")
-        # 鍔犵矖涓酱绾�
-
-        axes2.set_ylabel(u'娑ㄥ箙')
-        # 璁剧疆绾佃酱鐨勫�肩殑鑼冨洿
-        axes2.set_ylim(0 - max_rate * (1), max_rate * (1))
-        axes2.set_yticks(yticks2)
-        axes2.set_yticklabels(yticks2_labels)
-        axes.set_yticks(yticks)
-        axes.set_yticklabels(yticks_labels)
-        # 璁剧疆绾靛潗鏍囨暟鍊奸鑹�
-        for i in range(0, 9):
-            axes.get_yticklabels()[i].set_color("green")
-            axes2.get_yticklabels()[i].set_color("green")
-        for i in range(10, 10):
-            axes.get_yticklabels()[i].set_color("white")
-            axes2.get_yticklabels()[i].set_color("white")
-        for i in range(11, 21):
-            axes.get_yticklabels()[i].set_color("red")
-            axes2.get_yticklabels()[i].set_color("red")
-        line = axes2.plot([], [], color='white', linewidth=1)
-        average_line = axes2.plot([], [], color='yellow', linewidth=1)
-        cannvas = FigureCanvas(pannel, -1, figure_score)
-        axes2.text(1, 11.5, r'鐜颁环锛�0.0 娑ㄥ箙锛�0.00% \n鐣欐牸灞�锛�0%', fontsize=10, color='white')
-        axes2.text(-1, -11.5, r'鐜颁环锛�0.0 娑ㄥ箙锛�0.00% \n鐣欐牸灞�锛�0%', fontsize=10, color='white')
-
-        axes2.spines['top'].set_visible(False)
-        axes.spines['top'].set_visible(False)
-        axes2.spines['bottom'].set_visible(False)
-        axes.spines['bottom'].set_visible(False)
-        return (axes2, line, average_line)
-
-    def __set_juejin_params(self, event):
-        ps = self.GetPosition()
-        size = self.GetSize()
-        JueJinSettingFrame((ps[0] + size[0] / 2, ps[1] + size[1] / 2)).Show()
-
-    def __check_juejin(self, event):
-        frame = wx.Frame(None, -1, '鎺橀噾鍙傛暟璁剧疆', size=(400, 100))
-        frame.Center()
-        frame.Show()
-
-    def __manage_code(self, event):
-        ps = self.GetPosition()
-        size = self.GetSize()
-        CodesSettingFrame((ps[0] + size[0] / 2, ps[1] + size[1] / 2), self.set_codes_success).Show()
-
-    def __add_forbidden_codes(self, event):
-        ps = self.GetPosition()
-        size = self.GetSize()
-        FobiddenCodesFrame((ps[0] + size[0] / 2, ps[1] + size[1] / 2)).Show()
-
-    def __manage_ths_pos(self, event):
-        ps = self.GetPosition()
-        size = self.GetSize()
-        THSPositionSettingFrame((ps[0] + size[0] / 2, ps[1] + size[1] / 2)).Show()
-
-    def __ths_auto_click(self, event):
-        if event.Selection:
-            setting.set_ths_auto_click(1)
-        else:
-            setting.set_ths_auto_click(0)
-
-    def set_codes_success(self):
-        print("璁剧疆浠g爜鎴愬姛鍥炶皟")
-        p2.send("resub")
-        self.__re_draw()
-
-    def __show_top(self, event):
-        if event.Selection:
-            setting.set_stay_on_top(1)
-            self.WindowStyle = wx.MINIMIZE_BOX | wx.MAXIMIZE_BOX | wx.RESIZE_BORDER | wx.SYSTEM_MENU | wx.CAPTION | wx.CLOSE_BOX | wx.CLIP_CHILDREN | wx.STAY_ON_TOP
-        else:
-            setting.set_stay_on_top(0)
-            self.WindowStyle = wx.MINIMIZE_BOX | wx.MAXIMIZE_BOX | wx.RESIZE_BORDER | wx.SYSTEM_MENU | wx.CAPTION | wx.CLOSE_BOX | wx.CLIP_CHILDREN
-
-    def __menu(self):
-        self.mainmenu = wx.MenuBar()
-        setting_ = wx.Menu()
-        setting_.Append(105, '&娣诲姞绂佹浠g爜', '')
-        setting_.AppendSeparator()
-        setting_.Append(104, '&閽変綇', '', kind=wx.ITEM_CHECK)
-        setting_.Check(104, setting.is_stay_on_top())
-        setting_.AppendSeparator()
-        setting_.Append(101, '&鎺橀噾鍙傛暟閰嶇疆', 'Open a new document')
-        setting_.Append(102, '&鎺橀噾妫�娴�', 'Open a new document')
-        setting_.AppendSeparator()
-        setting_.Append(103, '&浠g爜绠$悊', 'Open a new document')
-
-        self.mainmenu.Append(setting_, '&璁剧疆')
-
-        auto_help = wx.Menu()
-        auto_help.Append(202, '&鍚岃姳椤鸿缃�', '')
-        auto_help.Append(201, '&鑷姩鐐瑰嚮', '', kind=wx.ITEM_CHECK)
-
-        auto_help.Check(201, setting.is_ths_auto_click())
-
-        self.mainmenu.Append(auto_help, '&鑷姩鍖�')
-        # 璁剧疆浜嬩欢
-        self.Bind(wx.EVT_MENU, self.__set_juejin_params, id=101)
-        self.Bind(wx.EVT_MENU, self.__check_juejin, id=102)
-        self.Bind(wx.EVT_MENU, self.__manage_code, id=103)
-        self.Bind(wx.EVT_MENU, self.__show_top, id=104)
-        self.Bind(wx.EVT_MENU, self.__add_forbidden_codes, id=105)
-        self.Bind(wx.EVT_MENU, self.__manage_ths_pos, id=202)
-        self.Bind(wx.EVT_MENU, self.__ths_auto_click, id=201)
-
-        self.SetMenuBar(self.mainmenu)
-
-    def OnExit(self, e):
-        try:
-            self.floatFrame.Close(True)
-            setting.set_window_info((self.Position[0], self.Position[1], self.Size[0], self.Size[1]), (
-                self.floatFrame.Position[0], self.floatFrame.Position[1], self.floatFrame.Size[0],
-                self.floatFrame.Size[1]))
-        except Exception as e:
-            print("")
-        jueJinProcess.terminate()
-        sys.exit(0)
-
-    def post_redraw(self, evt):
-
-        if abs(self.last_size[0] - self.Size[0]) > 20:
-            print("--------post_redraw--------")
-            self.last_size = (self.Size[0], self.Size[1])
-            self.__re_draw()
-
-    def OnResize(self, e):
-        print("鍙樺寲鍚庣殑灏哄", e.Size)
-        # 鐣欏嚭婊氬姩鏉★紝鐣欏嚭涓婅竟璺�
-        if self.scroll:
-            self.scroll.Size = (e.Size[0] - 15, e.Size[1] - 60)
-            for p in self.panels:
-                p_height = round(e.Size[0] * (450 / 800))
-                p.Size = (e.Size[0], p_height)
-        self.timer.Stop()
-        self.timer.StartOnce(1000)
-        # 闄嶄綆閲嶇粯棰戠巼
-        # self.__re_draw()
-
-
-# 缁樺浘绠$悊鍣�
-class DrawManager:
-
-    def __load_lack_datas(self, code, time_ranges):
-        codeDataManager = code_data_manager.CodeDataManager()
-        day = tool.get_now_date_str()
-        for time_range in time_ranges:
-            results = juejin_core.GPCodeManager().get_history_tick(code, day + " " + time_range[0],
-                                                                   day + " " + time_range[1])
-            datas = []
-            for data in results:
-                datas.append(juejin_core.parse_tick(data))
-            # 淇濆瓨鏁版嵁
-
-            for data in datas:
-                # 09:25:00涔嬪墠鐨勬暟鎹笉淇濆瓨
-                created_at = data["created_at"].strftime("%Y-%m-%d %H:%M:%S")
-                time_ = created_at[-8:]
-                if tool.trade_time_sub(time_, "09:25:00") < 0:
-                    continue
-                if tool.trade_time_sub(time_, "15:00:00") > 0:
-                    continue
-                if tool.trade_time_sub(time_, "11:30:00") > 0 and tool.trade_time_sub(time_, "13:00:00") < 0:
-                    continue
-
-                # 涓嶆槸浠婂ぉ鐨勬暟鎹笉淇濆瓨
-                if day != created_at[:10]:
-                    continue
-                codeDataManager.save_data(data)
-
-    def init_code_datas(self):
-        global code_datas
-        global max_min_prices
-        codeDataManager = code_data_manager.CodeDataManager()
-        gpCodeManager = juejin_core.GPCodeManager()
-        code_datas = {}
-        max_min_prices = {}
-        codes = gpCodeManager.get_codes()
-        if codes:
-            # 鑾峰彇褰撴棩鐨勬渶楂樹环鏈�浣庝环
-            res = juejin_core.GPCodeManager().get_min_and_max_price(codes)
-            for data in res:
-                max_min_prices[data[0]] = (data[1], data[2])
-
-            for code in codes:
-                # 鍔犺浇鍘嗗彶鏁版嵁
-                code_datas[code] = []
-                old_datas = codeDataManager.get_datas(code)
-                # 鑾峰彇缂哄け鐨勬暟鎹�
-                ranges = codeDataManager.get_lack_datas_time_range(old_datas)
-                if len(ranges) > 0:
-                    self.__load_lack_datas(code, ranges)
-                    old_datas = codeDataManager.get_datas(code)
-
-                if old_datas:
-                    code_datas[code].extend(old_datas)
-                    self.update(code, code_datas[code])
-
-    # 鏇存柊鏁版嵁
-    def __update_data(self, code, axes, datas, min_rate, max_rate):
-        def get_time_as_seconds(created_at):
-            time_ = created_at[-8:]
-            if tool.get_time_as_second("13:00:00") > tool.get_time_as_second(time_) > tool.get_time_as_second(
-                    "11:30:00"):
-                time_ = "11:30:00"
-            time_s = int(time_.split(":")[0]) * 3600 + int(time_.split(":")[1]) * 60 + int(
-                time_.split(":")[2]) - 9 * 3600 - 60 * 30
-
-            if int(time_.replace(":", "")) > int("11:30:00".replace(":", "")):
-                time_s -= 90 * 60
-            return time_s
-
-        def seconds_2_time_str(seconds):
-            seconds += 9 * 3600 + 60 * 30
-            if seconds > 11 * 3600 + 60 * 30:
-                seconds += 90 * 60
-            h = seconds // 3600
-            m = seconds % 3600 // 60
-            s = seconds % 60
-            return "{0:0>2}:{1:0>2}:{2:0>2}".format(h, m, s)
-
-        # 鍒犻櫎9:30浠ュ墠鐨勬暟鎹�
-        for i in range(0, len(datas)):
-            time_ = datas[i]["created_at"][-8:]
-            if int(time_.replace(":", "")) >= int("093000"):
-                datas = datas[i:]
-                break
-        # 鍙栨渶杩�12鍒嗛挓鐨勬暟鎹�
-        for i in range(len(datas) - 1, -1, -1):
-            time_ = datas[i]["created_at"][-8:]
-            if tool.trade_time_sub(datas[-1]["created_at"][-8:], time_) >= 14 * 60:
-                datas = datas[i:]
-                break
-
-        xs = []
-        ys_rate = []
-        ys_average_rate = []
-        for data in datas:
-            xs.append(get_time_as_seconds(data["created_at"]))
-            ys_rate.append(data["rate"] * 100)
-            ys_average_rate.append(data["average_rate"] * 100)
-
-        xticks = []
-        xticklabels = []
-        # 璁剧疆X杞磋寖鍥翠负09:30:00 鍒�15:00:00
-        # x杞磋寖鍥翠负0-15鍒嗛挓
-        end_x = "0000-00-00 " + tool.trade_time_add_second(datas[0]["created_at"][-8:], 15 * 60)
-        axes[0].set_xlim(get_time_as_seconds(datas[0]["created_at"]), get_time_as_seconds(end_x))
-
-        # if len(xs) < 2 or xs[-1] - xs[0] < 30 * 60:
-        #     axes[0].set_xlim(xs[0], xs[0] + 30 * 60)
-        # else:
-        #     axes[0].set_xlim(xs[0], xs[-1])
-        xms = axes[0].get_xlim()
-        yms = axes[0].get_ylim()
-        step = (int(xms[1]) - int(xms[0])) // 30
-        for i in range(int(xms[0]), int(xms[1] + 1), step):
-            xticks.append(i)
-            xticklabels.append("")
-
-        axes[0].set_xticks(xticks)
-        axes[0].set_xticklabels(xticklabels)
-
-        axes[1][0].set_data(xs, ys_rate)
-        axes[2][0].set_data(xs, ys_average_rate)
-        texts = axes[0].texts
-        texts[0].set_text("{}% \n鐣欐牸灞�锛�0%".format(round(datas[-1]["rate"] * 100, 2)))
-        texts[1].set_text("{}".format(datas[-1]["created_at"].split(" ")[1]))
-        texts[0].set_x(xms[1] - 80)
-        texts[0].set_y(yms[1] + 0.5)
-        texts[1].set_x(xms[0])
-        texts[1].set_y(yms[0] - 1.5)
-
-        # 鍒犻櫎涔嬪墠
-        if code in self.lines:
-            for key in self.lines[code]:
-                line = self.lines[code][key]
-                line.remove()
-            self.lines.pop(code)
-        # 缁樺埗鏈�澶ф渶灏忓潗鏍�
-        line_min = axes[0].axhline(min_rate, linestyle='--', color='yellow', lw=0.5)
-        line_max = axes[0].axhline(max_rate, linestyle='--', color='yellow', lw=0.5)
-        self.lines[code] = {"min": line_min, "max": line_max}
-        axes[0].figure.canvas.draw()
-        axes[0].figure.canvas.flush_events()
-
-    def __init__(self, axes_list, codes_info):
-        self.axes_list = axes_list
-        self.codes_info = codes_info
-        self.lines = {}
-
-    def update(self, code, datas):
-        # 鑾峰彇鍓嶉珮鍜屽墠浣�
-        max_rate = None
-        min_rate = None
-        if code in max_min_prices:
-            pre_price = juejin_core.GPCodeManager().get_pre_prices(code)
-            min_rate = round((max_min_prices[code][0] - pre_price) / pre_price, 4)
-            max_rate = round((max_min_prices[code][1] - pre_price) / pre_price, 4)
-
-        for data in datas:
-            rate = data["rate"] * 100
-            created_at = data["created_at"][-8:]
-            if tool.get_time_as_second("15:00:00") >= tool.get_time_as_second(created_at) >= tool.get_time_as_second(
-                    "09:30:00"):
-                if max_rate is None:
-                    max_rate = rate
-                if min_rate is None:
-                    min_rate = rate
-                if rate > max_rate:
-                    max_rate = rate
-                if rate < min_rate:
-                    min_rate = rate
-
-        # 灞曠ず鏈�杩戠殑600涓�
-        datas = datas[-450:]
-        for i in range(0, len(self.codes_info)):
-            if self.codes_info[i][0] == code:
-                try:
-                    self.__update_data(code, self.axes_list[i], datas, min_rate, max_rate)
-                except Exception as e:
-                    logging.exception(e)
-
-
-class mainApp(wx.App):
-
-    def __refresh(self):
-        codes = juejin_core.GPCodeManager().get_codes()
-        last_time = round(time.time())
-        while True:
-            try:
-                code = ocr_ths_code()
-                if not code:
-                    time.sleep(0.1)
-                    continue
-                # 1s鏇存柊涓�娆�
-                if round(time.time()) - last_time > 5:
-                    codes = juejin_core.GPCodeManager().get_codes()
-                    last_time = round(time.time())
-                for index in range(0, len(codes)):
-                    if codes[index] == code:
-                        self.Frame.scrollTo(index)
-                        break
-            except Exception as e:
-                print(str(e))
-            time.sleep(0.005)
-
-    def OnInit(self):
-        self.SetAppName(APP_TITLE)
-        self.Frame = mainFrame()
-        # self.Frame = FloatFrame(None)
-        self.Frame.Show()
-        t1 = threading.Thread(target=lambda: self.__refresh())
-        # 鍚庡彴杩愯
+    @pyqtSlot(str, str, str)
+    def http_request(self, path, params, callback_info):
+        url = path + "?"
+        if params:
+            params = json.loads(params)
+            url += "&".join([f"{key}={params[key]}" for key in params])
+        print("http璇锋眰", url)
+        callback_info = json.loads(callback_info)
+        t1 = threading.Thread(target=lambda: self.__http_request(url, callback_info))
         t1.setDaemon(True)
         t1.start()
 
-        return True
+    @pyqtSlot(str, str)
+    def socket_request(self, text, callback_info):
+        print("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))
+        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()
+
+    # 鑾峰彇瀹㈡埛绔疘D
+    @pyqtSlot(result=str)
+    def get_client(self):
+        return setting.get_client()
+
+    @pyqtSlot(str)
+    def add_code_to_ths(self, code):
+        # 娣诲姞鍒板悓鑺遍『
+        threading.Thread(target=lambda: ths_util.add_code_to_zixuan(code), daemon=True).start()
+
+    @pyqtSlot(str)
+    def open_webview_window(self, data):
+        """
+        鎵撳紑鐙珛缃戦〉绐楀彛
+        :param data:
+        :return:
+        """
+        data = json.loads(data)
+        url = data.get("url")
+        title = data.get("title")
+        key = data.get("key")
+        size = data.get("size")
+        common_window = CommonWindow(title, key, size, parent=self.__webview.window())
+        common_window.loadUrl(url)
+        common_window.show()
+
+    @pyqtSlot(str)
+    def set_target_code(self, code):
+        # 璁剧疆鐩爣浠g爜
+        window_msg_queue.put_nowait({"type": "set_target_code", "data": {"code": code}})
 
 
-def recieve_tick(pipe):
-    codeDataManager = code_data_manager.CodeDataManager()
-    while True:
-        data = pipe.recv()
-        if data:
-            type = data["type"]
-            if type == 0:
-                # tick鏁版嵁
-                data = data["data"]
-                code = data["code"]
-                if code not in code_datas:
-                    code_datas[code] = []
-                code_datas[code].append(data)
-                codeDataManager.save_data(data)
-                # 鏇存柊鏁版嵁
+class SecondWindowBridgeClass(BaseBridgeClass):
+    @pyqtSlot(str)
+    def set_target_code(self, code):
+        # 璁剧疆鐩爣浠g爜
+        window_msg_queue.put_nowait({"type": "set_target_code", "data": {"code": code}})
+
+
+class JSBridgeClass(BaseBridgeClass):
+
+    def __init__(self, window, webview):
+        super().__init__(webview)
+        self.window = window
+        self.webview = webview
+
+    @pyqtSlot(str)
+    def show_info(self, msg):
+        QMessageBox.information(self.window, "鎻愮ず", msg, QMessageBox.Yes)
+
+    @pyqtSlot(str, str, str, str, str, str)
+    def set_trade_info(self, code, name, trade_data, trade_record, initiative_buy_codes, passive_buy_codes):
+        self.window.set_trade_data(code, name, trade_data, trade_record, initiative_buy_codes, passive_buy_codes)
+
+
+class MessageWindow(QMainWindow):
+    msgChange = pyqtSignal(str)
+
+    def __setMsg(self, msg):
+        print("鏀跺埌淇℃伅锛�", msg)
+        palette = QPalette()
+        if msg.find("鎾ゅ崟") > -1:
+            palette.setColor(QPalette.WindowText, QColor(0, 128, 0))  # 璁剧疆瀛椾綋棰滆壊涓虹豢鑹�
+        elif msg.find("涓嬪崟") > -1:
+            palette.setColor(QPalette.WindowText, QColor(34, 26, 178))  # 璁剧疆瀛椾綋棰滆壊涓洪粍鑹�
+        elif msg.find("鎴愪氦") > -1:
+            palette.setColor(QPalette.WindowText, QColor(255, 0, 0))  # 璁剧疆瀛椾綋棰滆壊涓虹孩鑹�
+        self.label.setPalette(palette)
+        self.label.setText(msg)
+        self.show()
+        self.timer.stop()
+        self.timer.start(5000)
+
+    # 璁剧疆淇℃伅
+    def setMsg(self, msg):
+        # TODO 娴嬭瘯
+        self.msgChange.emit(msg)
+
+    def __init__(self):
+        super().__init__()
+        window_height = 80
+        padding = 10
+        self.resize(300, 50)
+        # 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)
+        # 鍘绘帀鏍囬鏍�
+        # self.setWindowFlags(Qt.FramelessWindowHint)
+        # 鍒犻櫎鏈�澶ф渶灏忓寲鎸夐挳
+        # self.setWindowFlags(self.windowFlags() & ~Qt.WindowMaximizeButtonHint & ~Qt.WindowMinimizeButtonHint)
+
+        font = QFont('寰蒋闆呴粦', 12)  # 璁剧疆瀛椾綋涓哄井杞泤榛戯紝瀛楀彿涓�12
+        palette = QPalette()  # 鍒涘缓涓�涓皟鑹叉澘
+        palette.setColor(QPalette.WindowText, QColor(255, 0, 0))  # 璁剧疆瀛椾綋棰滆壊涓虹孩鑹�
+
+        self.label = QLabel(self)
+        self.label.setStyleSheet(f"padding: {padding}px;")
+        self.label.setFont(font)
+        self.label.setPalette(palette)  # 灏嗚璋冭壊鏉垮簲鐢ㄥ埌QLabel涓�
+        self.label.setAlignment(Qt.AlignTop)
+        self.label.resize(self.width(), self.height())
+        # 璁剧疆澶氳鏄剧ず
+        self.label.setWordWrap(True)  # 璁剧疆Label鐨勮嚜鍔ㄦ崲琛�
+
+        self.timer = QTimer()
+        self.timer.timeout.connect(self.close)
+        # 鍙繍琛�1娆″畾鏃跺櫒
+        self.timer.setSingleShot(True)
+        self.msgChange.connect(self.__setMsg)
+
+
+class MsgListWindow(QMainWindow):
+
+    def __init__(self):
+        super().__init__()
+        self.setWindowTitle('鍘嗗彶娑堟伅')
+        # 绐楀彛缃《
+        self.setWindowFlag(Qt.WindowStaysOnTopHint, True)
+        self.resize(500, 800)
+        self.webview = QWebEngineView()
+        self.webview.settings().setAttribute(QWebEngineSettings.JavascriptEnabled, True)
+        self.webview.page().setZoomFactor(1)
+        self.setCentralWidget(self.webview)
+
+        # JS妗ヨ缃�
+        channel = QWebChannel(self.webview.page())
+        self.webview.page().setWebChannel(channel)
+        self.python_bridge = BaseBridgeClass(self.webview)
+        channel.registerObject("Bridge", self.python_bridge)
+
+    def loadUrl(self, url):
+        self.webview.load(QUrl(url))
+
+
+class SecondWindow(QMainWindow):
+    signal_update_kpl = pyqtSignal(str)
+
+    def update_kpl_func(self):
+        while True:
+            time.sleep(3)
+            try:
+                self.__update_kpl()
+            except:
+                pass
+
+    def __init__(self, parent=None):
+        super(SecondWindow, self).__init__(parent)
+        self.setWindowTitle('鐪嬬洏鍓睆')
+        window_info = setting.get_kp_second_window_info()
+        if window_info:
+            self.move(window_info[0], window_info[1])
+            self.resize(window_info[2], window_info[3])
+        else:
+            self.resize(500, 800)
+
+        self.webview = QWebEngineView()
+        self.webview.settings().setAttribute(QWebEngineSettings.JavascriptEnabled, True)
+        self.webview.page().setZoomFactor(1)
+        self.setCentralWidget(self.webview)
+
+        # JS妗ヨ缃�
+        channel = QWebChannel(self.webview.page())
+        self.webview.page().setWebChannel(channel)
+        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:
+            # 瑙f瀽鏁版嵁
+            # 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))
+
+    # 璁剧疆浜ゆ槗鏁版嵁
+    def set_trade_data(self, code, code_name, trade_data, trade_record, initiative_buy_codes, passive_buy_codes):
+        script_str = "try{"
+        script_str += "var trade_data = " + trade_data + ";"
+        script_str += "var trade_record = " + trade_record + ";"
+
+        script_str += "app.set_trade_info(\"{}\",\"{}\",trade_data,trade_record,'{}','{}');".format(code, code_name,
+                                                                                                    initiative_buy_codes,
+                                                                                                    passive_buy_codes)
+        script_str += "} catch(e){console.log(e)}"
+        self.webview.page().runJavaScript(script_str)
+
+    def set_kpl_data(self, data):
+        self.webview.page().runJavaScript(f"fill_kpl_data('{data}')")
+
+    # 鏇存柊寮�鐩樺暒鏁版嵁
+    def __update_kpl(self):
+        datas = network_util.http_get("/get_kpl_data")
+        self.signal_update_kpl.emit(datas)
+
+    def set_target_code(self, code):
+        print("set_target_code", code)
+        # 娴嬭瘯
+        self.webview.page().runJavaScript(f"app.set_target_code('{code}')")
+
+    def closeEvent(self, event):
+        try:
+            setting.set_kp_second_window_info(
+                (self.pos().x(), self.pos().y(), self.size().width(), self.size().height()))
+        except Exception as e:
+            print("")
+
+
+class DelegatingWindow(QMainWindow):
+    """
+    鍔犺礉鎺у埗涓績
+    """
+    signal_update_kpl = pyqtSignal(str)
+
+    def update_kpl_func(self):
+        while True:
+            time.sleep(3)
+            try:
+                self.__update_kpl()
+            except:
+                pass
+
+    def __init__(self, parent=None):
+        super(DelegatingWindow, self).__init__(parent)
+        self.setWindowTitle('鍔犺礉鎺у埗涓績')
+        window_info = setting.get_delegating_window_info()
+        if window_info:
+            self.move(window_info[0], window_info[1])
+            self.resize(window_info[2], window_info[3])
+        else:
+            self.resize(600, 800)
+
+        self.webview = QWebEngineView()
+        self.webview.settings().setAttribute(QWebEngineSettings.JavascriptEnabled, True)
+        self.webview.page().setZoomFactor(1)
+        self.setCentralWidget(self.webview)
+        # JS妗ヨ缃�
+        channel = QWebChannel(self.webview.page())
+        self.webview.page().setWebChannel(channel)
+        self.python_bridge = BaseBridgeClass(self.webview)
+        channel.registerObject("Bridge", self.python_bridge)
+
+    # 鑷畾涔夋秷鎭鐞嗗嚱鏁�
+    def handleCustomMessage(self, hwnd, msg, wparam, lparam):
+        if msg == win32con.WM_USER + 1024:
+            # 瑙f瀽鏁版嵁
+            # 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))
+
+    def closeEvent(self, event):
+        try:
+            setting.set_delegating_window_info(
+                (self.pos().x(), self.pos().y(), self.size().width(), self.size().height()))
+        except Exception as e:
+            print("")
+
+
+class CommonWindow(QMainWindow):
+    """
+    鍔犺礉鎺у埗涓績
+    """
+    signal_update_kpl = pyqtSignal(str)
+
+    def update_kpl_func(self):
+        while True:
+            time.sleep(3)
+            try:
+                self.__update_kpl()
+            except:
+                pass
+
+    def __init__(self, title, key, default_size, parent=None):
+        """
+        :param title: 鏍囬
+        :param key: 鏍囪瘑
+        :param default_size:(瀹�, 楂�)
+        :param parent:
+        """
+        super(CommonWindow, self).__init__(parent)
+        self.setWindowFlags(self.windowFlags() & ~Qt.WindowMaximizeButtonHint)
+
+        self.setWindowTitle(title)
+        window_info = setting.get_window_info(f"{key}_window_info")
+        if window_info:
+            self.move(window_info[0], window_info[1])
+            self.resize(window_info[2], window_info[3])
+        else:
+            self.resize(default_size[0], default_size[1])
+        self.key = key
+
+        self.webview = QWebEngineView()
+        self.webview.settings().setAttribute(QWebEngineSettings.JavascriptEnabled, True)
+        self.webview.page().setZoomFactor(1)
+        self.setCentralWidget(self.webview)
+
+        # JS妗ヨ缃�
+        channel = QWebChannel(self.webview.page())
+        self.webview.page().setWebChannel(channel)
+        self.python_bridge = BaseBridgeClass(self.webview)
+        channel.registerObject("Bridge", self.python_bridge)
+
+    # 鑷畾涔夋秷鎭鐞嗗嚱鏁�
+    def handleCustomMessage(self, hwnd, msg, wparam, lparam):
+        if msg == win32con.WM_USER + 1024:
+            # 瑙f瀽鏁版嵁
+            # 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))
+
+    def closeEvent(self, event):
+        try:
+            setting.set_window_info(f"{self.key}_window_info",
+                                    (self.pos().x(), self.pos().y(), self.size().width(), self.size().height()))
+        except Exception as e:
+            print("")
+        # self.webview.close()
+
+
+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):
+    signal_update_code = pyqtSignal(str)
+
+    def show_info(self, msg):
+        QMessageBox.information(self, "鎻愮ず", msg, QMessageBox.Yes)
+
+    def show_warning(self, msg):
+        QMessageBox.warning(self, "鎻愮ず", msg, QMessageBox.Yes)
+
+    def set_trade_data(self, code, code_name, trade_data, trade_record, initiative_buy_codes, passive_buy_codes):
+        self.secondWindow.set_trade_data(code, code_name, trade_data, trade_record, initiative_buy_codes,
+                                         passive_buy_codes)
+
+    # 璁剧疆鐩爣浠g爜
+    def set_target_code(self, code):
+        print("set_target_code")
+        self.wx_pipe.send(json.dumps({"type": "set_code", "code": code}))
+        self.webview.page().runJavaScript(f"app.set_target_code('{code}')")
+        self.secondWindow.set_target_code(code)
+
+    def read_window_msg(self):
+        while True:
+            try:
+                data = window_msg_queue.get()
+                if data["type"] == "set_target_code":
+                    code = data["data"]["code"]
+                    self.signal_update_code.emit(code)
+            except:
+                pass
+            finally:
+                pass
+
+    # 鑿滃崟鍙婅彍鍗曠偣鍑讳簨浠�
+    def __menu(self):
+        def __gpu_is_avaiable():
+            if torch.cuda.is_available():
+                self.show_info("GPU鍙敤")
+            else:
+                self.show_warning("GPU涓嶅彲鐢�")
+
+        def __set_juejin_params():
+            ps = (self.x(), self.y())
+            size = (self.width(), self.height())
+            self.wx_pipe.send(json.dumps({"type": "juejin_setting", "pos": (ps[0] + size[0] / 2, ps[1] + size[1] / 2)}))
+
+        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"璇嗗埆鍒扮殑浠g爜锛歿code}")
+            except Exception as e:
+                self.show_warning(f"璇嗗埆鍑洪敊锛歿str(e)}")
+
+        def __download_codes():
+            try:
+                result = self.__request("", 72)
+                result = json.loads(result)
+                if result['code'] == 0:
+                    codes_dict = result['data']
+                    if codes_dict:
+                        for key in codes_dict:
+                            # 灏嗕唬鐮佷繚瀛樺埌妗岄潰
+                            path = f"C:\\Users\\Administrator\\Desktop\\娑ㄥ仠浠g爜{key}.txt"
+                            with open(path, mode='w') as f:
+                                for c in codes_dict[key]:
+                                    f.write(c)
+                                    f.write("\n")
+                        self.show_info("涓嬭浇鎴愬姛")
+                else:
+                    self.show_warning(result['msg'])
+            except Exception as e:
+                self.show_warning(str(e))
+
+        def __manage_code():
+            ps = (self.x(), self.y())
+            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_second_window():
+            self.secondWindow.show()
+
+        def __show_delegating_window():
+            self.delegatingWindow.show()
+
+        def __show_want_buy_codes_window():
+            self.wantBuyCodesWindow.show()
+
+        def __show_his_msg_window():
+            self.msgListWindow.loadUrl(URL_MSG_LIST)
+            self.msgListWindow.show()
+
+        # 娓呴櫎娴忚鍣ㄧ紦瀛�
+        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('&璁剧疆')
+
+        action = QAction("&GPU妫�娴�", self)
+        action.triggered.connect(__gpu_is_avaiable)
+        setting_.addAction(action)
+
+        action = QAction("&娓呴櫎娴忚鍣ㄧ紦瀛�", self)
+        action.triggered.connect(__clear_webview_cache)
+        setting_.addAction(action)
+
+        action = QAction("&鍚岃姳椤轰唬鐮佽瘑鍒�", self)
+        action.triggered.connect(__ths_ocr_code)
+        setting_.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_delegating_window)
+        view_.addAction(action)
+
+        action = QAction("&鎵撳紑鎯充拱鍗�", self)
+        action.triggered.connect(__show_want_buy_codes_window)
+        view_.addAction(action)
+
+        action = QAction("&鎵撳紑鍘嗗彶娑堟伅", self)
+        action.triggered.connect(__show_his_msg_window)
+        view_.addAction(action)
+
+        view_ = menubar.addMenu('&鏄剧ず涓�閿崠鍑�')
+        view_.aboutToShow.connect(__show_ths_flash_trade)
+
+    def __init__(self, wx_pipe):
+        super().__init__()
+        self.wx_pipe = wx_pipe
+        self.setWindowTitle('鐪嬬洏椤甸潰')
+        window_info = setting.get_kp_window_info()
+        if window_info:
+            self.move(window_info[0], window_info[1])
+            self.resize(window_info[2], window_info[3])
+        else:
+            self.resize(1100, 1000)
+            self.center()
+        self.setWindowFlag(Qt.WindowStaysOnTopHint, True)
+        self.webview = QWebEngineView()
+        self.webview.setPage(WebEnginePage())
+        self.webview.settings().setAttribute(QWebEngineSettings.JavascriptEnabled, True)
+        self.__menu()
+        # JS妗ヨ缃�
+        channel = QWebChannel(self.webview.page())
+        self.webview.page().setWebChannel(channel)
+        self.python_bridge = JSBridgeClass(self, self.webview)
+        channel.registerObject("Bridge", self.python_bridge)
+        # 璁剧疆鍓睆
+        self.secondWindow = SecondWindow(self)
+        self.delegatingWindow = DelegatingWindow(self)
+        self.wantBuyCodesWindow = CommonWindow("鎯充拱鍗�", "want_buy_codes", (500, 1000), parent=self)
+
+        self.setCentralWidget(self.webview)
+        self.show()
+        if not constant.IS_TEST:
+            self.webview.load(QUrl(f"http://{constant.WEB_HOST}/kp/index23-05-04.html"))
+        else:
+            self.webview.load(QUrl("http://127.0.0.1:8848/kp/index23-05-04.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.delegatingWindow.show()
+        if not constant.IS_TEST:
+            self.delegatingWindow.loadUrl(f"http://{constant.WEB_HOST}/kp/delegating_list.html")
+        else:
+            self.delegatingWindow.loadUrl("http://127.0.0.1:8848/kp/delegating_list.html")
+
+        if not constant.IS_TEST:
+            self.wantBuyCodesWindow.loadUrl(f"http://{constant.WEB_HOST}/kp/want_buy_codes_list.html")
+        else:
+            self.wantBuyCodesWindow.loadUrl("http://127.0.0.1:8848/kp/want_buy_codes_list.html")
+
+        self.wantBuyCodesWindow.show()
+
+        # 缁戝畾妲藉嚱鏁�
+        self.signal_update_code.connect(self.set_target_code)
+        # self.statusBar().showMessage("杩欐槸鏉℃祴璇曟暟鎹", 10000)
+
+        self.messageWindow = MessageWindow()
+        self.msgListWindow = MsgListWindow()
+
+        threading.Thread(target=KPLLimitUpDataManager().run, daemon=True).start()
+        threading.Thread(target=xgb_api.run, daemon=True).start()
+        threading.Thread(target=self.read_window_msg, daemon=True).start()
+
+    def closeEvent(self, event):
+        event.accept()
+        try:
+            setting.set_kp_window_info((self.pos().x(), self.pos().y(), self.size().width(), self.size().height()))
+        except Exception as e:
+            print("")
+        self.wx_pipe.send(json.dumps({"type": "exit"}))
+        wxGuiProcess.terminate()
+        wxGuiProcess.join()
+        sys.exit(0)
+
+    # 璇诲彇娑堟伅
+    def read_msg(self):
+        client = setting.get_client()
+        if not client:
+            client = 'hxh'
+        while True:
+            if tool.is_trade_time():
                 try:
-                    drawManager.update(code, code_datas[code])
-                    print("鎺ュ彈鍒扮殑tick鏁版嵁:", data)
+                    res = network_util.http_get(f"/pull_kp_client_msg?client=" + client.strip())
+                    if res:
+                        res = json.loads(res)
+                        if res["code"] == 0:
+                            print("鎷夊彇鍒版秷鎭�", res)
+                            self.messageWindow.setMsg(res["data"])
                 except:
                     pass
+            time.sleep(0.5)
 
 
-def ths_auto_click():
-    hwnd = ths_util.get_ths_second_screen_menu_hwnd()
+def recieve_code(pipe, mainWindow):
+    latest_code = ''
     while True:
         try:
-            if hwnd is None or not win32gui.IsWindowVisible(hwnd):
-                # print("鏈壘鍒板悓鑺遍『鍓睆鍙ユ焺")
-                hwnd = ths_util.get_ths_second_screen_menu_hwnd()
-
-            if hwnd is None:
-                continue
-            if not setting.is_ths_auto_click():
-                continue
-            ps = setting.get_ths_auto_click_positions()
-            if not ps:
-                continue
-            ps_new = []
-            for p in ps:
-                p = eval(p)
-                ps_new.append(p)
-            space = setting.get_ths_auto_click_time_space()
-            if space is None:
-                space = 500
-            ths_util.betch_click(hwnd, ps_new, round(space / 1000, 4))
+            data = pipe.recv()
+            if data:
+                data = json.loads(data)
+                if data["type"] == "code":
+                    if latest_code != data["code"]:
+                        latest_code = data["code"]
+                        mainWindow.signal_update_code.emit(latest_code)
         except Exception as e:
-            pass
-        finally:
-            time.sleep(0.02)
+            logging.exception(e)
 
 
-def ths_auto_refresh():
-    hwnd = ths_util.get_trade_refesh_hwnd()
-    while True:
-        try:
-            if hwnd is None or not win32gui.IsWindowVisible(hwnd):
-                # print("鏈壘鍒板悓鑺遍『浜ゆ槗鍒锋柊鍙ユ焺")
-                hwnd = ths_util.get_trade_refesh_hwnd()
-
-            if hwnd is None:
-                continue
-            if not setting.is_ths_trade_auto_refresh():
-                continue
-            rect = win32gui.GetWindowRect(hwnd)
-            win32_util.visual_click(hwnd, (160, (rect[3] - rect[1]) // 2))
-            time_space = setting.get_ths_auto_refresh_time_space()
-            if time_space is None:
-                time_space = 500
-            time.sleep(round(time_space / 1000, 4))
-        except Exception as e:
-            pass
-        finally:
-            time.sleep(0.02)
-
-
-if __name__ == "__main__1":
-    hwnd = ths_util.get_ths_main_content_hwnd()
-    if not hwnd:
-        raise Exception("鐪嬬洏椤甸潰鍙ユ焺鏈幏鍙栧埌")
-    # 鍙ユ焺鎴浘
-    rect = win32gui.GetWindowRect(hwnd)
-    w = 150
-    height = 45
-    top = 38
-    # img = win32_util.window_capture(hwnd, (rect[2] - rect[0] -100 , 25, rect[2] - rect[0], 55))
-    # img = win32_util.window_capture(hwnd, rect)
-    img = win32_util.window_capture(hwnd, (0, 0, (rect[2] - rect[0]) * 15 // 10, (rect[3] - rect[1]) * 15 // 10))
+# 鎵撳寘鍛戒护
+# cd D:\workspace\GP\trade_desk
+# D:\workspace\GP\trade_desk\dist\env\pk_env\Scripts\pyinstaller.exe main.spec
+# 涓轰簡涓嶅嚭鐜版剰澶栫殑bug锛岃繍琛屾椂璇峰皢鐩綍鏀惧湪鑻辨枃璺緞
 
 if __name__ == "__main__":
-    print(pow(3, 1))
-    global p2
+    freeze_support()
     p1, p2 = multiprocessing.Pipe()
-    global jueJinProcess
-    jueJinProcess = multiprocessing.Process(target=juejin_core.run, args=(p1,))
-    jueJinProcess.start()
+    global wxGuiProcess
+    wxGuiProcess = Process(target=gui_wx.run, args=(p1,))
+    wxGuiProcess.start()
 
-    t1 = threading.Thread(target=lambda: recieve_tick(p2))
+    app = QApplication(sys.argv)
+    browser = MainWindow(p2)
+    t1 = threading.Thread(target=lambda: recieve_code(p2, browser))
     # 鍚庡彴杩愯
     t1.setDaemon(True)
     t1.start()
-
-    t2 = threading.Thread(target=lambda: ths_auto_click())
-    # 鍚庡彴杩愯
-    t2.setDaemon(True)
-    t2.start()
-
-    t3 = threading.Thread(target=lambda: ths_auto_refresh())
-    # 鍚庡彴杩愯
-    t3.setDaemon(True)
-    t3.start()
-
-    app = mainApp(redirect=False)
-    app.MainLoop()
+    sys.exit(app.exec_())

--
Gitblit v1.8.0