From 51cfd5cf21d328c4840d08a58fba524bb0b3dcb6 Mon Sep 17 00:00:00 2001
From: zyj <18107291228@163.com>
Date: Mon, 24 Nov 2025 11:45:42 +0800
Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E5=BA=94=E7=94=A8=E6=89=93?=
=?UTF-8?q?=E5=8C=85=E6=A8=A1=E5=9D=97?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
PACK_GUIDE.md | 244 +++++++++++++++++++++++
app.go | 120 +++++++----
build/windows/Taskfile.yml | 7 +-
frontend/app/pages/run/pack.vue | 80 +++++++-
services/pack_service.go | 340 ++++++++++++++++++++++++++++++++
5 files changed, 740 insertions(+), 51 deletions(-)
create mode 100644 PACK_GUIDE.md
create mode 100644 services/pack_service.go
diff --git a/PACK_GUIDE.md b/PACK_GUIDE.md
new file mode 100644
index 0000000..7c55fc4
--- /dev/null
+++ b/PACK_GUIDE.md
@@ -0,0 +1,244 @@
+# 网站打包成应用指南
+
+## 功能说明
+
+本工具可以将静态网站打包成独立的桌面应用程序,无需用户安装浏览器或其他运行环境。
+
+## 打包原理
+
+1. **创建 Wails 项目**:自动生成一个新的 Wails3 项目结构
+2. **嵌入网站文件**:将静态网站文件(HTML、CSS、JS等)嵌入到应用中
+3. **编译应用**:使用 Wails3 编译生成桌面应用
+4. **独立运行**:打包后的应用内置 WebView,无需浏览器
+
+## 环境要求
+
+### 必需环境
+
+- **Go 1.21+**:Go 编程语言环境
+- **Wails3**:桌面应用框架
+
+### 安装方式
+
+#### 方式一:使用本工具安装(推荐)
+
+1. 进入"应用打包"页面
+2. 查看环境检查卡片
+3. 点击"安装 Go"和"安装 Wails3"按钮
+4. 等待安装完成
+
+#### 方式二:手动安装
+
+**安装 Go:**
+```powershell
+# 下载 Go 安装包
+# https://go.dev/dl/
+
+# 或使用工具提供的脚本
+.\install\go.bat
+```
+
+**安装 Wails3:**
+```powershell
+# 确保已安装 Go
+go install github.com/wailsapp/wails/v3/cmd/wails3@latest
+
+# 或使用工具提供的脚本
+.\install\wails.bat
+```
+
+## 使用步骤
+
+### 1. 准备网站文件
+
+确保您的网站文件夹包含:
+- `index.html`(必需,作为应用入口)
+- CSS 文件
+- JavaScript 文件
+- 图片、字体等资源文件
+
+示例结构:
+```
+my-website/
+├── index.html
+├── css/
+│ └── style.css
+├── js/
+│ └── app.js
+└── images/
+ └── logo.png
+```
+
+### 2. 选择网站
+
+- 点击"选择文件夹"按钮
+- 选择包含网站文件的文件夹
+- 或从已下载的网站列表中选择
+
+### 3. 配置应用信息
+
+填写应用基本信息:
+- **应用名称**(必填):应用的显示名称
+- **版本号**:如 1.0.0
+- **作者**:您的名字或团队名称
+- **应用描述**:简短描述应用功能
+
+### 4. 打包设置
+
+配置打包参数:
+- **目标平台**:选择 Windows、macOS 或 Linux
+- **窗口宽度**:默认 1280px
+- **窗口高度**:默认 800px
+- **输出目录**:可自定义,默认为 `site-dist`
+
+### 5. 开始打包
+
+- 确认所有配置正确
+- 点击"开始打包"按钮
+- 等待编译完成(首次可能需要5-10分钟)
+
+## 打包输出
+
+### 文件位置
+
+默认输出到项目的 `site-dist` 目录,包含:
+- Windows:`your-app.exe`
+- macOS:`your-app.app`
+- Linux:`your-app`(可执行文件)
+
+### 文件大小
+
+打包后的应用大小取决于:
+- 网站文件大小
+- 平台差异
+- 通常在 20-50MB 之间
+
+## 注意事项
+
+### 首次打包
+
+- 需要下载 Go 依赖包
+- 可能耗时 5-10 分钟
+- 需要网络连接
+- 建议有至少 500MB 可用磁盘空间
+
+### 网站要求
+
+- **纯静态网站**:支持 HTML、CSS、JavaScript
+- **不支持服务端代码**:如 PHP、Python 等
+- **相对路径**:建议使用相对路径引用资源
+- **入口文件**:必须有 index.html
+
+### 资源引用
+
+在 HTML 中使用相对路径:
+```html
+
+
+
+
+
+
+
+
+```
+
+### 跨域问题
+
+打包后的应用使用 `file://` 协议,可能遇到跨域限制:
+- 避免使用外部 API(CORS 限制)
+- 避免使用绝对路径
+- 将所有资源放在网站文件夹内
+
+## 常见问题
+
+### Q: 打包失败怎么办?
+
+A: 检查以下几点:
+1. 确保 Go 和 Wails3 已正确安装
+2. 检查网络连接(首次打包需要下载依赖)
+3. 确保磁盘空间充足
+4. 查看错误信息,根据提示解决
+
+### Q: 打包的应用很大?
+
+A: 这是正常的,因为:
+1. 包含了 WebView 运行时
+2. 包含了 Go 运行时
+3. 包含了所有网站文件
+4. 可以通过压缩网站资源减小体积
+
+### Q: 应用可以在其他电脑运行吗?
+
+A: 可以!打包后的应用是独立的:
+- Windows 应用可在任何 Windows 7+ 系统运行
+- macOS 应用可在任何 macOS 10.13+ 系统运行
+- Linux 应用可在大多数 Linux 发行版运行
+- 无需安装 Go、Wails 或浏览器
+
+### Q: 如何更新应用?
+
+A: 重新打包即可:
+1. 修改网站文件
+2. 更改版本号
+3. 重新执行打包流程
+4. 分发新的可执行文件
+
+### Q: 可以添加自定义图标吗?
+
+A: 当前版本暂不支持,后续版本会添加此功能。
+
+## 高级用法
+
+### 自定义配置
+
+编辑生成的项目:
+1. 打包时会在临时目录创建项目
+2. 可以在 `main.go` 中自定义窗口行为
+3. 可以添加 Go 后端代码
+
+### 批量打包
+
+使用命令行方式:
+```powershell
+# 切换到临时项目目录
+cd C:\Users\{user}\AppData\Local\Temp\wails-pack-{app-name}
+
+# 执行构建
+wails3 build
+```
+
+## 技术架构
+
+```
+┌─────────────────────────────────────┐
+│ 桌面应用 (.exe) │
+├─────────────────────────────────────┤
+│ Wails3 框架 │
+│ ├─ WebView (渲染引擎) │
+│ ├─ Go 运行时 │
+│ └─ 嵌入的网站文件 │
+│ ├─ HTML │
+│ ├─ CSS │
+│ ├─ JavaScript │
+│ └─ 其他资源 │
+└─────────────────────────────────────┘
+```
+
+## 支持的平台
+
+| 平台 | 架构 | 输出格式 | 备注 |
+|------|------|---------|------|
+| Windows | x64 | .exe | Windows 7+ |
+| macOS | x64/arm64 | .app | macOS 10.13+ |
+| Linux | x64 | 可执行文件 | 主流发行版 |
+
+## 更多信息
+
+- Wails 官方文档:https://wails.io
+- Go 官方网站:https://go.dev
+- 项目 GitHub:待添加
+
+## 许可证
+
+本工具遵循 MIT 许可证。
diff --git a/app.go b/app.go
index de3d9fa..5a083e2 100644
--- a/app.go
+++ b/app.go
@@ -556,16 +556,35 @@ func (a *App) PackApp(packConfig map[string]interface{}) error {
// 获取配置参数
sitePath, _ := packConfig["sitePath"].(string)
appName, _ := packConfig["appName"].(string)
+ version, _ := packConfig["version"].(string)
+ author, _ := packConfig["author"].(string)
+ description, _ := packConfig["description"].(string)
outputDir, _ := packConfig["outputDir"].(string)
+ width, _ := packConfig["width"].(float64)
+ height, _ := packConfig["height"].(float64)
+
+ // 平台参数处理
+ platformsInterface, _ := packConfig["platforms"].([]interface{})
+ platforms := make([]string, 0)
+ for _, p := range platformsInterface {
+ if platform, ok := p.(string); ok {
+ platforms = append(platforms, platform)
+ }
+ }
if sitePath == "" || appName == "" {
- return fmt.Errorf("缺少必要参数")
+ return fmt.Errorf("缺少必要参数: 网站路径和应用名称不能为空")
+ }
+
+ // 检查网站路径是否存在
+ if _, err := os.Stat(sitePath); os.IsNotExist(err) {
+ return fmt.Errorf("网站路径不存在: %s", sitePath)
}
// 发送打包进度
a.app.Event.Emit("pack:progress", map[string]interface{}{
"step": "preparing",
- "percent": 10,
+ "percent": 5,
"message": "正在准备打包环境...",
})
@@ -576,15 +595,25 @@ func (a *App) PackApp(packConfig map[string]interface{}) error {
}
if !envStatus.HasGo || !envStatus.HasWails {
- return fmt.Errorf("缺少必要的环境: Go=%v, Wails=%v", envStatus.HasGo, envStatus.HasWails)
+ return fmt.Errorf("缺少必要的环境: Go=%v, Wails=%v。请先安装开发环境", envStatus.HasGo, envStatus.HasWails)
}
- // 创建临时项目目录
- a.app.Event.Emit("pack:progress", map[string]interface{}{
- "step": "creating",
- "percent": 30,
- "message": "正在创建项目结构...",
- })
+ // 设置默认值
+ if version == "" {
+ version = "1.0.0"
+ }
+ if description == "" {
+ description = appName
+ }
+ if len(platforms) == 0 {
+ platforms = []string{"windows"}
+ }
+ if width == 0 {
+ width = 1280
+ }
+ if height == 0 {
+ height = 800
+ }
// 设置输出目录
if outputDir == "" {
@@ -595,8 +624,12 @@ func (a *App) PackApp(packConfig map[string]interface{}) error {
}
}
- // 确保输出目录存在
- os.MkdirAll(outputDir, 0755)
+ // 创建临时项目目录
+ a.app.Event.Emit("pack:progress", map[string]interface{}{
+ "step": "creating",
+ "percent": 15,
+ "message": "正在创建Wails项目结构...",
+ })
tempDir := filepath.Join(os.TempDir(), "wails-pack-"+appName)
os.RemoveAll(tempDir) // 清理旧的
@@ -605,48 +638,63 @@ func (a *App) PackApp(packConfig map[string]interface{}) error {
return fmt.Errorf("创建临时目录失败: %v", err)
}
- // TODO: 创建Wails项目结构,复制网站文件等
- // 这里是完整打包逻辑的占位符
- // 实际需要:
- // 1. 创建wails项目结构 (go.mod, main.go等)
- // 2. 复制网站文件到项目的assets目录
- // 3. 配置wails项目参数
+ // 使用打包服务创建项目
+ packService := &services.PackService{}
+ config := services.PackConfig{
+ SitePath: sitePath,
+ AppName: appName,
+ Version: version,
+ Author: author,
+ Description: description,
+ Platforms: platforms,
+ Width: int(width),
+ Height: int(height),
+ OutputDir: outputDir,
+ }
- log.Printf("准备打包网站: %s 到应用: %s", sitePath, appName)
+ log.Printf("开始打包网站: %s", sitePath)
+ log.Printf("应用名称: %s", appName)
log.Printf("临时目录: %s", tempDir)
log.Printf("输出目录: %s", outputDir)
a.app.Event.Emit("pack:progress", map[string]interface{}{
- "step": "building",
- "percent": 60,
- "message": "正在编译应用...",
+ "step": "copying",
+ "percent": 30,
+ "message": "正在复制网站文件...",
})
- // 使用Wails构建
- wailsCmd := envStatus.WailsPath
- if wailsCmd == "" {
- wailsCmd = "wails3"
+ // 创建Wails项目结构
+ if err := packService.CreateWailsProject(config, tempDir); err != nil {
+ a.app.Event.Emit("pack:progress", map[string]interface{}{
+ "step": "error",
+ "percent": 0,
+ "error": fmt.Sprintf("创建项目失败: %v", err),
+ })
+ return fmt.Errorf("创建Wails项目失败: %v", err)
}
- // 模拟构建过程(实际项目中这里应该真正调用wails build)
- // cmd := exec.Command(wailsCmd, "build", "-o", filepath.Join(outputDir, appName+".exe"))
- // cmd.Dir = tempDir
-
- // 暂时模拟成功
a.app.Event.Emit("pack:progress", map[string]interface{}{
- "step": "packaging",
- "percent": 80,
- "message": "正在生成安装包...",
+ "step": "building",
+ "percent": 50,
+ "message": "正在编译应用(这可能需要几分钟)...",
})
- // 模拟延迟
- // time.Sleep(2 * time.Second)
+ // 构建应用
+ if err := packService.BuildWailsApp(tempDir, outputDir, platforms); err != nil {
+ a.app.Event.Emit("pack:progress", map[string]interface{}{
+ "step": "error",
+ "percent": 0,
+ "error": fmt.Sprintf("构建失败: %v", err),
+ })
+ return fmt.Errorf("构建应用失败: %v", err)
+ }
a.app.Event.Emit("pack:progress", map[string]interface{}{
"step": "completed",
"percent": 100,
- "message": fmt.Sprintf("打包完成! 输出目录: %s", outputDir),
+ "message": fmt.Sprintf("打包完成! 应用已保存到: %s", outputDir),
})
+ log.Printf("打包完成! 输出目录: %s", outputDir)
return nil
}
diff --git a/build/windows/Taskfile.yml b/build/windows/Taskfile.yml
index 19f1376..36ff667 100644
--- a/build/windows/Taskfile.yml
+++ b/build/windows/Taskfile.yml
@@ -33,12 +33,7 @@ tasks:
package:
summary: Packages a production build of the application
cmds:
- - |-
- if [ "{{.FORMAT | default "nsis"}}" = "msix" ]; then
- task: create:msix:package
- else
- task: create:nsis:installer
- fi
+ - task: create:nsis:installer
vars:
FORMAT: '{{.FORMAT | default "nsis"}}'
diff --git a/frontend/app/pages/run/pack.vue b/frontend/app/pages/run/pack.vue
index b253352..cb5d2ea 100644
--- a/frontend/app/pages/run/pack.vue
+++ b/frontend/app/pages/run/pack.vue
@@ -345,9 +345,15 @@
{{ packProgressText }}
+打包流程:
打包原理:
+注意事项:
输出位置:
+site-dist 目录