diff --git a/internal/tasks/task_check_updates.go b/internal/tasks/task_check_updates.go index 078e4efd..62f86d8b 100644 --- a/internal/tasks/task_check_updates.go +++ b/internal/tasks/task_check_updates.go @@ -119,7 +119,7 @@ func (this *CheckUpdatesTask) Loop() error { var vMap = maps.NewMap(version) if vMap.GetString("code") == "admin" { var latestVersion = vMap.GetString("version") - if stringutil.VersionCompare(teaconst.Version, latestVersion) < 0 { + if stringutil.VersionCompare(teaconst.Version, latestVersion) < 0 && (len(config.IgnoredVersion) == 0 || stringutil.VersionCompare(latestVersion, config.IgnoredVersion) > 0) { teaconst.NewVersionCode = latestVersion teaconst.NewVersionDownloadURL = dlHost + vMap.GetString("url") return nil diff --git a/internal/web/actions/default/settings/updates/ignoreVersion.go b/internal/web/actions/default/settings/updates/ignoreVersion.go new file mode 100644 index 00000000..7e8959a5 --- /dev/null +++ b/internal/web/actions/default/settings/updates/ignoreVersion.go @@ -0,0 +1,61 @@ +// Copyright 2023 GoEdge CDN goedge.cdn@gmail.com. All rights reserved. Official site: https://goedge.cn . + +package updates + +import ( + "encoding/json" + teaconst "github.com/TeaOSLab/EdgeAdmin/internal/const" + "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils" + "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb" + "github.com/TeaOSLab/EdgeCommon/pkg/systemconfigs" +) + +type IgnoreVersionAction struct { + actionutils.ParentAction +} + +func (this *IgnoreVersionAction) RunPost(params struct { + Version string +}) { + defer this.CreateLogInfo("忽略升级版本 %s", params.Version) + + if len(params.Version) == 0 { + this.Fail("请输入要忽略的版本号") + return + } + + valueResp, err := this.RPC().SysSettingRPC().ReadSysSetting(this.AdminContext(), &pb.ReadSysSettingRequest{Code: systemconfigs.SettingCodeCheckUpdates}) + if err != nil { + this.ErrorPage(err) + return + } + var valueJSON = valueResp.ValueJSON + var config = systemconfigs.NewCheckUpdatesConfig() + if len(valueJSON) > 0 { + err = json.Unmarshal(valueJSON, config) + if err != nil { + this.ErrorPage(err) + return + } + } + config.IgnoredVersion = params.Version + configJSON, err := json.Marshal(config) + if err != nil { + this.ErrorPage(err) + return + } + + _, err = this.RPC().SysSettingRPC().UpdateSysSetting(this.AdminContext(), &pb.UpdateSysSettingRequest{ + Code: systemconfigs.SettingCodeCheckUpdates, + ValueJSON: configJSON, + }) + if err != nil { + this.ErrorPage(err) + return + } + + // 清除状态 + teaconst.NewVersionCode = "" + + this.Success() +} diff --git a/internal/web/actions/default/settings/updates/index.go b/internal/web/actions/default/settings/updates/index.go index 8ec6dcbd..3bf19af0 100644 --- a/internal/web/actions/default/settings/updates/index.go +++ b/internal/web/actions/default/settings/updates/index.go @@ -4,12 +4,12 @@ package updates import ( "encoding/json" + "fmt" teaconst "github.com/TeaOSLab/EdgeAdmin/internal/const" "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils" "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb" "github.com/TeaOSLab/EdgeCommon/pkg/systemconfigs" "github.com/iwind/TeaGo/maps" - "github.com/iwind/TeaGo/types" stringutil "github.com/iwind/TeaGo/utils/string" "io" "net/http" @@ -25,8 +25,18 @@ func (this *IndexAction) Init() { this.Nav("", "updates", "") } -func (this *IndexAction) RunGet(params struct{}) { +func (this *IndexAction) RunGet(params struct { + DoCheck bool +}) { this.Data["version"] = teaconst.Version + this.Data["doCheck"] = params.DoCheck + + // 是否正在升级 + this.Data["isUpgrading"] = isUpgrading + this.Data["upgradeProgress"] = fmt.Sprintf("%.2f", upgradeProgress * 100) + if isUpgrading { + this.Data["doCheck"] = false + } valueResp, err := this.RPC().SysSettingRPC().ReadSysSetting(this.AdminContext(), &pb.ReadSysSettingRequest{Code: systemconfigs.SettingCodeCheckUpdates}) if err != nil { @@ -34,7 +44,7 @@ func (this *IndexAction) RunGet(params struct{}) { return } var valueJSON = valueResp.ValueJSON - var config = &systemconfigs.CheckUpdatesConfig{AutoCheck: false} + var config = systemconfigs.NewCheckUpdatesConfig() if len(valueJSON) > 0 { err = json.Unmarshal(valueJSON, config) if err != nil { @@ -49,6 +59,21 @@ func (this *IndexAction) RunGet(params struct{}) { func (this *IndexAction) RunPost(params struct { }) { + valueResp, err := this.RPC().SysSettingRPC().ReadSysSetting(this.AdminContext(), &pb.ReadSysSettingRequest{Code: systemconfigs.SettingCodeCheckUpdates}) + if err != nil { + this.ErrorPage(err) + return + } + var valueJSON = valueResp.ValueJSON + var config = systemconfigs.NewCheckUpdatesConfig() + if len(valueJSON) > 0 { + err = json.Unmarshal(valueJSON, config) + if err != nil { + this.ErrorPage(err) + return + } + } + type Response struct { Code int `json:"code"` Message string `json:"message"` @@ -66,6 +91,7 @@ func (this *IndexAction) RunPost(params struct { "message": "读取更新信息失败:" + err.Error(), } this.Success() + return } defer func() { @@ -78,6 +104,7 @@ func (this *IndexAction) RunPost(params struct { "message": "读取更新信息失败:" + err.Error(), } this.Success() + return } var apiResponse = &Response{} @@ -88,6 +115,7 @@ func (this *IndexAction) RunPost(params struct { "message": "解析更新信息失败:" + err.Error(), } this.Success() + return } if apiResponse.Code != 200 { @@ -96,6 +124,7 @@ func (this *IndexAction) RunPost(params struct { "message": "解析更新信息失败:" + apiResponse.Message, } this.Success() + return } var m = maps.NewMap(apiResponse.Data) @@ -107,19 +136,30 @@ func (this *IndexAction) RunPost(params struct { if vMap.GetString("code") == "admin" { var latestVersion = vMap.GetString("version") if stringutil.VersionCompare(teaconst.Version, latestVersion) < 0 { + // 是否已忽略 + if len(config.IgnoredVersion) > 0 && stringutil.VersionCompare(config.IgnoredVersion, latestVersion) >= 0 { + continue + } + this.Data["result"] = maps.Map{ - "isOk": true, - "message": "有最新的版本v" + types.String(latestVersion) + "可以更新", - "hasNew": true, - "dlURL": dlHost + vMap.GetString("url"), + "isOk": true, + "version": latestVersion, + "message": "有最新的版本 v" + latestVersion + " 可以更新", + "hasNew": true, + "dlURL": dlHost + vMap.GetString("url"), + "day": vMap.GetString("day"), + "description": vMap.GetString("description"), + "docURL": vMap.GetString("docURL"), } this.Success() + return } else { this.Data["result"] = maps.Map{ "isOk": true, "message": "你已安装最新版本,无需更新", } this.Success() + return } } } @@ -127,7 +167,7 @@ func (this *IndexAction) RunPost(params struct { this.Data["result"] = maps.Map{ "isOk": false, - "message": "找不到更新信息", + "message": "没有发现更新的版本", } this.Success() diff --git a/internal/web/actions/default/settings/updates/init.go b/internal/web/actions/default/settings/updates/init.go index f9df6999..e67b3c2a 100644 --- a/internal/web/actions/default/settings/updates/init.go +++ b/internal/web/actions/default/settings/updates/init.go @@ -15,6 +15,9 @@ func init() { Prefix("/settings/updates"). GetPost("", new(IndexAction)). Post("/update", new(UpdateAction)). + Post("/ignoreVersion", new(IgnoreVersionAction)). + Post("/resetIgnoredVersion", new(ResetIgnoredVersionAction)). + GetPost("/upgrade", new(UpgradeAction)). EndAll() }) } diff --git a/internal/web/actions/default/settings/updates/resetIgnoredVersion.go b/internal/web/actions/default/settings/updates/resetIgnoredVersion.go new file mode 100644 index 00000000..106a5bb0 --- /dev/null +++ b/internal/web/actions/default/settings/updates/resetIgnoredVersion.go @@ -0,0 +1,50 @@ +// Copyright 2023 GoEdge CDN goedge.cdn@gmail.com. All rights reserved. Official site: https://goedge.cn . + +package updates + +import ( + "encoding/json" + "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils" + "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb" + "github.com/TeaOSLab/EdgeCommon/pkg/systemconfigs" +) + +type ResetIgnoredVersionAction struct { + actionutils.ParentAction +} + +func (this *ResetIgnoredVersionAction) RunPost(params struct{}) { + defer this.CreateLogInfo("重置忽略升级版本") + + valueResp, err := this.RPC().SysSettingRPC().ReadSysSetting(this.AdminContext(), &pb.ReadSysSettingRequest{Code: systemconfigs.SettingCodeCheckUpdates}) + if err != nil { + this.ErrorPage(err) + return + } + var valueJSON = valueResp.ValueJSON + var config = systemconfigs.NewCheckUpdatesConfig() + if len(valueJSON) > 0 { + err = json.Unmarshal(valueJSON, config) + if err != nil { + this.ErrorPage(err) + return + } + } + config.IgnoredVersion = "" + configJSON, err := json.Marshal(config) + if err != nil { + this.ErrorPage(err) + return + } + + _, err = this.RPC().SysSettingRPC().UpdateSysSetting(this.AdminContext(), &pb.UpdateSysSettingRequest{ + Code: systemconfigs.SettingCodeCheckUpdates, + ValueJSON: configJSON, + }) + if err != nil { + this.ErrorPage(err) + return + } + + this.Success() +} diff --git a/internal/web/actions/default/settings/updates/update.go b/internal/web/actions/default/settings/updates/update.go index ca929a7a..e3863f3e 100644 --- a/internal/web/actions/default/settings/updates/update.go +++ b/internal/web/actions/default/settings/updates/update.go @@ -17,13 +17,16 @@ type UpdateAction struct { func (this *UpdateAction) RunPost(params struct { AutoCheck bool }) { + defer this.CreateLogInfo("修改检查更新设置") + + // 读取当前设置 valueResp, err := this.RPC().SysSettingRPC().ReadSysSetting(this.AdminContext(), &pb.ReadSysSettingRequest{Code: systemconfigs.SettingCodeCheckUpdates}) if err != nil { this.ErrorPage(err) return } var valueJSON = valueResp.ValueJSON - var config = &systemconfigs.CheckUpdatesConfig{AutoCheck: false} + var config = systemconfigs.NewCheckUpdatesConfig() if len(valueJSON) > 0 { err = json.Unmarshal(valueJSON, config) if err != nil { @@ -40,6 +43,7 @@ func (this *UpdateAction) RunPost(params struct { return } + // 修改设置 _, err = this.RPC().SysSettingRPC().UpdateSysSetting(this.AdminContext(), &pb.UpdateSysSettingRequest{ Code: systemconfigs.SettingCodeCheckUpdates, ValueJSON: configJSON, diff --git a/internal/web/actions/default/settings/updates/upgrade.go b/internal/web/actions/default/settings/updates/upgrade.go new file mode 100644 index 00000000..6b0b50f1 --- /dev/null +++ b/internal/web/actions/default/settings/updates/upgrade.go @@ -0,0 +1,73 @@ +// Copyright 2023 GoEdge CDN goedge.cdn@gmail.com. All rights reserved. Official site: https://goedge.cn . + +package updates + +import ( + "fmt" + "github.com/TeaOSLab/EdgeAdmin/internal/utils" + "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils" + "os" + "os/exec" + "time" +) + +var upgradeProgress float32 +var isUpgrading = false + +type UpgradeAction struct { + actionutils.ParentAction +} + +func (this *UpgradeAction) RunGet(params struct { +}) { + this.Data["isUpgrading"] = isUpgrading + this.Data["upgradeProgress"] = fmt.Sprintf("%.2f", upgradeProgress*100) + this.Success() +} + +func (this *UpgradeAction) RunPost(params struct { + Url string +}) { + if isUpgrading { + this.Success() + return + } + + isUpgrading = true + upgradeProgress = 0 + + defer func() { + isUpgrading = false + }() + + var manager = utils.NewUpgradeManager("admin", params.Url) + var ticker = time.NewTicker(1 * time.Second) + go func() { + for range ticker.C { + if manager.IsDownloading() { + var progress = manager.Progress() + if progress >= 0 { + upgradeProgress = progress + } + } else { + return + } + } + }() + err := manager.Start() + if err != nil { + this.Fail("下载失败:" + err.Error()) + return + } + + // restart + exe, _ := os.Executable() + if len(exe) > 0 { + go func() { + var cmd = exec.Command(exe, "restart") + _ = cmd.Run() + }() + } + + this.Success() +} diff --git a/web/views/@default/dashboard/index.html b/web/views/@default/dashboard/index.html index 936363aa..90d51de6 100644 --- a/web/views/@default/dashboard/index.html +++ b/web/views/@default/dashboard/index.html @@ -18,7 +18,7 @@
升级提醒:有新版本管理系统可以更新:v{{currentVersionCode}} -> v{{newVersionCode}}     - [去官网查看]     [直接下载] + [查看详情]
diff --git a/web/views/@default/settings/updates/index.css b/web/views/@default/settings/updates/index.css new file mode 100644 index 00000000..9a25a94b --- /dev/null +++ b/web/views/@default/settings/updates/index.css @@ -0,0 +1,5 @@ +.version-box { + line-height: 1.8; + color: #21ba45; +} +/*# sourceMappingURL=index.css.map */ \ No newline at end of file diff --git a/web/views/@default/settings/updates/index.css.map b/web/views/@default/settings/updates/index.css.map new file mode 100644 index 00000000..8d9fba9c --- /dev/null +++ b/web/views/@default/settings/updates/index.css.map @@ -0,0 +1 @@ +{"version":3,"sources":["index.less"],"names":[],"mappings":"AAAA;EACC,gBAAA;EACA,cAAA","file":"index.css"} \ No newline at end of file diff --git a/web/views/@default/settings/updates/index.html b/web/views/@default/settings/updates/index.html index f2e42918..cde76d6c 100644 --- a/web/views/@default/settings/updates/index.html +++ b/web/views/@default/settings/updates/index.html @@ -1,32 +1,68 @@ {$layout}
-
- - - - - - - - - - - - - -
当前已安装版本v{{version}}
自动检查 - -

选中后系统将定时检查是否有新版本更新。

-
最新版本 -
- 正在连接服务器检查更新... -
-
- {{result.message}}
下载地址:{{result.dlURL}}
- {{result.message}} -
-
- -
\ No newline at end of file +
+

正在下载升级到新版本,请耐心等待 {{upgradeProgress}}%...

+
+ +
+
+ + + + + + + + + + + + + + + + + +
当前已安装版本v{{version}}
已忽略版本 + v{{config.ignoredVersion}}   [重置] +
自动检查 + +

选中后系统将定时检查是否有新版本更新。

+
最新版本 +
+ 正在连接服务器检查更新... +
+
+
+ {{result.message}} +
下载地址:{{result.dlURL}}
+
+
+
+ + + +     + +
+ +
发布日期:{{result.day}}
+
+ 版本介绍:
{{result.description}}
+
+
+
完整变更说明:{{result.docURL}}
+
+
+
+
+ {{result.message}} +
+
+ + + +
+
\ No newline at end of file diff --git a/web/views/@default/settings/updates/index.js b/web/views/@default/settings/updates/index.js index 880c6b9f..be8c411d 100644 --- a/web/views/@default/settings/updates/index.js +++ b/web/views/@default/settings/updates/index.js @@ -1,8 +1,14 @@ Tea.context(function () { this.isStarted = false - this.isChecking = true + this.isChecking = false this.result = {isOk: false, message: "", hasNew: false, dlURL: ""} + this.$delay(function () { + if (this.doCheck) { + this.start() + } + }) + this.start = function () { this.isStarted = true this.isChecking = true @@ -28,4 +34,61 @@ Tea.context(function () { autoCheck: this.config.autoCheck ? 1 : 0 }) } + + this.ignoreVersion = function (version) { + teaweb.confirm("确定要忽略版本 v" + version + " 版本更新吗?", function () { + this.$post(".ignoreVersion") + .params({version: version}) + .success(function () { + teaweb.reload() + }) + }) + } + + this.resetIgnoredVersion = function (version) { + teaweb.confirm("确定要重置已忽略版本吗?", function () { + this.$post(".resetIgnoredVersion") + .success(function () { + teaweb.reload() + }) + }) + } + + this.install = function (dlURL) { + this.$post(".upgrade") + .params({ + url: dlURL + }) + .timeout(3600) + .success(function () { + teaweb.success("下载覆盖成功,系统将会尝试自动重启,请刷新页面查看重启状态。如果没能重启成功,请手动使用命令重启。", function () { + teaweb.reload() + }) + }) + + this.isUpgrading = true + this.updateUpgradeProgress() + } + + if (this.isUpgrading) { + this.$delay(function () { + this.updateUpgradeProgress() + }) + } + + this.updateUpgradeProgress = function () { + if (!this.isUpgrading) { + return + } + this.$get(".upgrade") + .success(function (resp) { + this.upgradeProgress = resp.data.upgradeProgress + this.isUpgrading = resp.data.isUpgrading + }) + .done(function () { + this.$delay(function () { + this.updateUpgradeProgress() + }, 3000) + }) + } }) \ No newline at end of file diff --git a/web/views/@default/settings/updates/index.less b/web/views/@default/settings/updates/index.less new file mode 100644 index 00000000..6e7f3e4b --- /dev/null +++ b/web/views/@default/settings/updates/index.less @@ -0,0 +1,4 @@ +.version-box { + line-height: 1.8; + color: #21ba45; +} \ No newline at end of file