package main import ( "embed" "io/fs" "os" "videoconcat/services" "github.com/wailsapp/wails/v3/pkg/application" ) //go:embed assets var assets embed.FS // 在开发模式下列出嵌入的文件,用于调试 func init() { if os.Getenv("DEV") == "true" { fs.WalkDir(assets, ".", func(path string, d fs.DirEntry, err error) error { if err == nil { services.LogDebugf("嵌入资源: %s (目录: %v)", path, d.IsDir()) } return nil }) } } // getEmbeddedFFmpeg 在平台特定文件中实现(ffmpeg_darwin.go, ffmpeg_windows.go, ffmpeg_linux.go, ffmpeg_default.go) // 根据编译时的 GOOS 自动选择对应的实现 // 注意:此函数没有在此文件中声明,而是在平台特定文件中声明和实现 func main() { // 检测开发模式并设置日志级别 if os.Getenv("DEV") == "true" { services.SetLogLevel("DEBUG") services.LogInfo("=== 开发模式启动 ===") services.LogDebug("详细日志已启用") } // 注意:如果看到 "SetProcessDpiAwarenessContext failed" 错误,这是非致命的 // Wails 运行时尝试设置 DPI 感知,但清单文件已经声明了 DPI 感知 // Windows 可能不允许运行时再次设置,这不会影响应用功能 // 初始化 FFmpeg 助手(传递嵌入的文件系统,根据编译平台自动选择) services.InitFFmpegHelper(getEmbeddedFFmpeg()) // 创建服务 services.LogDebug("开始创建服务...") videoService := services.NewVideoService() extractService := services.NewExtractService() authService := services.NewAuthService() fileService := services.NewFileService() services.LogDebug("所有服务创建完成") services.LogDebug("创建 Wails 应用...") // 尝试不同的路径映射方式 // 方式1:使用子文件系统(推荐),去除 "assets" 前缀 // 这样 /index.html 会映射到 assets/index.html assetsFS, err := fs.Sub(assets, "assets") var useSubFS bool if err != nil { services.LogErrorf("创建子文件系统失败: %v,使用原始文件系统", err) assetsFS = assets useSubFS = false } else { services.LogDebug("成功创建子文件系统") useSubFS = true } app := application.New(application.Options{ Name: "VideoConcat", Description: "视频拼接工具", Assets: application.AssetOptions{Handler: application.AssetFileServerFS(assetsFS)}, Services: []application.Service{ application.NewService(videoService), application.NewService(extractService), application.NewService(authService), application.NewService(fileService), }, Mac: application.MacOptions{ ApplicationShouldTerminateAfterLastWindowClosed: true, }, }) services.LogDebug("Wails 应用创建完成") // 创建窗口 services.LogDebug("创建应用窗口...") window := app.Window.NewWithOptions(application.WebviewWindowOptions{ Title: "视频拼接工具", Width: 1100, Height: 800, MinWidth: 800, MinHeight: 600, DevToolsEnabled: true, // 暂时启用开发者工具以便调试 }) // 加载主页面 // 使用子文件系统时,路径映射: // URL /index.html -> 文件系统 index.html (对应 assets/index.html) // URL /assets/xxx.js -> 文件系统 assets/xxx.js (对应 assets/assets/xxx.js) urlPath := "/index.html" if !useSubFS { // 如果不使用子文件系统,需要调整路径 urlPath = "/assets/index.html" services.LogWarn("未使用子文件系统,URL 路径: " + urlPath) } window.SetURL(urlPath) services.LogInfo("应用窗口已创建,URL: " + urlPath) // 注意:如果页面空白,可能是: // 1. JavaScript 文件加载失败(检查网络请求) // 2. Vue 应用未正确挂载 // 3. 资源路径不正确(虽然验证通过,但实际加载时可能有问题) // 验证文件是否存在并列出所有可用文件(用于调试) // 使用 LogInfo 确保在所有模式下都能看到 services.LogInfo("=== 开始验证嵌入的资源文件 ===") // 列出所有文件 fs.WalkDir(assetsFS, ".", func(path string, d fs.DirEntry, err error) error { if err == nil { if d.IsDir() { services.LogInfof("目录: %s", path) } else { services.LogInfof("文件: %s", path) } } return nil }) // 验证关键文件 testFiles := []string{"index.html", "assets/index-B-ziti-G.js", "assets/index-dkqEFoMI.css"} for _, file := range testFiles { if data, err := assetsFS.Open(file); err == nil { data.Close() services.LogInfof("✓ 验证成功: %s 存在", file) } else { services.LogErrorf("✗ 验证失败: %s 不存在 - %v", file, err) } } services.LogInfo("=== 验证完成 ===") services.LogInfo("=== 应用启动完成,开始运行 ===") if err := app.Run(); err != nil { services.LogErrorf("应用运行错误: %v", err) panic(err) } }