Files
ssq-desk/internal/api/update_api.go
2026-01-14 14:17:38 +08:00

255 lines
6.4 KiB
Go

package api
import (
"context"
"encoding/json"
"ssq-desk/internal/service"
"time"
"github.com/wailsapp/wails/v2/pkg/runtime"
)
// UpdateAPI 版本更新 API
type UpdateAPI struct {
updateService *service.UpdateService
ctx context.Context
}
// NewUpdateAPI 创建版本更新 API
func NewUpdateAPI(checkURL string) (*UpdateAPI, error) {
updateService := service.NewUpdateService(checkURL)
return &UpdateAPI{
updateService: updateService,
}, nil
}
// SetContext 设置上下文(用于事件推送)
func (api *UpdateAPI) SetContext(ctx context.Context) {
api.ctx = ctx
}
// CheckUpdate 检查更新
func (api *UpdateAPI) CheckUpdate() (map[string]interface{}, error) {
if api.updateService == nil {
return map[string]interface{}{
"success": false,
"message": "更新服务未初始化",
}, nil
}
result, err := api.updateService.CheckUpdate()
if err != nil {
errorMsg := err.Error()
if errorMsg == "" {
errorMsg = "未知错误"
}
return map[string]interface{}{
"success": false,
"message": errorMsg,
}, nil
}
if result == nil {
return map[string]interface{}{
"success": false,
"message": "检查更新返回结果为空",
}, nil
}
return map[string]interface{}{
"success": true,
"data": result,
}, nil
}
// GetCurrentVersion 获取当前版本号
func (api *UpdateAPI) GetCurrentVersion() (map[string]interface{}, error) {
version := service.GetCurrentVersion()
// 更新配置中的版本号
if config, err := service.LoadUpdateConfig(); err == nil && config.CurrentVersion != version {
config.CurrentVersion = version
service.SaveUpdateConfig(config)
}
return map[string]interface{}{
"success": true,
"data": map[string]interface{}{
"version": version,
},
}, nil
}
// GetUpdateConfig 获取更新配置
func (api *UpdateAPI) GetUpdateConfig() (map[string]interface{}, error) {
config, err := service.LoadUpdateConfig()
if err != nil {
return map[string]interface{}{
"success": false,
"message": err.Error(),
}, nil
}
// 确保版本号是最新的
latestVersion := service.GetCurrentVersion()
if config.CurrentVersion != latestVersion {
config.CurrentVersion = latestVersion
service.SaveUpdateConfig(config)
}
return map[string]interface{}{
"success": true,
"data": map[string]interface{}{
"current_version": config.CurrentVersion,
"last_check_time": config.LastCheckTime.Format("2006-01-02 15:04:05"),
"auto_check_enabled": config.AutoCheckEnabled,
"check_interval_minutes": config.CheckIntervalMinutes,
"check_url": config.CheckURL,
},
}, nil
}
// SetUpdateConfig 设置更新配置
func (api *UpdateAPI) SetUpdateConfig(autoCheckEnabled bool, checkIntervalMinutes int, checkURL string) (map[string]interface{}, error) {
config, err := service.LoadUpdateConfig()
if err != nil {
return map[string]interface{}{
"success": false,
"message": err.Error(),
}, nil
}
config.AutoCheckEnabled = autoCheckEnabled
config.CheckIntervalMinutes = checkIntervalMinutes
if checkURL != "" {
config.CheckURL = checkURL
// 如果 URL 改变,需要重新创建服务
api.updateService = service.NewUpdateService(checkURL)
}
if err := service.SaveUpdateConfig(config); err != nil {
return map[string]interface{}{
"success": false,
"message": err.Error(),
}, nil
}
return map[string]interface{}{
"success": true,
"message": "配置保存成功",
}, nil
}
// DownloadUpdate 下载更新包(异步,通过事件推送进度)
func (api *UpdateAPI) DownloadUpdate(downloadURL string) (map[string]interface{}, error) {
if downloadURL == "" {
return map[string]interface{}{
"success": false,
"message": "下载地址不能为空",
}, nil
}
go func() {
progressCallback := func(progress float64, speed float64, downloaded int64, total int64) {
if api.ctx == nil {
return
}
// 确保进度值在 0-100 之间
if progress < 0 {
progress = 0
} else if progress > 100 {
progress = 100
}
progressInfo := map[string]interface{}{
"progress": progress,
"speed": speed,
"downloaded": downloaded,
"total": total,
}
progressJSON, _ := json.Marshal(progressInfo)
runtime.EventsEmit(api.ctx, "download-progress", string(progressJSON))
time.Sleep(10 * time.Millisecond)
}
time.Sleep(100 * time.Millisecond)
result, err := service.DownloadUpdate(downloadURL, progressCallback)
if api.ctx != nil {
if err != nil {
errorInfo := map[string]interface{}{"error": err.Error()}
errorJSON, _ := json.Marshal(errorInfo)
runtime.EventsEmit(api.ctx, "download-complete", string(errorJSON))
} else {
resultInfo := map[string]interface{}{
"success": true,
"file_path": result.FilePath,
"file_size": result.FileSize,
}
resultJSON, _ := json.Marshal(resultInfo)
runtime.EventsEmit(api.ctx, "download-complete", string(resultJSON))
}
}
}()
return map[string]interface{}{
"success": true,
"message": "下载已开始",
}, nil
}
// InstallUpdate 安装更新包
func (api *UpdateAPI) InstallUpdate(installerPath string, autoRestart bool) (map[string]interface{}, error) {
return api.InstallUpdateWithHash(installerPath, autoRestart, "", "")
}
// InstallUpdateWithHash 安装更新包(带哈希验证)
func (api *UpdateAPI) InstallUpdateWithHash(installerPath string, autoRestart bool, expectedHash string, hashType string) (map[string]interface{}, error) {
if installerPath == "" {
return map[string]interface{}{
"success": false,
"message": "安装文件路径不能为空",
}, nil
}
result, err := service.InstallUpdateWithHash(installerPath, autoRestart, expectedHash, hashType)
if err != nil {
return map[string]interface{}{
"success": false,
"message": err.Error(),
}, nil
}
return map[string]interface{}{
"success": result.Success,
"message": result.Message,
"data": result,
}, nil
}
// VerifyUpdateFile 验证更新文件哈希值
func (api *UpdateAPI) VerifyUpdateFile(filePath string, expectedHash string, hashType string) (map[string]interface{}, error) {
if filePath == "" {
return map[string]interface{}{
"success": false,
"message": "文件路径不能为空",
}, nil
}
valid, err := service.VerifyFileHash(filePath, expectedHash, hashType)
if err != nil {
return map[string]interface{}{
"success": false,
"message": err.Error(),
}, nil
}
return map[string]interface{}{
"success": true,
"data": map[string]interface{}{
"valid": valid,
},
}, nil
}