[patch] 新增用户余额不足 交互模式代码
This commit is contained in:
@@ -32,6 +32,7 @@ class BackendClient:
|
||||
self.token_error_callback: Optional[Callable] = None # 新增:token错误回调
|
||||
self.version_callback: Optional[Callable] = None # 新增:版本检查回调
|
||||
self.disconnect_callback: Optional[Callable] = None # 新增:被踢下线回调
|
||||
self.balance_insufficient_callback: Optional[Callable] = None # 新增:余额不足回调
|
||||
self.log_callback: Optional[Callable] = None # 新增:日志回调
|
||||
|
||||
self.is_connected = False
|
||||
@@ -52,7 +53,7 @@ class BackendClient:
|
||||
"""Unified logging method that works in both dev and packaged environments"""
|
||||
# Always print to console (visible in dev mode)
|
||||
print(f"[{level}] {message}")
|
||||
|
||||
|
||||
# Also call the log callback if available (for file logging)
|
||||
if self.log_callback:
|
||||
try:
|
||||
@@ -130,10 +131,10 @@ class BackendClient:
|
||||
self._log("已禁用心跳机制", "WARNING")
|
||||
|
||||
self.is_connected = True
|
||||
|
||||
|
||||
# 🔥 在重置之前记录是否是重连(用于后续上报平台状态)
|
||||
was_reconnecting = self.reconnect_attempts > 0
|
||||
|
||||
|
||||
self.reconnect_attempts = 0 # 重置重连计数
|
||||
self.is_reconnecting = False
|
||||
self._log("后端WebSocket连接成功", "SUCCESS")
|
||||
@@ -285,6 +286,7 @@ class BackendClient:
|
||||
token_error: Callable = None,
|
||||
version: Callable = None,
|
||||
disconnect: Callable = None,
|
||||
balance_insufficient: Callable = None,
|
||||
log: Callable = None):
|
||||
"""设置各种消息类型的回调函数"""
|
||||
if store_list:
|
||||
@@ -309,6 +311,8 @@ class BackendClient:
|
||||
self.version_callback = version
|
||||
if disconnect:
|
||||
self.disconnect_callback = disconnect
|
||||
if balance_insufficient:
|
||||
self.balance_insufficient_callback = balance_insufficient
|
||||
if log:
|
||||
self.log_callback = log
|
||||
|
||||
@@ -333,11 +337,11 @@ class BackendClient:
|
||||
if hasattr(manager, 'platform_listeners') and manager.platform_listeners:
|
||||
platform_count = len(manager.platform_listeners)
|
||||
self._log(f"🔄 检测到 {platform_count} 个活跃平台连接,准备重新上报状态", "INFO")
|
||||
|
||||
|
||||
# 延迟1秒,确保后端完全准备好
|
||||
import time
|
||||
time.sleep(1.0)
|
||||
|
||||
|
||||
for platform_key, listener_info in manager.platform_listeners.items():
|
||||
store_id = listener_info.get('store_id')
|
||||
platform = listener_info.get('platform')
|
||||
@@ -353,7 +357,7 @@ class BackendClient:
|
||||
"status": True,
|
||||
"cookies": "" # 重连时无需再次发送cookies
|
||||
}
|
||||
|
||||
|
||||
# 同步发送,确保发送成功
|
||||
future = asyncio.run_coroutine_threadsafe(
|
||||
self._send_to_backend(reconnect_message),
|
||||
@@ -361,7 +365,7 @@ class BackendClient:
|
||||
)
|
||||
# 等待发送完成(最多2秒)
|
||||
future.result(timeout=2)
|
||||
|
||||
|
||||
self._log(f"✅ 已重新上报 {platform} 平台状态: {store_display}", "SUCCESS")
|
||||
except Exception as e:
|
||||
self._log(f"❌ 上报 {platform} 平台状态失败: {e}", "ERROR")
|
||||
@@ -386,7 +390,7 @@ class BackendClient:
|
||||
try:
|
||||
from WebSocket.backend_singleton import get_websocket_manager
|
||||
manager = get_websocket_manager()
|
||||
|
||||
|
||||
# 从 platform_listeners 获取活跃平台
|
||||
if hasattr(manager, 'platform_listeners') and manager.platform_listeners:
|
||||
# 获取第一个活跃平台的 store_id
|
||||
@@ -475,6 +479,8 @@ class BackendClient:
|
||||
self._handle_version_response(message)
|
||||
elif msg_type == 'disconnect': # 新增:被踢下线
|
||||
self._handle_disconnect(message)
|
||||
elif msg_type == 'balance_insufficient': # 新增:余额不足
|
||||
self._handle_balance_insufficient(message)
|
||||
else:
|
||||
print(f"未知消息类型: {msg_type}")
|
||||
|
||||
@@ -1203,7 +1209,8 @@ class BackendClient:
|
||||
self.login_callback(platform_name, store_id, full_message, store_name)
|
||||
else:
|
||||
# 普通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:
|
||||
self.login_callback(platform_name, store_id, cookies, store_name)
|
||||
|
||||
@@ -1275,6 +1282,16 @@ class BackendClient:
|
||||
if self.disconnect_callback:
|
||||
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):
|
||||
|
||||
@@ -60,7 +60,8 @@ class WebSocketManager:
|
||||
|
||||
def set_callbacks(self, log: Callable = None, success: Callable = None, error: 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:
|
||||
self.callbacks['log'] = log
|
||||
@@ -76,6 +77,8 @@ class WebSocketManager:
|
||||
self.callbacks['token_error'] = token_error
|
||||
if disconnect:
|
||||
self.callbacks['disconnect'] = disconnect
|
||||
if balance_insufficient:
|
||||
self.callbacks['balance_insufficient'] = balance_insufficient
|
||||
|
||||
def _log(self, message: str, level: str = "INFO"):
|
||||
"""内部日志方法"""
|
||||
@@ -104,15 +107,16 @@ class WebSocketManager:
|
||||
except Exception as e:
|
||||
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平台被踢下线(供平台监听器调用)"""
|
||||
try:
|
||||
self._log(f"⚠️ 平台被踢下线: {platform_name} - {store_name}, 原因: {reason}", "WARNING")
|
||||
|
||||
|
||||
# 从连接列表中移除
|
||||
if platform_name in self.connected_platforms:
|
||||
self.connected_platforms.remove(platform_name)
|
||||
|
||||
|
||||
# 🔥 发送平台断开消息给后端(status=false)
|
||||
if store_id and self.backend_client:
|
||||
try:
|
||||
@@ -126,13 +130,63 @@ class WebSocketManager:
|
||||
self._log(f"✅ 已通知后端 {platform_name} 平台断开: {store_id}", "INFO")
|
||||
except Exception as send_error:
|
||||
self._log(f"❌ 发送平台断开消息失败: {send_error}", "ERROR")
|
||||
|
||||
|
||||
# 通知GUI显示弹窗
|
||||
if self.callbacks['platform_disconnected']:
|
||||
self.callbacks['platform_disconnected'](platform_name, store_name, reason)
|
||||
except Exception as e:
|
||||
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:
|
||||
"""连接后端WebSocket"""
|
||||
try:
|
||||
@@ -188,12 +242,18 @@ class WebSocketManager:
|
||||
if self.callbacks['disconnect']:
|
||||
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"):
|
||||
"""Backend client log callback"""
|
||||
self._log(message, level)
|
||||
|
||||
backend.set_callbacks(success=_on_backend_success, login=_on_backend_login,
|
||||
token_error=_on_token_error, disconnect=_on_disconnect,
|
||||
balance_insufficient=_on_balance_insufficient,
|
||||
log=_on_log)
|
||||
|
||||
if not backend.is_connected:
|
||||
@@ -235,12 +295,18 @@ class WebSocketManager:
|
||||
if self.callbacks['disconnect']:
|
||||
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"):
|
||||
"""Backend client log callback"""
|
||||
self._log(message, level)
|
||||
|
||||
backend.set_callbacks(login=_on_backend_login, success=_on_backend_success,
|
||||
token_error=_on_token_error, disconnect=_on_disconnect,
|
||||
balance_insufficient=_on_balance_insufficient,
|
||||
log=_on_log)
|
||||
backend.connect()
|
||||
|
||||
@@ -261,15 +327,15 @@ class WebSocketManager:
|
||||
# 🔥 检查并断开当前店铺的旧连接(策略B:先断开旧连接,再建立新连接)
|
||||
store_key_pattern = f":{store_id}" # 匹配 "平台名:store_id" 格式
|
||||
keys_to_remove = [key for key in self.platform_listeners.keys() if key.endswith(store_key_pattern)]
|
||||
|
||||
|
||||
if keys_to_remove:
|
||||
self._log(f"🔄 检测到店铺 {store_id} 重复登录,断开 {len(keys_to_remove)} 个旧连接", "INFO")
|
||||
|
||||
|
||||
for key in keys_to_remove:
|
||||
listener_info = self.platform_listeners.get(key)
|
||||
if listener_info:
|
||||
platform_type = listener_info.get('platform', '')
|
||||
|
||||
|
||||
# 从各平台的 WebsocketManager 中获取连接并关闭WebSocket
|
||||
try:
|
||||
if platform_type == "京东":
|
||||
@@ -289,7 +355,7 @@ class WebSocketManager:
|
||||
pass
|
||||
jd_mgr.remove_connection(key)
|
||||
self._log(f"✅ 已从京东管理器移除连接: {key}", "DEBUG")
|
||||
|
||||
|
||||
elif platform_type == "抖音":
|
||||
from Utils.Dy.DyUtils import DouYinWebsocketManager as DYWSManager
|
||||
dy_mgr = DYWSManager()
|
||||
@@ -307,13 +373,13 @@ class WebSocketManager:
|
||||
pass
|
||||
dy_mgr.remove_connection(key)
|
||||
self._log(f"✅ 已从抖音管理器移除连接: {key}", "DEBUG")
|
||||
|
||||
|
||||
elif platform_type == "千牛":
|
||||
from Utils.QianNiu.QianNiuUtils import QianNiuWebsocketManager as QNWSManager
|
||||
qn_mgr = QNWSManager()
|
||||
qn_mgr.remove_connection(key)
|
||||
self._log(f"✅ 已从千牛管理器移除连接: {key}", "DEBUG")
|
||||
|
||||
|
||||
elif platform_type == "拼多多":
|
||||
from Utils.Pdd.PddUtils import WebsocketManager as PDDWSManager
|
||||
pdd_mgr = PDDWSManager()
|
||||
@@ -332,17 +398,17 @@ class WebSocketManager:
|
||||
self._log(f"⚠️ 关闭WebSocket时出错: {ws_e}", "DEBUG")
|
||||
pdd_mgr.remove_connection(key)
|
||||
self._log(f"✅ 已从拼多多管理器移除连接: {key}", "DEBUG")
|
||||
|
||||
|
||||
except Exception as e:
|
||||
self._log(f"⚠️ 移除{platform_type}连接时出错: {e}", "WARNING")
|
||||
|
||||
|
||||
# 从监听器字典中移除
|
||||
self.platform_listeners.pop(key, None)
|
||||
|
||||
|
||||
# 给WebSocket一点时间完全关闭
|
||||
import time
|
||||
time.sleep(0.5)
|
||||
|
||||
|
||||
self._log(f"✅ 旧连接已全部断开,准备建立新连接", "INFO")
|
||||
|
||||
# 平台名称映射
|
||||
|
||||
Reference in New Issue
Block a user