- web/ → frontend/ 目录重命名(Wails v3 标准结构) - main.go: Middleware 修复 custom.js 404 + DevTools 延迟启动 - Sidebar: 收藏夹内部独立滚动 + 帮助区块固定底部 - useFavorites.ts: longPressTimer const→let 修复 TypeError - App.vue: Arco Tabs padding-top 覆盖 - build: config.yml / Taskfile.yml 对齐官方模板,devtools build tag - 新增 v3 bindings、vite.config.js、跨平台构建配置 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
179 lines
5.1 KiB
Go
179 lines
5.1 KiB
Go
package api
|
|
|
|
import (
|
|
"context"
|
|
"u-desk/internal/service"
|
|
"time"
|
|
)
|
|
|
|
// UpdateAPI 版本更新 API
|
|
type UpdateAPI struct {
|
|
updateService *service.UpdateService
|
|
ctx context.Context
|
|
eventEmitter func(name string, data ...any)
|
|
}
|
|
|
|
// NewUpdateAPI 创建版本更新 API
|
|
func NewUpdateAPI(checkURL string) (*UpdateAPI, error) {
|
|
return &UpdateAPI{
|
|
updateService: service.NewUpdateService(checkURL),
|
|
}, nil
|
|
}
|
|
|
|
// SetEventEmitter 设置事件发射器(由 App.ServiceStartup 注入)
|
|
func (api *UpdateAPI) SetEventEmitter(emitter func(name string, data ...any)) {
|
|
api.eventEmitter = emitter
|
|
}
|
|
|
|
// SetContext 设置上下文(用于事件推送)
|
|
func (api *UpdateAPI) SetContext(ctx context.Context) {
|
|
api.ctx = ctx
|
|
}
|
|
|
|
// emit 发送事件到前端
|
|
func (api *UpdateAPI) emit(name string, data ...any) {
|
|
if api.eventEmitter != nil {
|
|
api.eventEmitter(name, data...)
|
|
}
|
|
}
|
|
|
|
// successResponse 构造成功响应
|
|
func successResponse(data interface{}) map[string]interface{} {
|
|
return map[string]interface{}{"success": true, "data": data}
|
|
}
|
|
|
|
// errorResponse 构造错误响应
|
|
func errorResponse(message string) map[string]interface{} {
|
|
return map[string]interface{}{"success": false, "message": message}
|
|
}
|
|
|
|
// CheckUpdate 检查更新
|
|
func (api *UpdateAPI) CheckUpdate() (map[string]interface{}, error) {
|
|
result, err := api.updateService.CheckUpdate()
|
|
if err != nil {
|
|
return errorResponse(err.Error()), nil
|
|
}
|
|
|
|
return successResponse(result), nil
|
|
}
|
|
|
|
// GetCurrentVersion 获取当前版本号
|
|
func (api *UpdateAPI) GetCurrentVersion() (map[string]interface{}, error) {
|
|
version := service.GetCurrentVersion()
|
|
return successResponse(map[string]interface{}{
|
|
"version": version,
|
|
}), nil
|
|
}
|
|
|
|
// GetUpdateConfig 获取更新配置
|
|
func (api *UpdateAPI) GetUpdateConfig() (map[string]interface{}, error) {
|
|
config, err := service.LoadUpdateConfig()
|
|
if err != nil {
|
|
return errorResponse(err.Error()), nil
|
|
}
|
|
|
|
return successResponse(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 errorResponse(err.Error()), nil
|
|
}
|
|
|
|
config.AutoCheckEnabled = autoCheckEnabled
|
|
config.CheckIntervalMinutes = checkIntervalMinutes
|
|
if checkURL != "" {
|
|
config.CheckURL = checkURL
|
|
api.updateService = service.NewUpdateService(checkURL)
|
|
}
|
|
|
|
if err := service.SaveUpdateConfig(config); err != nil {
|
|
return errorResponse(err.Error()), nil
|
|
}
|
|
|
|
return successResponse(map[string]interface{}{
|
|
"message": "配置保存成功",
|
|
}), nil
|
|
}
|
|
|
|
// DownloadUpdate 下载更新包(异步,通过事件推送进度)
|
|
func (api *UpdateAPI) DownloadUpdate(downloadURL string) (map[string]interface{}, error) {
|
|
if downloadURL == "" {
|
|
return errorResponse("下载地址不能为空"), nil
|
|
}
|
|
|
|
go func() {
|
|
progressCallback := func(progress float64, speed float64, downloaded int64, total int64) {
|
|
progressInfo := map[string]interface{}{
|
|
"progress": progress,
|
|
"speed": speed,
|
|
"downloaded": downloaded,
|
|
"total": total,
|
|
}
|
|
api.emit("download-progress", progressInfo)
|
|
}
|
|
|
|
time.Sleep(100 * time.Millisecond)
|
|
result, err := service.DownloadUpdate(downloadURL, progressCallback)
|
|
|
|
if err != nil {
|
|
errorInfo := map[string]interface{}{"error": err.Error()}
|
|
api.emit("download-complete", errorInfo)
|
|
} else {
|
|
resultInfo := map[string]interface{}{
|
|
"success": true,
|
|
"file_path": result.FilePath,
|
|
"file_size": result.FileSize,
|
|
}
|
|
api.emit("download-complete", resultInfo)
|
|
}
|
|
}()
|
|
|
|
return successResponse(map[string]interface{}{
|
|
"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 errorResponse("安装文件路径不能为空"), nil
|
|
}
|
|
|
|
result, err := service.InstallUpdateWithHash(installerPath, autoRestart, expectedHash, hashType)
|
|
if err != nil {
|
|
return errorResponse(err.Error()), nil
|
|
}
|
|
|
|
return successResponse(result), nil
|
|
}
|
|
|
|
// VerifyUpdateFile 验证更新文件哈希值
|
|
func (api *UpdateAPI) VerifyUpdateFile(filePath string, expectedHash string, hashType string) (map[string]interface{}, error) {
|
|
if filePath == "" {
|
|
return errorResponse("文件路径不能为空"), nil
|
|
}
|
|
|
|
valid, err := service.VerifyFileHash(filePath, expectedHash, hashType)
|
|
if err != nil {
|
|
return errorResponse(err.Error()), nil
|
|
}
|
|
|
|
return successResponse(map[string]interface{}{
|
|
"valid": valid,
|
|
}), nil
|
|
}
|