[patch] 修改逻辑: 在用户误触或开了多个GUI程序的时候不能同时建立多个连接 确保一个账号只能建立一个与后端的连接 友好提示的集成review

This commit is contained in:
2025-10-13 10:27:15 +08:00
parent 7ef6b36ff5
commit f6c55d4185
4 changed files with 231 additions and 139 deletions

View File

@@ -31,6 +31,7 @@ class BackendClient:
self.success_callback: Optional[Callable] = None # 新增:后端连接成功回调
self.token_error_callback: Optional[Callable] = None # 新增token错误回调
self.version_callback: Optional[Callable] = None # 新增:版本检查回调
self.disconnect_callback: Optional[Callable] = None # 新增:被踢下线回调
self.is_connected = False
@@ -265,7 +266,8 @@ class BackendClient:
login: Callable = None,
success: Callable = None,
token_error: Callable = None,
version: Callable = None):
version: Callable = None,
disconnect: Callable = None):
"""设置各种消息类型的回调函数"""
if store_list:
self.store_list_callback = store_list
@@ -287,6 +289,8 @@ class BackendClient:
self.token_error_callback = token_error
if version:
self.version_callback = version
if disconnect:
self.disconnect_callback = disconnect
def on_connected(self):
"""连接成功时的处理"""
@@ -443,6 +447,8 @@ class BackendClient:
self._handle_staff_list(message)
elif msg_type == 'version_response': # 新增:版本检查响应
self._handle_version_response(message)
elif msg_type == 'disconnect': # 新增:被踢下线
self._handle_disconnect(message)
else:
print(f"未知消息类型: {msg_type}")
@@ -1229,6 +1235,19 @@ class BackendClient:
if self.version_callback:
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)
# ==================== 辅助方法 ====================
def set_token(self, token: str):

View File

@@ -54,10 +54,11 @@ class WebSocketManager:
'error': None,
'platform_connected': None,
'token_error': None,
'disconnect': 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:
self.callbacks['log'] = log
@@ -69,6 +70,8 @@ class WebSocketManager:
self.callbacks['platform_connected'] = platform_connected
if token_error:
self.callbacks['token_error'] = token_error
if disconnect:
self.callbacks['disconnect'] = disconnect
def _log(self, message: str, level: str = "INFO"):
"""内部日志方法"""
@@ -146,8 +149,13 @@ class WebSocketManager:
if self.callbacks['token_error']:
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,
token_error=_on_token_error)
token_error=_on_token_error, disconnect=_on_disconnect)
if not backend.is_connected:
backend.connect()
@@ -182,7 +190,13 @@ class WebSocketManager:
if self.callbacks['token_error']:
self.callbacks['token_error'](error_content)
backend.set_callbacks(login=_on_backend_login, success=_on_backend_success, token_error=_on_token_error)
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, disconnect=_on_disconnect)
backend.connect()
set_backend_client(backend)

61
main.py
View File

@@ -25,6 +25,12 @@ class UpdateSignals(QObject):
update_available = pyqtSignal(str, str) # (latest_version, download_url)
# 新增: 断开连接信号类(用于线程安全的断开提示)
class DisconnectSignals(QObject):
"""断开连接信号"""
disconnected = pyqtSignal(str) # (disconnect_message)
# 新增: 用户名密码输入对话框类
class LoginWindow(QMainWindow):
def __init__(self):
@@ -50,6 +56,10 @@ class LoginWindow(QMainWindow):
self.update_signals = UpdateSignals()
self.update_signals.update_available.connect(self._show_update_dialog)
# 创建断开连接信号对象(线程安全)
self.disconnect_signals = DisconnectSignals()
self.disconnect_signals.disconnected.connect(self._show_disconnect_dialog)
self.initUI()
# 延迟设置版本检查器确保WebSocket连接已建立
@@ -437,6 +447,54 @@ class LoginWindow(QMainWindow):
except Exception as e:
self.add_log(f"处理token错误失败: {e}", "ERROR")
def on_disconnect(self, disconnect_msg: str):
"""处理被踢下线 - 发射信号到主线程(可在任何线程中调用)"""
try:
self.add_log(f"📡 收到断开通知,准备发射信号: {disconnect_msg}", "INFO")
# 发射信号Qt 自动调度到主线程)
self.disconnect_signals.disconnected.emit(disconnect_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):
"""显示断开连接提示框(信号槽函数,始终在主线程中执行)"""
try:
self.add_log(f"🎯 主线程收到断开信号: {disconnect_msg}", "INFO")
# 在状态标签显示警告信息
self.status_label.setText(f"⚠️ 账号在其他设备登录")
self.status_label.setStyleSheet(
"color: #ff9800; background: rgba(255, 152, 0, 0.1); border-radius: 12px; padding: 5px 10px; font-weight: bold;")
# 重置按钮状态
self.login_btn.setEnabled(True)
self.login_btn.setText("重新连接")
self.login_btn.setObjectName("loginButton") # 恢复原始样式
self.login_btn.setStyleSheet(self.login_btn.styleSheet()) # 刷新样式
# 清空已连接平台列表
self.connected_platforms.clear()
# 显示友好的提示对话框(主线程中执行,不会卡顿)
QMessageBox.warning(
self,
"连接已断开",
f"{disconnect_msg}\n\n"
"如果是您本人在其他设备登录,可以忽略此提示。\n"
"如需继续使用,请点击\"重新连接\"按钮。",
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):
"""定时器触发的汇总显示更新"""
try:
@@ -651,7 +709,8 @@ class LoginWindow(QMainWindow):
success=lambda: self.add_log("WebSocket连接管理器连接成功", "SUCCESS"),
error=lambda error: self.add_log(f"WebSocket连接管理器错误: {error}", "ERROR"),
platform_connected=self.on_platform_connected, # 新增:平台连接回调
token_error=self.on_token_error # 新增token错误回调
token_error=self.on_token_error, # 新增token错误回调
disconnect=self.on_disconnect # 新增:被踢下线回调
)
# 连接后端