新增软件打包模块

This commit is contained in:
zyj
2025-11-22 18:47:47 +08:00
parent c854ebd819
commit f393d2b1de
6 changed files with 979 additions and 69 deletions

230
app.go
View File

@@ -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
}

View File

@@ -22,6 +22,129 @@
</div>
</div>
<!-- 环境检查卡片 -->
<a-card class="env-card" :bordered="false">
<template #title>
<div class="card-title-wrapper">
<tool-outlined class="title-icon" />
<span>开发环境检查</span>
<a-button type="link" size="small" @click="checkEnv" :loading="envChecking">
<template #icon><reload-outlined /></template>
刷新
</a-button>
</div>
</template>
<a-row :gutter="24">
<a-col :xs="24" :md="12">
<div class="env-item">
<div class="env-header">
<div class="env-title">
<code-outlined class="env-icon go-icon" />
<span class="env-name">Go 环境</span>
</div>
<a-tag :color="envStatus.hasGo ? 'success' : 'default'">
{{ envStatus.hasGo ? '已安装' : '未安装' }}
</a-tag>
</div>
<div class="env-info" v-if="envStatus.hasGo">
<div class="info-row">
<span class="label">版本:</span>
<span class="value">{{ envStatus.goVersion }}</span>
</div>
<div class="info-row">
<span class="label">路径:</span>
<span class="value path">{{ envStatus.goPath }}</span>
</div>
</div>
<div class="env-actions" v-if="!envStatus.hasGo">
<a-button
type="primary"
@click="showInstallGoModal"
:loading="goInstalling"
>
<template #icon><download-outlined /></template>
安装 Go
</a-button>
</div>
</div>
</a-col>
<a-col :xs="24" :md="12">
<div class="env-item">
<div class="env-header">
<div class="env-title">
<code-outlined class="env-icon wails-icon" />
<span class="env-name">Wails3 环境</span>
</div>
<a-tag :color="envStatus.hasWails ? 'success' : 'default'">
{{ envStatus.hasWails ? '已安装' : '未安装' }}
</a-tag>
</div>
<div class="env-info" v-if="envStatus.hasWails">
<div class="info-row">
<span class="label">版本:</span>
<span class="value">{{ envStatus.wailsVersion }}</span>
</div>
<div class="info-row">
<span class="label">路径:</span>
<span class="value path">{{ envStatus.wailsPath }}</span>
</div>
</div>
<div class="env-actions" v-if="!envStatus.hasWails">
<a-button
type="primary"
@click="installWails"
:loading="wailsInstalling"
:disabled="!envStatus.hasGo"
>
<template #icon><download-outlined /></template>
安装 Wails3
</a-button>
<p class="hint-text" v-if="!envStatus.hasGo">请先安装 Go 环境</p>
</div>
</div>
</a-col>
</a-row>
<a-alert
v-if="!envStatus.hasGo || !envStatus.hasWails"
type="warning"
message="环境检查"
:description="getEnvWarning()"
show-icon
style="margin-top: 16px;"
/>
</a-card>
<!-- 安装Go对话框 -->
<a-modal
v-model:open="installGoModalVisible"
title="安装 Go 环境"
@ok="installGo"
@cancel="installGoModalVisible = false"
:confirm-loading="goInstalling"
>
<a-form layout="vertical">
<a-form-item label="Go 版本">
<a-input
v-model:value="goVersionToInstall"
placeholder="1.25.3"
/>
<div class="form-tip" style="margin-top: 8px;">
<info-circle-outlined />
<span>默认安装到 plugin/go/ 目录</span>
</div>
</a-form-item>
</a-form>
<a-alert
message="安装说明"
description="安装过程可能需要几分钟,请耐心等待。安装脚本会自动下载并解压 Go 到本地目录。"
type="info"
show-icon
/>
</a-modal>
<!-- 打包向导 -->
<a-card class="wizard-card" :bordered="false">
<a-steps :current="currentStep" class="pack-steps">
@@ -37,12 +160,39 @@
<div v-if="currentStep === 0" class="step-panel">
<div class="step-header">
<h3 class="step-title">选择要打包的网站</h3>
<a-space>
<a-button @click="selectSiteFolder" size="small">
<template #icon><folder-open-outlined /></template>
选择文件夹
</a-button>
<a-button @click="getDownloadList" :loading="loading" size="small">
<template #icon><reload-outlined /></template>
刷新列表
</a-button>
</a-space>
</div>
<a-form layout="vertical" class="site-select-form">
<a-form-item label="网站路径" required>
<a-input
v-model:value="packConfig.sitePath"
placeholder="请选择或输入网站文件夹路径"
size="large"
>
<template #suffix>
<folder-outlined
class="input-icon"
@click="selectSiteFolder"
/>
</template>
</a-input>
<div class="form-tip">
<info-circle-outlined />
<span>可以选择已下载的网站,或任意其他网站文件夹</span>
</div>
</a-form-item>
</a-form>
<div v-if="loading" class="loading-state">
<a-spin size="large" tip="加载中..." />
</div>
@@ -170,15 +320,22 @@
</a-row>
<a-form-item label="输出目录">
<a-input-group compact style="display: flex;">
<a-input
v-model:value="packConfig.outputDir"
placeholder="选择输出目录"
size="large"
>
<template #suffix>
<folder-outlined class="input-icon" />
</template>
</a-input>
style="flex: 1;"
/>
<a-button size="large" @click="selectOutputDir">
<template #icon><folder-open-outlined /></template>
选择
</a-button>
</a-input-group>
<div class="form-tip">
<info-circle-outlined />
<span>打包后的应用将保存到此目录</span>
</div>
</a-form-item>
</a-form>
</div>
@@ -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<string>('');
@@ -302,6 +480,117 @@ const loading = ref(false);
// 从后端获取已下载的网站列表
const availableSites = ref<any[]>([]);
// 应用配置
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();
// 监听安装进度
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 appConfig = ref({
name: '',
version: '1.0.0',
author: '',
description: ''
// 监听打包进度
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 packConfig = ref({
platforms: ['windows'],
width: 1280,
height: 800,
outputDir: ''
});
// 计算属性
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);
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;
}
}, 500);
};
// 获取头像颜色
@@ -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;

