feat: 完善版本管理功能 1. 优化使用步骤说明的样式,调整行高和字体大小,提升可读性 2. 新增版本截图 3. 更新依赖包版本 4. 添加版本管理相关文件

This commit is contained in:
huangzhenpc
2025-02-13 15:16:55 +08:00
parent e3b5820d8b
commit d81244c7e4
8 changed files with 936 additions and 82 deletions

View File

@@ -14,6 +14,7 @@ import time
sys.path.append(str(Path(__file__).parent.parent))
from utils.config import Config
from utils.version_manager import VersionManager
from account_switcher import AccountSwitcher
def get_version():
@@ -130,11 +131,33 @@ class ApiWorker(QThread):
except Exception as e:
self.finished.emit((False, str(e)))
class UpdateWorker(QThread):
"""更新检查工作线程"""
progress = pyqtSignal(str) # 发送进度信息
finished = pyqtSignal(tuple) # 发送结果信号
def __init__(self, version_manager):
super().__init__()
self.version_manager = version_manager
def run(self):
try:
self.progress.emit("正在检查更新...")
has_update, is_force, version_info = self.version_manager.needs_update()
if has_update and version_info:
self.finished.emit((True, is_force, version_info))
else:
self.finished.emit((False, False, None))
except Exception as e:
self.finished.emit((False, False, str(e)))
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.config = Config()
self.switcher = AccountSwitcher()
self.version_manager = VersionManager()
# 添加激活状态缓存
self._activation_status = None # 缓存的激活状态
@@ -148,7 +171,7 @@ class MainWindow(QMainWindow):
version = get_version()
cursor_version = self.switcher.get_cursor_version()
self.setWindowTitle(f"听泉Cursor助手 v{version} (本机Cursor版本: {cursor_version})")
self.setMinimumSize(600, 500)
self.setMinimumSize(600, 680) # 增加最小宽度到600
# 设置窗口图标
icon_path = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "icon", "two.ico")
@@ -175,9 +198,31 @@ class MainWindow(QMainWindow):
stop:0.5 #ffffff,
stop:1 #f8f9fa);
}
QLabel {
color: #495057;
QFrame {
border: none;
background: transparent;
}
""")
# 创建主布局
main_layout = QVBoxLayout(central_widget)
main_layout.setSpacing(12) # 减小区域间距
main_layout.setContentsMargins(20, 15, 20, 15) # 调整外边距
# 设备ID区域
device_frame = QFrame()
device_frame.setStyleSheet("""
QFrame {
background: transparent;
padding: 8px;
}
""")
device_layout = QHBoxLayout(device_frame)
device_layout.setContentsMargins(0, 0, 0, 0)
device_layout.addWidget(QLabel("设备识别码(勿动):"))
self.hardware_id_edit = QLineEdit(self.switcher.hardware_id)
self.hardware_id_edit.setReadOnly(True)
self.hardware_id_edit.setStyleSheet("""
QLineEdit {
background-color: #ffffff;
border: 1px solid #ced4da;
@@ -185,27 +230,8 @@ class MainWindow(QMainWindow):
padding: 5px;
color: #495057;
}
QTextEdit {
background-color: #ffffff;
border: 1px solid #ced4da;
border-radius: 4px;
padding: 5px;
color: #495057;
}
""")
# 创建主布局
main_layout = QVBoxLayout(central_widget)
main_layout.setSpacing(15)
main_layout.setContentsMargins(30, 30, 30, 30)
# 设备ID区域
device_layout = QHBoxLayout()
device_layout.addWidget(QLabel("设备识别码(勿动):"))
self.hardware_id_edit = QLineEdit(self.switcher.hardware_id)
self.hardware_id_edit.setReadOnly(True)
device_layout.addWidget(self.hardware_id_edit)
copy_btn = QPushButton("复制ID")
copy_btn.setStyleSheet("""
QPushButton {
@@ -221,67 +247,121 @@ class MainWindow(QMainWindow):
""")
copy_btn.clicked.connect(self.copy_device_id)
device_layout.addWidget(copy_btn)
main_layout.addLayout(device_layout)
# 添加分隔线
line = QFrame()
line.setFrameShape(QFrame.HLine)
line.setStyleSheet("background-color: #e9ecef;")
main_layout.addWidget(line)
main_layout.addWidget(device_frame)
# 会员状态区域
status_label = QLabel("会员状态")
status_label.setStyleSheet("font-weight: bold; margin-top: 10px;")
main_layout.addWidget(status_label)
status_frame = QFrame()
status_frame.setStyleSheet("""
QFrame {
background: transparent;
padding: 8px;
}
QLabel {
color: #495057;
font-weight: bold;
}
QTextEdit {
background-color: #ffffff;
border: 1px solid #ced4da;
border-radius: 4px;
padding: 5px;
color: #495057;
}
QTextEdit QScrollBar:vertical {
width: 8px;
background: transparent;
margin: 0px;
}
QTextEdit QScrollBar::handle:vertical {
background: #ced4da;
min-height: 30px;
border-radius: 4px;
}
QTextEdit QScrollBar::handle:vertical:hover {
background: #adb5bd;
}
QTextEdit QScrollBar::add-line:vertical,
QTextEdit QScrollBar::sub-line:vertical {
height: 0px;
}
QTextEdit QScrollBar::add-page:vertical,
QTextEdit QScrollBar::sub-page:vertical {
background: none;
}
""")
status_layout = QVBoxLayout(status_frame)
status_layout.setContentsMargins(0, 0, 0, 0)
status_layout.addWidget(QLabel("会员状态"))
self.status_text = QTextEdit()
self.status_text.setReadOnly(True)
self.status_text.setMinimumHeight(100)
main_layout.addWidget(self.status_text)
# 添加分隔线
line2 = QFrame()
line2.setFrameShape(QFrame.HLine)
line2.setStyleSheet("background-color: #e9ecef;")
main_layout.addWidget(line2)
status_layout.addWidget(self.status_text)
main_layout.addWidget(status_frame)
# 激活区域
main_layout.addWidget(QLabel("激活(叠加)会员,多个激活码可叠加整体时长"))
activation_frame = QFrame()
activation_frame.setStyleSheet("""
QFrame {
background: transparent;
padding: 12px 0;
}
""")
activation_layout = QVBoxLayout(activation_frame)
activation_layout.setContentsMargins(0, 0, 0, 0)
# 激活码输入区域
input_layout = QHBoxLayout()
input_layout.addWidget(QLabel("激活码:"))
activation_layout.addWidget(QLabel("激活(叠加)会员,多个激活码可叠加整体时长"))
input_frame = QFrame()
input_layout = QHBoxLayout(input_frame)
input_layout.setSpacing(10)
input_layout.setContentsMargins(0, 0, 0, 0)
self.activation_edit = QLineEdit()
self.activation_edit.setPlaceholderText("请输入激活码")
self.activation_edit.setMinimumWidth(350) # 增加输入框宽度
self.activation_edit.setFixedHeight(35)
self.activation_edit.setStyleSheet("""
QLineEdit {
background-color: #ffffff;
border: 1px solid #ced4da;
border-radius: 4px;
padding: 8px;
color: #495057;
font-size: 13px;
}
QLineEdit:focus {
border-color: #86b7fe;
}
""")
input_layout.addWidget(self.activation_edit)
# 激活按钮
activate_btn = QPushButton("激活")
activate_btn.setFixedWidth(100)
activate_btn.setFixedHeight(35)
activate_btn.setStyleSheet("""
QPushButton {
background-color: #0d6efd;
color: white;
border: none;
padding: 8px 25px;
border-radius: 4px;
font-size: 13px;
min-width: 80px;
}
QPushButton:hover {
background-color: #0b5ed7;
}
QPushButton:pressed {
background-color: #0a58ca;
}
""")
activate_btn.clicked.connect(self.activate_account)
input_layout.addWidget(activate_btn)
main_layout.addLayout(input_layout)
activation_layout.addWidget(input_frame)
# 使用说明
usage_label = QLabel()
usage_text = (
"<div style='background-color: #f8f9fa; padding: 15px; border-radius: 8px; border: 2px solid #0d6efd;'>"
"<p style='margin-bottom: 15px; font-size: 15px;'><b style='color: #0d6efd;'>使用步骤说明:</b></p>"
"<p style='line-height: 2.0;'>"
"<div style='padding: 15px 0;'>"
"<p style='margin-bottom: 10px; font-size: 15px;'><b style='color: #0d6efd;'>使用步骤说明:</b></p>"
"<p style='line-height: 2; font-size: 14px;'>"
"<span style='font-size: 14px; color: #dc3545;'><b>第一步:</b></span> "
"输入激活码点击<b style='color: #0d6efd;'>【激活】</b>按钮完成激活<br>"
@@ -301,68 +381,117 @@ class MainWindow(QMainWindow):
QLabel {
color: #333333;
font-size: 13px;
padding: 0px;
margin: 10px 0;
background: transparent;
}
""")
usage_label.setTextFormat(Qt.RichText)
usage_label.setWordWrap(True)
main_layout.addWidget(usage_label)
activation_layout.addWidget(usage_label)
main_layout.addWidget(activation_frame)
# 操作按钮区域
btn_frame = QFrame()
btn_layout = QVBoxLayout(btn_frame)
btn_layout.setSpacing(15) # 增加按钮间距
btn_layout.setContentsMargins(0, 10, 0, 10)
# 设置按钮样式
# 按钮基础样式
button_style = """
QPushButton {
background-color: #0d6efd;
color: white;
border: none;
padding: 15px;
border-radius: 6px;
font-size: 13px;
min-width: 300px;
margin: 5px;
font-size: 14px;
font-weight: 500;
min-width: 500px;
}
"""
# 刷新授权按钮(主按钮)
refresh_btn = QPushButton("刷新 Cursor 编辑器授权")
refresh_btn.setStyleSheet(button_style + """
QPushButton {
background-color: #0d6efd;
padding: 15px;
}
QPushButton:hover {
background-color: #0b5ed7;
}
QPushButton:pressed {
background-color: #0a58ca;
}
"""
# 刷新授权按钮
refresh_btn = QPushButton("刷新 Cursor 编辑器授权")
refresh_btn.setStyleSheet(button_style)
""")
refresh_btn.clicked.connect(self.refresh_cursor_auth)
refresh_btn.setMinimumHeight(50)
btn_layout.addWidget(refresh_btn)
refresh_btn.setMinimumHeight(60)
refresh_btn.setMinimumWidth(500)
btn_layout.addWidget(refresh_btn, 0, Qt.AlignCenter)
# 突破限制按钮
bypass_btn = QPushButton("突破 Cursor 0.45.x 限制")
bypass_btn.setStyleSheet(button_style.replace("#0d6efd", "#198754").replace("#0b5ed7", "#157347").replace("#0a58ca", "#146c43"))
bypass_btn.setStyleSheet(button_style + """
QPushButton {
background-color: #198754;
padding: 12px;
}
QPushButton:hover {
background-color: #157347;
}
""")
bypass_btn.clicked.connect(self.bypass_cursor_limit)
bypass_btn.setMinimumHeight(50)
btn_layout.addWidget(bypass_btn)
bypass_btn.setMinimumWidth(500)
btn_layout.addWidget(bypass_btn, 0, Qt.AlignCenter)
# 禁用更新按钮
disable_update_btn = QPushButton("禁用 Cursor 版本更新")
disable_update_btn.setStyleSheet(button_style.replace("#0d6efd", "#dc3545").replace("#0b5ed7", "#bb2d3b").replace("#0a58ca", "#b02a37"))
disable_update_btn.setStyleSheet(button_style + """
QPushButton {
background-color: #dc3545;
padding: 12px;
}
QPushButton:hover {
background-color: #bb2d3b;
}
""")
disable_update_btn.clicked.connect(self.disable_cursor_update)
disable_update_btn.setMinimumHeight(50)
btn_layout.addWidget(disable_update_btn)
# 设置按钮间距
btn_layout.setSpacing(10)
btn_layout.setContentsMargins(20, 10, 20, 10)
disable_update_btn.setMinimumWidth(500)
btn_layout.addWidget(disable_update_btn, 0, Qt.AlignCenter)
main_layout.addWidget(btn_frame)
# 检查更新按钮
update_frame = QFrame()
update_frame.setStyleSheet("""
QFrame {
background: transparent;
padding: 5px;
}
""")
update_layout = QHBoxLayout(update_frame)
update_layout.setContentsMargins(0, 0, 0, 0)
check_update_btn = QPushButton("检查更新")
check_update_btn.setStyleSheet("""
QPushButton {
background-color: #6c757d;
color: white;
border: none;
padding: 8px 20px;
border-radius: 4px;
font-size: 13px;
}
QPushButton:hover {
background-color: #5a6268;
}
""")
check_update_btn.clicked.connect(self.check_for_updates)
update_layout.addWidget(check_update_btn)
main_layout.addWidget(update_frame)
# 启动时检查一次状态
QTimer.singleShot(0, self.check_status)
# 启动时自动检查更新
QTimer.singleShot(1000, self.check_for_updates)
def create_tray_icon(self):
"""创建系统托盘图标"""
try:
@@ -1324,4 +1453,203 @@ class MainWindow(QMainWindow):
def _request_complete(self):
"""请求完成,重置状态"""
self._is_requesting = False
self._is_requesting = False
def check_for_updates(self):
"""检查更新"""
if self._is_requesting:
return
self._is_requesting = True
self.show_loading_dialog("正在检查更新...")
self.update_worker = UpdateWorker(self.version_manager)
self.update_worker.progress.connect(lambda msg: self.loading_dialog.message_label.setText(msg))
self.update_worker.finished.connect(self.on_update_check_complete)
self.update_worker.start()
def on_update_check_complete(self, result):
"""更新检查完成的回调"""
self.hide_loading_dialog()
self._is_requesting = False
has_update, is_force, version_info = result
if isinstance(version_info, str): # 发生错误
self.show_custom_error("检查更新失败", f"检查更新时发生错误: {version_info}")
return
if not has_update:
self.show_custom_message(
"检查更新",
"已是最新版本",
"您当前使用的已经是最新版本。",
QStyle.SP_DialogApplyButton,
"#198754"
)
return
# 显示更新信息
msg = QDialog(self)
msg.setWindowTitle("发现新版本")
msg.setFixedWidth(500)
msg.setWindowFlags(msg.windowFlags() & ~Qt.WindowContextHelpButtonHint)
layout = QVBoxLayout()
# 添加图标
icon_label = QLabel()
icon_label.setPixmap(self.style().standardIcon(QStyle.SP_MessageBoxInformation).pixmap(32, 32))
icon_label.setAlignment(Qt.AlignCenter)
layout.addWidget(icon_label)
# 添加标题
title_label = QLabel("发现新版本")
title_label.setAlignment(Qt.AlignCenter)
title_label.setStyleSheet("""
font-size: 16px;
font-weight: bold;
color: #0d6efd;
padding: 10px;
""")
layout.addWidget(title_label)
# 版本信息
version_frame = QFrame()
version_frame.setStyleSheet("""
QFrame {
background-color: #f8f9fa;
border-radius: 8px;
border: 1px solid #dee2e6;
margin: 10px;
padding: 15px;
}
QLabel {
color: #333333;
font-size: 14px;
padding: 5px;
}
""")
version_layout = QVBoxLayout(version_frame)
# 当前版本
current_version_label = QLabel(f"当前版本v{self.version_manager.current_version}")
version_layout.addWidget(current_version_label)
# 最新版本
new_version_label = QLabel(f"最新版本v{version_info.get('version_no', '未知')} ({version_info.get('version_name', '未知')})")
new_version_label.setStyleSheet("font-weight: bold; color: #0d6efd;")
version_layout.addWidget(new_version_label)
# 分割线
line = QFrame()
line.setFrameShape(QFrame.HLine)
line.setStyleSheet("background-color: #dee2e6;")
version_layout.addWidget(line)
# 更新说明
desc_label = QLabel("更新说明:")
desc_label.setStyleSheet("font-weight: bold; padding-top: 10px;")
version_layout.addWidget(desc_label)
desc_text = version_info.get('description', '')
desc_content = QLabel(desc_text if desc_text else "无更新说明")
desc_content.setWordWrap(True)
desc_content.setStyleSheet("padding: 5px 10px;")
version_layout.addWidget(desc_content)
# 强制更新提示
if is_force:
force_label = QLabel("* 此更新为强制更新,请立即更新!")
force_label.setStyleSheet("color: #dc3545; font-weight: bold; padding-top: 10px;")
version_layout.addWidget(force_label)
layout.addWidget(version_frame)
# 按钮区域
btn_layout = QHBoxLayout()
# 暂不更新按钮
if not is_force:
later_btn = QPushButton("暂不更新")
later_btn.setStyleSheet("""
QPushButton {
background-color: #6c757d;
color: white;
border: none;
padding: 8px 20px;
border-radius: 4px;
font-size: 13px;
min-width: 100px;
}
QPushButton:hover {
background-color: #5a6268;
}
""")
later_btn.clicked.connect(msg.reject)
btn_layout.addWidget(later_btn)
# 立即更新按钮
update_btn = QPushButton("立即更新")
update_btn.setStyleSheet("""
QPushButton {
background-color: #0d6efd;
color: white;
border: none;
padding: 8px 20px;
border-radius: 4px;
font-size: 13px;
min-width: 100px;
font-weight: bold;
}
QPushButton:hover {
background-color: #0b5ed7;
}
""")
update_btn.clicked.connect(msg.accept)
btn_layout.addWidget(update_btn)
layout.addLayout(btn_layout)
msg.setLayout(layout)
# 显示对话框
if msg.exec_() == QDialog.Accepted:
self.download_update(version_info.get('download_url'))
def download_update(self, download_url):
"""下载更新"""
if not download_url:
self.show_custom_error("更新失败", "无法获取下载地址,请联系管理员")
return
try:
# 创建下载目录
download_dir = Path.home() / "Downloads" / "CursorHelper"
download_dir.mkdir(parents=True, exist_ok=True)
# 下载文件名
file_name = download_url.split('/')[-1]
save_path = download_dir / file_name
self.show_loading_dialog("正在下载更新...")
# 开始下载
success, message = self.version_manager.download_update(download_url, str(save_path))
self.hide_loading_dialog()
if success:
self.show_custom_message(
"下载完成",
"更新包下载成功",
f"更新包已下载到:\n{save_path}\n\n请关闭程序后运行更新包完成更新。",
QStyle.SP_DialogApplyButton,
"#198754"
)
# 退出程序
self.quit_application()
else:
self.show_custom_error("下载失败", message)
except Exception as e:
self.hide_loading_dialog()
self.show_custom_error("下载失败", f"下载更新时发生错误: {str(e)}")