修复: 版本更新与设置面板走查问题
- 更新链路: 检查记录远端SHA256,下载完成事件回传,安装时带哈希校验 - 续传: 服务器忽略Range返回200时截断重下防追加损坏,文件名去query - 定时器: 自动检查可重入,配置变更免重启生效,关闭即停,下载加互斥 - 前端: 支持跳过此版本并按版本去重,手动检查不受门禁限制,启动未就绪延时重试 - 更新面板: 新增自动检查开关/间隔/地址配置与进度条状态映射 - 版本历史: cache参数强制刷新与加载超时重试兜底 - 配置: 侧边栏分区全链路持久化,保存请求复用api类型防字段丢失 - 侧边栏: 区块定位改显式类名,不再依赖排序位置 - 绑定: 重新生成并与镜像目录同步
This commit is contained in:
@@ -2,15 +2,20 @@ package api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"u-desk/internal/service"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"u-desk/internal/service"
|
||||
)
|
||||
|
||||
// UpdateAPI 版本更新 API
|
||||
type UpdateAPI struct {
|
||||
updateService *service.UpdateService
|
||||
ctx context.Context
|
||||
eventEmitter func(name string, data ...any)
|
||||
updateService *service.UpdateService
|
||||
ctx context.Context
|
||||
eventEmitter func(name string, data ...any)
|
||||
configChanged func() // 更新配置变更回调(重置自动检查定时器)
|
||||
expectedSHA256 string // 最近一次检查得到的远端包 SHA256
|
||||
downloading atomic.Bool // 下载进行中标志(并发互斥)
|
||||
}
|
||||
|
||||
// NewUpdateAPI 创建版本更新 API
|
||||
@@ -25,6 +30,11 @@ func (api *UpdateAPI) SetEventEmitter(emitter func(name string, data ...any)) {
|
||||
api.eventEmitter = emitter
|
||||
}
|
||||
|
||||
// SetConfigChangedCallback 设置配置变更回调(由 App 注入,用于重置自动检查定时器)
|
||||
func (api *UpdateAPI) SetConfigChangedCallback(cb func()) {
|
||||
api.configChanged = cb
|
||||
}
|
||||
|
||||
// SetContext 设置上下文(用于事件推送)
|
||||
func (api *UpdateAPI) SetContext(ctx context.Context) {
|
||||
api.ctx = ctx
|
||||
@@ -54,6 +64,9 @@ func (api *UpdateAPI) CheckUpdate() (map[string]interface{}, error) {
|
||||
return errorResponse(err.Error()), nil
|
||||
}
|
||||
|
||||
// 记录远端包哈希,供下载完成事件比对
|
||||
api.expectedSHA256 = result.SHA256
|
||||
|
||||
return successResponse(result), nil
|
||||
}
|
||||
|
||||
@@ -99,6 +112,11 @@ func (api *UpdateAPI) SetUpdateConfig(autoCheckEnabled bool, checkIntervalMinute
|
||||
return errorResponse(err.Error()), nil
|
||||
}
|
||||
|
||||
// 配置已变更,通知重置自动检查定时器(免重启生效)
|
||||
if api.configChanged != nil {
|
||||
api.configChanged()
|
||||
}
|
||||
|
||||
return successResponse(map[string]interface{}{
|
||||
"message": "配置保存成功",
|
||||
}), nil
|
||||
@@ -110,7 +128,14 @@ func (api *UpdateAPI) DownloadUpdate(downloadURL string) (map[string]interface{}
|
||||
return errorResponse("下载地址不能为空"), nil
|
||||
}
|
||||
|
||||
// 并发互斥:已有下载任务进行中则拒绝
|
||||
if !api.downloading.CompareAndSwap(false, true) {
|
||||
return errorResponse("已有下载任务进行中"), nil
|
||||
}
|
||||
|
||||
go func() {
|
||||
defer api.downloading.Store(false)
|
||||
|
||||
progressCallback := func(progress float64, speed float64, downloaded int64, total int64) {
|
||||
progressInfo := map[string]interface{}{
|
||||
"progress": progress,
|
||||
@@ -129,9 +154,11 @@ func (api *UpdateAPI) DownloadUpdate(downloadURL string) (map[string]interface{}
|
||||
api.emit("download-complete", errorInfo)
|
||||
} else {
|
||||
resultInfo := map[string]interface{}{
|
||||
"success": true,
|
||||
"file_path": result.FilePath,
|
||||
"file_size": result.FileSize,
|
||||
"success": true,
|
||||
"file_path": result.FilePath,
|
||||
"file_size": result.FileSize,
|
||||
"sha256": result.SHA256Hash,
|
||||
"expected_sha256": api.expectedSHA256,
|
||||
}
|
||||
api.emit("download-complete", resultInfo)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user