From f393d2b1de816fc4f5cabcecf696ceb47e1a8006 Mon Sep 17 00:00:00 2001 From: zyj <18107291228@163.com> Date: Sat, 22 Nov 2025 18:47:47 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E8=BD=AF=E4=BB=B6=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 --- app.go | 230 ++++++++ frontend/app/pages/run/pack.vue | 545 ++++++++++++++++-- frontend/bindings/go-site-clone/app.js | 70 ++- .../bindings/go-site-clone/utils/index.js | 1 + .../bindings/go-site-clone/utils/models.js | 66 +++ utils/index.go | 136 +++++ 6 files changed, 979 insertions(+), 69 deletions(-) diff --git a/app.go b/app.go index ff35251..de3d9fa 100644 --- a/app.go +++ b/app.go @@ -1,6 +1,7 @@ package main import ( + "bytes" "fmt" "go-site-clone/config" "go-site-clone/services" @@ -420,3 +421,232 @@ func (a *App) SelectFolder() (string, error) { } return result, nil } + +// ========== 打包相关方法 ========== + +// CheckEnvironment 检查Go和Wails环境 +func (a *App) CheckEnvironment() (*utils.EnvStatus, error) { + return utils.GetEnvStatus() +} + +// InstallGo 安装Go环境 +func (a *App) InstallGo(version string) error { + scriptPath, err := utils.GetInstallScriptPath("go") + if err != nil { + return err + } + + // 构建命令参数 + args := []string{"/c", scriptPath} + if version != "" { + args = append(args, version) + } + + // 发送安装进度事件 + a.app.Event.Emit("install:progress", map[string]interface{}{ + "tool": "go", + "step": "downloading", + "percent": 10, + "message": "正在下载 Go...", + }) + + // 在Windows上使用cmd.exe执行bat文件 + cmd := exec.Command("cmd.exe", args...) + cmd.Dir = filepath.Dir(scriptPath) + + var stdout, stderr bytes.Buffer + cmd.Stdout = &stdout + cmd.Stderr = &stderr + + // 启动命令但不等待完成(bat脚本会暂停) + err = cmd.Start() + if err != nil { + a.app.Event.Emit("install:progress", map[string]interface{}{ + "tool": "go", + "step": "error", + "percent": 0, + "error": fmt.Sprintf("启动安装脚本失败: %v", err), + }) + return fmt.Errorf("安装失败: %v", err) + } + + // 在后台等待完成 + go func() { + err := cmd.Wait() + if err != nil { + a.app.Event.Emit("install:progress", map[string]interface{}{ + "tool": "go", + "step": "error", + "percent": 0, + "error": stderr.String(), + }) + } else { + a.app.Event.Emit("install:progress", map[string]interface{}{ + "tool": "go", + "step": "completed", + "percent": 100, + "message": "Go 安装完成", + }) + } + }() + + return nil +} + +// InstallWails 安装Wails3环境 +func (a *App) InstallWails() error { + scriptPath, err := utils.GetInstallScriptPath("wails") + if err != nil { + return err + } + + // 发送安装进度事件 + a.app.Event.Emit("install:progress", map[string]interface{}{ + "tool": "wails", + "step": "installing", + "percent": 10, + "message": "正在安装 Wails3...", + }) + + // 在Windows上使用cmd.exe执行bat文件 + cmd := exec.Command("cmd.exe", "/c", scriptPath) + cmd.Dir = filepath.Dir(scriptPath) + + var stdout, stderr bytes.Buffer + cmd.Stdout = &stdout + cmd.Stderr = &stderr + + // 启动命令但不等待完成 + err = cmd.Start() + if err != nil { + a.app.Event.Emit("install:progress", map[string]interface{}{ + "tool": "wails", + "step": "error", + "percent": 0, + "error": fmt.Sprintf("启动安装脚本失败: %v", err), + }) + return fmt.Errorf("安装失败: %v", err) + } + + // 在后台等待完成 + go func() { + err := cmd.Wait() + if err != nil { + a.app.Event.Emit("install:progress", map[string]interface{}{ + "tool": "wails", + "step": "error", + "percent": 0, + "error": stderr.String(), + }) + } else { + a.app.Event.Emit("install:progress", map[string]interface{}{ + "tool": "wails", + "step": "completed", + "percent": 100, + "message": "Wails3 安装完成", + }) + } + }() + + return nil +} + +// PackApp 打包应用 +func (a *App) PackApp(packConfig map[string]interface{}) error { + // 获取配置参数 + sitePath, _ := packConfig["sitePath"].(string) + appName, _ := packConfig["appName"].(string) + outputDir, _ := packConfig["outputDir"].(string) + + if sitePath == "" || appName == "" { + return fmt.Errorf("缺少必要参数") + } + + // 发送打包进度 + a.app.Event.Emit("pack:progress", map[string]interface{}{ + "step": "preparing", + "percent": 10, + "message": "正在准备打包环境...", + }) + + // 检查环境 + envStatus, err := utils.GetEnvStatus() + if err != nil { + return fmt.Errorf("检查环境失败: %v", err) + } + + if !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 outputDir == "" { + appConfig, _ := config.LoadConfig() + outputDir = appConfig.PackSiteFileDir + if outputDir == "" { + outputDir = "site-dist" + } + } + + // 确保输出目录存在 + os.MkdirAll(outputDir, 0755) + + tempDir := filepath.Join(os.TempDir(), "wails-pack-"+appName) + os.RemoveAll(tempDir) // 清理旧的 + err = os.MkdirAll(tempDir, 0755) + if err != nil { + return fmt.Errorf("创建临时目录失败: %v", err) + } + + // TODO: 创建Wails项目结构,复制网站文件等 + // 这里是完整打包逻辑的占位符 + // 实际需要: + // 1. 创建wails项目结构 (go.mod, main.go等) + // 2. 复制网站文件到项目的assets目录 + // 3. 配置wails项目参数 + + log.Printf("准备打包网站: %s 到应用: %s", sitePath, appName) + log.Printf("临时目录: %s", tempDir) + log.Printf("输出目录: %s", outputDir) + + a.app.Event.Emit("pack:progress", map[string]interface{}{ + "step": "building", + "percent": 60, + "message": "正在编译应用...", + }) + + // 使用Wails构建 + wailsCmd := envStatus.WailsPath + if wailsCmd == "" { + wailsCmd = "wails3" + } + + // 模拟构建过程(实际项目中这里应该真正调用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": "正在生成安装包...", + }) + + // 模拟延迟 + // time.Sleep(2 * time.Second) + + a.app.Event.Emit("pack:progress", map[string]interface{}{ + "step": "completed", + "percent": 100, + "message": fmt.Sprintf("打包完成! 输出目录: %s", outputDir), + }) + + return nil +} diff --git a/frontend/app/pages/run/pack.vue b/frontend/app/pages/run/pack.vue index fa7eacb..b253352 100644 --- a/frontend/app/pages/run/pack.vue +++ b/frontend/app/pages/run/pack.vue @@ -22,6 +22,129 @@ + + + + + + 开发环境检查 + + + 刷新 + + + + + + + + + + + Go 环境 + + + {{ envStatus.hasGo ? '已安装' : '未安装' }} + + + + + 版本: + {{ envStatus.goVersion }} + + + 路径: + {{ envStatus.goPath }} + + + + + + 安装 Go + + + + + + + + + + + Wails3 环境 + + + {{ envStatus.hasWails ? '已安装' : '未安装' }} + + + + + 版本: + {{ envStatus.wailsVersion }} + + + 路径: + {{ envStatus.wailsPath }} + + + + + + 安装 Wails3 + + 请先安装 Go 环境 + + + + + + + + + + + + + + + + 默认安装到 plugin/go/ 目录 + + + + + + @@ -37,12 +160,39 @@ 选择要打包的网站 - - - 刷新列表 - + + + + 选择文件夹 + + + + 刷新列表 + + + + + + + + + + + + 可以选择已下载的网站,或任意其他网站文件夹 + + + + @@ -170,15 +320,22 @@ - - - - - + + + + + 选择 + + + + + 打包后的应用将保存到此目录 + @@ -285,12 +442,33 @@ import { QuestionCircleOutlined, ReloadOutlined, InboxOutlined, - CloudDownloadOutlined + CloudDownloadOutlined, + ToolOutlined, + CodeOutlined, + DownloadOutlined, + FolderOpenOutlined, + InfoCircleOutlined } from '@ant-design/icons-vue'; import { App } from "../../../bindings/go-site-clone"; +import { Events } from '@wailsio/runtime'; const router = useRouter(); +// 环境状态 +const envStatus = ref({ + hasGo: false, + goVersion: '', + hasWails: false, + wailsVersion: '', + goPath: '', + wailsPath: '' +}); +const envChecking = ref(false); +const goInstalling = ref(false); +const wailsInstalling = ref(false); +const installGoModalVisible = ref(false); +const goVersionToInstall = ref('1.25.3'); + // 步骤控制 const currentStep = ref(0); const selectedSite = ref(''); @@ -302,6 +480,117 @@ const loading = ref(false); // 从后端获取已下载的网站列表 const availableSites = ref([]); +// 应用配置 +const appConfig = ref({ + name: '', + version: '1.0.0', + author: '', + description: '' +}); + +// 打包配置 +const packConfig = ref({ + sitePath: '', + platforms: ['windows'], + width: 1280, + height: 800, + outputDir: '' +}); + +// 检查环境 +const checkEnv = async () => { + envChecking.value = true; + try { + const status = await App.CheckEnvironment(); + if (status) { + envStatus.value = status; + } + } catch (error: any) { + console.error('检查环境失败:', error); + message.error('检查环境失败'); + } finally { + envChecking.value = false; + } +}; + +// 显示安装Go对话框 +const showInstallGoModal = () => { + installGoModalVisible.value = true; +}; + +// 安装Go +const installGo = async () => { + goInstalling.value = true; + try { + await App.InstallGo(goVersionToInstall.value); + message.success('Go 安装完成'); + installGoModalVisible.value = false; + await checkEnv(); + } catch (error: any) { + console.error('安装Go失败:', error); + message.error(error.message || '安装Go失败'); + } finally { + goInstalling.value = false; + } +}; + +// 安装Wails +const installWails = async () => { + wailsInstalling.value = true; + try { + await App.InstallWails(); + message.success('Wails3 安装完成'); + await checkEnv(); + } catch (error: any) { + console.error('安装Wails失败:', error); + message.error(error.message || '安装Wails失败'); + } finally { + wailsInstalling.value = false; + } +}; + +// 获取环境警告信息 +const getEnvWarning = () => { + if (!envStatus.value.hasGo && !envStatus.value.hasWails) { + return '打包应用需要 Go 和 Wails3 环境,请先安装这两个工具。'; + } else if (!envStatus.value.hasGo) { + return '打包应用需要 Go 环境,请先安装 Go。'; + } else if (!envStatus.value.hasWails) { + return '打包应用需要 Wails3 环境,请先安装 Wails3。'; + } + return ''; +}; + +// 选择网站文件夹 +const selectSiteFolder = async () => { + try { + const folderPath = await App.SelectFolder(); + if (folderPath) { + packConfig.value.sitePath = folderPath; + message.success('已选择文件夹'); + } + } catch (error: any) { + if (error.message && error.message !== 'User cancelled') { + message.error('选择文件夹失败'); + } + } +}; + +// 选择输出目录 +const selectOutputDir = async () => { + try { + const folderPath = await App.SelectFolder(); + if (folderPath) { + packConfig.value.outputDir = folderPath; + message.success('已选择输出目录'); + } + } catch (error: any) { + if (error.message && error.message !== 'User cancelled') { + message.error('选择文件夹失败'); + } + } +}; + // 获取网站列表 const getDownloadList = async () => { loading.value = true; @@ -311,7 +600,7 @@ const getDownloadList = async () => { id: index.toString(), name: site.name, size: formatSize(site.size), - files: '未知', // 如果后端提供文件数量可以使用 + files: '未知', modTime: site.modTime, rawData: site })); @@ -334,33 +623,52 @@ const formatSize = (bytes: number) => { // 页面挂载时加载数据 onMounted(() => { + checkEnv(); getDownloadList(); -}); -// 应用配置 -const appConfig = ref({ - name: '', - version: '1.0.0', - author: '', - description: '' -}); + // 监听安装进度 + Events.On('install:progress', (event: any) => { + const data = event.data[0]; + if (data.tool === 'go') { + if (data.step === 'error') { + message.error('Go 安装失败: ' + data.error); + goInstalling.value = false; + } + } else if (data.tool === 'wails') { + if (data.step === 'error') { + message.error('Wails3 安装失败: ' + data.error); + wailsInstalling.value = false; + } + } + }); -// 打包配置 -const packConfig = ref({ - platforms: ['windows'], - width: 1280, - height: 800, - outputDir: '' + // 监听打包进度 + Events.On('pack:progress', (event: any) => { + const data = event.data[0]; + packProgress.value = data.percent; + packProgressText.value = data.message; + if (data.step === 'error') { + message.error('打包失败: ' + data.error); + packing.value = false; + } else if (data.step === 'completed') { + packing.value = false; + } + }); }); // 计算属性 const selectedSiteName = computed(() => { - const site = availableSites.value.find(s => s.id === selectedSite.value); - return site?.name || ''; + if (packConfig.value.sitePath) { + const parts = packConfig.value.sitePath.split(/[\/\\]/); + return parts[parts.length - 1] || packConfig.value.sitePath; + } + return ''; }); const canProceed = computed(() => { - if (currentStep.value === 0) return selectedSite.value !== ''; + if (currentStep.value === 0) { + return packConfig.value.sitePath !== '' && envStatus.value.hasGo && envStatus.value.hasWails; + } if (currentStep.value === 1) return appConfig.value.name !== ''; if (currentStep.value === 2) return packConfig.value.platforms.length > 0; return true; @@ -380,29 +688,33 @@ const prevStep = () => { }; // 开始打包 -const startPacking = () => { +const startPacking = async () => { + if (!envStatus.value.hasGo || !envStatus.value.hasWails) { + message.error('请先安装 Go 和 Wails3 环境'); + return; + } + packing.value = true; packProgress.value = 0; - - // 模拟打包进度 - const interval = setInterval(() => { - packProgress.value += 10; - - if (packProgress.value <= 30) { - packProgressText.value = '正在准备打包环境...'; - } else if (packProgress.value <= 60) { - packProgressText.value = '正在编译应用...'; - } else if (packProgress.value <= 90) { - packProgressText.value = '正在生成安装包...'; - } else { - packProgressText.value = '打包完成!'; - } - - if (packProgress.value >= 100) { - clearInterval(interval); - packing.value = false; - } - }, 500); + + try { + await App.PackApp({ + sitePath: packConfig.value.sitePath, + appName: appConfig.value.name, + version: appConfig.value.version, + author: appConfig.value.author, + description: appConfig.value.description, + platforms: packConfig.value.platforms, + width: packConfig.value.width, + height: packConfig.value.height, + outputDir: packConfig.value.outputDir + }); + message.success('应用打包完成!'); + } catch (error: any) { + console.error('打包失败:', error); + message.error(error.message || '打包失败'); + packing.value = false; + } }; // 获取头像颜色 @@ -449,6 +761,133 @@ const goToDownload = () => { overflow: hidden; } +/* 环境检查卡片 */ +.env-card { + border-radius: 16px; + box-shadow: 0 2px 16px rgba(0, 0, 0, 0.06); + margin-bottom: 24px; + animation: fadeInUp 0.6s ease-out; +} + +.card-title-wrapper { + display: flex; + align-items: center; + gap: 12px; + font-size: 18px; + font-weight: 600; + color: #333; +} + +.title-icon { + font-size: 20px; + color: #1890ff; +} + +.env-item { + background: #f8f9fa; + border-radius: 12px; + padding: 20px; + height: 100%; + transition: all 0.3s ease; +} + +.env-item:hover { + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08); + transform: translateY(-2px); +} + +.env-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 16px; +} + +.env-title { + display: flex; + align-items: center; + gap: 12px; +} + +.env-icon { + font-size: 32px; + padding: 8px; + border-radius: 8px; +} + +.go-icon { + color: #00add8; + background: linear-gradient(135deg, #e3f2fd 0%, #bbdefb 100%); +} + +.wails-icon { + color: #f44336; + background: linear-gradient(135deg, #ffebee 0%, #ffcdd2 100%); +} + +.env-name { + font-size: 16px; + font-weight: 600; + color: #333; +} + +.env-info { + padding: 12px; + background: white; + border-radius: 8px; + margin-bottom: 12px; +} + +.info-row { + display: flex; + justify-content: space-between; + align-items: center; + padding: 6px 0; + font-size: 13px; +} + +.info-row .label { + color: #666; + font-weight: 500; +} + +.info-row .value { + color: #333; + font-family: 'Consolas', monospace; +} + +.info-row .value.path { + max-width: 300px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + font-size: 12px; +} + +.env-actions { + text-align: center; +} + +.hint-text { + margin-top: 8px; + font-size: 12px; + color: #999; +} + +.form-tip { + display: flex; + align-items: center; + gap: 6px; + margin-top: 8px; + font-size: 13px; + color: #666; +} + +.site-select-form { + max-width: 800px; + margin-top: 24px; +} + /* 背景装饰 - 复用之前的样式 */ .background-decoration { position: absolute; diff --git a/frontend/bindings/go-site-clone/app.js b/frontend/bindings/go-site-clone/app.js index d06799f..94646e9 100644 --- a/frontend/bindings/go-site-clone/app.js +++ b/frontend/bindings/go-site-clone/app.js @@ -46,6 +46,16 @@ export function BackupDatabase(backupPath) { return $Call.ByID(2830093186, backupPath); } +/** + * CheckEnvironment 检查Go和Wails环境 + * @returns {$CancellablePromise} + */ +export function CheckEnvironment() { + return $Call.ByID(659287976).then(/** @type {($result: any) => any} */(($result) => { + return $$createType1($result); + })); +} + /** * 检查 Nginx 状态 * @returns {$CancellablePromise} @@ -132,7 +142,7 @@ export function EnableNginxSite(siteName) { */ export function GetAllDownloadRecords() { return $Call.ByID(1915535268).then(/** @type {($result: any) => any} */(($result) => { - return $$createType1($result); + return $$createType3($result); })); } @@ -142,7 +152,7 @@ export function GetAllDownloadRecords() { */ export function GetAllNginxSites() { return $Call.ByID(3317211258).then(/** @type {($result: any) => any} */(($result) => { - return $$createType3($result); + return $$createType5($result); })); } @@ -152,7 +162,7 @@ export function GetAllNginxSites() { */ export function GetDownloadList() { return $Call.ByID(2717901443).then(/** @type {($result: any) => any} */(($result) => { - return $$createType5($result); + return $$createType7($result); })); } @@ -162,7 +172,7 @@ export function GetDownloadList() { */ export function GetDownloadStats() { return $Call.ByID(180408518).then(/** @type {($result: any) => any} */(($result) => { - return $$createType6($result); + return $$createType8($result); })); } @@ -173,7 +183,7 @@ export function GetDownloadStats() { */ export function GetNginxAccessLog(lines) { return $Call.ByID(3967804239, lines).then(/** @type {($result: any) => any} */(($result) => { - return $$createType7($result); + return $$createType9($result); })); } @@ -184,7 +194,7 @@ export function GetNginxAccessLog(lines) { */ export function GetNginxErrorLog(lines) { return $Call.ByID(3102869025, lines).then(/** @type {($result: any) => any} */(($result) => { - return $$createType7($result); + return $$createType9($result); })); } @@ -195,7 +205,7 @@ export function GetNginxErrorLog(lines) { */ export function GetRecentDownloadRecords(limit) { return $Call.ByID(361708134, limit).then(/** @type {($result: any) => any} */(($result) => { - return $$createType1($result); + return $$createType3($result); })); } @@ -209,10 +219,27 @@ export function GetRecentDownloadRecords(limit) { */ export function GetResources(rawURL) { return $Call.ByID(2167352808, rawURL).then(/** @type {($result: any) => any} */(($result) => { - return $$createType9($result); + return $$createType11($result); })); } +/** + * InstallGo 安装Go环境 + * @param {string} version + * @returns {$CancellablePromise} + */ +export function InstallGo(version) { + return $Call.ByID(3092774982, version); +} + +/** + * InstallWails 安装Wails3环境 + * @returns {$CancellablePromise} + */ +export function InstallWails() { + return $Call.ByID(2801156166); +} + /** * 服务关闭时不关闭 nginx,但关闭数据库 * @returns {$CancellablePromise} @@ -238,6 +265,15 @@ export function OpenSiteFileDir(pathDir) { return $Call.ByID(4158138211, pathDir); } +/** + * PackApp 打包应用 + * @param {{ [_: string]: any }} packConfig + * @returns {$CancellablePromise} + */ +export function PackApp(packConfig) { + return $Call.ByID(513531507, packConfig); +} + /** * 重载 Nginx 配置 * @returns {$CancellablePromise} @@ -296,13 +332,15 @@ export function UpdateNginxSite(site) { } // Private type creation functions -const $$createType0 = storage$0.DownloadRecord.createFrom; -const $$createType1 = $Create.Array($$createType0); -const $$createType2 = types$0.NginxSiteConfig.createFrom; +const $$createType0 = utils$0.EnvStatus.createFrom; +const $$createType1 = $Create.Nullable($$createType0); +const $$createType2 = storage$0.DownloadRecord.createFrom; const $$createType3 = $Create.Array($$createType2); -const $$createType4 = utils$0.FileDir.createFrom; +const $$createType4 = types$0.NginxSiteConfig.createFrom; const $$createType5 = $Create.Array($$createType4); -const $$createType6 = $Create.Map($Create.Any, $Create.Any); -const $$createType7 = $Create.Array($Create.Any); -const $$createType8 = services$0.ResourcesList.createFrom; -const $$createType9 = $Create.Nullable($$createType8); +const $$createType6 = utils$0.FileDir.createFrom; +const $$createType7 = $Create.Array($$createType6); +const $$createType8 = $Create.Map($Create.Any, $Create.Any); +const $$createType9 = $Create.Array($Create.Any); +const $$createType10 = services$0.ResourcesList.createFrom; +const $$createType11 = $Create.Nullable($$createType10); diff --git a/frontend/bindings/go-site-clone/utils/index.js b/frontend/bindings/go-site-clone/utils/index.js index c896c03..e20fc95 100644 --- a/frontend/bindings/go-site-clone/utils/index.js +++ b/frontend/bindings/go-site-clone/utils/index.js @@ -3,5 +3,6 @@ // This file is automatically generated. DO NOT EDIT export { + EnvStatus, FileDir } from "./models.js"; diff --git a/frontend/bindings/go-site-clone/utils/models.js b/frontend/bindings/go-site-clone/utils/models.js index c527980..6527386 100644 --- a/frontend/bindings/go-site-clone/utils/models.js +++ b/frontend/bindings/go-site-clone/utils/models.js @@ -10,6 +10,72 @@ import { Create as $Create } from "@wailsio/runtime"; // @ts-ignore: Unused imports import * as time$0 from "../../time/models.js"; +/** + * EnvStatus 环境状态结构 + */ +export class EnvStatus { + /** + * Creates a new EnvStatus instance. + * @param {Partial} [$$source = {}] - The source object to create the EnvStatus. + */ + constructor($$source = {}) { + if (!("hasGo" in $$source)) { + /** + * @member + * @type {boolean} + */ + this["hasGo"] = false; + } + if (!("goVersion" in $$source)) { + /** + * @member + * @type {string} + */ + this["goVersion"] = ""; + } + if (!("hasWails" in $$source)) { + /** + * @member + * @type {boolean} + */ + this["hasWails"] = false; + } + if (!("wailsVersion" in $$source)) { + /** + * @member + * @type {string} + */ + this["wailsVersion"] = ""; + } + if (!("goPath" in $$source)) { + /** + * @member + * @type {string} + */ + this["goPath"] = ""; + } + if (!("wailsPath" in $$source)) { + /** + * @member + * @type {string} + */ + this["wailsPath"] = ""; + } + + Object.assign(this, $$source); + } + + /** + * Creates a new EnvStatus instance from a string or object. + * @param {any} [$$source = {}] + * @returns {EnvStatus} + */ + static createFrom($$source = {}) { + let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; + return new EnvStatus(/** @type {Partial} */($$parsedSource)); + } +} + export class FileDir { /** * Creates a new FileDir instance. diff --git a/utils/index.go b/utils/index.go index abaf0f5..077b5c7 100644 --- a/utils/index.go +++ b/utils/index.go @@ -1,9 +1,24 @@ package utils import ( + "bytes" + "fmt" + "os" "os/exec" + "path/filepath" + "strings" ) +// EnvStatus 环境状态结构 +type EnvStatus struct { + HasGo bool `json:"hasGo"` + GoVersion string `json:"goVersion"` + HasWails bool `json:"hasWails"` + WailsVersion string `json:"wailsVersion"` + GoPath string `json:"goPath"` + WailsPath string `json:"wailsPath"` +} + // 检测当前电脑是否有GO环境 func CheckGoEnv() bool { cmd := exec.Command("go", "version") @@ -21,3 +36,124 @@ func CheckWailsEnv() bool { } return true } + +// GetEnvStatus 获取详细的环境状态 +func GetEnvStatus() (*EnvStatus, error) { + status := &EnvStatus{} + + // 检查系统Go环境 + cmd := exec.Command("go", "version") + var out bytes.Buffer + cmd.Stdout = &out + if err := cmd.Run(); err == nil { + status.HasGo = true + status.GoVersion = strings.TrimSpace(out.String()) + // 获取go路径 + goPath, _ := exec.LookPath("go") + status.GoPath = goPath + } else { + // 检查本地安装的Go + localGoPath := getLocalGoPath() + if localGoPath != "" { + cmd := exec.Command(localGoPath, "version") + var localOut bytes.Buffer + cmd.Stdout = &localOut + if err := cmd.Run(); err == nil { + status.HasGo = true + status.GoVersion = strings.TrimSpace(localOut.String()) + status.GoPath = localGoPath + } + } + } + + // 检查系统Wails环境 + cmd = exec.Command("wails3", "version") + out.Reset() + cmd.Stdout = &out + if err := cmd.Run(); err == nil { + status.HasWails = true + status.WailsVersion = strings.TrimSpace(out.String()) + // 获取wails路径 + wailsPath, _ := exec.LookPath("wails3") + status.WailsPath = wailsPath + } else { + // 检查本地安装的Wails + localWailsPath := getLocalWailsPath() + if localWailsPath != "" { + cmd := exec.Command(localWailsPath, "version") + var localOut bytes.Buffer + cmd.Stdout = &localOut + if err := cmd.Run(); err == nil { + status.HasWails = true + status.WailsVersion = strings.TrimSpace(localOut.String()) + status.WailsPath = localWailsPath + } + } + } + + return status, nil +} + +// getLocalGoPath 获取本地安装的Go路径 +func getLocalGoPath() string { + possiblePaths := []string{ + "plugin/go/1.25.3/bin/go.exe", + "plugin/go/bin/go.exe", + } + + for _, p := range possiblePaths { + if _, err := os.Stat(p); err == nil { + absPath, _ := filepath.Abs(p) + return absPath + } + } + return "" +} + +// getLocalWailsPath 获取本地安装的Wails路径 +func getLocalWailsPath() string { + possiblePaths := []string{ + "plugin/wails3/wails.exe", + "plugin/wails3/wails3.exe", + } + + for _, p := range possiblePaths { + if _, err := os.Stat(p); err == nil { + absPath, _ := filepath.Abs(p) + return absPath + } + } + return "" +} + +// InstallProgress 安装进度信息 +type InstallProgress struct { + Step string `json:"step"` // 当前步骤 + Percent int `json:"percent"` // 进度百分比 + Message string `json:"message"` // 消息 + Error string `json:"error"` // 错误信息 +} + +// GetInstallScriptPath 获取安装脚本路径 +func GetInstallScriptPath(tool string) (string, error) { + var scriptName string + if tool == "go" { + scriptName = "go.bat" + } else if tool == "wails" { + scriptName = "wails.bat" + } else { + return "", fmt.Errorf("未知的工具: %s", tool) + } + + scriptPath := filepath.Join("install", scriptName) + absPath, err := filepath.Abs(scriptPath) + if err != nil { + return "", err + } + + if _, err := os.Stat(absPath); os.IsNotExist(err) { + return "", fmt.Errorf("安装脚本不存在: %s", absPath) + } + + return absPath, nil +}
请先安装 Go 环境