diff --git a/backend/app/dto/app.go b/backend/app/dto/app.go index c0486d64a..7e286f18c 100644 --- a/backend/app/dto/app.go +++ b/backend/app/dto/app.go @@ -47,10 +47,11 @@ type CheckInstalled struct { type AppInstalled struct { model.AppInstall - Total int `json:"total"` - Ready int `json:"ready"` - AppName string `json:"appName"` - Icon string `json:"icon"` + Total int `json:"total"` + Ready int `json:"ready"` + AppName string `json:"appName"` + Icon string `json:"icon"` + CanUpdate bool `json:"canUpdate"` } type AppInstalledRequest struct { diff --git a/backend/app/model/app_install.go b/backend/app/model/app_install.go index 96bd0a740..cc1a35903 100644 --- a/backend/app/model/app_install.go +++ b/backend/app/model/app_install.go @@ -7,17 +7,17 @@ import ( type AppInstall struct { BaseModel - Name string `json:"name" gorm:"type:varchar(64);not null"` - AppId uint `json:"appId" gorm:"type:integer;not null"` - AppDetailId uint `json:"appDetailId" gorm:"type:integer;not null"` - Version string `json:"version" gorm:"type:varchar(64);not null"` - Param string `json:"param" gorm:"type:longtext;"` - Env string `json:"env" gorm:"type:longtext;"` - DockerCompose string `json:"dockerCompose" gorm:"type:longtext;"` - Status string `json:"status" gorm:"type:varchar(256);not null"` - Description string `json:"description" gorm:"type:varchar(256);"` - Message string `json:"message" gorm:"type:longtext;"` - CanUpdate bool `json:"canUpdate"` + Name string `json:"name" gorm:"type:varchar(64);not null"` + AppId uint `json:"appId" gorm:"type:integer;not null"` + AppDetailId uint `json:"appDetailId" gorm:"type:integer;not null"` + Version string `json:"version" gorm:"type:varchar(64);not null"` + Param string `json:"param" gorm:"type:longtext;"` + Env string `json:"env" gorm:"type:longtext;"` + DockerCompose string `json:"dockerCompose" gorm:"type:longtext;"` + Status string `json:"status" gorm:"type:varchar(256);not null"` + Description string `json:"description" gorm:"type:varchar(256);"` + Message string `json:"message" gorm:"type:longtext;"` + //CanUpdate bool `json:"canUpdate"` ContainerName string `json:"containerName" gorm:"type:varchar(256);not null"` ServiceName string `json:"serviceName" gorm:"type:varchar(256);not null"` HttpPort int `json:"httpPort" gorm:"type:integer;not null"` diff --git a/backend/app/service/app.go b/backend/app/service/app.go index f8915161a..ffb92616b 100644 --- a/backend/app/service/app.go +++ b/backend/app/service/app.go @@ -524,9 +524,9 @@ func syncCanUpdate() { if err := appDetailRepo.BatchUpdateBy(map[string]interface{}{"last_version": lastVersion}, commonRepo.WithIdsIn(updateDetailIds)); err != nil { global.LOG.Errorf("sync update app error: %s", err.Error()) } - if err := appInstallRepo.BatchUpdateBy(map[string]interface{}{"can_update": 1}, appInstallRepo.WithDetailIdsIn(updateDetailIds)); err != nil { - global.LOG.Errorf("sync update app error: %s", err.Error()) - } + //if err := appInstallRepo.BatchUpdateBy(map[string]interface{}{"can_update": 1}, appInstallRepo.WithDetailIdsIn(updateDetailIds)); err != nil { + // global.LOG.Errorf("sync update app error: %s", err.Error()) + //} } } diff --git a/backend/app/service/app_install.go b/backend/app/service/app_install.go index 5247d038d..e16d17cab 100644 --- a/backend/app/service/app_install.go +++ b/backend/app/service/app_install.go @@ -24,16 +24,14 @@ type AppInstallService struct { } func (a AppInstallService) Page(req dto.AppInstalledRequest) (int64, []dto.AppInstalled, error) { - total, installed, err := appInstallRepo.Page(req.Page, req.PageSize) + total, installs, err := appInstallRepo.Page(req.Page, req.PageSize) if err != nil { return 0, nil, err } - var installDTOs []dto.AppInstalled - for _, in := range installed { - installDto := dto.AppInstalled{ - AppInstall: in, - } - installDTOs = append(installDTOs, installDto) + + installDTOs, err := handleInstalled(installs) + if err != nil { + return 0, nil, err } return total, installDTOs, nil @@ -74,15 +72,7 @@ func (a AppInstallService) Search(req dto.AppInstalledRequest) ([]dto.AppInstall } } - var installDTOs []dto.AppInstalled - for _, in := range installs { - installDto := dto.AppInstalled{ - AppInstall: in, - } - installDTOs = append(installDTOs, installDto) - } - - return installDTOs, nil + return handleInstalled(installs) } func (a AppInstallService) Operate(req dto.AppInstallOperate) error { diff --git a/backend/app/service/app_utils.go b/backend/app/service/app_utils.go index 46f678a0a..db373af56 100644 --- a/backend/app/service/app_utils.go +++ b/backend/app/service/app_utils.go @@ -211,18 +211,18 @@ func updateInstall(installId uint, detailId uint) error { if err != nil { return err } - oldDetail, err := appDetailRepo.GetFirst(commonRepo.WithByID(install.AppDetailId)) - if err != nil { - return err - } + //oldDetail, err := appDetailRepo.GetFirst(commonRepo.WithByID(install.AppDetailId)) + //if err != nil { + // return err + //} detail, err := appDetailRepo.GetFirst(commonRepo.WithByID(detailId)) if err != nil { return err } - if oldDetail.LastVersion == detail.Version { - install.CanUpdate = false - } + //if oldDetail.LastVersion == detail.Version { + // install.CanUpdate = false + //} if install.Version == detail.Version { return errors.New("two version is same") } @@ -556,3 +556,38 @@ func getAppFromOss() error { }() return nil } + +func handleInstalled(installed []model.AppInstall) ([]dto.AppInstalled, error) { + var res []dto.AppInstalled + + for _, installed := range installed { + + installDTO := dto.AppInstalled{ + AppInstall: installed, + } + + app, err := appRepo.GetFirst(commonRepo.WithByID(installed.AppId)) + if err != nil { + return nil, err + } + details, err := appDetailRepo.GetBy(appDetailRepo.WithAppId(app.ID)) + if err != nil { + return nil, err + } + var versions []string + for _, detail := range details { + versions = append(versions, detail.Version) + } + versions = common.GetSortedVersions(versions) + lastVersion := versions[0] + + if common.IsCrossVersion(installed.Version, lastVersion) { + installDTO.CanUpdate = app.CrossVersionUpdate + } else { + installDTO.CanUpdate = common.CompareVersion(lastVersion, installed.Version) + } + res = append(res, installDTO) + } + + return res, nil +} diff --git a/frontend/src/lang/modules/zh.ts b/frontend/src/lang/modules/zh.ts index 77ec5f0d5..2ac589a94 100644 --- a/frontend/src/lang/modules/zh.ts +++ b/frontend/src/lang/modules/zh.ts @@ -686,6 +686,7 @@ export default { restoreWarn: '回滚操作会重启应用,并替换数据,此操作不可回滚,是否继续?', update: '升级', versioneSelect: '请选择版本', + operatorHelper: '将对选中应用进行 {0} 操作,是否继续?', }, website: { primaryDomain: '主域名', diff --git a/frontend/src/views/app-store/installed/index.vue b/frontend/src/views/app-store/installed/index.vue index 27b96176c..bf699e705 100644 --- a/frontend/src/views/app-store/installed/index.vue +++ b/frontend/src/views/app-store/installed/index.vue @@ -97,7 +97,7 @@ import { onMounted, onUnmounted, reactive, ref } from 'vue'; import ComplexTable from '@/components/complex-table/index.vue'; import { dateFromat } from '@/utils/util'; import i18n from '@/lang'; -import { ElMessage } from 'element-plus'; +import { ElMessage, ElMessageBox } from 'element-plus'; import Backups from './backups.vue'; import { App } from '@/api/interface/app'; @@ -154,7 +154,7 @@ const openOperate = (row: any, op: string) => { open.value = true; }); } else { - open.value = true; + onOperate(op); } }; @@ -175,6 +175,29 @@ const handleClose = () => { open.value = false; }; +const onOperate = async (operation: string) => { + ElMessageBox.confirm( + i18n.global.t('app.operatorHelper', [i18n.global.t('app.' + operation)]), + i18n.global.t('app.' + operation), + { + confirmButtonText: i18n.global.t('commons.button.confirm'), + cancelButtonText: i18n.global.t('commons.button.cancel'), + type: 'info', + }, + ).then(() => { + open.value = false; + loading.value = true; + InstalledOp(operateReq) + .then(() => { + ElMessage.success(i18n.global.t('commons.msg.operationSuccess')); + search(); + }) + .finally(() => { + loading.value = false; + }); + }); +}; + const getMsg = (op: string) => { let tip = ''; switch (op) {