feat: 完成macOS应用打包功能

This commit is contained in:
ruisu
2025-02-19 16:29:59 +08:00
parent 6a00193333
commit 0b6b3f13aa
7 changed files with 253 additions and 8 deletions

171
build.py
View File

@@ -1,9 +1,15 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import warnings
import os
import platform
import subprocess
import time
import threading
import json
import sys
from pathlib import Path
# Ignore specific SyntaxWarning
warnings.filterwarnings("ignore", category=SyntaxWarning, module="DrissionPage")
@@ -79,6 +85,169 @@ def filter_output(output):
return "\n".join(important_lines)
def increment_version():
"""增加构建版本号"""
version_file = Path("version.json")
if version_file.exists():
with open(version_file, "r") as f:
version_data = json.load(f)
# 增加构建号
version_data["build"] += 1
# 更新版本号的最后一位
version_parts = version_data["version"].split(".")
version_parts[-1] = str(version_data["build"])
version_data["version"] = ".".join(version_parts)
# 保存更新后的版本信息
with open(version_file, "w") as f:
json.dump(version_data, f, indent=4)
return version_data
else:
print("错误:未找到 version.json 文件")
sys.exit(1)
def create_icns():
"""将 SVG 转换为 ICNS 格式"""
if not Path("icons/logo.svg").exists():
print("错误:未找到 logo.svg 文件")
sys.exit(1)
# 创建临时目录
os.makedirs("icons/tmp.iconset", exist_ok=True)
# 转换 SVG 到 PNG
sizes = [16, 32, 64, 128, 256, 512, 1024]
for size in sizes:
# 普通分辨率
os.system(f"rsvg-convert -w {size} -h {size} icons/logo.svg > icons/tmp.iconset/icon_{size}x{size}.png")
# 高分辨率(@2x
if size <= 512:
os.system(f"rsvg-convert -w {size*2} -h {size*2} icons/logo.svg > icons/tmp.iconset/icon_{size}x{size}@2x.png")
# 生成 icns 文件
os.system("iconutil -c icns icons/tmp.iconset -o icons/logo.icns")
# 清理临时文件
os.system("rm -rf icons/tmp.iconset")
def update_spec(version_data):
"""更新 spec 文件中的版本信息"""
spec_content = f'''# -*- mode: python ; coding: utf-8 -*-
block_cipher = None
a = Analysis(
['cursor_gui.py'],
pathex=[],
binaries=[],
datas=[],
hiddenimports=[],
hookspath=[],
hooksconfig={{}},
runtime_hooks=[],
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher,
noarchive=False,
)
pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher)
exe = EXE(
pyz,
a.scripts,
[],
exclude_binaries=True,
name='听泉Cursor助手',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
console=False,
disable_windowed_traceback=False,
argv_emulation=True,
target_arch=None,
codesign_identity=None,
entitlements_file=None,
icon='icons/logo.icns',
)
coll = COLLECT(
exe,
a.binaries,
a.zipfiles,
a.datas,
strip=False,
upx=True,
upx_exclude=[],
name='听泉Cursor助手',
)
app = BUNDLE(
coll,
name='听泉Cursor助手.app',
icon='icons/logo.icns',
bundle_identifier='com.tingquan.cursor',
info_plist={{
'CFBundleShortVersionString': '{version_data["version"]}',
'CFBundleVersion': '{version_data["build"]}',
'NSHighResolutionCapable': 'True',
'LSMinimumSystemVersion': '10.13.0',
'CFBundleName': '听泉Cursor助手',
'CFBundleDisplayName': '听泉Cursor助手',
}},
)'''
with open("cursor_app.spec", "w") as f:
f.write(spec_content)
def build_app():
"""构建应用程序"""
# 增加版本号
version_data = increment_version()
# 创建图标
create_icns()
# 更新 spec 文件
update_spec(version_data)
# 更新主程序中的版本号
update_main_version(version_data["version"])
# 构建应用
os.system("pyinstaller cursor_app.spec")
# 创建压缩包
os.system(f'cd dist && zip -r "听泉Cursor助手_v{version_data["version"]}.zip" "听泉Cursor助手.app"')
print(f"\n构建完成版本号v{version_data['version']}")
print(f"应用程序位置dist/听泉Cursor助手.app")
print(f"压缩包位置dist/听泉Cursor助手_v{version_data['version']}.zip")
def update_main_version(version):
"""更新主程序中的版本号"""
with open("cursor_gui.py", "r") as f:
content = f.read()
# 替换版本号
content = content.replace(
'self.setWindowTitle("Cursor账号管理器 v3.5.3")',
f'self.setWindowTitle("听泉Cursor助手 v{version}")'
)
with open("cursor_gui.py", "w") as f:
f.write(content)
def build():
# Clear screen
os.system("cls" if platform.system().lower() == "windows" else "clear")
@@ -176,4 +345,4 @@ def build():
if __name__ == "__main__":
build()
build_app()

