[patch] 新增用户余额不足 交互模式代码
This commit is contained in:
@@ -32,6 +32,7 @@ class BackendClient:
|
|||||||
self.token_error_callback: Optional[Callable] = None # 新增:token错误回调
|
self.token_error_callback: Optional[Callable] = None # 新增:token错误回调
|
||||||
self.version_callback: Optional[Callable] = None # 新增:版本检查回调
|
self.version_callback: Optional[Callable] = None # 新增:版本检查回调
|
||||||
self.disconnect_callback: Optional[Callable] = None # 新增:被踢下线回调
|
self.disconnect_callback: Optional[Callable] = None # 新增:被踢下线回调
|
||||||
|
self.balance_insufficient_callback: Optional[Callable] = None # 新增:余额不足回调
|
||||||
self.log_callback: Optional[Callable] = None # 新增:日志回调
|
self.log_callback: Optional[Callable] = None # 新增:日志回调
|
||||||
|
|
||||||
self.is_connected = False
|
self.is_connected = False
|
||||||
@@ -285,6 +286,7 @@ class BackendClient:
|
|||||||
token_error: Callable = None,
|
token_error: Callable = None,
|
||||||
version: Callable = None,
|
version: Callable = None,
|
||||||
disconnect: Callable = None,
|
disconnect: Callable = None,
|
||||||
|
balance_insufficient: Callable = None,
|
||||||
log: Callable = None):
|
log: Callable = None):
|
||||||
"""设置各种消息类型的回调函数"""
|
"""设置各种消息类型的回调函数"""
|
||||||
if store_list:
|
if store_list:
|
||||||
@@ -309,6 +311,8 @@ class BackendClient:
|
|||||||
self.version_callback = version
|
self.version_callback = version
|
||||||
if disconnect:
|
if disconnect:
|
||||||
self.disconnect_callback = disconnect
|
self.disconnect_callback = disconnect
|
||||||
|
if balance_insufficient:
|
||||||
|
self.balance_insufficient_callback = balance_insufficient
|
||||||
if log:
|
if log:
|
||||||
self.log_callback = log
|
self.log_callback = log
|
||||||
|
|
||||||
@@ -475,6 +479,8 @@ class BackendClient:
|
|||||||
self._handle_version_response(message)
|
self._handle_version_response(message)
|
||||||
elif msg_type == 'disconnect': # 新增:被踢下线
|
elif msg_type == 'disconnect': # 新增:被踢下线
|
||||||
self._handle_disconnect(message)
|
self._handle_disconnect(message)
|
||||||
|
elif msg_type == 'balance_insufficient': # 新增:余额不足
|
||||||
|
self._handle_balance_insufficient(message)
|
||||||
else:
|
else:
|
||||||
print(f"未知消息类型: {msg_type}")
|
print(f"未知消息类型: {msg_type}")
|
||||||
|
|
||||||
@@ -1203,7 +1209,8 @@ class BackendClient:
|
|||||||
self.login_callback(platform_name, store_id, full_message, store_name)
|
self.login_callback(platform_name, store_id, full_message, store_name)
|
||||||
else:
|
else:
|
||||||
# 普通Cookie模式
|
# 普通Cookie模式
|
||||||
print(f"收到登录指令: 平台={platform_name}, 店铺={store_name or store_id}, cookies_len={len(cookies) if cookies else 0}")
|
print(
|
||||||
|
f"收到登录指令: 平台={platform_name}, 店铺={store_name or store_id}, cookies_len={len(cookies) if cookies else 0}")
|
||||||
if self.login_callback:
|
if self.login_callback:
|
||||||
self.login_callback(platform_name, store_id, cookies, store_name)
|
self.login_callback(platform_name, store_id, cookies, store_name)
|
||||||
|
|
||||||
@@ -1275,6 +1282,16 @@ class BackendClient:
|
|||||||
if self.disconnect_callback:
|
if self.disconnect_callback:
|
||||||
self.disconnect_callback(disconnect_message)
|
self.disconnect_callback(disconnect_message)
|
||||||
|
|
||||||
|
def _handle_balance_insufficient(self, message: Dict[str, Any]):
|
||||||
|
"""处理余额不足消息"""
|
||||||
|
balance_message = message.get('content', '所有平台已断开。请充值条数后,重新连接')
|
||||||
|
|
||||||
|
self._log(f"⚠️ 余额不足: {balance_message}", "WARNING")
|
||||||
|
|
||||||
|
# 触发余额不足回调(在主线程中处理断开逻辑)
|
||||||
|
if self.balance_insufficient_callback:
|
||||||
|
self.balance_insufficient_callback(balance_message)
|
||||||
|
|
||||||
# ==================== 辅助方法 ====================
|
# ==================== 辅助方法 ====================
|
||||||
|
|
||||||
def set_token(self, token: str):
|
def set_token(self, token: str):
|
||||||
|
|||||||
@@ -60,7 +60,8 @@ class WebSocketManager:
|
|||||||
|
|
||||||
def set_callbacks(self, log: Callable = None, success: Callable = None, error: Callable = None,
|
def set_callbacks(self, log: Callable = None, success: Callable = None, error: Callable = None,
|
||||||
platform_connected: Callable = None, platform_disconnected: Callable = None,
|
platform_connected: Callable = None, platform_disconnected: Callable = None,
|
||||||
token_error: Callable = None, disconnect: Callable = None):
|
token_error: Callable = None, disconnect: Callable = None,
|
||||||
|
balance_insufficient: Callable = None):
|
||||||
"""设置回调函数"""
|
"""设置回调函数"""
|
||||||
if log:
|
if log:
|
||||||
self.callbacks['log'] = log
|
self.callbacks['log'] = log
|
||||||
@@ -76,6 +77,8 @@ class WebSocketManager:
|
|||||||
self.callbacks['token_error'] = token_error
|
self.callbacks['token_error'] = token_error
|
||||||
if disconnect:
|
if disconnect:
|
||||||
self.callbacks['disconnect'] = disconnect
|
self.callbacks['disconnect'] = disconnect
|
||||||
|
if balance_insufficient:
|
||||||
|
self.callbacks['balance_insufficient'] = balance_insufficient
|
||||||
|
|
||||||
def _log(self, message: str, level: str = "INFO"):
|
def _log(self, message: str, level: str = "INFO"):
|
||||||
"""内部日志方法"""
|
"""内部日志方法"""
|
||||||
@@ -104,7 +107,8 @@ class WebSocketManager:
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
self._log(f"通知平台连接失败: {e}", "ERROR")
|
self._log(f"通知平台连接失败: {e}", "ERROR")
|
||||||
|
|
||||||
def notify_platform_kicked(self, platform_name: str, store_name: str, reason: str = "账号在其他设备登录", store_id: str = None):
|
def notify_platform_kicked(self, platform_name: str, store_name: str, reason: str = "账号在其他设备登录",
|
||||||
|
store_id: str = None):
|
||||||
"""通知GUI平台被踢下线(供平台监听器调用)"""
|
"""通知GUI平台被踢下线(供平台监听器调用)"""
|
||||||
try:
|
try:
|
||||||
self._log(f"⚠️ 平台被踢下线: {platform_name} - {store_name}, 原因: {reason}", "WARNING")
|
self._log(f"⚠️ 平台被踢下线: {platform_name} - {store_name}, 原因: {reason}", "WARNING")
|
||||||
@@ -133,6 +137,56 @@ class WebSocketManager:
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
self._log(f"通知平台断开失败: {e}", "ERROR")
|
self._log(f"通知平台断开失败: {e}", "ERROR")
|
||||||
|
|
||||||
|
def disconnect_all_async(self):
|
||||||
|
"""异步断开所有连接(余额不足时调用)- 不阻塞当前线程"""
|
||||||
|
try:
|
||||||
|
self._log("🔴 收到余额不足通知,开始断开所有连接...", "ERROR")
|
||||||
|
|
||||||
|
# 1. 断开所有平台连接
|
||||||
|
if self.platform_listeners:
|
||||||
|
platform_count = len(self.platform_listeners)
|
||||||
|
self._log(f"正在断开 {platform_count} 个平台连接...", "INFO")
|
||||||
|
|
||||||
|
# 复制键列表,避免遍历时修改字典
|
||||||
|
platform_keys = list(self.platform_listeners.keys())
|
||||||
|
|
||||||
|
for key in platform_keys:
|
||||||
|
try:
|
||||||
|
listener_info = self.platform_listeners.get(key)
|
||||||
|
if listener_info:
|
||||||
|
platform_type = listener_info.get('platform', '')
|
||||||
|
self._log(f"断开 {platform_type} 平台连接: {key}", "INFO")
|
||||||
|
|
||||||
|
# 移除连接记录
|
||||||
|
self.platform_listeners.pop(key, None)
|
||||||
|
except Exception as e:
|
||||||
|
self._log(f"断开平台连接失败: {e}", "ERROR")
|
||||||
|
|
||||||
|
self._log(f"✅ 已断开所有 {platform_count} 个平台连接", "INFO")
|
||||||
|
|
||||||
|
# 清空连接列表
|
||||||
|
self.connected_platforms.clear()
|
||||||
|
|
||||||
|
# 2. 延迟断开后端连接(在新线程中执行,避免阻塞)
|
||||||
|
import threading
|
||||||
|
def _delayed_backend_disconnect():
|
||||||
|
try:
|
||||||
|
import time
|
||||||
|
time.sleep(0.5) # 延迟0.5秒,确保上面的操作完成
|
||||||
|
|
||||||
|
if self.backend_client:
|
||||||
|
self.backend_client.should_stop = True
|
||||||
|
self.backend_client.is_connected = False
|
||||||
|
self._log("✅ 已标记后端连接为断开状态", "INFO")
|
||||||
|
except Exception as e:
|
||||||
|
self._log(f"断开后端连接失败: {e}", "ERROR")
|
||||||
|
|
||||||
|
disconnect_thread = threading.Thread(target=_delayed_backend_disconnect, daemon=True)
|
||||||
|
disconnect_thread.start()
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
self._log(f"断开所有连接失败: {e}", "ERROR")
|
||||||
|
|
||||||
def connect_backend(self, token: str) -> bool:
|
def connect_backend(self, token: str) -> bool:
|
||||||
"""连接后端WebSocket"""
|
"""连接后端WebSocket"""
|
||||||
try:
|
try:
|
||||||
@@ -188,12 +242,18 @@ class WebSocketManager:
|
|||||||
if self.callbacks['disconnect']:
|
if self.callbacks['disconnect']:
|
||||||
self.callbacks['disconnect'](disconnect_msg)
|
self.callbacks['disconnect'](disconnect_msg)
|
||||||
|
|
||||||
|
def _on_balance_insufficient(balance_msg: str):
|
||||||
|
"""余额不足回调"""
|
||||||
|
if self.callbacks['balance_insufficient']:
|
||||||
|
self.callbacks['balance_insufficient'](balance_msg)
|
||||||
|
|
||||||
def _on_log(message: str, level: str = "INFO"):
|
def _on_log(message: str, level: str = "INFO"):
|
||||||
"""Backend client log callback"""
|
"""Backend client log callback"""
|
||||||
self._log(message, level)
|
self._log(message, level)
|
||||||
|
|
||||||
backend.set_callbacks(success=_on_backend_success, login=_on_backend_login,
|
backend.set_callbacks(success=_on_backend_success, login=_on_backend_login,
|
||||||
token_error=_on_token_error, disconnect=_on_disconnect,
|
token_error=_on_token_error, disconnect=_on_disconnect,
|
||||||
|
balance_insufficient=_on_balance_insufficient,
|
||||||
log=_on_log)
|
log=_on_log)
|
||||||
|
|
||||||
if not backend.is_connected:
|
if not backend.is_connected:
|
||||||
@@ -235,12 +295,18 @@ class WebSocketManager:
|
|||||||
if self.callbacks['disconnect']:
|
if self.callbacks['disconnect']:
|
||||||
self.callbacks['disconnect'](disconnect_msg)
|
self.callbacks['disconnect'](disconnect_msg)
|
||||||
|
|
||||||
|
def _on_balance_insufficient(balance_msg: str):
|
||||||
|
"""余额不足回调"""
|
||||||
|
if self.callbacks['balance_insufficient']:
|
||||||
|
self.callbacks['balance_insufficient'](balance_msg)
|
||||||
|
|
||||||
def _on_log(message: str, level: str = "INFO"):
|
def _on_log(message: str, level: str = "INFO"):
|
||||||
"""Backend client log callback"""
|
"""Backend client log callback"""
|
||||||
self._log(message, level)
|
self._log(message, level)
|
||||||
|
|
||||||
backend.set_callbacks(login=_on_backend_login, success=_on_backend_success,
|
backend.set_callbacks(login=_on_backend_login, success=_on_backend_success,
|
||||||
token_error=_on_token_error, disconnect=_on_disconnect,
|
token_error=_on_token_error, disconnect=_on_disconnect,
|
||||||
|
balance_insufficient=_on_balance_insufficient,
|
||||||
log=_on_log)
|
log=_on_log)
|
||||||
backend.connect()
|
backend.connect()
|
||||||
|
|
||||||
|
|||||||
69
main.py
69
main.py
@@ -12,7 +12,6 @@ from WebSocket.backend_singleton import get_websocket_manager
|
|||||||
from windows_taskbar_fix import setup_windows_taskbar_icon
|
from windows_taskbar_fix import setup_windows_taskbar_icon
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
|
||||||
# ===================== 文件日志系统 - 生产环境启用 =====================
|
# ===================== 文件日志系统 - 生产环境启用 =====================
|
||||||
# 重定向所有输出到文件,确保有日志记录
|
# 重定向所有输出到文件,确保有日志记录
|
||||||
from exe_file_logger import setup_file_logging, log_to_file # 开发环境启用
|
from exe_file_logger import setup_file_logging, log_to_file # 开发环境启用
|
||||||
@@ -33,6 +32,12 @@ class DisconnectSignals(QObject):
|
|||||||
disconnected = pyqtSignal(str) # (disconnect_message)
|
disconnected = pyqtSignal(str) # (disconnect_message)
|
||||||
|
|
||||||
|
|
||||||
|
# 新增: 余额不足信号类(用于线程安全的余额不足提示)
|
||||||
|
class BalanceInsufficientSignals(QObject):
|
||||||
|
"""余额不足信号"""
|
||||||
|
balance_insufficient = pyqtSignal(str) # (balance_message)
|
||||||
|
|
||||||
|
|
||||||
# 新增: 用户名密码输入对话框类
|
# 新增: 用户名密码输入对话框类
|
||||||
class LoginWindow(QMainWindow):
|
class LoginWindow(QMainWindow):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
@@ -62,6 +67,10 @@ class LoginWindow(QMainWindow):
|
|||||||
self.disconnect_signals = DisconnectSignals()
|
self.disconnect_signals = DisconnectSignals()
|
||||||
self.disconnect_signals.disconnected.connect(self._show_disconnect_dialog)
|
self.disconnect_signals.disconnected.connect(self._show_disconnect_dialog)
|
||||||
|
|
||||||
|
# 创建余额不足信号对象(线程安全)
|
||||||
|
self.balance_insufficient_signals = BalanceInsufficientSignals()
|
||||||
|
self.balance_insufficient_signals.balance_insufficient.connect(self._show_balance_insufficient_dialog)
|
||||||
|
|
||||||
# 横幅相关
|
# 横幅相关
|
||||||
self.promo_banner = None
|
self.promo_banner = None
|
||||||
self.banner_shadow = None # 阴影效果引用
|
self.banner_shadow = None # 阴影效果引用
|
||||||
@@ -678,6 +687,18 @@ class LoginWindow(QMainWindow):
|
|||||||
import traceback
|
import traceback
|
||||||
self.add_log(f"详细错误: {traceback.format_exc()}", "ERROR")
|
self.add_log(f"详细错误: {traceback.format_exc()}", "ERROR")
|
||||||
|
|
||||||
|
def on_balance_insufficient(self, balance_msg: str):
|
||||||
|
"""处理余额不足 - 发射信号到主线程(可在任何线程中调用)"""
|
||||||
|
try:
|
||||||
|
self.add_log(f"📡 收到余额不足通知,准备发射信号: {balance_msg}", "INFO")
|
||||||
|
# 发射信号(Qt 自动调度到主线程)
|
||||||
|
self.balance_insufficient_signals.balance_insufficient.emit(balance_msg)
|
||||||
|
self.add_log(f"✅ 余额不足信号已发射", "DEBUG")
|
||||||
|
except Exception as e:
|
||||||
|
self.add_log(f"❌ 发射余额不足信号失败: {e}", "ERROR")
|
||||||
|
import traceback
|
||||||
|
self.add_log(f"详细错误: {traceback.format_exc()}", "ERROR")
|
||||||
|
|
||||||
def _show_disconnect_dialog(self, disconnect_msg: str):
|
def _show_disconnect_dialog(self, disconnect_msg: str):
|
||||||
"""显示断开连接提示框(信号槽函数,始终在主线程中执行)"""
|
"""显示断开连接提示框(信号槽函数,始终在主线程中执行)"""
|
||||||
try:
|
try:
|
||||||
@@ -714,6 +735,49 @@ class LoginWindow(QMainWindow):
|
|||||||
import traceback
|
import traceback
|
||||||
self.add_log(f"详细错误: {traceback.format_exc()}", "ERROR")
|
self.add_log(f"详细错误: {traceback.format_exc()}", "ERROR")
|
||||||
|
|
||||||
|
def _show_balance_insufficient_dialog(self, balance_msg: str):
|
||||||
|
"""显示余额不足提示框(信号槽函数,始终在主线程中执行)"""
|
||||||
|
try:
|
||||||
|
self.add_log(f"🎯 主线程收到余额不足信号: {balance_msg}", "INFO")
|
||||||
|
|
||||||
|
# 1. 断开所有连接(异步,不阻塞)
|
||||||
|
ws_manager = get_websocket_manager()
|
||||||
|
if ws_manager:
|
||||||
|
self.add_log("🔴 开始断开所有连接...", "INFO")
|
||||||
|
ws_manager.disconnect_all_async()
|
||||||
|
self.add_log("✅ 断开连接指令已发送", "INFO")
|
||||||
|
|
||||||
|
# 2. 更新UI状态
|
||||||
|
self.status_label.setText("🔴 余额不足")
|
||||||
|
self.status_label.setStyleSheet(
|
||||||
|
"color: #dc3545; background: rgba(220, 53, 69, 0.1); border-radius: 12px; padding: 5px 10px; font-weight: bold;")
|
||||||
|
|
||||||
|
# 3. 重置按钮状态
|
||||||
|
self.login_btn.setEnabled(True)
|
||||||
|
self.login_btn.setText("重新连接")
|
||||||
|
self.login_btn.setObjectName("loginButton")
|
||||||
|
self.login_btn.setStyleSheet(self.login_btn.styleSheet()) # 刷新样式
|
||||||
|
|
||||||
|
# 4. 清空已连接平台列表
|
||||||
|
self.connected_platforms.clear()
|
||||||
|
|
||||||
|
# 5. 显示弹窗提示(主线程中执行,不会卡顿)
|
||||||
|
QMessageBox.critical(
|
||||||
|
self,
|
||||||
|
"余额不足",
|
||||||
|
f"{balance_msg}\n\n"
|
||||||
|
f"已断开所有平台连接和后端连接。\n\n"
|
||||||
|
f"请充值后,点击「连接服务」按钮重新连接。",
|
||||||
|
QMessageBox.Ok
|
||||||
|
)
|
||||||
|
|
||||||
|
self.add_log("✅ 余额不足提示已显示,所有连接已断开", "INFO")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
self.add_log(f"❌ 显示余额不足提示框失败: {e}", "ERROR")
|
||||||
|
import traceback
|
||||||
|
self.add_log(f"详细错误: {traceback.format_exc()}", "ERROR")
|
||||||
|
|
||||||
def delayed_platform_summary(self):
|
def delayed_platform_summary(self):
|
||||||
"""定时器触发的汇总显示更新"""
|
"""定时器触发的汇总显示更新"""
|
||||||
try:
|
try:
|
||||||
@@ -1004,7 +1068,8 @@ class LoginWindow(QMainWindow):
|
|||||||
platform_connected=self.on_platform_connected, # 新增:平台连接回调
|
platform_connected=self.on_platform_connected, # 新增:平台连接回调
|
||||||
platform_disconnected=self.on_platform_kicked, # 新增:平台被踢回调
|
platform_disconnected=self.on_platform_kicked, # 新增:平台被踢回调
|
||||||
token_error=self.on_token_error, # 新增:token错误回调
|
token_error=self.on_token_error, # 新增:token错误回调
|
||||||
disconnect=self.on_disconnect # 新增:被踢下线回调
|
disconnect=self.on_disconnect, # 新增:被踢下线回调
|
||||||
|
balance_insufficient=self.on_balance_insufficient # 新增:余额不足回调
|
||||||
)
|
)
|
||||||
|
|
||||||
# 连接后端
|
# 连接后端
|
||||||
|
|||||||
Reference in New Issue
Block a user