[patch] 新增用户余额不足 交互模式代码

This commit is contained in:
2025-10-17 17:38:02 +08:00
parent a5c2a44512
commit 8eb03ddedc
4 changed files with 225 additions and 77 deletions

View File

@@ -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):

View File

@@ -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
View File

@@ -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 # 新增:余额不足回调
) )
# 连接后端 # 连接后端