292 lines
9.2 KiB
Python
292 lines
9.2 KiB
Python
|
#!/usr/bin/env python
|
|||
|
# -*- coding: utf-8 -*-
|
|||
|
|
|||
|
"""
|
|||
|
自动化打包脚本
|
|||
|
用于构建VWED任务系统的Windows可执行文件
|
|||
|
"""
|
|||
|
|
|||
|
import os
|
|||
|
import sys
|
|||
|
import shutil
|
|||
|
import subprocess
|
|||
|
from pathlib import Path
|
|||
|
import argparse
|
|||
|
|
|||
|
class VWEDBuildTool:
|
|||
|
"""VWED打包工具"""
|
|||
|
|
|||
|
def __init__(self):
|
|||
|
self.project_root = Path(__file__).parent.parent.parent
|
|||
|
self.packaging_dir = self.project_root / "packaging"
|
|||
|
self.dist_dir = self.project_root / "dist"
|
|||
|
self.build_dir = self.project_root / "build"
|
|||
|
|
|||
|
def clean_build(self):
|
|||
|
"""清理构建目录"""
|
|||
|
print("清理构建目录...")
|
|||
|
|
|||
|
dirs_to_clean = [self.dist_dir, self.build_dir]
|
|||
|
|
|||
|
try:
|
|||
|
for dir_path in dirs_to_clean:
|
|||
|
if dir_path.exists():
|
|||
|
print(f"删除目录: {dir_path}")
|
|||
|
shutil.rmtree(dir_path)
|
|||
|
|
|||
|
print("构建目录清理完成")
|
|||
|
return True
|
|||
|
except Exception as e:
|
|||
|
print(f"清理构建目录失败: {e}")
|
|||
|
return False
|
|||
|
|
|||
|
def install_dependencies(self):
|
|||
|
"""安装打包依赖"""
|
|||
|
print("安装打包依赖...")
|
|||
|
|
|||
|
requirements_file = self.packaging_dir / "requirements_build.txt"
|
|||
|
|
|||
|
if not requirements_file.exists():
|
|||
|
print(f"错误: 找不到依赖文件 {requirements_file}")
|
|||
|
return False
|
|||
|
|
|||
|
try:
|
|||
|
subprocess.run([
|
|||
|
sys.executable, "-m", "pip", "install", "-r", str(requirements_file)
|
|||
|
], check=True)
|
|||
|
print("依赖安装完成")
|
|||
|
return True
|
|||
|
except subprocess.CalledProcessError as e:
|
|||
|
print(f"依赖安装失败: {e}")
|
|||
|
return False
|
|||
|
|
|||
|
def build_main_app(self):
|
|||
|
"""构建主应用程序"""
|
|||
|
print("构建主应用程序...")
|
|||
|
|
|||
|
spec_file = self.packaging_dir / "vwed_task_main.spec"
|
|||
|
|
|||
|
if not spec_file.exists():
|
|||
|
print(f"错误: 找不到spec文件 {spec_file}")
|
|||
|
return False
|
|||
|
|
|||
|
try:
|
|||
|
subprocess.run([
|
|||
|
"pyinstaller", "--clean", str(spec_file)
|
|||
|
], cwd=str(self.project_root), check=True)
|
|||
|
print("主应用程序构建完成")
|
|||
|
return True
|
|||
|
except subprocess.CalledProcessError as e:
|
|||
|
print(f"主应用程序构建失败: {e}")
|
|||
|
return False
|
|||
|
|
|||
|
def build_config_tool(self):
|
|||
|
"""构建配置工具"""
|
|||
|
print("构建配置工具...")
|
|||
|
|
|||
|
spec_file = self.packaging_dir / "vwed_config_tool.spec"
|
|||
|
|
|||
|
if not spec_file.exists():
|
|||
|
print(f"错误: 找不到spec文件 {spec_file}")
|
|||
|
return False
|
|||
|
|
|||
|
try:
|
|||
|
subprocess.run([
|
|||
|
"pyinstaller", "--clean", str(spec_file)
|
|||
|
], cwd=str(self.project_root), check=True)
|
|||
|
print("配置工具构建完成")
|
|||
|
return True
|
|||
|
except subprocess.CalledProcessError as e:
|
|||
|
print(f"配置工具构建失败: {e}")
|
|||
|
return False
|
|||
|
|
|||
|
def create_release_package(self):
|
|||
|
"""创建发布包"""
|
|||
|
print("创建发布包...")
|
|||
|
|
|||
|
try:
|
|||
|
release_dir = self.dist_dir / "VWED_Task_Release"
|
|||
|
release_dir.mkdir(parents=True, exist_ok=True)
|
|||
|
|
|||
|
# 复制单文件可执行程序
|
|||
|
main_exe = self.dist_dir / "vwed_task_main.exe"
|
|||
|
config_exe = self.dist_dir / "vwed_config_tool.exe"
|
|||
|
|
|||
|
if main_exe.exists():
|
|||
|
shutil.copy2(main_exe, release_dir / "vwed_task_main.exe")
|
|||
|
print("主程序复制完成")
|
|||
|
else:
|
|||
|
print(f"警告: 主程序文件不存在 {main_exe}")
|
|||
|
|
|||
|
if config_exe.exists():
|
|||
|
shutil.copy2(config_exe, release_dir / "vwed_config_tool.exe")
|
|||
|
print("配置工具复制完成")
|
|||
|
else:
|
|||
|
print(f"警告: 配置工具文件不存在 {config_exe}")
|
|||
|
|
|||
|
# 创建启动脚本
|
|||
|
self.create_startup_scripts(release_dir)
|
|||
|
|
|||
|
# 复制文档
|
|||
|
self.copy_documentation(release_dir)
|
|||
|
|
|||
|
print(f"发布包创建完成: {release_dir}")
|
|||
|
return True
|
|||
|
except Exception as e:
|
|||
|
print(f"创建发布包失败: {e}")
|
|||
|
return False
|
|||
|
|
|||
|
def create_startup_scripts(self, release_dir: Path):
|
|||
|
"""创建启动脚本"""
|
|||
|
print("创建启动脚本...")
|
|||
|
|
|||
|
# 配置工具启动脚本
|
|||
|
config_script = release_dir / "启动配置工具.bat"
|
|||
|
with open(config_script, 'w', encoding='gbk') as f:
|
|||
|
f.write("""@echo off
|
|||
|
chcp 65001 >nul
|
|||
|
echo 正在启动VWED任务系统配置工具...
|
|||
|
cd /d "%~dp0"
|
|||
|
if exist "vwed_config_tool.exe" (
|
|||
|
start "" "vwed_config_tool.exe"
|
|||
|
) else (
|
|||
|
echo 错误: 找不到配置工具可执行文件 vwed_config_tool.exe
|
|||
|
pause
|
|||
|
)
|
|||
|
""")
|
|||
|
|
|||
|
# 直接启动主程序脚本
|
|||
|
main_script = release_dir / "直接启动服务.bat"
|
|||
|
with open(main_script, 'w', encoding='gbk') as f:
|
|||
|
f.write("""@echo off
|
|||
|
chcp 65001 >nul
|
|||
|
echo 正在启动VWED任务系统服务...
|
|||
|
cd /d "%~dp0"
|
|||
|
if exist "vwed_task_main.exe" (
|
|||
|
"vwed_task_main.exe"
|
|||
|
) else (
|
|||
|
echo 错误: 找不到主程序可执行文件 vwed_task_main.exe
|
|||
|
pause
|
|||
|
)
|
|||
|
""")
|
|||
|
|
|||
|
# 停止服务脚本
|
|||
|
stop_script = release_dir / "停止服务.bat"
|
|||
|
with open(stop_script, 'w', encoding='gbk') as f:
|
|||
|
f.write("""@echo off
|
|||
|
chcp 65001 >nul
|
|||
|
echo 正在停止VWED任务系统服务...
|
|||
|
taskkill /f /im vwed_task_main.exe 2>nul
|
|||
|
if %errorlevel%==0 (
|
|||
|
echo 服务已停止
|
|||
|
) else (
|
|||
|
echo 没有找到运行中的服务进程
|
|||
|
)
|
|||
|
pause
|
|||
|
""")
|
|||
|
|
|||
|
print("启动脚本创建完成")
|
|||
|
|
|||
|
def copy_documentation(self, release_dir: Path):
|
|||
|
"""复制文档"""
|
|||
|
print("复制文档...")
|
|||
|
|
|||
|
docs_source = self.project_root / "VWED任务模块接口文档"
|
|||
|
if docs_source.exists():
|
|||
|
docs_target = release_dir / "文档"
|
|||
|
if docs_target.exists():
|
|||
|
shutil.rmtree(docs_target)
|
|||
|
shutil.copytree(docs_source, docs_target)
|
|||
|
print("API文档复制完成")
|
|||
|
|
|||
|
# 复制README
|
|||
|
readme_source = self.project_root / "README.md"
|
|||
|
if readme_source.exists():
|
|||
|
shutil.copy2(readme_source, release_dir / "使用说明.md")
|
|||
|
print("使用说明复制完成")
|
|||
|
|
|||
|
# 创建部署说明
|
|||
|
deploy_readme = release_dir / "部署说明.txt"
|
|||
|
with open(deploy_readme, 'w', encoding='utf-8') as f:
|
|||
|
f.write("""VWED任务系统部署说明
|
|||
|
========================
|
|||
|
|
|||
|
1. 首次部署:
|
|||
|
- 双击运行 "启动配置工具.bat"
|
|||
|
- 在配置工具中设置数据库连接参数和API地址
|
|||
|
- 点击"测试数据库连接"确保连接正常
|
|||
|
- 点击"保存配置"保存设置
|
|||
|
- 点击"启动服务"启动系统服务
|
|||
|
|
|||
|
2. 日常使用:
|
|||
|
- 如果配置无需修改,可直接双击 "直接启动服务.bat"
|
|||
|
- 如需修改配置,使用 "启动配置工具.bat"
|
|||
|
|
|||
|
3. 停止服务:
|
|||
|
- 双击运行 "停止服务.bat"
|
|||
|
|
|||
|
4. 访问系统:
|
|||
|
- 服务启动后,在浏览器中访问: http://localhost:8000
|
|||
|
- API文档地址: http://localhost:8000/docs
|
|||
|
|
|||
|
5. 日志文件:
|
|||
|
- 系统运行日志位于 logs/ 目录下
|
|||
|
|
|||
|
6. 配置文件:
|
|||
|
- 配置保存在 config.ini 文件中
|
|||
|
- 如需手动修改,请停止服务后编辑
|
|||
|
|
|||
|
注意事项:
|
|||
|
- 确保MySQL数据库服务已启动
|
|||
|
- 确保防火墙允许8000端口访问
|
|||
|
- 首次运行会自动创建数据库表结构
|
|||
|
""")
|
|||
|
|
|||
|
print("部署说明创建完成")
|
|||
|
|
|||
|
def build_all(self):
|
|||
|
"""执行完整构建流程"""
|
|||
|
print("开始构建VWED任务系统...")
|
|||
|
|
|||
|
steps = [
|
|||
|
("清理构建环境", self.clean_build),
|
|||
|
("安装打包依赖", self.install_dependencies),
|
|||
|
("构建主应用程序", self.build_main_app),
|
|||
|
("构建配置工具", self.build_config_tool),
|
|||
|
("创建发布包", self.create_release_package)
|
|||
|
]
|
|||
|
|
|||
|
for step_name, step_func in steps:
|
|||
|
print(f"\n=== {step_name} ===")
|
|||
|
if not step_func():
|
|||
|
print(f"构建失败于步骤: {step_name}")
|
|||
|
return False
|
|||
|
|
|||
|
print("\n=== 构建完成 ===")
|
|||
|
print(f"发布包位置: {self.dist_dir / 'VWED_Task_Release'}")
|
|||
|
return True
|
|||
|
|
|||
|
def main():
|
|||
|
"""主函数"""
|
|||
|
parser = argparse.ArgumentParser(description="VWED任务系统打包工具")
|
|||
|
parser.add_argument("--clean", action="store_true", help="仅清理构建目录")
|
|||
|
parser.add_argument("--main-only", action="store_true", help="仅构建主程序")
|
|||
|
parser.add_argument("--config-only", action="store_true", help="仅构建配置工具")
|
|||
|
|
|||
|
args = parser.parse_args()
|
|||
|
|
|||
|
builder = VWEDBuildTool()
|
|||
|
|
|||
|
if args.clean:
|
|||
|
builder.clean_build()
|
|||
|
elif args.main_only:
|
|||
|
builder.install_dependencies()
|
|||
|
builder.build_main_app()
|
|||
|
elif args.config_only:
|
|||
|
builder.install_dependencies()
|
|||
|
builder.build_config_tool()
|
|||
|
else:
|
|||
|
builder.build_all()
|
|||
|
|
|||
|
if __name__ == "__main__":
|
|||
|
main()
|