View File

@@ -46,6 +46,16 @@ export function BackupDatabase(backupPath) {
return $Call.ByID(2830093186, backupPath);
}
/**
* CheckEnvironment 检查Go和Wails环境
* @returns {$CancellablePromise<utils$0.EnvStatus | null>}
*/
export function CheckEnvironment() {
return $Call.ByID(659287976).then(/** @type {($result: any) => any} */(($result) => {
return $$createType1($result);
}));
}
/**
* 检查 Nginx 状态
* @returns {$CancellablePromise<boolean>}
@@ -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<void>}
*/
export function InstallGo(version) {
return $Call.ByID(3092774982, version);
}
/**
* InstallWails 安装Wails3环境
* @returns {$CancellablePromise<void>}
*/
export function InstallWails() {
return $Call.ByID(2801156166);
}
/**
* 服务关闭时不关闭 nginx但关闭数据库
* @returns {$CancellablePromise<void>}
@@ -238,6 +265,15 @@ export function OpenSiteFileDir(pathDir) {
return $Call.ByID(4158138211, pathDir);
}
/**
* PackApp 打包应用
* @param {{ [_: string]: any }} packConfig
* @returns {$CancellablePromise<void>}
*/
export function PackApp(packConfig) {
return $Call.ByID(513531507, packConfig);
}
/**
* 重载 Nginx 配置
* @returns {$CancellablePromise<void>}
@@ -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);

View File

@@ -3,5 +3,6 @@
// This file is automatically generated. DO NOT EDIT
export {
EnvStatus,
FileDir
} from "./models.js";

View File

@@ -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<EnvStatus>} [$$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<EnvStatus>} */($$parsedSource));
}
}
export class FileDir {
/**
* Creates a new FileDir instance.

View File

@@ -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
}