diff --git a/backend/app/api/v1/snapshot.go b/backend/app/api/v1/snapshot.go index a6dde9d8c..a98b95f30 100644 --- a/backend/app/api/v1/snapshot.go +++ b/backend/app/api/v1/snapshot.go @@ -120,6 +120,28 @@ func (b *BaseApi) SearchSnapshot(c *gin.Context) { }) } +// @Tags System Setting +// @Summary Load system snapshot size +// @Description 获取系统快照大小 +// @Accept json +// @Param request body dto.PageSnapshot true "request" +// @Success 200 +// @Security ApiKeyAuth +// @Router /settings/snapshot/size [post] +func (b *BaseApi) LoadSnapshotSize(c *gin.Context) { + var req dto.PageSnapshot + if err := helper.CheckBindAndValidate(&req, c); err != nil { + return + } + + data, err := snapshotService.LoadSize(req) + if err != nil { + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) + return + } + helper.SuccessWithData(c, data) +} + // @Tags System Setting // @Summary Recover system backup // @Description 从系统快照恢复 diff --git a/backend/app/dto/setting.go b/backend/app/dto/setting.go index ed84c2c9f..1de8d8129 100644 --- a/backend/app/dto/setting.go +++ b/backend/app/dto/setting.go @@ -149,7 +149,6 @@ type SnapshotInfo struct { Message string `json:"message"` CreatedAt time.Time `json:"createdAt"` Version string `json:"version"` - Size int64 `json:"size"` InterruptStep string `json:"interruptStep"` RecoverStatus string `json:"recoverStatus"` @@ -160,6 +159,12 @@ type SnapshotInfo struct { LastRollbackedAt string `json:"lastRollbackedAt"` } +type SnapshotFile struct { + ID uint `json:"id"` + Name string `json:"name"` + Size int64 `json:"size"` +} + type UpgradeInfo struct { TestVersion string `json:"testVersion"` NewVersion string `json:"newVersion"` diff --git a/backend/app/service/snapshot.go b/backend/app/service/snapshot.go index ae230d9d1..082033085 100644 --- a/backend/app/service/snapshot.go +++ b/backend/app/service/snapshot.go @@ -28,6 +28,7 @@ type SnapshotService struct { type ISnapshotService interface { SearchWithPage(req dto.PageSnapshot) (int64, interface{}, error) + LoadSize(req dto.PageSnapshot) ([]dto.SnapshotFile, error) SnapshotCreate(req dto.SnapshotCreate) error SnapshotRecover(req dto.SnapshotRecover) error SnapshotRollback(req dto.SnapshotRecover) error @@ -47,15 +48,31 @@ func NewISnapshotService() ISnapshotService { } func (u *SnapshotService) SearchWithPage(req dto.PageSnapshot) (int64, interface{}, error) { - total, systemBackups, err := snapshotRepo.Page(req.Page, req.PageSize, commonRepo.WithLikeName(req.Info), commonRepo.WithOrderRuleBy(req.OrderBy, req.Order)) + total, records, err := snapshotRepo.Page(req.Page, req.PageSize, commonRepo.WithLikeName(req.Info), commonRepo.WithOrderRuleBy(req.OrderBy, req.Order)) if err != nil { return 0, nil, err } - dtoSnap, err := loadSnapSize(systemBackups) - if err != nil { - return 0, nil, err + var data []dto.SnapshotInfo + for _, record := range records { + var item dto.SnapshotInfo + if err := copier.Copy(&item, &record); err != nil { + return 0, nil, errors.WithMessage(constant.ErrStructTransform, err.Error()) + } + data = append(data, item) } - return total, dtoSnap, err + return total, data, err +} + +func (u *SnapshotService) LoadSize(req dto.PageSnapshot) ([]dto.SnapshotFile, error) { + _, records, err := snapshotRepo.Page(req.Page, req.PageSize, commonRepo.WithLikeName(req.Info), commonRepo.WithOrderRuleBy(req.OrderBy, req.Order)) + if err != nil { + return nil, err + } + data, err := loadSnapSize(records) + if err != nil { + return nil, err + } + return data, err } func (u *SnapshotService) SnapshotImport(req dto.SnapshotImport) error { @@ -510,15 +527,12 @@ func loadOs() string { } } -func loadSnapSize(records []model.Snapshot) ([]dto.SnapshotInfo, error) { - var datas []dto.SnapshotInfo +func loadSnapSize(records []model.Snapshot) ([]dto.SnapshotFile, error) { + var datas []dto.SnapshotFile clientMap := make(map[string]loadSizeHelper) var wg sync.WaitGroup for i := 0; i < len(records); i++ { - var item dto.SnapshotInfo - if err := copier.Copy(&item, &records[i]); err != nil { - return nil, errors.WithMessage(constant.ErrStructTransform, err.Error()) - } + item := dto.SnapshotFile{Name: records[i].Name, ID: records[i].ID} itemPath := fmt.Sprintf("system_snapshot/%s.tar.gz", item.Name) if _, ok := clientMap[records[i].DefaultDownload]; !ok { backup, err := backupRepo.Get(commonRepo.WithByType(records[i].DefaultDownload)) diff --git a/backend/router/ro_setting.go b/backend/router/ro_setting.go index e2a911e0a..5d25f465d 100644 --- a/backend/router/ro_setting.go +++ b/backend/router/ro_setting.go @@ -37,6 +37,7 @@ func (s *SettingRouter) InitRouter(Router *gin.RouterGroup) { settingRouter.POST("/snapshot", baseApi.CreateSnapshot) settingRouter.POST("/snapshot/status", baseApi.LoadSnapShotStatus) settingRouter.POST("/snapshot/search", baseApi.SearchSnapshot) + settingRouter.POST("/snapshot/size", baseApi.LoadSnapshotSize) settingRouter.POST("/snapshot/import", baseApi.ImportSnapshot) settingRouter.POST("/snapshot/del", baseApi.DeleteSnapshot) settingRouter.POST("/snapshot/recover", baseApi.RecoverSnapshot) diff --git a/frontend/src/api/interface/setting.ts b/frontend/src/api/interface/setting.ts index c5d2def9c..2e60ce791 100644 --- a/frontend/src/api/interface/setting.ts +++ b/frontend/src/api/interface/setting.ts @@ -145,6 +145,11 @@ export namespace Setting { lastRollbackedAt: string; secret: string; } + export interface SnapshotFile { + id: number; + name: string; + size: number; + } export interface SnapshotStatus { panel: string; panelInfo: string; diff --git a/frontend/src/api/modules/setting.ts b/frontend/src/api/modules/setting.ts index d9ecd3137..9e70c72dc 100644 --- a/frontend/src/api/modules/setting.ts +++ b/frontend/src/api/modules/setting.ts @@ -196,6 +196,9 @@ export const snapshotRollback = (param: Setting.SnapshotRecover) => { export const searchSnapshotPage = (param: SearchWithPage) => { return http.post<ResPage<Setting.SnapshotInfo>>(`/settings/snapshot/search`, param); }; +export const loadSnapshotSize = (param: SearchWithPage) => { + return http.post<Array<Setting.SnapshotFile>>(`/settings/snapshot/size`, param); +}; // upgrade export const loadUpgradeInfo = () => { diff --git a/frontend/src/views/setting/snapshot/index.vue b/frontend/src/views/setting/snapshot/index.vue index fafd06fa2..ec017cc26 100644 --- a/frontend/src/views/setting/snapshot/index.vue +++ b/frontend/src/views/setting/snapshot/index.vue @@ -75,10 +75,15 @@ </el-table-column> <el-table-column :label="$t('file.size')" prop="size" min-width="60" show-overflow-tooltip> <template #default="{ row }"> - <span v-if="row.size"> - {{ computeSize(row.size) }} - </span> - <span v-else>-</span> + <div v-if="row.hasLoad"> + <span v-if="row.size"> + {{ computeSize(row.size) }} + </span> + <span v-else>-</span> + </div> + <div v-if="!row.hasLoad"> + <el-button link loading></el-button> + </div> </template> </el-table-column> <el-table-column :label="$t('commons.table.status')" min-width="80" prop="status"> @@ -197,7 +202,13 @@ <script setup lang="ts"> import DrawerHeader from '@/components/drawer-header/index.vue'; -import { snapshotCreate, searchSnapshotPage, snapshotDelete, updateSnapshotDescription } from '@/api/modules/setting'; +import { + snapshotCreate, + searchSnapshotPage, + snapshotDelete, + updateSnapshotDescription, + loadSnapshotSize, +} from '@/api/modules/setting'; import { onMounted, reactive, ref } from 'vue'; import { computeSize, dateFormat } from '@/utils/util'; import { ElForm } from 'element-plus'; @@ -418,6 +429,7 @@ const search = async (column?: any) => { await searchSnapshotPage(params) .then((res) => { loading.value = false; + loadSize(params); cleanData.value = false; data.value = res.data.items || []; paginationConfig.total = res.data.total; @@ -427,6 +439,28 @@ const search = async (column?: any) => { }); }; +const loadSize = async (params: any) => { + await loadSnapshotSize(params) + .then((res) => { + let stats = res.data || []; + if (stats.length === 0) { + return; + } + for (const snap of data.value) { + for (const item of stats) { + if (snap.id === item.id) { + snap.hasLoad = true; + snap.size = item.size; + break; + } + } + } + }) + .catch(() => { + loading.value = false; + }); +}; + onMounted(() => { search(); loadBackups();