Files
shuidrop_gui/quick_build.py

318 lines
10 KiB
Python
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
快速打包脚本 - 避免spec文件缩进问题
"""
import os
import subprocess
import shutil
def clean_build():
"""清理构建目录"""
print("🧹 清理旧的构建文件...")
# 跳过进程结束步骤,避免影响当前脚本运行
print("🔄 跳过进程结束步骤(避免脚本自终止)...")
# 等待少量时间确保文件句柄释放
import time
print("⏳ 等待文件句柄释放...")
time.sleep(0.5)
dirs_to_clean = ['dist', 'build']
for dir_name in dirs_to_clean:
print(f"🔍 检查目录: {dir_name}")
if os.path.exists(dir_name):
try:
print(f"🗑️ 正在删除: {dir_name}")
shutil.rmtree(dir_name)
print(f"✅ 已删除: {dir_name}")
except PermissionError as e:
print(f"⚠️ {dir_name} 被占用,尝试强制删除... 错误: {e}")
try:
subprocess.run(['rd', '/s', '/q', dir_name],
shell=True, check=True)
print(f"✅ 强制删除成功: {dir_name}")
except Exception as e2:
print(f"❌ 无法删除 {dir_name}: {e2}")
print("💡 请手动删除或运行 force_clean_dist.bat")
except Exception as e:
print(f"❌ 删除 {dir_name} 时出错: {e}")
else:
print(f" {dir_name} 不存在,跳过")
print("✅ 清理阶段完成")
def build_with_command():
"""使用命令行参数直接打包"""
print("🚀 开始打包...")
cmd = [
'pyinstaller',
'--name=main',
'--onedir', # 相当于 --exclude-binaries
'--windowed', # 相当于 -w
'--add-data=config.py;.',
'--add-data=exe_file_logger.py;.',
'--add-data=windows_taskbar_fix.py;.',
'--add-data=Utils/PythonNew32;Utils/PythonNew32',
'--add-data=Utils/JD;Utils/JD',
'--add-data=Utils/Dy;Utils/Dy',
'--add-data=Utils/Pdd;Utils/Pdd',
'--add-data=Utils/QianNiu;Utils/QianNiu',
'--add-data=Utils/message_models.py;Utils',
'--add-data=Utils/__init__.py;Utils',
'--add-data=WebSocket;WebSocket',
'--add-data=static;static',
'--add-binary=Utils/PythonNew32/SaiNiuApi.dll;Utils/PythonNew32',
'--add-binary=Utils/PythonNew32/SaiNiuSys.dll;Utils/PythonNew32',
'--add-binary=Utils/PythonNew32/SaiNiuServer.dll;Utils/PythonNew32',
'--add-binary=Utils/PythonNew32/python32.exe;Utils/PythonNew32',
'--add-binary=Utils/PythonNew32/python313.dll;Utils/PythonNew32',
'--add-binary=Utils/PythonNew32/vcruntime140.dll;Utils/PythonNew32',
'--hidden-import=PyQt5.QtCore',
'--hidden-import=PyQt5.QtGui',
'--hidden-import=PyQt5.QtWidgets',
'--hidden-import=websockets',
'--hidden-import=asyncio',
'--hidden-import=Utils.QianNiu.QianNiuUtils',
'--hidden-import=Utils.JD.JdUtils',
'--hidden-import=Utils.Dy.DyUtils',
'--hidden-import=Utils.Pdd.PddUtils',
'--hidden-import=WebSocket.backend_singleton',
'--hidden-import=WebSocket.BackendClient',
'--hidden-import=windows_taskbar_fix',
'main.py'
]
try:
print(f"执行命令: {' '.join(cmd[:5])}... (共{len(cmd)}个参数)")
result = subprocess.run(cmd, capture_output=True, text=True, encoding='utf-8')
if result.returncode == 0:
print("✅ 打包成功!")
print("📁 打包结果: dist/main/")
# 重命名目录
if os.path.exists('dist/main'):
try:
if os.path.exists('dist/MultiPlatformGUI'):
shutil.rmtree('dist/MultiPlatformGUI')
os.rename('dist/main', 'dist/MultiPlatformGUI')
print("✅ 已重命名为: dist/MultiPlatformGUI/")
except Exception as e:
print(f"⚠️ 重命名失败: {e}")
print("💡 可以手动重命名: dist/main -> dist/MultiPlatformGUI")
print("📁 当前可用路径: dist/main/")
# 创建使用说明
try:
create_usage_guide()
except:
create_usage_guide_fallback()
return True
else:
print("❌ 打包失败")
if result.stderr:
print("错误信息:")
print(result.stderr)
return False
except Exception as e:
print(f"❌ 打包过程出错: {e}")
return False
def create_usage_guide():
"""创建使用说明"""
guide_content = r"""# 多平台客服GUI使用说明
## 🚀 运行方式
```
cd dist/MultiPlatformGUI
.\main.exe
```
## 📝 支持平台
- 千牛 (淘宝)
- 京东 (JD)
- 抖音 (DY)
- 拼多多 (PDD)
## 🎯 特点
- 支持多平台同时监听
- 无平台间冲突
- 自动生成日志文件
- 美观的系统托盘图标
- 现代化UI界面
## 📁 文件结构
```
MultiPlatformGUI/
├── main.exe # 主程序
└── _internal/ # 程序依赖文件
├── static/ # 图标资源
│ ├── ai_assistant_icon_16.png
│ ├── ai_assistant_icon_32.png
│ └── ai_assistant_icon_64.png
├── Utils/
│ ├── PythonNew32/ # 千牛DLL文件
│ ├── JD/ # 京东模块
│ ├── Dy/ # 抖音模块
│ └── Pdd/ # 拼多多模块
└── ...
```
## 🔧 故障排除
1. **图标不显示**:检查 _internal/static/ 目录下的图标文件是否存在
2. **连接失败**:检查网络连接和令牌是否正确
3. **平台无响应**:查看日志文件了解详细错误信息
## 📞 技术支持
如有问题,请提供:
- 错误截图
- 具体的错误描述
- 操作步骤
"""
try:
with open('dist/MultiPlatformGUI/使用说明.txt', 'w', encoding='utf-8') as f:
f.write(guide_content)
print("✅ 已生成使用说明文件")
except:
print("⚠️ 使用说明生成失败")
def create_usage_guide_fallback():
"""备用使用说明生成"""
guide_content = r"""# 多平台客服GUI使用说明
## 🚀 运行方式
```
cd dist/main
.\main.exe
```
## 📝 支持平台
- 千牛 (淘宝)
- 京东 (JD)
- 抖音 (DY)
- 拼多多 (PDD)
## 🎯 特点
- 支持多平台同时监听
- 无平台间冲突
- 自动生成日志文件
"""
try:
with open('dist/main/使用说明.txt', 'w', encoding='utf-8') as f:
f.write(guide_content)
print("✅ 已生成使用说明文件 (备用路径)")
except:
print("⚠️ 使用说明生成失败")
def verify_result():
"""验证打包结果"""
print("\n🔍 验证打包结果...")
# 先检查MultiPlatformGUI再检查main目录
base_dirs = ["dist/MultiPlatformGUI", "dist/main"]
for base_dir in base_dirs:
if os.path.exists(base_dir):
exe_path = f"{base_dir}/main.exe"
dll_path = f"{base_dir}/_internal/Utils/PythonNew32/SaiNiuApi.dll"
if os.path.exists(exe_path):
size = os.path.getsize(exe_path)
print(f"✅ 主程序: {exe_path} ({size:,} bytes)")
if os.path.exists(dll_path):
dll_size = os.path.getsize(dll_path)
print(f"✅ 千牛DLL: SaiNiuApi.dll ({dll_size:,} bytes)")
print(f"📁 有效路径: {base_dir}/")
print("✅ 验证通过")
return True
else:
print("❌ 千牛DLL不存在")
else:
print(f"{exe_path} 不存在")
print("❌ 未找到有效的打包结果")
return False
def main():
"""主函数"""
print("🔥 多平台客服GUI快速打包工具")
print("=" * 60)
try:
# 检查依赖
print("🔍 检查打包依赖...")
try:
import subprocess
result = subprocess.run(['pyinstaller', '--version'],
capture_output=True, text=True, check=False)
if result.returncode == 0:
print(f"✅ PyInstaller 版本: {result.stdout.strip()}")
else:
print("❌ PyInstaller 未安装或不可用")
print("💡 请运行: pip install pyinstaller")
return False
except Exception as e:
print(f"❌ 检查PyInstaller时出错: {e}")
return False
# 清理
print("\n📍 开始清理阶段...")
clean_build()
print("📍 清理阶段完成")
# 打包
print("\n📍 开始打包阶段...")
if not build_with_command():
print("❌ 打包阶段失败")
return False
print("📍 打包阶段完成")
# 验证
print("\n📍 开始验证阶段...")
if not verify_result():
print("❌ 验证阶段失败")
return False
print("📍 验证阶段完成")
print("\n" + "=" * 60)
print("🎉 打包完成!")
# 智能显示可用路径
if os.path.exists("dist/MultiPlatformGUI"):
print("📁 打包结果: dist/MultiPlatformGUI/")
print("🚀 运行方式: cd dist/MultiPlatformGUI && .\\main.exe")
elif os.path.exists("dist/main"):
print("<EFBFBD><EFBFBD> 打包结果: dist/main/")
print("🚀 运行方式: cd dist/main && .\\main.exe")
print("💡 提示: 可手动重命名为 MultiPlatformGUI")
print("=" * 60)
return True
except Exception as e:
print(f"❌ 打包失败: {e}")
return False
if __name__ == "__main__":
success = main()
if success:
print("\n✅ 可以开始测试了!")
else:
print("\n❌ 请检查错误信息并重试")