[patch] 新增用户余额不足 交互模式代码
This commit is contained in:
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
|
||||
import os
|
||||
|
||||
|
||||
# ===================== 文件日志系统 - 生产环境启用 =====================
|
||||
# 重定向所有输出到文件,确保有日志记录
|
||||
from exe_file_logger import setup_file_logging, log_to_file # 开发环境启用
|
||||
@@ -33,6 +32,12 @@ class DisconnectSignals(QObject):
|
||||
disconnected = pyqtSignal(str) # (disconnect_message)
|
||||
|
||||
|
||||
# 新增: 余额不足信号类(用于线程安全的余额不足提示)
|
||||
class BalanceInsufficientSignals(QObject):
|
||||
"""余额不足信号"""
|
||||
balance_insufficient = pyqtSignal(str) # (balance_message)
|
||||
|
||||
|
||||
# 新增: 用户名密码输入对话框类
|
||||
class LoginWindow(QMainWindow):
|
||||
def __init__(self):
|
||||
@@ -62,6 +67,10 @@ class LoginWindow(QMainWindow):
|
||||
self.disconnect_signals = DisconnectSignals()
|
||||
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.banner_shadow = None # 阴影效果引用
|
||||
@@ -170,7 +179,7 @@ class LoginWindow(QMainWindow):
|
||||
|
||||
# 系统初始化日志输出到终端
|
||||
print("[INFO] 系统初始化完成")
|
||||
|
||||
|
||||
# 让窗口自适应内容高度(最小化)
|
||||
self.adjustSize()
|
||||
print("[INFO] 窗口已自适应内容大小")
|
||||
@@ -182,41 +191,41 @@ class LoginWindow(QMainWindow):
|
||||
banner_frame = QFrame()
|
||||
banner_frame.setObjectName("promoBanner")
|
||||
banner_frame.setCursor(Qt.PointingHandCursor) # 鼠标变手型
|
||||
|
||||
|
||||
# 保存横幅引用,用于动画
|
||||
self.promo_banner = banner_frame
|
||||
|
||||
|
||||
# 使用图片标签
|
||||
banner_image = QLabel()
|
||||
banner_image.setObjectName("bannerImage")
|
||||
|
||||
|
||||
# 加载横幅图片
|
||||
from windows_taskbar_fix import get_resource_path
|
||||
image_path = get_resource_path("static/hengfu.jpg")
|
||||
|
||||
|
||||
if os.path.exists(image_path):
|
||||
from PyQt5.QtGui import QPixmap
|
||||
pixmap = QPixmap(image_path)
|
||||
|
||||
|
||||
# 设置固定的横幅尺寸
|
||||
target_width = 400 # 固定宽度
|
||||
target_height = 70 # 固定高度(调整为70px,更紧凑)
|
||||
|
||||
|
||||
# 缩放图片以适应目标尺寸
|
||||
scaled_pixmap = pixmap.scaled(
|
||||
target_width,
|
||||
target_width,
|
||||
target_height,
|
||||
Qt.IgnoreAspectRatio, # 忽略宽高比,拉伸填充
|
||||
Qt.SmoothTransformation # 平滑缩放,提高图片质量
|
||||
)
|
||||
|
||||
|
||||
# 设置图片
|
||||
banner_image.setPixmap(scaled_pixmap)
|
||||
banner_image.setScaledContents(False)
|
||||
|
||||
|
||||
banner_frame.setFixedHeight(target_height)
|
||||
banner_image.setFixedSize(target_width, target_height)
|
||||
|
||||
|
||||
# 🔧 使用CSS圆角来处理边角(更简单稳定)
|
||||
banner_image.setStyleSheet("""
|
||||
QLabel#bannerImage {
|
||||
@@ -224,7 +233,7 @@ class LoginWindow(QMainWindow):
|
||||
background-color: transparent;
|
||||
}
|
||||
""")
|
||||
|
||||
|
||||
print(f"[INFO] 横幅图片已加载: {image_path}, 尺寸: {target_width}x{target_height}")
|
||||
else:
|
||||
# 图片不存在时的备用方案
|
||||
@@ -241,14 +250,14 @@ class LoginWindow(QMainWindow):
|
||||
""")
|
||||
banner_frame.setFixedHeight(60)
|
||||
print(f"[WARNING] 横幅图片未找到: {image_path},使用备用样式")
|
||||
|
||||
|
||||
# 创建布局
|
||||
banner_layout = QHBoxLayout()
|
||||
banner_layout.setContentsMargins(0, 0, 0, 0)
|
||||
banner_layout.setSpacing(0)
|
||||
banner_frame.setLayout(banner_layout)
|
||||
banner_layout.addWidget(banner_image)
|
||||
|
||||
|
||||
# 设置圆角和边框
|
||||
banner_frame.setStyleSheet("""
|
||||
QFrame#promoBanner {
|
||||
@@ -256,7 +265,7 @@ class LoginWindow(QMainWindow):
|
||||
background: transparent;
|
||||
}
|
||||
""")
|
||||
|
||||
|
||||
# 初始阴影效果
|
||||
self.banner_shadow = QGraphicsDropShadowEffect()
|
||||
self.banner_shadow.setBlurRadius(15)
|
||||
@@ -264,7 +273,7 @@ class LoginWindow(QMainWindow):
|
||||
self.banner_shadow.setYOffset(3)
|
||||
self.banner_shadow.setColor(QColor(0, 0, 0, 60))
|
||||
banner_frame.setGraphicsEffect(self.banner_shadow)
|
||||
|
||||
|
||||
# 点击事件 - 跳转官网
|
||||
def open_official_website():
|
||||
try:
|
||||
@@ -274,9 +283,9 @@ class LoginWindow(QMainWindow):
|
||||
self.add_log(f"已打开官网: {official_url}", "INFO")
|
||||
except Exception as e:
|
||||
self.add_log(f"打开官网失败: {e}", "ERROR")
|
||||
|
||||
|
||||
banner_frame.mousePressEvent = lambda event: open_official_website()
|
||||
|
||||
|
||||
# 🎯 添加鼠标悬停事件(动态效果)
|
||||
def on_enter(event):
|
||||
"""鼠标进入时的动画效果"""
|
||||
@@ -285,30 +294,30 @@ class LoginWindow(QMainWindow):
|
||||
self.banner_shadow.setBlurRadius(25)
|
||||
self.banner_shadow.setYOffset(5)
|
||||
self.banner_shadow.setColor(QColor(0, 0, 0, 100))
|
||||
|
||||
|
||||
# 轻微放大动画
|
||||
animation = QPropertyAnimation(banner_frame, b"geometry")
|
||||
original_rect = banner_frame.geometry()
|
||||
|
||||
|
||||
expanded_rect = QRect(
|
||||
original_rect.x() - 3,
|
||||
original_rect.y() - 2,
|
||||
original_rect.width() + 6,
|
||||
original_rect.height() + 4
|
||||
)
|
||||
|
||||
|
||||
animation.setDuration(200)
|
||||
animation.setStartValue(original_rect)
|
||||
animation.setEndValue(expanded_rect)
|
||||
animation.setEasingCurve(QEasingCurve.OutCubic)
|
||||
animation.start()
|
||||
|
||||
|
||||
# 保存动画引用避免被垃圾回收
|
||||
banner_frame.hover_animation = animation
|
||||
|
||||
|
||||
except Exception as e:
|
||||
print(f"[DEBUG] 悬停动画错误: {e}")
|
||||
|
||||
|
||||
def on_leave(event):
|
||||
"""鼠标离开时的动画效果"""
|
||||
try:
|
||||
@@ -316,42 +325,42 @@ class LoginWindow(QMainWindow):
|
||||
self.banner_shadow.setBlurRadius(15)
|
||||
self.banner_shadow.setYOffset(3)
|
||||
self.banner_shadow.setColor(QColor(0, 0, 0, 60))
|
||||
|
||||
|
||||
# 恢复原始大小
|
||||
animation = QPropertyAnimation(banner_frame, b"geometry")
|
||||
current_rect = banner_frame.geometry()
|
||||
|
||||
|
||||
original_rect = QRect(
|
||||
current_rect.x() + 3,
|
||||
current_rect.y() + 2,
|
||||
current_rect.width() - 6,
|
||||
current_rect.height() - 4
|
||||
)
|
||||
|
||||
|
||||
animation.setDuration(200)
|
||||
animation.setStartValue(current_rect)
|
||||
animation.setEndValue(original_rect)
|
||||
animation.setEasingCurve(QEasingCurve.InCubic)
|
||||
animation.start()
|
||||
|
||||
|
||||
# 保存动画引用避免被垃圾回收
|
||||
banner_frame.leave_animation = animation
|
||||
|
||||
|
||||
except Exception as e:
|
||||
print(f"[DEBUG] 离开动画错误: {e}")
|
||||
|
||||
|
||||
# 安装事件过滤器
|
||||
banner_frame.enterEvent = on_enter
|
||||
banner_frame.leaveEvent = on_leave
|
||||
|
||||
|
||||
# 添加到主布局
|
||||
layout.addWidget(banner_frame)
|
||||
|
||||
|
||||
print("[INFO] 宣传横幅已创建(使用图片,带悬停动画)")
|
||||
|
||||
|
||||
except Exception as e:
|
||||
print(f"[WARNING] 创建宣传横幅失败: {e}")
|
||||
|
||||
|
||||
# 横幅颜色动画相关方法已移除(改用图片横幅)
|
||||
|
||||
def apply_modern_styles(self):
|
||||
@@ -617,7 +626,7 @@ class LoginWindow(QMainWindow):
|
||||
"""处理平台被踢下线 - 显示弹窗警告"""
|
||||
try:
|
||||
self.add_log(f"⚠️ {platform_name}平台被踢下线: {store_name}, 原因: {reason}", "WARNING")
|
||||
|
||||
|
||||
# 显示弹窗提示
|
||||
message_text = (
|
||||
f"【{store_name}】连接已断开\n\n"
|
||||
@@ -634,12 +643,12 @@ class LoginWindow(QMainWindow):
|
||||
message_text,
|
||||
QMessageBox.Ok
|
||||
)
|
||||
|
||||
|
||||
# 更新状态显示
|
||||
self.status_label.setText(f"⚠️ {platform_name}已断开")
|
||||
self.status_label.setStyleSheet(
|
||||
"color: #ff6b6b; background: rgba(255, 107, 107, 0.1); border-radius: 12px; padding: 5px 10px;")
|
||||
|
||||
|
||||
except Exception as e:
|
||||
self.add_log(f"显示平台断开提示失败: {e}", "ERROR")
|
||||
|
||||
@@ -678,6 +687,18 @@ class LoginWindow(QMainWindow):
|
||||
import traceback
|
||||
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):
|
||||
"""显示断开连接提示框(信号槽函数,始终在主线程中执行)"""
|
||||
try:
|
||||
@@ -714,6 +735,49 @@ class LoginWindow(QMainWindow):
|
||||
import traceback
|
||||
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):
|
||||
"""定时器触发的汇总显示更新"""
|
||||
try:
|
||||
@@ -818,16 +882,16 @@ class LoginWindow(QMainWindow):
|
||||
try:
|
||||
# 清空现有菜单
|
||||
self.tray_menu.clear()
|
||||
|
||||
|
||||
# 获取WebSocket管理器
|
||||
ws_manager = get_websocket_manager()
|
||||
|
||||
|
||||
# 1. 显示后端连接状态
|
||||
if ws_manager and ws_manager.backend_client and ws_manager.backend_client.is_connected:
|
||||
backend_status = QAction("✅ 后端已连接", self)
|
||||
backend_status.setEnabled(False) # 不可点击
|
||||
self.tray_menu.addAction(backend_status)
|
||||
|
||||
|
||||
# 2. 显示已连接的平台信息
|
||||
platform_listeners = ws_manager.platform_listeners
|
||||
if platform_listeners:
|
||||
@@ -837,18 +901,18 @@ class LoginWindow(QMainWindow):
|
||||
platform = info.get('platform', '')
|
||||
store_name = info.get('store_name', '')
|
||||
store_id = info.get('store_id', '')
|
||||
|
||||
|
||||
if platform not in platform_stores:
|
||||
platform_stores[platform] = []
|
||||
|
||||
|
||||
# 优先显示店铺名称,如果没有则显示 store_id 前8位
|
||||
if store_name:
|
||||
display_name = store_name
|
||||
else:
|
||||
display_name = store_id[:8] + "..." if len(store_id) > 8 else store_id
|
||||
|
||||
|
||||
platform_stores[platform].append(display_name)
|
||||
|
||||
|
||||
# 显示每个平台的店铺
|
||||
for platform, stores in platform_stores.items():
|
||||
stores_text = ", ".join(stores)
|
||||
@@ -865,23 +929,23 @@ class LoginWindow(QMainWindow):
|
||||
backend_disconnected = QAction("❌ 后端未连接", self)
|
||||
backend_disconnected.setEnabled(False)
|
||||
self.tray_menu.addAction(backend_disconnected)
|
||||
|
||||
|
||||
# 添加分隔线
|
||||
self.tray_menu.addSeparator()
|
||||
|
||||
|
||||
# 3. 显示主窗口
|
||||
show_action = QAction("显示主窗口", self)
|
||||
show_action.triggered.connect(self.show_window)
|
||||
self.tray_menu.addAction(show_action)
|
||||
|
||||
|
||||
# 添加分隔线
|
||||
self.tray_menu.addSeparator()
|
||||
|
||||
|
||||
# 4. 退出程序
|
||||
quit_action = QAction("退出程序", self)
|
||||
quit_action.triggered.connect(self.quit_application)
|
||||
self.tray_menu.addAction(quit_action)
|
||||
|
||||
|
||||
except Exception as e:
|
||||
print(f"[ERROR] 更新托盘菜单失败: {e}")
|
||||
# 如果更新失败,至少保证基本功能可用
|
||||
@@ -889,7 +953,7 @@ class LoginWindow(QMainWindow):
|
||||
show_action = QAction("显示主窗口", self)
|
||||
show_action.triggered.connect(self.show_window)
|
||||
self.tray_menu.addAction(show_action)
|
||||
|
||||
|
||||
quit_action = QAction("退出程序", self)
|
||||
quit_action.triggered.connect(self.quit_application)
|
||||
self.tray_menu.addAction(quit_action)
|
||||
@@ -1004,7 +1068,8 @@ class LoginWindow(QMainWindow):
|
||||
platform_connected=self.on_platform_connected, # 新增:平台连接回调
|
||||
platform_disconnected=self.on_platform_kicked, # 新增:平台被踢回调
|
||||
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