[patch] 修改逻辑: 在用户误触或开了多个GUI程序的时候不能同时建立多个连接 确保一个账号只能建立一个与后端的连接
This commit is contained in:
@@ -31,6 +31,7 @@ class BackendClient:
|
|||||||
self.success_callback: Optional[Callable] = None # 新增:后端连接成功回调
|
self.success_callback: Optional[Callable] = None # 新增:后端连接成功回调
|
||||||
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.is_connected = False
|
self.is_connected = False
|
||||||
|
|
||||||
@@ -265,7 +266,8 @@ class BackendClient:
|
|||||||
login: Callable = None,
|
login: Callable = None,
|
||||||
success: Callable = None,
|
success: Callable = None,
|
||||||
token_error: Callable = None,
|
token_error: Callable = None,
|
||||||
version: Callable = None):
|
version: Callable = None,
|
||||||
|
disconnect: Callable = None):
|
||||||
"""设置各种消息类型的回调函数"""
|
"""设置各种消息类型的回调函数"""
|
||||||
if store_list:
|
if store_list:
|
||||||
self.store_list_callback = store_list
|
self.store_list_callback = store_list
|
||||||
@@ -287,6 +289,8 @@ class BackendClient:
|
|||||||
self.token_error_callback = token_error
|
self.token_error_callback = token_error
|
||||||
if version:
|
if version:
|
||||||
self.version_callback = version
|
self.version_callback = version
|
||||||
|
if disconnect:
|
||||||
|
self.disconnect_callback = disconnect
|
||||||
|
|
||||||
def on_connected(self):
|
def on_connected(self):
|
||||||
"""连接成功时的处理"""
|
"""连接成功时的处理"""
|
||||||
@@ -443,6 +447,8 @@ class BackendClient:
|
|||||||
self._handle_staff_list(message)
|
self._handle_staff_list(message)
|
||||||
elif msg_type == 'version_response': # 新增:版本检查响应
|
elif msg_type == 'version_response': # 新增:版本检查响应
|
||||||
self._handle_version_response(message)
|
self._handle_version_response(message)
|
||||||
|
elif msg_type == 'disconnect': # 新增:被踢下线
|
||||||
|
self._handle_disconnect(message)
|
||||||
else:
|
else:
|
||||||
print(f"未知消息类型: {msg_type}")
|
print(f"未知消息类型: {msg_type}")
|
||||||
|
|
||||||
@@ -1228,6 +1234,19 @@ class BackendClient:
|
|||||||
|
|
||||||
if self.version_callback:
|
if self.version_callback:
|
||||||
self.version_callback(message)
|
self.version_callback(message)
|
||||||
|
|
||||||
|
def _handle_disconnect(self, message: Dict[str, Any]):
|
||||||
|
"""处理被踢下线消息"""
|
||||||
|
disconnect_message = message.get('message', '您的账号在其他设备登录,当前连接已断开')
|
||||||
|
|
||||||
|
print(f"[断开] 收到后端断开通知: {disconnect_message}")
|
||||||
|
|
||||||
|
# 停止重连机制(不再尝试重连)
|
||||||
|
self.should_stop = True
|
||||||
|
|
||||||
|
# 触发断开回调
|
||||||
|
if self.disconnect_callback:
|
||||||
|
self.disconnect_callback(disconnect_message)
|
||||||
|
|
||||||
# ==================== 辅助方法 ====================
|
# ==================== 辅助方法 ====================
|
||||||
|
|
||||||
|
|||||||
@@ -54,10 +54,11 @@ class WebSocketManager:
|
|||||||
'error': None,
|
'error': None,
|
||||||
'platform_connected': None,
|
'platform_connected': None,
|
||||||
'token_error': None,
|
'token_error': None,
|
||||||
|
'disconnect': None, # 新增:被踢下线回调
|
||||||
}
|
}
|
||||||
|
|
||||||
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, token_error: Callable = None):
|
platform_connected: Callable = None, token_error: Callable = None, disconnect: Callable = None):
|
||||||
"""设置回调函数"""
|
"""设置回调函数"""
|
||||||
if log:
|
if log:
|
||||||
self.callbacks['log'] = log
|
self.callbacks['log'] = log
|
||||||
@@ -69,6 +70,8 @@ class WebSocketManager:
|
|||||||
self.callbacks['platform_connected'] = platform_connected
|
self.callbacks['platform_connected'] = platform_connected
|
||||||
if token_error:
|
if token_error:
|
||||||
self.callbacks['token_error'] = token_error
|
self.callbacks['token_error'] = token_error
|
||||||
|
if disconnect:
|
||||||
|
self.callbacks['disconnect'] = disconnect
|
||||||
|
|
||||||
def _log(self, message: str, level: str = "INFO"):
|
def _log(self, message: str, level: str = "INFO"):
|
||||||
"""内部日志方法"""
|
"""内部日志方法"""
|
||||||
@@ -145,9 +148,14 @@ class WebSocketManager:
|
|||||||
self._log(f"Token验证失败: {error_content}", "ERROR")
|
self._log(f"Token验证失败: {error_content}", "ERROR")
|
||||||
if self.callbacks['token_error']:
|
if self.callbacks['token_error']:
|
||||||
self.callbacks['token_error'](error_content)
|
self.callbacks['token_error'](error_content)
|
||||||
|
|
||||||
|
def _on_disconnect(disconnect_msg: str):
|
||||||
|
self._log(f"被踢下线: {disconnect_msg}", "WARNING")
|
||||||
|
if self.callbacks['disconnect']:
|
||||||
|
self.callbacks['disconnect'](disconnect_msg)
|
||||||
|
|
||||||
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)
|
token_error=_on_token_error, disconnect=_on_disconnect)
|
||||||
|
|
||||||
if not backend.is_connected:
|
if not backend.is_connected:
|
||||||
backend.connect()
|
backend.connect()
|
||||||
@@ -181,8 +189,14 @@ class WebSocketManager:
|
|||||||
self._log(f"Token验证失败: {error_content}", "ERROR")
|
self._log(f"Token验证失败: {error_content}", "ERROR")
|
||||||
if self.callbacks['token_error']:
|
if self.callbacks['token_error']:
|
||||||
self.callbacks['token_error'](error_content)
|
self.callbacks['token_error'](error_content)
|
||||||
|
|
||||||
|
def _on_disconnect(disconnect_msg: str):
|
||||||
|
self._log(f"被踢下线: {disconnect_msg}", "ERROR")
|
||||||
|
if self.callbacks['disconnect']:
|
||||||
|
self.callbacks['disconnect'](disconnect_msg)
|
||||||
|
|
||||||
backend.set_callbacks(login=_on_backend_login, success=_on_backend_success, token_error=_on_token_error)
|
backend.set_callbacks(login=_on_backend_login, success=_on_backend_success,
|
||||||
|
token_error=_on_token_error, disconnect=_on_disconnect)
|
||||||
backend.connect()
|
backend.connect()
|
||||||
|
|
||||||
set_backend_client(backend)
|
set_backend_client(backend)
|
||||||
|
|||||||
85
main.py
85
main.py
@@ -25,6 +25,12 @@ class UpdateSignals(QObject):
|
|||||||
update_available = pyqtSignal(str, str) # (latest_version, download_url)
|
update_available = pyqtSignal(str, str) # (latest_version, download_url)
|
||||||
|
|
||||||
|
|
||||||
|
# 新增: 断开连接信号类(用于线程安全的通知)
|
||||||
|
class DisconnectSignals(QObject):
|
||||||
|
"""断开连接信号"""
|
||||||
|
account_disconnected = pyqtSignal(str) # (disconnect_message)
|
||||||
|
|
||||||
|
|
||||||
# 新增: 用户名密码输入对话框类
|
# 新增: 用户名密码输入对话框类
|
||||||
class LoginWindow(QMainWindow):
|
class LoginWindow(QMainWindow):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
@@ -49,6 +55,10 @@ class LoginWindow(QMainWindow):
|
|||||||
# 创建版本更新信号对象(线程安全)
|
# 创建版本更新信号对象(线程安全)
|
||||||
self.update_signals = UpdateSignals()
|
self.update_signals = UpdateSignals()
|
||||||
self.update_signals.update_available.connect(self._show_update_dialog)
|
self.update_signals.update_available.connect(self._show_update_dialog)
|
||||||
|
|
||||||
|
# 创建断开连接信号对象(线程安全)
|
||||||
|
self.disconnect_signals = DisconnectSignals()
|
||||||
|
self.disconnect_signals.account_disconnected.connect(self._show_disconnect_dialog)
|
||||||
|
|
||||||
self.initUI()
|
self.initUI()
|
||||||
|
|
||||||
@@ -436,6 +446,78 @@ class LoginWindow(QMainWindow):
|
|||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.add_log(f"处理token错误失败: {e}", "ERROR")
|
self.add_log(f"处理token错误失败: {e}", "ERROR")
|
||||||
|
|
||||||
|
def on_disconnect(self, disconnect_msg: str):
|
||||||
|
"""处理被踢下线通知(可能在子线程中调用)"""
|
||||||
|
try:
|
||||||
|
self.add_log(f"⚠️ 收到断开通知: {disconnect_msg}", "WARNING")
|
||||||
|
# 通过信号发射到主线程(线程安全)
|
||||||
|
self.disconnect_signals.account_disconnected.emit(disconnect_msg)
|
||||||
|
except Exception as e:
|
||||||
|
self.add_log(f"❌ 处理断开通知失败: {e}", "ERROR")
|
||||||
|
|
||||||
|
def _show_disconnect_dialog(self, disconnect_msg: str):
|
||||||
|
"""显示断开连接对话框(信号槽函数,在主线程中执行)"""
|
||||||
|
try:
|
||||||
|
self.add_log(f"⚠️ 显示断开连接对话框: {disconnect_msg}", "WARNING")
|
||||||
|
|
||||||
|
# 显示警告对话框
|
||||||
|
QMessageBox.warning(
|
||||||
|
self,
|
||||||
|
"连接已断开",
|
||||||
|
f"{disconnect_msg}\n\n请确保用户只在一台设备登录。",
|
||||||
|
QMessageBox.Ok
|
||||||
|
)
|
||||||
|
|
||||||
|
# 断开所有连接
|
||||||
|
self._disconnect_all_connections()
|
||||||
|
|
||||||
|
# 重置 UI 状态(返回登录界面)
|
||||||
|
self._reset_to_login_state()
|
||||||
|
|
||||||
|
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 _disconnect_all_connections(self):
|
||||||
|
"""断开所有连接"""
|
||||||
|
try:
|
||||||
|
self.add_log("🔌 正在断开所有连接...", "INFO")
|
||||||
|
|
||||||
|
# 使用 WebSocket 管理器断开所有连接
|
||||||
|
from WebSocket.backend_singleton import get_websocket_manager
|
||||||
|
ws_manager = get_websocket_manager()
|
||||||
|
ws_manager.disconnect_all()
|
||||||
|
|
||||||
|
self.add_log("✅ 所有连接已断开", "SUCCESS")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
self.add_log(f"❌ 断开连接失败: {e}", "ERROR")
|
||||||
|
|
||||||
|
def _reset_to_login_state(self):
|
||||||
|
"""重置到登录状态"""
|
||||||
|
try:
|
||||||
|
# 清空已连接平台列表
|
||||||
|
self.connected_platforms.clear()
|
||||||
|
|
||||||
|
# 重置状态标签
|
||||||
|
self.status_label.setText("等待连接...")
|
||||||
|
self.status_label.setStyleSheet(
|
||||||
|
"color: #95a5a6; margin-top: 5px;")
|
||||||
|
|
||||||
|
# 重置按钮状态
|
||||||
|
self.login_btn.setEnabled(True)
|
||||||
|
self.login_btn.setText("重新连接")
|
||||||
|
self.login_btn.setObjectName("loginButton") # 恢复原始样式
|
||||||
|
self.login_btn.setStyleSheet(self.login_btn.styleSheet()) # 刷新样式
|
||||||
|
|
||||||
|
self.add_log("✅ UI 已重置到登录状态", "DEBUG")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
self.add_log(f"❌ 重置 UI 状态失败: {e}", "ERROR")
|
||||||
|
|
||||||
def delayed_platform_summary(self):
|
def delayed_platform_summary(self):
|
||||||
"""定时器触发的汇总显示更新"""
|
"""定时器触发的汇总显示更新"""
|
||||||
@@ -651,7 +733,8 @@ class LoginWindow(QMainWindow):
|
|||||||
success=lambda: self.add_log("WebSocket连接管理器连接成功", "SUCCESS"),
|
success=lambda: self.add_log("WebSocket连接管理器连接成功", "SUCCESS"),
|
||||||
error=lambda error: self.add_log(f"WebSocket连接管理器错误: {error}", "ERROR"),
|
error=lambda error: self.add_log(f"WebSocket连接管理器错误: {error}", "ERROR"),
|
||||||
platform_connected=self.on_platform_connected, # 新增:平台连接回调
|
platform_connected=self.on_platform_connected, # 新增:平台连接回调
|
||||||
token_error=self.on_token_error # 新增:token错误回调
|
token_error=self.on_token_error, # 新增:token错误回调
|
||||||
|
disconnect=self.on_disconnect # 新增:被踢下线回调
|
||||||
)
|
)
|
||||||
|
|
||||||
# 连接后端
|
# 连接后端
|
||||||
|
|||||||
Reference in New Issue
Block a user