diff --git a/agent/app/service/app.go b/agent/app/service/app.go index 44a57c5..68f5135 100644 --- a/agent/app/service/app.go +++ b/agent/app/service/app.go @@ -845,6 +845,8 @@ func (a AppService) GetAppUpdate() (*response.AppUpdateRes, error) { if err != nil { return nil, err } + storedCompatibility, err := settingRepo.GetValueByKey(global.AppStoreCompatibilitySettingKey) + compatibilityChanged := err != nil || storedCompatibility != global.AppStoreCompatibilityVersion if setting.AppStoreSyncStatus == constant.StatusSyncing { res.IsSyncing = true return res, nil @@ -852,22 +854,24 @@ func (a AppService) GetAppUpdate() (*response.AppUpdateRes, error) { appStoreLastModified, _ := strconv.Atoi(setting.AppStoreLastModified) res.AppStoreLastModified = appStoreLastModified - if setting.AppStoreLastModified == "" || lastModified != appStoreLastModified { + if !compatibilityChanged && (setting.AppStoreLastModified == "" || lastModified != appStoreLastModified) { res.CanUpdate = true return res, err } - apps, _ := appRepo.GetBy(appRepo.WithResource(constant.AppResourceRemote)) - for _, app := range apps { - if app.Icon == "" { - res.CanUpdate = true - return res, err - } - if appicon.IsIconFile(app.Icon) { - fileName, _ := appicon.ParseIconField(app.Icon) - if fileName == "" || !appicon.IconFileExists(fileName) { + if !compatibilityChanged { + apps, _ := appRepo.GetBy(appRepo.WithResource(constant.AppResourceRemote)) + for _, app := range apps { + if app.Icon == "" { res.CanUpdate = true return res, err } + if appicon.IsIconFile(app.Icon) { + fileName, _ := appicon.ParseIconField(app.Icon) + if fileName == "" || !appicon.IconFileExists(fileName) { + res.CanUpdate = true + return res, err + } + } } } @@ -880,6 +884,7 @@ func (a AppService) GetAppUpdate() (*response.AppUpdateRes, error) { return nil, buserr.New("ErrVersionTooLow") } res.AppList = list + res.CanUpdate = compatibilityChanged return res, nil } diff --git a/agent/app/service/app_sync_task.go b/agent/app/service/app_sync_task.go index 70024e8..4517eef 100644 --- a/agent/app/service/app_sync_task.go +++ b/agent/app/service/app_sync_task.go @@ -410,6 +410,10 @@ func (a AppService) createSyncAppStoreMetaTask(sharedCtx **appSyncContext) func( t.LogFailedWithErr(i18n.GetMsgByKey("PersistAppDetails"), err) return err } + if err = ctx.settingService.Update(global.AppStoreCompatibilitySettingKey, global.AppStoreCompatibilityVersion); err != nil { + t.LogFailedWithErr(i18n.GetMsgByKey("PersistAppDetails"), err) + return err + } global.LOG.Infof("[AppStore] Appstore meta sync completed") return nil diff --git a/agent/global/compatibility.go b/agent/global/compatibility.go index 70e2a71..7fae6b9 100644 --- a/agent/global/compatibility.go +++ b/agent/global/compatibility.go @@ -4,3 +4,8 @@ package global // that nPanel has audited against. It is intentionally separate from the // nPanel product version stored in SystemVersion. const AppStoreCompatibilityVersion = "v2.2.3" + +// AppStoreCompatibilitySettingKey records the compatibility level used to +// build the currently cached app catalog. A level change requires a full +// catalog refresh even when the remote catalog timestamp is unchanged. +const AppStoreCompatibilitySettingKey = "AppStoreCompatibilityVersion" diff --git a/docs/nPanel-nixos-design.md b/docs/nPanel-nixos-design.md index d6aa476..75d99ba 100644 --- a/docs/nPanel-nixos-design.md +++ b/docs/nPanel-nixos-design.md @@ -120,7 +120,7 @@ nPanel 不向用户导向上游社区或商业站点。删除: 应用商店与资源端点需要单独进行兼容性审计:只要它们是保留 Docker 应用生态所必需的,就不自动删除;但 UI 不得展示上游品牌、商业、支持或社区链接。 -应用商店使用单独的内部兼容级别 `v2.2.3`。它表示 nPanel 已审计应用目录及其版本门槛所需的上游协议基线,不是 nPanel 的产品版本,也不写入用户配置或开放给用户覆盖。nPanel 的产品版本仍独立维护。 +应用商店使用单独的内部兼容级别 `v2.2.3`。它表示 nPanel 已审计应用目录及其版本门槛所需的上游协议基线,不是 nPanel 的产品版本,也不写入用户配置或开放给用户覆盖。nPanel 的产品版本仍独立维护。该级别会与缓存的应用目录一起记录;级别变化强制刷新目录详情,不能因远端目录时间戳未变而继续使用按旧规则筛选的缓存。 ## 架构