View File

@@ -7,6 +7,42 @@ from PyQt6.QtCore import Qt, QTimer, QPropertyAnimation
from PyQt6.QtGui import QIcon, QPixmap
import cursor_account_manager as backend
from logger import logging
import traceback
# 设置日志文件路径
def setup_logging():
try:
# 获取应用程序所在目录
if getattr(sys, 'frozen', False):
# 如果是打包后的应用程序
app_dir = os.path.dirname(sys.executable)
else:
# 如果是开发环境
app_dir = os.path.dirname(os.path.abspath(__file__))
# 创建日志目录
log_dir = os.path.join(app_dir, 'logs')
os.makedirs(log_dir, exist_ok=True)
# 设置日志文件路径
log_file = os.path.join(log_dir, 'app.log')
# 配置日志记录
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s [%(levelname)s] %(message)s',
handlers=[
logging.FileHandler(log_file, encoding='utf-8'),
logging.StreamHandler()
]
)
logging.info('日志系统初始化成功')
logging.info(f'日志文件路径: {log_file}')
except Exception as e:
print(f"设置日志系统时出错: {str(e)}")
print(traceback.format_exc())
class SuccessDialog(QDialog):
def __init__(self, message, parent=None):
@@ -154,7 +190,7 @@ class PasswordDialog(QDialog):
class CursorGUI(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("Cursor账号管理器 v3.5.3")
self.setWindowTitle("听泉Cursor助手 v3.0.2")
self.setFixedSize(600, 600)
# 设置整体样式
@@ -488,7 +524,27 @@ class CursorGUI(QMainWindow):
QMessageBox.information(self, "提示", "更新功能开发中")
if __name__ == "__main__":
app = QApplication(sys.argv)
window = CursorGUI()
window.show()
sys.exit(app.exec())
try:
# 初始化日志系统
setup_logging()
# 记录启动信息
logging.info("=== 应用程序启动 ===")
logging.info(f"Python 版本: {sys.version}")
logging.info(f"操作系统: {sys.platform}")
app = QApplication(sys.argv)
window = CursorGUI()
window.show()
# 捕获未处理的异常
def handle_exception(exc_type, exc_value, exc_traceback):
logging.error("未捕获的异常:", exc_info=(exc_type, exc_value, exc_traceback))
sys.excepthook = handle_exception
sys.exit(app.exec())
except Exception as e:
logging.error(f"程序启动失败: {str(e)}")
logging.error(traceback.format_exc())
raise

BIN
icons/logo.icns Normal file

Binary file not shown.

14
icons/logo.svg Normal file
View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="1024" height="1024" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg">
<!-- 背景 -->
<rect width="1024" height="1024" rx="200" fill="#1e88e5"/>
<!-- 水波纹效果 -->
<path d="M312,512 Q512,412 712,512" stroke="white" stroke-width="20" fill="none" opacity="0.6"/>
<path d="M312,562 Q512,462 712,562" stroke="white" stroke-width="15" fill="none" opacity="0.4"/>
<path d="M312,612 Q512,512 712,612" stroke="white" stroke-width="10" fill="none" opacity="0.2"/>
<!-- 主文字 -->
<text x="512" y="480" font-family="Arial" font-size="180" font-weight="bold" text-anchor="middle" fill="white">听泉</text>
<text x="512" y="680" font-family="Arial" font-size="120" font-weight="bold" text-anchor="middle" fill="white">Cursor</text>
</svg>

After

Width:  |  Height:  |  Size: 838 B

BIN
logo.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

View File

@@ -1,7 +1,9 @@
DrissionPage==4.1.0.9
colorama==0.4.6
python-dotenv==1.0.0
pyinstaller
pyinstaller==6.3.0
PyQt6==6.6.1
PyQt6-Qt6==6.6.1
PyQt6-sip==13.6.0
PyQt6-sip==13.6.0
requests==2.31.0
urllib3==2.1.0

4
version.json Normal file
View File

@@ -0,0 +1,4 @@
{
"version": "3.0.5",
"build": 5
}