[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
|
||||||
@@ -52,7 +53,7 @@ class BackendClient:
|
|||||||
"""Unified logging method that works in both dev and packaged environments"""
|
"""Unified logging method that works in both dev and packaged environments"""
|
||||||
# Always print to console (visible in dev mode)
|
# Always print to console (visible in dev mode)
|
||||||
print(f"[{level}] {message}")
|
print(f"[{level}] {message}")
|
||||||
|
|
||||||
# Also call the log callback if available (for file logging)
|
# Also call the log callback if available (for file logging)
|
||||||
if self.log_callback:
|
if self.log_callback:
|
||||||
try:
|
try:
|
||||||
@@ -130,10 +131,10 @@ class BackendClient:
|
|||||||
self._log("已禁用心跳机制", "WARNING")
|
self._log("已禁用心跳机制", "WARNING")
|
||||||
|
|
||||||
self.is_connected = True
|
self.is_connected = True
|
||||||
|
|
||||||
# 🔥 在重置之前记录是否是重连(用于后续上报平台状态)
|
# 🔥 在重置之前记录是否是重连(用于后续上报平台状态)
|
||||||
was_reconnecting = self.reconnect_attempts > 0
|
was_reconnecting = self.reconnect_attempts > 0
|
||||||
|
|
||||||
self.reconnect_attempts = 0 # 重置重连计数
|
self.reconnect_attempts = 0 # 重置重连计数
|
||||||
self.is_reconnecting = False
|
self.is_reconnecting = False
|
||||||
self._log("后端WebSocket连接成功", "SUCCESS")
|
self._log("后端WebSocket连接成功", "SUCCESS")
|
||||||
@@ -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
|
||||||
|
|
||||||
@@ -333,11 +337,11 @@ class BackendClient:
|
|||||||
if hasattr(manager, 'platform_listeners') and manager.platform_listeners:
|
if hasattr(manager, 'platform_listeners') and manager.platform_listeners:
|
||||||
platform_count = len(manager.platform_listeners)
|
platform_count = len(manager.platform_listeners)
|
||||||
self._log(f"🔄 检测到 {platform_count} 个活跃平台连接,准备重新上报状态", "INFO")
|
self._log(f"🔄 检测到 {platform_count} 个活跃平台连接,准备重新上报状态", "INFO")
|
||||||
|
|
||||||
# 延迟1秒,确保后端完全准备好
|
# 延迟1秒,确保后端完全准备好
|
||||||
import time
|
import time
|
||||||
time.sleep(1.0)
|
time.sleep(1.0)
|
||||||
|
|
||||||
for platform_key, listener_info in manager.platform_listeners.items():
|
for platform_key, listener_info in manager.platform_listeners.items():
|
||||||
store_id = listener_info.get('store_id')
|
store_id = listener_info.get('store_id')
|
||||||
platform = listener_info.get('platform')
|
platform = listener_info.get('platform')
|
||||||
@@ -353,7 +357,7 @@ class BackendClient:
|
|||||||
"status": True,
|
"status": True,
|
||||||
"cookies": "" # 重连时无需再次发送cookies
|
"cookies": "" # 重连时无需再次发送cookies
|
||||||
}
|
}
|
||||||
|
|
||||||
# 同步发送,确保发送成功
|
# 同步发送,确保发送成功
|
||||||
future = asyncio.run_coroutine_threadsafe(
|
future = asyncio.run_coroutine_threadsafe(
|
||||||
self._send_to_backend(reconnect_message),
|
self._send_to_backend(reconnect_message),
|
||||||
@@ -361,7 +365,7 @@ class BackendClient:
|
|||||||
)
|
)
|
||||||
# 等待发送完成(最多2秒)
|
# 等待发送完成(最多2秒)
|
||||||
future.result(timeout=2)
|
future.result(timeout=2)
|
||||||
|
|
||||||
self._log(f"✅ 已重新上报 {platform} 平台状态: {store_display}", "SUCCESS")
|
self._log(f"✅ 已重新上报 {platform} 平台状态: {store_display}", "SUCCESS")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self._log(f"❌ 上报 {platform} 平台状态失败: {e}", "ERROR")
|
self._log(f"❌ 上报 {platform} 平台状态失败: {e}", "ERROR")
|
||||||
@@ -386,7 +390,7 @@ class BackendClient:
|
|||||||
try:
|
try:
|
||||||
from WebSocket.backend_singleton import get_websocket_manager
|
from WebSocket.backend_singleton import get_websocket_manager
|
||||||
manager = get_websocket_manager()
|
manager = get_websocket_manager()
|
||||||
|
|
||||||
# 从 platform_listeners 获取活跃平台
|
# 从 platform_listeners 获取活跃平台
|
||||||
if hasattr(manager, 'platform_listeners') and manager.platform_listeners:
|
if hasattr(manager, 'platform_listeners') and manager.platform_listeners:
|
||||||
# 获取第一个活跃平台的 store_id
|
# 获取第一个活跃平台的 store_id
|
||||||
@@ -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,15 +107,16 @@ 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")
|
||||||
|
|
||||||
# 从连接列表中移除
|
# 从连接列表中移除
|
||||||
if platform_name in self.connected_platforms:
|
if platform_name in self.connected_platforms:
|
||||||
self.connected_platforms.remove(platform_name)
|
self.connected_platforms.remove(platform_name)
|
||||||
|
|
||||||
# 🔥 发送平台断开消息给后端(status=false)
|
# 🔥 发送平台断开消息给后端(status=false)
|
||||||
if store_id and self.backend_client:
|
if store_id and self.backend_client:
|
||||||
try:
|
try:
|
||||||
@@ -126,13 +130,63 @@ class WebSocketManager:
|
|||||||
self._log(f"✅ 已通知后端 {platform_name} 平台断开: {store_id}", "INFO")
|
self._log(f"✅ 已通知后端 {platform_name} 平台断开: {store_id}", "INFO")
|
||||||
except Exception as send_error:
|
except Exception as send_error:
|
||||||
self._log(f"❌ 发送平台断开消息失败: {send_error}", "ERROR")
|
self._log(f"❌ 发送平台断开消息失败: {send_error}", "ERROR")
|
||||||
|
|
||||||
# 通知GUI显示弹窗
|
# 通知GUI显示弹窗
|
||||||
if self.callbacks['platform_disconnected']:
|
if self.callbacks['platform_disconnected']:
|
||||||
self.callbacks['platform_disconnected'](platform_name, store_name, reason)
|
self.callbacks['platform_disconnected'](platform_name, store_name, reason)
|
||||||
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()
|
||||||
|
|
||||||
@@ -261,15 +327,15 @@ class WebSocketManager:
|
|||||||
# 🔥 检查并断开当前店铺的旧连接(策略B:先断开旧连接,再建立新连接)
|
# 🔥 检查并断开当前店铺的旧连接(策略B:先断开旧连接,再建立新连接)
|
||||||
store_key_pattern = f":{store_id}" # 匹配 "平台名:store_id" 格式
|
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)]
|
keys_to_remove = [key for key in self.platform_listeners.keys() if key.endswith(store_key_pattern)]
|
||||||
|
|
||||||
if keys_to_remove:
|
if keys_to_remove:
|
||||||
self._log(f"🔄 检测到店铺 {store_id} 重复登录,断开 {len(keys_to_remove)} 个旧连接", "INFO")
|
self._log(f"🔄 检测到店铺 {store_id} 重复登录,断开 {len(keys_to_remove)} 个旧连接", "INFO")
|
||||||
|
|
||||||
for key in keys_to_remove:
|
for key in keys_to_remove:
|
||||||
listener_info = self.platform_listeners.get(key)
|
listener_info = self.platform_listeners.get(key)
|
||||||
if listener_info:
|
if listener_info:
|
||||||
platform_type = listener_info.get('platform', '')
|
platform_type = listener_info.get('platform', '')
|
||||||
|
|
||||||
# 从各平台的 WebsocketManager 中获取连接并关闭WebSocket
|
# 从各平台的 WebsocketManager 中获取连接并关闭WebSocket
|
||||||
try:
|
try:
|
||||||
if platform_type == "京东":
|
if platform_type == "京东":
|
||||||
@@ -289,7 +355,7 @@ class WebSocketManager:
|
|||||||
pass
|
pass
|
||||||
jd_mgr.remove_connection(key)
|
jd_mgr.remove_connection(key)
|
||||||
self._log(f"✅ 已从京东管理器移除连接: {key}", "DEBUG")
|
self._log(f"✅ 已从京东管理器移除连接: {key}", "DEBUG")
|
||||||
|
|
||||||
elif platform_type == "抖音":
|
elif platform_type == "抖音":
|
||||||
from Utils.Dy.DyUtils import DouYinWebsocketManager as DYWSManager
|
from Utils.Dy.DyUtils import DouYinWebsocketManager as DYWSManager
|
||||||
dy_mgr = DYWSManager()
|
dy_mgr = DYWSManager()
|
||||||
@@ -307,13 +373,13 @@ class WebSocketManager:
|
|||||||
pass
|
pass
|
||||||
dy_mgr.remove_connection(key)
|
dy_mgr.remove_connection(key)
|
||||||
self._log(f"✅ 已从抖音管理器移除连接: {key}", "DEBUG")
|
self._log(f"✅ 已从抖音管理器移除连接: {key}", "DEBUG")
|
||||||
|
|
||||||
elif platform_type == "千牛":
|
elif platform_type == "千牛":
|
||||||
from Utils.QianNiu.QianNiuUtils import QianNiuWebsocketManager as QNWSManager
|
from Utils.QianNiu.QianNiuUtils import QianNiuWebsocketManager as QNWSManager
|
||||||
qn_mgr = QNWSManager()
|
qn_mgr = QNWSManager()
|
||||||
qn_mgr.remove_connection(key)
|
qn_mgr.remove_connection(key)
|
||||||
self._log(f"✅ 已从千牛管理器移除连接: {key}", "DEBUG")
|
self._log(f"✅ 已从千牛管理器移除连接: {key}", "DEBUG")
|
||||||
|
|
||||||
elif platform_type == "拼多多":
|
elif platform_type == "拼多多":
|
||||||
from Utils.Pdd.PddUtils import WebsocketManager as PDDWSManager
|
from Utils.Pdd.PddUtils import WebsocketManager as PDDWSManager
|
||||||
pdd_mgr = PDDWSManager()
|
pdd_mgr = PDDWSManager()
|
||||||
@@ -332,17 +398,17 @@ class WebSocketManager:
|
|||||||
self._log(f"⚠️ 关闭WebSocket时出错: {ws_e}", "DEBUG")
|
self._log(f"⚠️ 关闭WebSocket时出错: {ws_e}", "DEBUG")
|
||||||
pdd_mgr.remove_connection(key)
|
pdd_mgr.remove_connection(key)
|
||||||
self._log(f"✅ 已从拼多多管理器移除连接: {key}", "DEBUG")
|
self._log(f"✅ 已从拼多多管理器移除连接: {key}", "DEBUG")
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self._log(f"⚠️ 移除{platform_type}连接时出错: {e}", "WARNING")
|
self._log(f"⚠️ 移除{platform_type}连接时出错: {e}", "WARNING")
|
||||||
|
|
||||||
# 从监听器字典中移除
|
# 从监听器字典中移除
|
||||||
self.platform_listeners.pop(key, None)
|
self.platform_listeners.pop(key, None)
|
||||||
|
|
||||||
# 给WebSocket一点时间完全关闭
|
# 给WebSocket一点时间完全关闭
|
||||||
import time
|
import time
|
||||||
time.sleep(0.5)
|
time.sleep(0.5)
|
||||||
|
|
||||||
self._log(f"✅ 旧连接已全部断开,准备建立新连接", "INFO")
|
self._log(f"✅ 旧连接已全部断开,准备建立新连接", "INFO")
|
||||||
|
|
||||||
# 平台名称映射
|
# 平台名称映射
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ PLATFORMS = {
|
|||||||
"ws_url": "wss://dongdong.jd.com/workbench/websocket"
|
"ws_url": "wss://dongdong.jd.com/workbench/websocket"
|
||||||
},
|
},
|
||||||
"DOUYIN": {
|
"DOUYIN": {
|
||||||
"name": "抖音",
|
"name": "抖音",
|
||||||
"ws_url": None # 动态获取
|
"ws_url": None # 动态获取
|
||||||
},
|
},
|
||||||
"QIANNIU": {
|
"QIANNIU": {
|
||||||
|
|||||||
169
main.py
169
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 # 阴影效果引用
|
||||||
@@ -170,7 +179,7 @@ class LoginWindow(QMainWindow):
|
|||||||
|
|
||||||
# 系统初始化日志输出到终端
|
# 系统初始化日志输出到终端
|
||||||
print("[INFO] 系统初始化完成")
|
print("[INFO] 系统初始化完成")
|
||||||
|
|
||||||
# 让窗口自适应内容高度(最小化)
|
# 让窗口自适应内容高度(最小化)
|
||||||
self.adjustSize()
|
self.adjustSize()
|
||||||
print("[INFO] 窗口已自适应内容大小")
|
print("[INFO] 窗口已自适应内容大小")
|
||||||
@@ -182,41 +191,41 @@ class LoginWindow(QMainWindow):
|
|||||||
banner_frame = QFrame()
|
banner_frame = QFrame()
|
||||||
banner_frame.setObjectName("promoBanner")
|
banner_frame.setObjectName("promoBanner")
|
||||||
banner_frame.setCursor(Qt.PointingHandCursor) # 鼠标变手型
|
banner_frame.setCursor(Qt.PointingHandCursor) # 鼠标变手型
|
||||||
|
|
||||||
# 保存横幅引用,用于动画
|
# 保存横幅引用,用于动画
|
||||||
self.promo_banner = banner_frame
|
self.promo_banner = banner_frame
|
||||||
|
|
||||||
# 使用图片标签
|
# 使用图片标签
|
||||||
banner_image = QLabel()
|
banner_image = QLabel()
|
||||||
banner_image.setObjectName("bannerImage")
|
banner_image.setObjectName("bannerImage")
|
||||||
|
|
||||||
# 加载横幅图片
|
# 加载横幅图片
|
||||||
from windows_taskbar_fix import get_resource_path
|
from windows_taskbar_fix import get_resource_path
|
||||||
image_path = get_resource_path("static/hengfu.jpg")
|
image_path = get_resource_path("static/hengfu.jpg")
|
||||||
|
|
||||||
if os.path.exists(image_path):
|
if os.path.exists(image_path):
|
||||||
from PyQt5.QtGui import QPixmap
|
from PyQt5.QtGui import QPixmap
|
||||||
pixmap = QPixmap(image_path)
|
pixmap = QPixmap(image_path)
|
||||||
|
|
||||||
# 设置固定的横幅尺寸
|
# 设置固定的横幅尺寸
|
||||||
target_width = 400 # 固定宽度
|
target_width = 400 # 固定宽度
|
||||||
target_height = 70 # 固定高度(调整为70px,更紧凑)
|
target_height = 70 # 固定高度(调整为70px,更紧凑)
|
||||||
|
|
||||||
# 缩放图片以适应目标尺寸
|
# 缩放图片以适应目标尺寸
|
||||||
scaled_pixmap = pixmap.scaled(
|
scaled_pixmap = pixmap.scaled(
|
||||||
target_width,
|
target_width,
|
||||||
target_height,
|
target_height,
|
||||||
Qt.IgnoreAspectRatio, # 忽略宽高比,拉伸填充
|
Qt.IgnoreAspectRatio, # 忽略宽高比,拉伸填充
|
||||||
Qt.SmoothTransformation # 平滑缩放,提高图片质量
|
Qt.SmoothTransformation # 平滑缩放,提高图片质量
|
||||||
)
|
)
|
||||||
|
|
||||||
# 设置图片
|
# 设置图片
|
||||||
banner_image.setPixmap(scaled_pixmap)
|
banner_image.setPixmap(scaled_pixmap)
|
||||||
banner_image.setScaledContents(False)
|
banner_image.setScaledContents(False)
|
||||||
|
|
||||||
banner_frame.setFixedHeight(target_height)
|
banner_frame.setFixedHeight(target_height)
|
||||||
banner_image.setFixedSize(target_width, target_height)
|
banner_image.setFixedSize(target_width, target_height)
|
||||||
|
|
||||||
# 🔧 使用CSS圆角来处理边角(更简单稳定)
|
# 🔧 使用CSS圆角来处理边角(更简单稳定)
|
||||||
banner_image.setStyleSheet("""
|
banner_image.setStyleSheet("""
|
||||||
QLabel#bannerImage {
|
QLabel#bannerImage {
|
||||||
@@ -224,7 +233,7 @@ class LoginWindow(QMainWindow):
|
|||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
}
|
}
|
||||||
""")
|
""")
|
||||||
|
|
||||||
print(f"[INFO] 横幅图片已加载: {image_path}, 尺寸: {target_width}x{target_height}")
|
print(f"[INFO] 横幅图片已加载: {image_path}, 尺寸: {target_width}x{target_height}")
|
||||||
else:
|
else:
|
||||||
# 图片不存在时的备用方案
|
# 图片不存在时的备用方案
|
||||||
@@ -241,14 +250,14 @@ class LoginWindow(QMainWindow):
|
|||||||
""")
|
""")
|
||||||
banner_frame.setFixedHeight(60)
|
banner_frame.setFixedHeight(60)
|
||||||
print(f"[WARNING] 横幅图片未找到: {image_path},使用备用样式")
|
print(f"[WARNING] 横幅图片未找到: {image_path},使用备用样式")
|
||||||
|
|
||||||
# 创建布局
|
# 创建布局
|
||||||
banner_layout = QHBoxLayout()
|
banner_layout = QHBoxLayout()
|
||||||
banner_layout.setContentsMargins(0, 0, 0, 0)
|
banner_layout.setContentsMargins(0, 0, 0, 0)
|
||||||
banner_layout.setSpacing(0)
|
banner_layout.setSpacing(0)
|
||||||
banner_frame.setLayout(banner_layout)
|
banner_frame.setLayout(banner_layout)
|
||||||
banner_layout.addWidget(banner_image)
|
banner_layout.addWidget(banner_image)
|
||||||
|
|
||||||
# 设置圆角和边框
|
# 设置圆角和边框
|
||||||
banner_frame.setStyleSheet("""
|
banner_frame.setStyleSheet("""
|
||||||
QFrame#promoBanner {
|
QFrame#promoBanner {
|
||||||
@@ -256,7 +265,7 @@ class LoginWindow(QMainWindow):
|
|||||||
background: transparent;
|
background: transparent;
|
||||||
}
|
}
|
||||||
""")
|
""")
|
||||||
|
|
||||||
# 初始阴影效果
|
# 初始阴影效果
|
||||||
self.banner_shadow = QGraphicsDropShadowEffect()
|
self.banner_shadow = QGraphicsDropShadowEffect()
|
||||||
self.banner_shadow.setBlurRadius(15)
|
self.banner_shadow.setBlurRadius(15)
|
||||||
@@ -264,7 +273,7 @@ class LoginWindow(QMainWindow):
|
|||||||
self.banner_shadow.setYOffset(3)
|
self.banner_shadow.setYOffset(3)
|
||||||
self.banner_shadow.setColor(QColor(0, 0, 0, 60))
|
self.banner_shadow.setColor(QColor(0, 0, 0, 60))
|
||||||
banner_frame.setGraphicsEffect(self.banner_shadow)
|
banner_frame.setGraphicsEffect(self.banner_shadow)
|
||||||
|
|
||||||
# 点击事件 - 跳转官网
|
# 点击事件 - 跳转官网
|
||||||
def open_official_website():
|
def open_official_website():
|
||||||
try:
|
try:
|
||||||
@@ -274,9 +283,9 @@ class LoginWindow(QMainWindow):
|
|||||||
self.add_log(f"已打开官网: {official_url}", "INFO")
|
self.add_log(f"已打开官网: {official_url}", "INFO")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.add_log(f"打开官网失败: {e}", "ERROR")
|
self.add_log(f"打开官网失败: {e}", "ERROR")
|
||||||
|
|
||||||
banner_frame.mousePressEvent = lambda event: open_official_website()
|
banner_frame.mousePressEvent = lambda event: open_official_website()
|
||||||
|
|
||||||
# 🎯 添加鼠标悬停事件(动态效果)
|
# 🎯 添加鼠标悬停事件(动态效果)
|
||||||
def on_enter(event):
|
def on_enter(event):
|
||||||
"""鼠标进入时的动画效果"""
|
"""鼠标进入时的动画效果"""
|
||||||
@@ -285,30 +294,30 @@ class LoginWindow(QMainWindow):
|
|||||||
self.banner_shadow.setBlurRadius(25)
|
self.banner_shadow.setBlurRadius(25)
|
||||||
self.banner_shadow.setYOffset(5)
|
self.banner_shadow.setYOffset(5)
|
||||||
self.banner_shadow.setColor(QColor(0, 0, 0, 100))
|
self.banner_shadow.setColor(QColor(0, 0, 0, 100))
|
||||||
|
|
||||||
# 轻微放大动画
|
# 轻微放大动画
|
||||||
animation = QPropertyAnimation(banner_frame, b"geometry")
|
animation = QPropertyAnimation(banner_frame, b"geometry")
|
||||||
original_rect = banner_frame.geometry()
|
original_rect = banner_frame.geometry()
|
||||||
|
|
||||||
expanded_rect = QRect(
|
expanded_rect = QRect(
|
||||||
original_rect.x() - 3,
|
original_rect.x() - 3,
|
||||||
original_rect.y() - 2,
|
original_rect.y() - 2,
|
||||||
original_rect.width() + 6,
|
original_rect.width() + 6,
|
||||||
original_rect.height() + 4
|
original_rect.height() + 4
|
||||||
)
|
)
|
||||||
|
|
||||||
animation.setDuration(200)
|
animation.setDuration(200)
|
||||||
animation.setStartValue(original_rect)
|
animation.setStartValue(original_rect)
|
||||||
animation.setEndValue(expanded_rect)
|
animation.setEndValue(expanded_rect)
|
||||||
animation.setEasingCurve(QEasingCurve.OutCubic)
|
animation.setEasingCurve(QEasingCurve.OutCubic)
|
||||||
animation.start()
|
animation.start()
|
||||||
|
|
||||||
# 保存动画引用避免被垃圾回收
|
# 保存动画引用避免被垃圾回收
|
||||||
banner_frame.hover_animation = animation
|
banner_frame.hover_animation = animation
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"[DEBUG] 悬停动画错误: {e}")
|
print(f"[DEBUG] 悬停动画错误: {e}")
|
||||||
|
|
||||||
def on_leave(event):
|
def on_leave(event):
|
||||||
"""鼠标离开时的动画效果"""
|
"""鼠标离开时的动画效果"""
|
||||||
try:
|
try:
|
||||||
@@ -316,42 +325,42 @@ class LoginWindow(QMainWindow):
|
|||||||
self.banner_shadow.setBlurRadius(15)
|
self.banner_shadow.setBlurRadius(15)
|
||||||
self.banner_shadow.setYOffset(3)
|
self.banner_shadow.setYOffset(3)
|
||||||
self.banner_shadow.setColor(QColor(0, 0, 0, 60))
|
self.banner_shadow.setColor(QColor(0, 0, 0, 60))
|
||||||
|
|
||||||
# 恢复原始大小
|
# 恢复原始大小
|
||||||
animation = QPropertyAnimation(banner_frame, b"geometry")
|
animation = QPropertyAnimation(banner_frame, b"geometry")
|
||||||
current_rect = banner_frame.geometry()
|
current_rect = banner_frame.geometry()
|
||||||
|
|
||||||
original_rect = QRect(
|
original_rect = QRect(
|
||||||
current_rect.x() + 3,
|
current_rect.x() + 3,
|
||||||
current_rect.y() + 2,
|
current_rect.y() + 2,
|
||||||
current_rect.width() - 6,
|
current_rect.width() - 6,
|
||||||
current_rect.height() - 4
|
current_rect.height() - 4
|
||||||
)
|
)
|
||||||
|
|
||||||
animation.setDuration(200)
|
animation.setDuration(200)
|
||||||
animation.setStartValue(current_rect)
|
animation.setStartValue(current_rect)
|
||||||
animation.setEndValue(original_rect)
|
animation.setEndValue(original_rect)
|
||||||
animation.setEasingCurve(QEasingCurve.InCubic)
|
animation.setEasingCurve(QEasingCurve.InCubic)
|
||||||
animation.start()
|
animation.start()
|
||||||
|
|
||||||
# 保存动画引用避免被垃圾回收
|
# 保存动画引用避免被垃圾回收
|
||||||
banner_frame.leave_animation = animation
|
banner_frame.leave_animation = animation
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"[DEBUG] 离开动画错误: {e}")
|
print(f"[DEBUG] 离开动画错误: {e}")
|
||||||
|
|
||||||
# 安装事件过滤器
|
# 安装事件过滤器
|
||||||
banner_frame.enterEvent = on_enter
|
banner_frame.enterEvent = on_enter
|
||||||
banner_frame.leaveEvent = on_leave
|
banner_frame.leaveEvent = on_leave
|
||||||
|
|
||||||
# 添加到主布局
|
# 添加到主布局
|
||||||
layout.addWidget(banner_frame)
|
layout.addWidget(banner_frame)
|
||||||
|
|
||||||
print("[INFO] 宣传横幅已创建(使用图片,带悬停动画)")
|
print("[INFO] 宣传横幅已创建(使用图片,带悬停动画)")
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"[WARNING] 创建宣传横幅失败: {e}")
|
print(f"[WARNING] 创建宣传横幅失败: {e}")
|
||||||
|
|
||||||
# 横幅颜色动画相关方法已移除(改用图片横幅)
|
# 横幅颜色动画相关方法已移除(改用图片横幅)
|
||||||
|
|
||||||
def apply_modern_styles(self):
|
def apply_modern_styles(self):
|
||||||
@@ -617,7 +626,7 @@ class LoginWindow(QMainWindow):
|
|||||||
"""处理平台被踢下线 - 显示弹窗警告"""
|
"""处理平台被踢下线 - 显示弹窗警告"""
|
||||||
try:
|
try:
|
||||||
self.add_log(f"⚠️ {platform_name}平台被踢下线: {store_name}, 原因: {reason}", "WARNING")
|
self.add_log(f"⚠️ {platform_name}平台被踢下线: {store_name}, 原因: {reason}", "WARNING")
|
||||||
|
|
||||||
# 显示弹窗提示
|
# 显示弹窗提示
|
||||||
message_text = (
|
message_text = (
|
||||||
f"【{store_name}】连接已断开\n\n"
|
f"【{store_name}】连接已断开\n\n"
|
||||||
@@ -634,12 +643,12 @@ class LoginWindow(QMainWindow):
|
|||||||
message_text,
|
message_text,
|
||||||
QMessageBox.Ok
|
QMessageBox.Ok
|
||||||
)
|
)
|
||||||
|
|
||||||
# 更新状态显示
|
# 更新状态显示
|
||||||
self.status_label.setText(f"⚠️ {platform_name}已断开")
|
self.status_label.setText(f"⚠️ {platform_name}已断开")
|
||||||
self.status_label.setStyleSheet(
|
self.status_label.setStyleSheet(
|
||||||
"color: #ff6b6b; background: rgba(255, 107, 107, 0.1); border-radius: 12px; padding: 5px 10px;")
|
"color: #ff6b6b; background: rgba(255, 107, 107, 0.1); border-radius: 12px; padding: 5px 10px;")
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.add_log(f"显示平台断开提示失败: {e}", "ERROR")
|
self.add_log(f"显示平台断开提示失败: {e}", "ERROR")
|
||||||
|
|
||||||
@@ -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:
|
||||||
@@ -818,16 +882,16 @@ class LoginWindow(QMainWindow):
|
|||||||
try:
|
try:
|
||||||
# 清空现有菜单
|
# 清空现有菜单
|
||||||
self.tray_menu.clear()
|
self.tray_menu.clear()
|
||||||
|
|
||||||
# 获取WebSocket管理器
|
# 获取WebSocket管理器
|
||||||
ws_manager = get_websocket_manager()
|
ws_manager = get_websocket_manager()
|
||||||
|
|
||||||
# 1. 显示后端连接状态
|
# 1. 显示后端连接状态
|
||||||
if ws_manager and ws_manager.backend_client and ws_manager.backend_client.is_connected:
|
if ws_manager and ws_manager.backend_client and ws_manager.backend_client.is_connected:
|
||||||
backend_status = QAction("✅ 后端已连接", self)
|
backend_status = QAction("✅ 后端已连接", self)
|
||||||
backend_status.setEnabled(False) # 不可点击
|
backend_status.setEnabled(False) # 不可点击
|
||||||
self.tray_menu.addAction(backend_status)
|
self.tray_menu.addAction(backend_status)
|
||||||
|
|
||||||
# 2. 显示已连接的平台信息
|
# 2. 显示已连接的平台信息
|
||||||
platform_listeners = ws_manager.platform_listeners
|
platform_listeners = ws_manager.platform_listeners
|
||||||
if platform_listeners:
|
if platform_listeners:
|
||||||
@@ -837,18 +901,18 @@ class LoginWindow(QMainWindow):
|
|||||||
platform = info.get('platform', '')
|
platform = info.get('platform', '')
|
||||||
store_name = info.get('store_name', '')
|
store_name = info.get('store_name', '')
|
||||||
store_id = info.get('store_id', '')
|
store_id = info.get('store_id', '')
|
||||||
|
|
||||||
if platform not in platform_stores:
|
if platform not in platform_stores:
|
||||||
platform_stores[platform] = []
|
platform_stores[platform] = []
|
||||||
|
|
||||||
# 优先显示店铺名称,如果没有则显示 store_id 前8位
|
# 优先显示店铺名称,如果没有则显示 store_id 前8位
|
||||||
if store_name:
|
if store_name:
|
||||||
display_name = store_name
|
display_name = store_name
|
||||||
else:
|
else:
|
||||||
display_name = store_id[:8] + "..." if len(store_id) > 8 else store_id
|
display_name = store_id[:8] + "..." if len(store_id) > 8 else store_id
|
||||||
|
|
||||||
platform_stores[platform].append(display_name)
|
platform_stores[platform].append(display_name)
|
||||||
|
|
||||||
# 显示每个平台的店铺
|
# 显示每个平台的店铺
|
||||||
for platform, stores in platform_stores.items():
|
for platform, stores in platform_stores.items():
|
||||||
stores_text = ", ".join(stores)
|
stores_text = ", ".join(stores)
|
||||||
@@ -865,23 +929,23 @@ class LoginWindow(QMainWindow):
|
|||||||
backend_disconnected = QAction("❌ 后端未连接", self)
|
backend_disconnected = QAction("❌ 后端未连接", self)
|
||||||
backend_disconnected.setEnabled(False)
|
backend_disconnected.setEnabled(False)
|
||||||
self.tray_menu.addAction(backend_disconnected)
|
self.tray_menu.addAction(backend_disconnected)
|
||||||
|
|
||||||
# 添加分隔线
|
# 添加分隔线
|
||||||
self.tray_menu.addSeparator()
|
self.tray_menu.addSeparator()
|
||||||
|
|
||||||
# 3. 显示主窗口
|
# 3. 显示主窗口
|
||||||
show_action = QAction("显示主窗口", self)
|
show_action = QAction("显示主窗口", self)
|
||||||
show_action.triggered.connect(self.show_window)
|
show_action.triggered.connect(self.show_window)
|
||||||
self.tray_menu.addAction(show_action)
|
self.tray_menu.addAction(show_action)
|
||||||
|
|
||||||
# 添加分隔线
|
# 添加分隔线
|
||||||
self.tray_menu.addSeparator()
|
self.tray_menu.addSeparator()
|
||||||
|
|
||||||
# 4. 退出程序
|
# 4. 退出程序
|
||||||
quit_action = QAction("退出程序", self)
|
quit_action = QAction("退出程序", self)
|
||||||
quit_action.triggered.connect(self.quit_application)
|
quit_action.triggered.connect(self.quit_application)
|
||||||
self.tray_menu.addAction(quit_action)
|
self.tray_menu.addAction(quit_action)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"[ERROR] 更新托盘菜单失败: {e}")
|
print(f"[ERROR] 更新托盘菜单失败: {e}")
|
||||||
# 如果更新失败,至少保证基本功能可用
|
# 如果更新失败,至少保证基本功能可用
|
||||||
@@ -889,7 +953,7 @@ class LoginWindow(QMainWindow):
|
|||||||
show_action = QAction("显示主窗口", self)
|
show_action = QAction("显示主窗口", self)
|
||||||
show_action.triggered.connect(self.show_window)
|
show_action.triggered.connect(self.show_window)
|
||||||
self.tray_menu.addAction(show_action)
|
self.tray_menu.addAction(show_action)
|
||||||
|
|
||||||
quit_action = QAction("退出程序", self)
|
quit_action = QAction("退出程序", self)
|
||||||
quit_action.triggered.connect(self.quit_application)
|
quit_action.triggered.connect(self.quit_application)
|
||||||
self.tray_menu.addAction(quit_action)
|
self.tray_menu.addAction(quit_action)
|
||||||
@@ -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