[patch] 修改GUI页面布局以自适应横幅位置 与 横幅跳转功能实现

This commit is contained in:
2025-10-13 17:07:22 +08:00
parent 5e9e87bbba
commit 177eddc695
2 changed files with 198 additions and 32 deletions

211
main.py
View File

@@ -62,6 +62,11 @@ 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.promo_banner = None
self.banner_animation = None
self.banner_color_index = 0
self.initUI() self.initUI()
# 延迟设置版本检查器确保WebSocket连接已建立 # 延迟设置版本检查器确保WebSocket连接已建立
@@ -70,9 +75,9 @@ class LoginWindow(QMainWindow):
def initUI(self): def initUI(self):
# 设置窗口基本属性 # 设置窗口基本属性
self.setWindowTitle(f'AI客服智能助手 v{config.APP_VERSION}') self.setWindowTitle(f'AI客服智能助手 v{config.APP_VERSION}')
self.setGeometry(300, 300, 450, 300) # 进一步减小窗口尺寸 # 只设置宽度,高度自适应内容
self.setMinimumSize(420, 280) # 设置更小的最小尺寸 self.setFixedWidth(450) # 固定宽度
self.setMaximumSize(500, 350) # 设置最大尺寸,保持紧凑 # 设置固定高度,让窗口根据内容自适应
# 窗口图标将由统一的任务栏修复模块设置,这里只做备用检查 # 窗口图标将由统一的任务栏修复模块设置,这里只做备用检查
print("[INFO] 窗口图标将由统一模块设置") print("[INFO] 窗口图标将由统一模块设置")
@@ -81,34 +86,31 @@ class LoginWindow(QMainWindow):
central_widget = QWidget() central_widget = QWidget()
self.setCentralWidget(central_widget) self.setCentralWidget(central_widget)
# 创建主布局 # 创建主布局(最小化间距)
main_layout = QVBoxLayout() main_layout = QVBoxLayout()
main_layout.setSpacing(15) # 小间距 main_layout.setSpacing(8) # 小间距
main_layout.setContentsMargins(30, 20, 30, 20) # 小边距 main_layout.setContentsMargins(25, 12, 25, 12) # 小边距
central_widget.setLayout(main_layout) central_widget.setLayout(main_layout)
# 添加标题和副标题 # 添加标题和副标题
title_label = QLabel('AI客服智能助手') title_label = QLabel('AI客服智能助手')
title_label.setObjectName("title") title_label.setObjectName("title")
title_label.setAlignment(Qt.AlignCenter) title_label.setAlignment(Qt.AlignCenter)
title_label.setFont(QFont('Microsoft YaHei', 18, QFont.Bold)) # 减小字体 title_label.setFont(QFont('Microsoft YaHei', 16, QFont.Bold)) # 稍微减小字体
title_label.setStyleSheet("color: #2c3e50; margin-bottom: 3px;") title_label.setStyleSheet("color: #2c3e50; margin-bottom: 2px;")
main_layout.addWidget(title_label) main_layout.addWidget(title_label)
# 添加副标题说明 # 添加副标题说明
subtitle_label = QLabel('智能连接多平台客服提供AI自动回复服务') subtitle_label = QLabel('智能连接多平台客服提供AI自动回复服务')
subtitle_label.setObjectName("subtitle") subtitle_label.setObjectName("subtitle")
subtitle_label.setAlignment(Qt.AlignCenter) subtitle_label.setAlignment(Qt.AlignCenter)
subtitle_label.setFont(QFont('Microsoft YaHei', 9)) # 减小字体 subtitle_label.setFont(QFont('Microsoft YaHei', 9))
subtitle_label.setStyleSheet("color: #7f8c8d; margin-bottom: 10px;") subtitle_label.setStyleSheet("color: #7f8c8d; margin-bottom: 5px;")
main_layout.addWidget(subtitle_label) main_layout.addWidget(subtitle_label)
# 添加少量垂直空间 # 创建令牌输入区域(移除额外间距)
main_layout.addStretch(1)
# 创建令牌输入区域
token_layout = QVBoxLayout() token_layout = QVBoxLayout()
token_layout.setSpacing(8) # 小间距 token_layout.setSpacing(6) # 小间距
token_label = QLabel('访问令牌') token_label = QLabel('访问令牌')
token_label.setFont(QFont('Microsoft YaHei', 11, QFont.Bold)) # 减小字体 token_label.setFont(QFont('Microsoft YaHei', 11, QFont.Bold)) # 减小字体
@@ -117,10 +119,10 @@ class LoginWindow(QMainWindow):
self.token_input = QLineEdit() self.token_input = QLineEdit()
self.token_input.setPlaceholderText('请输入您的访问令牌以连接服务') self.token_input.setPlaceholderText('请输入您的访问令牌以连接服务')
self.token_input.setEchoMode(QLineEdit.Password) self.token_input.setEchoMode(QLineEdit.Password)
self.token_input.setFont(QFont('Microsoft YaHei', 10)) # 减小字体 self.token_input.setFont(QFont('Microsoft YaHei', 10))
# noinspection PyUnresolvedReferences # noinspection PyUnresolvedReferences
self.token_input.returnPressed.connect(self.login) # 表示回车提交 self.token_input.returnPressed.connect(self.login) # 表示回车提交
self.token_input.setMinimumHeight(38) # 小输入框高度 self.token_input.setMinimumHeight(34) # 小输入框高度
# 预填已保存的令牌(如果存在) # 预填已保存的令牌(如果存在)
try: try:
from config import get_saved_token from config import get_saved_token
@@ -136,8 +138,8 @@ class LoginWindow(QMainWindow):
# 创建连接按钮 # 创建连接按钮
self.login_btn = QPushButton('连接服务') self.login_btn = QPushButton('连接服务')
self.login_btn.setFont(QFont('Microsoft YaHei', 11, QFont.Bold)) # 减小字体 self.login_btn.setFont(QFont('Microsoft YaHei', 11, QFont.Bold))
self.login_btn.setMinimumHeight(40) # 小按钮高度 self.login_btn.setMinimumHeight(36) # 小按钮高度
self.login_btn.clicked.connect(self.login) # 表示点击提交 self.login_btn.clicked.connect(self.login) # 表示点击提交
main_layout.addWidget(self.login_btn) main_layout.addWidget(self.login_btn)
@@ -145,12 +147,15 @@ class LoginWindow(QMainWindow):
self.status_label = QLabel('等待连接...') self.status_label = QLabel('等待连接...')
self.status_label.setObjectName("status") self.status_label.setObjectName("status")
self.status_label.setAlignment(Qt.AlignCenter) self.status_label.setAlignment(Qt.AlignCenter)
self.status_label.setFont(QFont('Microsoft YaHei', 9)) # 减小字体 self.status_label.setFont(QFont('Microsoft YaHei', 9))
self.status_label.setStyleSheet("color: #95a5a6; margin-top: 5px;") self.status_label.setStyleSheet("color: #95a5a6; margin-top: 2px;")
main_layout.addWidget(self.status_label) main_layout.addWidget(self.status_label)
# 添加少量底部空间 # 添加最小间距(为横幅留出位置)
main_layout.addStretch(1) main_layout.addSpacing(8)
# ============ 添加宣传横幅 ============
self.create_promo_banner(main_layout)
# 日志框已永久删除,只使用终端输出 # 日志框已永久删除,只使用终端输出
self.log_display = None self.log_display = None
@@ -167,6 +172,161 @@ class LoginWindow(QMainWindow):
# 系统初始化日志输出到终端 # 系统初始化日志输出到终端
print("[INFO] 系统初始化完成") print("[INFO] 系统初始化完成")
# 让窗口自适应内容高度(最小化)
self.adjustSize()
print("[INFO] 窗口已自适应内容大小")
def create_promo_banner(self, layout):
"""创建宣传横幅(带动态渐变效果)"""
try:
# 创建横幅容器(最小化高度)
banner_frame = QFrame()
banner_frame.setObjectName("promoBanner")
banner_frame.setCursor(Qt.PointingHandCursor) # 鼠标变手型
banner_frame.setMinimumHeight(65) # 最小高度
banner_frame.setMaximumHeight(65) # 固定高度
# 保存横幅引用,用于动画
self.promo_banner = banner_frame
# 横幅布局(最小内边距)
banner_layout = QHBoxLayout()
banner_layout.setContentsMargins(10, 6, 10, 6) # 最小内边距
banner_layout.setSpacing(8) # 最小间距
banner_frame.setLayout(banner_layout)
# 左侧图标(最小化)
icon_label = QLabel("🎁")
icon_label.setFont(QFont('Microsoft YaHei', 22)) # 更小的图标字体
icon_label.setAlignment(Qt.AlignCenter)
icon_label.setFixedSize(45, 45) # 更小的图标尺寸
banner_layout.addWidget(icon_label)
# 右侧文字区域
text_layout = QVBoxLayout()
text_layout.setSpacing(1) # 最小文字间距
# 标题
title_label = QLabel("🌟 限时优惠活动进行中")
title_label.setFont(QFont('Microsoft YaHei', 10, QFont.Bold)) # 更小字体
title_label.setStyleSheet("color: white;")
text_layout.addWidget(title_label)
# 副标题
subtitle_label = QLabel("立即访问官网了解更多优惠详情 →")
subtitle_label.setFont(QFont('Microsoft YaHei', 8)) # 更小字体
subtitle_label.setStyleSheet("color: rgba(255, 255, 255, 0.9);")
text_layout.addWidget(subtitle_label)
banner_layout.addLayout(text_layout)
banner_layout.addStretch()
# 初始样式(紫色渐变背景)
self.update_banner_style(0)
# 添加阴影效果(更轻量)
shadow = QGraphicsDropShadowEffect()
shadow.setBlurRadius(10) # 减小模糊半径
shadow.setXOffset(0)
shadow.setYOffset(2) # 减小偏移
shadow.setColor(QColor(0, 0, 0, 40)) # 降低不透明度
banner_frame.setGraphicsEffect(shadow)
# 点击事件 - 跳转官网
def open_official_website():
try:
import webbrowser
official_url = "https://shuidrop.com/"
webbrowser.open(official_url)
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()
# 添加到主布局
layout.addWidget(banner_frame)
# 启动颜色渐变动画
self.start_banner_animation()
print("[INFO] 宣传横幅已创建(带动态渐变效果)")
except Exception as e:
print(f"[WARNING] 创建宣传横幅失败: {e}")
def update_banner_style(self, color_index):
"""更新横幅颜色样式"""
if not self.promo_banner:
return
# 定义多组渐变颜色方案(呼吸效果)
color_schemes = [
# 紫色(原色)
{
'normal': ('667eea', '764ba2'),
'hover': ('778ff5', '865cb3')
},
# 深紫色(变暗)
{
'normal': ('5a6dc8', '6a3f8f'),
'hover': ('6b7ed9', '7b50a0')
},
# 亮紫色(变亮)
{
'normal': ('7890fc', '8658b4'),
'hover': ('89a1ff', '9769c5')
},
# 紫色(原色)- 循环
{
'normal': ('667eea', '764ba2'),
'hover': ('778ff5', '865cb3')
}
]
scheme = color_schemes[color_index % len(color_schemes)]
style = f"""
QFrame#promoBanner {{
background: qlineargradient(
x1:0, y1:0, x2:1, y2:0,
stop:0 #{scheme['normal'][0]},
stop:1 #{scheme['normal'][1]}
);
border-radius: 12px;
border: 1px solid rgba(255, 255, 255, 0.2);
}}
QFrame#promoBanner:hover {{
background: qlineargradient(
x1:0, y1:0, x2:1, y2:0,
stop:0 #{scheme['hover'][0]},
stop:1 #{scheme['hover'][1]}
);
}}
"""
self.promo_banner.setStyleSheet(style)
def start_banner_animation(self):
"""启动横幅呼吸动画"""
try:
# 创建定时器每2秒切换一次颜色
self.banner_animation = QTimer(self)
self.banner_animation.timeout.connect(self.animate_banner_color)
self.banner_animation.start(2000) # 2秒间隔
print("[INFO] 横幅呼吸动画已启动")
except Exception as e:
print(f"[WARNING] 启动横幅动画失败: {e}")
def animate_banner_color(self):
"""动画:循环改变横幅颜色"""
try:
self.banner_color_index = (self.banner_color_index + 1) % 4
self.update_banner_style(self.banner_color_index)
except Exception as e:
print(f"[WARNING] 横幅颜色动画失败: {e}")
def apply_modern_styles(self): def apply_modern_styles(self):
"""应用现代化简约样式 - 精致美化版""" """应用现代化简约样式 - 精致美化版"""
self.setStyleSheet(""" self.setStyleSheet("""
@@ -619,6 +779,11 @@ class LoginWindow(QMainWindow):
"""真正退出应用程序""" """真正退出应用程序"""
print("[INFO] 正在退出应用程序...") print("[INFO] 正在退出应用程序...")
# 停止横幅动画
if hasattr(self, 'banner_animation') and self.banner_animation:
self.banner_animation.stop()
print("[INFO] 横幅动画已停止")
# 执行原来的关闭逻辑 # 执行原来的关闭逻辑
try: try:
# 使用 WebSocket 管理器断开所有连接 # 使用 WebSocket 管理器断开所有连接

View File

@@ -246,6 +246,7 @@ def verify_result():
print("TIP: Please check if PyInstaller executed successfully") print("TIP: Please check if PyInstaller executed successfully")
return False return False
def _verify_directory(base_dir): def _verify_directory(base_dir):
"""验证指定目录的打包结果""" """验证指定目录的打包结果"""
# 检查可能的 exe 名称 # 检查可能的 exe 名称
@@ -305,7 +306,7 @@ def main():
try: try:
import subprocess import subprocess
result = subprocess.run(['pyinstaller', '--version'], result = subprocess.run(['pyinstaller', '--version'],
capture_output=True, text=True, check=False) capture_output=True, text=True, check=False)
if result.returncode == 0: if result.returncode == 0:
print(f"PyInstaller version: {result.stdout.strip()}") print(f"PyInstaller version: {result.stdout.strip()}")
else: else: