mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2025-01-31 14:08:06 +08:00
feat: 增加系统临时文件清理功能 (#2402)
This commit is contained in:
parent
2624238354
commit
e8564f38ab
@ -277,6 +277,37 @@ func (b *BaseApi) CleanMonitor(c *gin.Context) {
|
||||
helper.SuccessWithData(c, nil)
|
||||
}
|
||||
|
||||
// @Tags System Setting
|
||||
// @Summary Scan system
|
||||
// @Description 扫描系统垃圾文件
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /settings/scan [post]
|
||||
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFuntions":[],"formatZH":"扫描系统垃圾文件","formatEN":"scan System Junk Files"}
|
||||
func (b *BaseApi) ScanSystem(c *gin.Context) {
|
||||
helper.SuccessWithData(c, settingService.SystemScan())
|
||||
}
|
||||
|
||||
// @Tags System Setting
|
||||
// @Summary System clean
|
||||
// @Description 清理系统垃圾文件
|
||||
// @Accept json
|
||||
// @Param request body []dto.Clean true "request"
|
||||
// @Success 200
|
||||
// @Security ApiKeyAuth
|
||||
// @Router /settings/clean [post]
|
||||
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFuntions":[],"formatZH":"清理系统垃圾文件","formatEN":"Clean system junk files"}
|
||||
func (b *BaseApi) SystemClean(c *gin.Context) {
|
||||
var req []dto.Clean
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
|
||||
return
|
||||
}
|
||||
settingService.SystemClean(req)
|
||||
|
||||
helper.SuccessWithData(c, nil)
|
||||
}
|
||||
|
||||
// @Tags System Setting
|
||||
// @Summary Load mfa info
|
||||
// @Description 获取 mfa 信息
|
||||
|
@ -18,6 +18,9 @@ type SettingInfo struct {
|
||||
Theme string `json:"theme"`
|
||||
Language string `json:"language"`
|
||||
DefaultNetwork string `json:"defaultNetwork"`
|
||||
LastCleanTime string `json:"lastCleanTime"`
|
||||
LastCleanSize string `json:"lastCleanSize"`
|
||||
LastCleanData string `json:"lastCleanData"`
|
||||
|
||||
ServerPort string `json:"serverPort"`
|
||||
SSL string `json:"ssl"`
|
||||
@ -136,3 +139,29 @@ type SyncTime struct {
|
||||
type Upgrade struct {
|
||||
Version string `json:"version"`
|
||||
}
|
||||
|
||||
type CleanData struct {
|
||||
SystemClean []CleanTree `json:"systemClean"`
|
||||
UploadClean []CleanTree `json:"uploadClean"`
|
||||
DownloadClean []CleanTree `json:"downloadClean"`
|
||||
SystemLogClean []CleanTree `json:"systemLogClean"`
|
||||
}
|
||||
|
||||
type CleanTree struct {
|
||||
ID string `json:"id"`
|
||||
Label string `json:"label"`
|
||||
Children []CleanTree `json:"children"`
|
||||
|
||||
Type string `json:"type"`
|
||||
Name string `json:"name"`
|
||||
|
||||
Size uint64 `json:"size"`
|
||||
IsCheck bool `json:"isCheck"`
|
||||
IsRecommend bool `json:"isRecommend"`
|
||||
}
|
||||
|
||||
type Clean struct {
|
||||
TreeType string `json:"treeType"`
|
||||
Name string `json:"name"`
|
||||
Size uint64 `json:"size"`
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ type ICronjobRepo interface {
|
||||
WithByJobID(id int) DBOption
|
||||
WithByBackupID(id uint) DBOption
|
||||
WithByRecordDropID(id int) DBOption
|
||||
WithByRecordFile(file string) DBOption
|
||||
Save(id uint, cronjob model.Cronjob) error
|
||||
Update(id uint, vars map[string]interface{}) error
|
||||
Delete(opts ...DBOption) error
|
||||
@ -121,6 +122,12 @@ func (c *CronjobRepo) WithByBackupID(id uint) DBOption {
|
||||
}
|
||||
}
|
||||
|
||||
func (c *CronjobRepo) WithByRecordFile(file string) DBOption {
|
||||
return func(g *gorm.DB) *gorm.DB {
|
||||
return g.Where("records = ?", file)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *CronjobRepo) WithByRecordDropID(id int) DBOption {
|
||||
return func(g *gorm.DB) *gorm.DB {
|
||||
return g.Where("id < ?", id)
|
||||
|
@ -38,6 +38,9 @@ type ISettingService interface {
|
||||
LoadFromCert() (*dto.SSLInfo, error)
|
||||
HandlePasswordExpired(c *gin.Context, old, new string) error
|
||||
SyncTime(req dto.SyncTime) error
|
||||
|
||||
SystemScan() dto.CleanData
|
||||
SystemClean(req []dto.Clean)
|
||||
}
|
||||
|
||||
func NewISettingService() ISettingService {
|
||||
|
358
backend/app/service/setting_clean.go
Normal file
358
backend/app/service/setting_clean.go
Normal file
@ -0,0 +1,358 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/backend/app/dto"
|
||||
"github.com/1Panel-dev/1Panel/backend/global"
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/cmd"
|
||||
fileUtils "github.com/1Panel-dev/1Panel/backend/utils/files"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
func (u *SettingService) SystemScan() dto.CleanData {
|
||||
var (
|
||||
SystemClean dto.CleanData
|
||||
treeData []dto.CleanTree
|
||||
)
|
||||
fileOp := fileUtils.NewFileOp()
|
||||
|
||||
originalPath := path.Join(global.CONF.System.BaseDir, "1panel_original")
|
||||
originalSize, _ := fileOp.GetDirSize(originalPath)
|
||||
treeData = append(treeData, dto.CleanTree{
|
||||
ID: uuid.NewString(),
|
||||
Label: "1panel_original",
|
||||
Size: uint64(originalSize),
|
||||
IsCheck: true,
|
||||
IsRecommend: true,
|
||||
Type: "1panel_original",
|
||||
Children: loadTreeWithDir(true, "1panel_original", originalPath, fileOp),
|
||||
})
|
||||
|
||||
upgradePath := path.Join(global.CONF.System.BaseDir, "1panel/tmp/upgrade")
|
||||
upgradeSize, _ := fileOp.GetDirSize(upgradePath)
|
||||
treeData = append(treeData, dto.CleanTree{
|
||||
ID: uuid.NewString(),
|
||||
Label: "upgrade",
|
||||
Size: uint64(upgradeSize),
|
||||
IsCheck: false,
|
||||
IsRecommend: true,
|
||||
Type: "upgrade",
|
||||
Children: loadTreeWithDir(true, "upgrade", upgradePath, fileOp),
|
||||
})
|
||||
|
||||
snapTree := loadSnapshotTree(fileOp)
|
||||
snapSize := uint64(0)
|
||||
for _, snap := range snapTree {
|
||||
snapSize += uint64(snap.Size)
|
||||
}
|
||||
treeData = append(treeData, dto.CleanTree{
|
||||
ID: uuid.NewString(),
|
||||
Label: "snapshot",
|
||||
Size: snapSize,
|
||||
IsCheck: true,
|
||||
IsRecommend: true,
|
||||
Type: "snapshot",
|
||||
Children: snapTree,
|
||||
})
|
||||
|
||||
cachePath := path.Join(global.CONF.System.BaseDir, "1panel/cache")
|
||||
cacheSize, _ := fileOp.GetDirSize(cachePath)
|
||||
treeData = append(treeData, dto.CleanTree{
|
||||
ID: uuid.NewString(),
|
||||
Label: "cache",
|
||||
Size: uint64(cacheSize),
|
||||
IsCheck: false,
|
||||
IsRecommend: false,
|
||||
Type: "cache",
|
||||
})
|
||||
|
||||
unusedTree := loadUnusedFile(fileOp)
|
||||
unusedSize := uint64(0)
|
||||
for _, unused := range unusedTree {
|
||||
unusedSize += uint64(unused.Size)
|
||||
}
|
||||
treeData = append(treeData, dto.CleanTree{
|
||||
ID: uuid.NewString(),
|
||||
Label: "unused",
|
||||
Size: unusedSize,
|
||||
IsCheck: true,
|
||||
IsRecommend: true,
|
||||
Type: "unused",
|
||||
Children: unusedTree,
|
||||
})
|
||||
SystemClean.SystemClean = treeData
|
||||
|
||||
uploadPath := path.Join(global.CONF.System.BaseDir, "1panel/uploads")
|
||||
uploadTreeData := loadTreeWithAllFile(true, uploadPath, "upload", uploadPath, fileOp)
|
||||
SystemClean.UploadClean = append(SystemClean.UploadClean, uploadTreeData...)
|
||||
|
||||
downloadPath := path.Join(global.CONF.System.BaseDir, "1panel/download")
|
||||
downloadTreeData := loadTreeWithAllFile(true, downloadPath, "download", downloadPath, fileOp)
|
||||
SystemClean.DownloadClean = append(SystemClean.DownloadClean, downloadTreeData...)
|
||||
|
||||
logTree := loadLogTree(fileOp)
|
||||
SystemClean.SystemLogClean = append(SystemClean.SystemLogClean, logTree...)
|
||||
|
||||
return SystemClean
|
||||
}
|
||||
|
||||
func (u *SettingService) SystemClean(req []dto.Clean) {
|
||||
size := uint64(0)
|
||||
for _, item := range req {
|
||||
size += item.Size
|
||||
switch item.TreeType {
|
||||
case "1panel_original":
|
||||
dropFileOrDir(path.Join(global.CONF.System.BaseDir, "1panel_original", item.Name))
|
||||
|
||||
case "upgrade":
|
||||
dropFileOrDir(path.Join(global.CONF.System.BaseDir, "1panel/tmp/upgrade", item.Name))
|
||||
|
||||
case "snapshot":
|
||||
dropFileOrDir(path.Join(global.CONF.System.BaseDir, "1panel/tmp/system", item.Name))
|
||||
dropFileOrDir(path.Join(global.CONF.System.Backup, "system", item.Name))
|
||||
case "snapshot_tmp":
|
||||
dropFileOrDir(path.Join(global.CONF.System.BaseDir, "1panel/tmp/system", item.Name))
|
||||
case "snapshot_local":
|
||||
dropFileOrDir(path.Join(global.CONF.System.Backup, "system", item.Name))
|
||||
|
||||
case "cache":
|
||||
dropFileOrDir(path.Join(global.CONF.System.BaseDir, "1panel/cache", item.Name))
|
||||
defer func() {
|
||||
_, _ = cmd.Exec("systemctl restart 1panel.service")
|
||||
}()
|
||||
|
||||
case "unused":
|
||||
dropFileOrDir(path.Join(global.CONF.System.BaseDir, "original", item.Name))
|
||||
dropFileOrDir(path.Join(global.CONF.System.BaseDir, "1panel/resource/apps_bak", item.Name))
|
||||
dropFileOrDir(path.Join(global.CONF.System.BaseDir, "1panel/tmp/download", item.Name))
|
||||
dropFileOrDir(path.Join(global.CONF.System.BaseDir, "1panel/tmp", item.Name))
|
||||
case "old_original":
|
||||
dropFileOrDir(path.Join(global.CONF.System.BaseDir, "original", item.Name))
|
||||
case "old_apps_bak":
|
||||
dropFileOrDir(path.Join(global.CONF.System.BaseDir, "1panel/resource/apps_bak", item.Name))
|
||||
case "old_download":
|
||||
dropFileOrDir(path.Join(global.CONF.System.BaseDir, "1panel/tmp/download", item.Name))
|
||||
case "old_upgrade":
|
||||
if len(item.Name) == 0 {
|
||||
files, _ := os.ReadDir(path.Join(global.CONF.System.BaseDir, "1panel/tmp"))
|
||||
if len(files) == 0 {
|
||||
continue
|
||||
}
|
||||
for _, file := range files {
|
||||
dropFileOrDir(path.Join(global.CONF.System.BaseDir, "1panel/tmp", file.Name()))
|
||||
}
|
||||
} else {
|
||||
dropFileOrDir(path.Join(global.CONF.System.BaseDir, "1panel/tmp", item.Name))
|
||||
}
|
||||
|
||||
case "upload":
|
||||
dropFileOrDir(path.Join(global.CONF.System.BaseDir, "1panel/uploads", item.Name))
|
||||
case "download":
|
||||
dropFileOrDir(path.Join(global.CONF.System.BaseDir, "1panel/download", item.Name))
|
||||
|
||||
case "system_log":
|
||||
if len(item.Name) == 0 {
|
||||
files, _ := os.ReadDir(path.Join(global.CONF.System.BaseDir, "1panel/log"))
|
||||
if len(files) == 0 {
|
||||
continue
|
||||
}
|
||||
for _, file := range files {
|
||||
if file.Name() == "1Panel.log" {
|
||||
continue
|
||||
}
|
||||
dropFileOrDir(path.Join(global.CONF.System.BaseDir, "1panel/log", file.Name()))
|
||||
}
|
||||
} else {
|
||||
dropFileOrDir(path.Join(global.CONF.System.BaseDir, "1panel/log", item.Name))
|
||||
}
|
||||
case "docker_log":
|
||||
dropFileOrDir(path.Join(global.CONF.System.BaseDir, "1panel/tmp/docker_logs", item.Name))
|
||||
case "task_log":
|
||||
pathItem := path.Join(global.CONF.System.BaseDir, "1panel/task", item.Name)
|
||||
dropFileOrDir(path.Join(global.CONF.System.BaseDir, "1panel/task", item.Name))
|
||||
if len(item.Name) == 0 {
|
||||
files, _ := os.ReadDir(pathItem)
|
||||
if len(files) == 0 {
|
||||
continue
|
||||
}
|
||||
for _, file := range files {
|
||||
_ = cronjobRepo.DeleteRecord(cronjobRepo.WithByRecordFile(path.Join(pathItem, file.Name())))
|
||||
}
|
||||
} else {
|
||||
_ = cronjobRepo.DeleteRecord(cronjobRepo.WithByRecordFile(pathItem))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_ = settingRepo.Update("LastCleanTime", time.Now().Format("2006-01-02 15:04:05"))
|
||||
_ = settingRepo.Update("LastCleanSize", fmt.Sprintf("%v", size))
|
||||
_ = settingRepo.Update("LastCleanData", fmt.Sprintf("%v", len(req)))
|
||||
}
|
||||
|
||||
func loadSnapshotTree(fileOp fileUtils.FileOp) []dto.CleanTree {
|
||||
var treeData []dto.CleanTree
|
||||
path1 := path.Join(global.CONF.System.BaseDir, "1panel/tmp/system")
|
||||
list1 := loadTreeWithAllFile(true, path1, "snapshot_tmp", path1, fileOp)
|
||||
if len(list1) != 0 {
|
||||
size, _ := fileOp.GetDirSize(path1)
|
||||
treeData = append(treeData, dto.CleanTree{ID: uuid.NewString(), Label: "snapshot_tmp", Size: uint64(size), Children: list1, Type: "snapshot_tmp", IsRecommend: true})
|
||||
}
|
||||
|
||||
path2 := path.Join(global.CONF.System.Backup, "system")
|
||||
list2 := loadTreeWithAllFile(true, path2, "snapshot_local", path2, fileOp)
|
||||
if len(list2) != 0 {
|
||||
size, _ := fileOp.GetDirSize(path2)
|
||||
treeData = append(treeData, dto.CleanTree{ID: uuid.NewString(), Label: "snapshot_local", Size: uint64(size), Children: list2, Type: "snapshot_local", IsRecommend: true})
|
||||
}
|
||||
return treeData
|
||||
}
|
||||
|
||||
func loadUnusedFile(fileOp fileUtils.FileOp) []dto.CleanTree {
|
||||
var treeData []dto.CleanTree
|
||||
path1 := path.Join(global.CONF.System.BaseDir, "original")
|
||||
list1 := loadTreeWithAllFile(true, path1, "old_original", path1, fileOp)
|
||||
if len(list1) != 0 {
|
||||
size, _ := fileOp.GetDirSize(path1)
|
||||
treeData = append(treeData, dto.CleanTree{ID: uuid.NewString(), Label: "old_original", Size: uint64(size), Children: list1, Type: "old_original"})
|
||||
}
|
||||
|
||||
path2 := path.Join(global.CONF.System.BaseDir, "1panel/resource/apps_bak")
|
||||
list2 := loadTreeWithAllFile(true, path2, "old_apps_bak", path2, fileOp)
|
||||
if len(list2) != 0 {
|
||||
size, _ := fileOp.GetDirSize(path2)
|
||||
treeData = append(treeData, dto.CleanTree{ID: uuid.NewString(), Label: "old_apps_bak", Size: uint64(size), Children: list2, Type: "old_apps_bak"})
|
||||
}
|
||||
|
||||
path3 := path.Join(global.CONF.System.BaseDir, "1panel/tmp/download")
|
||||
list3 := loadTreeWithAllFile(true, path3, "old_download", path3, fileOp)
|
||||
if len(list3) != 0 {
|
||||
size, _ := fileOp.GetDirSize(path3)
|
||||
treeData = append(treeData, dto.CleanTree{ID: uuid.NewString(), Label: "old_download", Size: uint64(size), Children: list3, Type: "old_download"})
|
||||
}
|
||||
|
||||
path4 := path.Join(global.CONF.System.BaseDir, "1panel/tmp")
|
||||
list4 := loadTreeWithDir(true, "old_upgrade", path4, fileOp)
|
||||
itemSize := uint64(0)
|
||||
for _, item := range list4 {
|
||||
itemSize += item.Size
|
||||
}
|
||||
if len(list4) != 0 {
|
||||
treeData = append(treeData, dto.CleanTree{ID: uuid.NewString(), Label: "old_upgrade", Size: itemSize, Children: list4, Type: "old_upgrade"})
|
||||
}
|
||||
return treeData
|
||||
}
|
||||
|
||||
func loadLogTree(fileOp fileUtils.FileOp) []dto.CleanTree {
|
||||
var treeData []dto.CleanTree
|
||||
path1 := path.Join(global.CONF.System.BaseDir, "1panel/log")
|
||||
list1 := loadTreeWithAllFile(true, path1, "system_log", path1, fileOp)
|
||||
size := uint64(0)
|
||||
for _, file := range list1 {
|
||||
size += file.Size
|
||||
}
|
||||
treeData = append(treeData, dto.CleanTree{ID: uuid.NewString(), Label: "system_log", Size: uint64(size), Children: list1, Type: "system_log", IsRecommend: true})
|
||||
|
||||
path2 := path.Join(global.CONF.System.BaseDir, "1panel/tmp/docker_logs")
|
||||
list2 := loadTreeWithAllFile(true, path2, "docker_log", path2, fileOp)
|
||||
size2, _ := fileOp.GetDirSize(path2)
|
||||
treeData = append(treeData, dto.CleanTree{ID: uuid.NewString(), Label: "docker_log", Size: uint64(size2), Children: list2, Type: "docker_log", IsRecommend: true})
|
||||
|
||||
path3 := path.Join(global.CONF.System.BaseDir, "1panel/task")
|
||||
list3 := loadTreeWithAllFile(false, path3, "task_log", path3, fileOp)
|
||||
size3, _ := fileOp.GetDirSize(path3)
|
||||
treeData = append(treeData, dto.CleanTree{ID: uuid.NewString(), Label: "task_log", Size: uint64(size3), Children: list3, Type: "task_log"})
|
||||
return treeData
|
||||
}
|
||||
|
||||
func loadTreeWithDir(isCheck bool, treeType, pathItem string, fileOp fileUtils.FileOp) []dto.CleanTree {
|
||||
var lists []dto.CleanTree
|
||||
files, err := os.ReadDir(pathItem)
|
||||
if err != nil {
|
||||
return lists
|
||||
}
|
||||
sort.Slice(files, func(i, j int) bool {
|
||||
return files[i].Name() > files[j].Name()
|
||||
})
|
||||
for _, file := range files {
|
||||
if (treeType == "old_upgrade" || treeType == "upgrade") && !strings.HasPrefix(file.Name(), "upgrade_2023") {
|
||||
continue
|
||||
}
|
||||
if file.IsDir() {
|
||||
size, err := fileOp.GetDirSize(path.Join(pathItem, file.Name()))
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
item := dto.CleanTree{
|
||||
ID: uuid.NewString(),
|
||||
Label: file.Name(),
|
||||
Type: treeType,
|
||||
Size: uint64(size),
|
||||
Name: strings.TrimPrefix(file.Name(), "/"),
|
||||
IsCheck: isCheck,
|
||||
IsRecommend: isCheck,
|
||||
}
|
||||
if treeType == "upgrade" && len(lists) == 0 {
|
||||
item.IsCheck = false
|
||||
item.IsRecommend = false
|
||||
}
|
||||
lists = append(lists, item)
|
||||
}
|
||||
}
|
||||
return lists
|
||||
}
|
||||
|
||||
func loadTreeWithAllFile(isCheck bool, originalPath, treeType, pathItem string, fileOp fileUtils.FileOp) []dto.CleanTree {
|
||||
var lists []dto.CleanTree
|
||||
|
||||
files, err := os.ReadDir(pathItem)
|
||||
if err != nil {
|
||||
return lists
|
||||
}
|
||||
for _, file := range files {
|
||||
if treeType == "system_log" && file.Name() == "1Panel.log" {
|
||||
continue
|
||||
}
|
||||
size := uint64(0)
|
||||
name := strings.TrimPrefix(path.Join(pathItem, file.Name()), originalPath+"/")
|
||||
if file.IsDir() {
|
||||
sizeItem, err := fileOp.GetDirSize(path.Join(pathItem, file.Name()))
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
size = uint64(sizeItem)
|
||||
} else {
|
||||
fileInfo, err := file.Info()
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
size = uint64(fileInfo.Size())
|
||||
}
|
||||
item := dto.CleanTree{
|
||||
ID: uuid.NewString(),
|
||||
Label: file.Name(),
|
||||
Type: treeType,
|
||||
Size: uint64(size),
|
||||
Name: name,
|
||||
IsCheck: isCheck,
|
||||
IsRecommend: isCheck,
|
||||
}
|
||||
if file.IsDir() {
|
||||
item.Children = loadTreeWithAllFile(isCheck, originalPath, treeType, path.Join(pathItem, file.Name()), fileOp)
|
||||
}
|
||||
lists = append(lists, item)
|
||||
}
|
||||
return lists
|
||||
}
|
||||
|
||||
func dropFileOrDir(itemPath string) {
|
||||
global.LOG.Debugf("drop file %s", itemPath)
|
||||
if err := os.RemoveAll(itemPath); err != nil {
|
||||
global.LOG.Errorf("drop file %s failed, err %v", itemPath, err)
|
||||
}
|
||||
}
|
@ -7,11 +7,20 @@ import (
|
||||
)
|
||||
|
||||
var AddDefaultNetwork = &gormigrate.Migration{
|
||||
ID: "20230918-add-default-network",
|
||||
ID: "20230928-add-default-network",
|
||||
Migrate: func(tx *gorm.DB) error {
|
||||
if err := tx.Create(&model.Setting{Key: "DefaultNetwork", Value: ""}).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if err := tx.Create(&model.Setting{Key: "LastCleanTime", Value: ""}).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if err := tx.Create(&model.Setting{Key: "LastCleanSize", Value: ""}).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if err := tx.Create(&model.Setting{Key: "LastCleanData", Value: ""}).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
@ -32,6 +32,8 @@ func (s *SettingRouter) InitSettingRouter(Router *gin.RouterGroup) {
|
||||
settingRouter.POST("/monitor/clean", baseApi.CleanMonitor)
|
||||
settingRouter.GET("/mfa/:interval", baseApi.GetMFA)
|
||||
settingRouter.POST("/mfa/bind", baseApi.MFABind)
|
||||
settingRouter.POST("/scan", baseApi.ScanSystem)
|
||||
settingRouter.POST("/clean", baseApi.SystemClean)
|
||||
|
||||
settingRouter.POST("/snapshot", baseApi.CreateSnapshot)
|
||||
settingRouter.POST("/snapshot/status", baseApi.LoadSnapShotStatus)
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Package docs GENERATED BY SWAG; DO NOT EDIT
|
||||
// This file was generated by swaggo/swag
|
||||
// Code generated by swaggo/swag. DO NOT EDIT.
|
||||
|
||||
package docs
|
||||
|
||||
import "github.com/swaggo/swag"
|
||||
@ -8565,6 +8565,49 @@ const docTemplate = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"/settings/clean": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"description": "清理系统垃圾文件",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"System Setting"
|
||||
],
|
||||
"summary": "System clean",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "request",
|
||||
"name": "request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/dto.Clean"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK"
|
||||
}
|
||||
},
|
||||
"x-panel-log": {
|
||||
"BeforeFuntions": [],
|
||||
"bodyKeys": [],
|
||||
"formatEN": "Clean system junk files",
|
||||
"formatZH": "清理系统垃圾文件",
|
||||
"paramKeys": []
|
||||
}
|
||||
}
|
||||
},
|
||||
"/settings/expired/handle": {
|
||||
"post": {
|
||||
"security": [
|
||||
@ -8784,6 +8827,32 @@ const docTemplate = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"/settings/scan": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"description": "扫描系统垃圾文件",
|
||||
"tags": [
|
||||
"System Setting"
|
||||
],
|
||||
"summary": "Scan system",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK"
|
||||
}
|
||||
},
|
||||
"x-panel-log": {
|
||||
"BeforeFuntions": [],
|
||||
"bodyKeys": [],
|
||||
"formatEN": "scan System Junk Files",
|
||||
"formatZH": "扫描系统垃圾文件",
|
||||
"paramKeys": []
|
||||
}
|
||||
}
|
||||
},
|
||||
"/settings/search": {
|
||||
"post": {
|
||||
"security": [
|
||||
@ -12132,6 +12201,20 @@ const docTemplate = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"dto.Clean": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"size": {
|
||||
"type": "integer"
|
||||
},
|
||||
"treeType": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"dto.CleanLog": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
@ -14904,6 +14987,15 @@ const docTemplate = `{
|
||||
"language": {
|
||||
"type": "string"
|
||||
},
|
||||
"lastCleanData": {
|
||||
"type": "string"
|
||||
},
|
||||
"lastCleanSize": {
|
||||
"type": "string"
|
||||
},
|
||||
"lastCleanTime": {
|
||||
"type": "string"
|
||||
},
|
||||
"localTime": {
|
||||
"type": "string"
|
||||
},
|
||||
|
@ -8558,6 +8558,49 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/settings/clean": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"description": "清理系统垃圾文件",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"System Setting"
|
||||
],
|
||||
"summary": "System clean",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "request",
|
||||
"name": "request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/dto.Clean"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK"
|
||||
}
|
||||
},
|
||||
"x-panel-log": {
|
||||
"BeforeFuntions": [],
|
||||
"bodyKeys": [],
|
||||
"formatEN": "Clean system junk files",
|
||||
"formatZH": "清理系统垃圾文件",
|
||||
"paramKeys": []
|
||||
}
|
||||
}
|
||||
},
|
||||
"/settings/expired/handle": {
|
||||
"post": {
|
||||
"security": [
|
||||
@ -8777,6 +8820,32 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/settings/scan": {
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"ApiKeyAuth": []
|
||||
}
|
||||
],
|
||||
"description": "扫描系统垃圾文件",
|
||||
"tags": [
|
||||
"System Setting"
|
||||
],
|
||||
"summary": "Scan system",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK"
|
||||
}
|
||||
},
|
||||
"x-panel-log": {
|
||||
"BeforeFuntions": [],
|
||||
"bodyKeys": [],
|
||||
"formatEN": "scan System Junk Files",
|
||||
"formatZH": "扫描系统垃圾文件",
|
||||
"paramKeys": []
|
||||
}
|
||||
}
|
||||
},
|
||||
"/settings/search": {
|
||||
"post": {
|
||||
"security": [
|
||||
@ -12125,6 +12194,20 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"dto.Clean": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"size": {
|
||||
"type": "integer"
|
||||
},
|
||||
"treeType": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"dto.CleanLog": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
@ -14897,6 +14980,15 @@
|
||||
"language": {
|
||||
"type": "string"
|
||||
},
|
||||
"lastCleanData": {
|
||||
"type": "string"
|
||||
},
|
||||
"lastCleanSize": {
|
||||
"type": "string"
|
||||
},
|
||||
"lastCleanTime": {
|
||||
"type": "string"
|
||||
},
|
||||
"localTime": {
|
||||
"type": "string"
|
||||
},
|
||||
|
@ -170,6 +170,15 @@ definitions:
|
||||
required:
|
||||
- value
|
||||
type: object
|
||||
dto.Clean:
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
size:
|
||||
type: integer
|
||||
treeType:
|
||||
type: string
|
||||
type: object
|
||||
dto.CleanLog:
|
||||
properties:
|
||||
logType:
|
||||
@ -2038,6 +2047,12 @@ definitions:
|
||||
type: string
|
||||
language:
|
||||
type: string
|
||||
lastCleanData:
|
||||
type: string
|
||||
lastCleanSize:
|
||||
type: string
|
||||
lastCleanTime:
|
||||
type: string
|
||||
localTime:
|
||||
type: string
|
||||
messageType:
|
||||
@ -9542,6 +9557,34 @@ paths:
|
||||
summary: Load local backup dir
|
||||
tags:
|
||||
- System Setting
|
||||
/settings/clean:
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
description: 清理系统垃圾文件
|
||||
parameters:
|
||||
- description: request
|
||||
in: body
|
||||
name: request
|
||||
required: true
|
||||
schema:
|
||||
items:
|
||||
$ref: '#/definitions/dto.Clean'
|
||||
type: array
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
security:
|
||||
- ApiKeyAuth: []
|
||||
summary: System clean
|
||||
tags:
|
||||
- System Setting
|
||||
x-panel-log:
|
||||
BeforeFuntions: []
|
||||
bodyKeys: []
|
||||
formatEN: Clean system junk files
|
||||
formatZH: 清理系统垃圾文件
|
||||
paramKeys: []
|
||||
/settings/expired/handle:
|
||||
post:
|
||||
consumes:
|
||||
@ -9683,6 +9726,23 @@ paths:
|
||||
formatEN: update system port => [serverPort]
|
||||
formatZH: 修改系统端口 => [serverPort]
|
||||
paramKeys: []
|
||||
/settings/scan:
|
||||
post:
|
||||
description: 扫描系统垃圾文件
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
security:
|
||||
- ApiKeyAuth: []
|
||||
summary: Scan system
|
||||
tags:
|
||||
- System Setting
|
||||
x-panel-log:
|
||||
BeforeFuntions: []
|
||||
bodyKeys: []
|
||||
formatEN: scan System Junk Files
|
||||
formatZH: 扫描系统垃圾文件
|
||||
paramKeys: []
|
||||
/settings/search:
|
||||
post:
|
||||
description: 加载系统配置信息
|
||||
|
@ -17,6 +17,9 @@ export namespace Setting {
|
||||
theme: string;
|
||||
language: string;
|
||||
defaultNetwork: string;
|
||||
lastCleanTime: string;
|
||||
lastCleanSize: string;
|
||||
lastCleanData: string;
|
||||
|
||||
serverPort: number;
|
||||
ssl: string;
|
||||
@ -76,6 +79,24 @@ export namespace Setting {
|
||||
code: string;
|
||||
interval: string;
|
||||
}
|
||||
|
||||
export interface CleanData {
|
||||
systemClean: Array<CleanTree>;
|
||||
uploadClean: Array<CleanTree>;
|
||||
downloadClean: Array<CleanTree>;
|
||||
systemLogClean: Array<CleanTree>;
|
||||
}
|
||||
export interface CleanTree {
|
||||
id: string;
|
||||
label: string;
|
||||
children: Array<CleanTree>;
|
||||
type: string;
|
||||
name: string;
|
||||
size: number;
|
||||
isCheck: boolean;
|
||||
isRecommend: boolean;
|
||||
}
|
||||
|
||||
export interface SnapshotCreate {
|
||||
id: number;
|
||||
from: string;
|
||||
|
@ -39,6 +39,13 @@ export const handleExpired = (param: Setting.PasswordUpdate) => {
|
||||
return http.post(`/settings/expired/handle`, param);
|
||||
};
|
||||
|
||||
export const scanSystem = () => {
|
||||
return http.post<Setting.CleanData>(`/settings/scan`, {});
|
||||
};
|
||||
export const cleanSystem = (param: any) => {
|
||||
return http.post(`/settings/clean`, param);
|
||||
};
|
||||
|
||||
export const loadTimeZone = () => {
|
||||
return http.get<Array<string>>(`/settings/time/option`);
|
||||
};
|
||||
|
@ -89,7 +89,6 @@ const message = {
|
||||
loadingText: {
|
||||
Upgrading: 'System upgrade, please wait...',
|
||||
Restarting: 'System restart, please wait...',
|
||||
Snapshoting: 'Making snapshots, please wait...',
|
||||
Recovering: 'Recovering from snapshot, please wait...',
|
||||
Rollbacking: 'Rollbacking from snapshot, please wait...',
|
||||
},
|
||||
@ -1203,6 +1202,58 @@ const message = {
|
||||
doc2: 'Document',
|
||||
currentVersion: 'Version',
|
||||
},
|
||||
clean: {
|
||||
scan: 'Start Scanning',
|
||||
clean: 'Clean Now',
|
||||
reScan: 'Rescan',
|
||||
cleanHelper:
|
||||
'After checking the files and directories for cleaning, it cannot be undone (system cache cleaning requires a service restart). Do you want to continue?',
|
||||
statusSuggest: '( Recommended Cleaning )',
|
||||
statusClean: '( Very Clean )',
|
||||
statusEmpty: 'Very clean, no cleaning needed!',
|
||||
statusWarning: '( Proceed with Caution )',
|
||||
lastCleanTime: 'Last Cleaned: {0}',
|
||||
lastCleanHelper: 'Files and directories cleaned: {0}, Total cleaned: {1}',
|
||||
cleanSuccessful: 'Cleaning Successful!',
|
||||
currentCleanHelper: 'Files and directories cleaned in this session: {0}, Total cleaned: {1}',
|
||||
suggest: '(Recommended)',
|
||||
totalScan: 'Total junk files to be cleaned: ',
|
||||
selectScan: 'Total selected junk files: ',
|
||||
|
||||
system: 'System Junk',
|
||||
systemHelper:
|
||||
'Scan system junk (specifically includes temporary files generated during snapshots, upgrades, and obsolete file contents during version iterations)',
|
||||
panelOriginal: 'System snapshot recovery backup files',
|
||||
upgrade: 'System upgrade backup files',
|
||||
cache: 'System cache files',
|
||||
snapshot: 'System snapshot temporary files',
|
||||
snapshotTmp: 'System snapshot upload temporary files',
|
||||
snapshotLocal: 'System snapshot creation temporary files',
|
||||
unused: 'Unused system directories',
|
||||
oldUpgrade: 'Unused pre-upgrade backup directories',
|
||||
oldOriginal: 'Unused pre-snapshot recovery backup directories',
|
||||
oldAppsBak: 'Unused application backup directories',
|
||||
|
||||
upload: 'Temporary upload files',
|
||||
uploadHelper:
|
||||
'Scan temporary upload directory (specifically includes temporary files uploaded from the system backup list)',
|
||||
download: 'Temporary Download Files',
|
||||
downloadHelper:
|
||||
'Scan temporary download directory (specifically includes temporary files downloaded from third-party backup accounts by the system)',
|
||||
website: 'Website',
|
||||
app: 'Application',
|
||||
database: 'Database',
|
||||
directory: 'Directory',
|
||||
|
||||
systemLog: 'System Log Files',
|
||||
systemLogHelper:
|
||||
'Scan system junk (specifically includes system log information, container build or image pull log information, and log files generated in scheduled tasks)',
|
||||
dockerLog: 'Container operation log files',
|
||||
taskLog: 'Scheduled task execution log files',
|
||||
shell: 'Shell script scheduled tasks',
|
||||
containerShell: 'Container internal Shell script scheduled tasks',
|
||||
curl: 'CURL scheduled tasks',
|
||||
},
|
||||
app: {
|
||||
app: 'Application',
|
||||
installName: 'Name',
|
||||
|
@ -89,7 +89,6 @@ const message = {
|
||||
loadingText: {
|
||||
Upgrading: '系統升級中,請稍候...',
|
||||
Restarting: '系統重啟中,請稍候...',
|
||||
Snapshoting: '製作快照中,請稍候...',
|
||||
Recovering: '從快照恢復中,請稍候...',
|
||||
Rollbacking: '快照回滾中,請稍候...',
|
||||
},
|
||||
@ -1144,6 +1143,54 @@ const message = {
|
||||
doc2: '文檔',
|
||||
currentVersion: '當前運行版本:',
|
||||
},
|
||||
clean: {
|
||||
scan: '開始掃描',
|
||||
clean: '立即清理',
|
||||
reScan: '重新掃描',
|
||||
cleanHelper: '已勾選文件及目錄清理後無法回滾(系統緩存文件清理需要重啟服務),是否繼續?',
|
||||
statusSuggest: '( 建議清理 )',
|
||||
statusClean: '( 很幹凈 )',
|
||||
statusEmpty: '非常幹凈,無需清理!',
|
||||
statusWarning: '( 謹慎操作 )',
|
||||
lastCleanTime: '上次清理時間: {0}',
|
||||
lastCleanHelper: '清理文件及目錄:{0} 個, 總計清理:{1}',
|
||||
cleanSuccessful: '清理成功!',
|
||||
currentCleanHelper: '本次清理文件及目錄:{0} 個, 總計清理:{1}',
|
||||
suggest: '( 建議清理 )',
|
||||
totalScan: '待清理垃圾文件共計: ',
|
||||
selectScan: '已選中垃圾文件共計: ',
|
||||
|
||||
system: '系統垃圾',
|
||||
systemHelper: '掃描系統垃圾(具體包括:快照、升級等過程中產生的臨時文件以及版本叠代過程中廢棄的文件內容)',
|
||||
panelOriginal: '系統快照恢復前備份文件',
|
||||
upgrade: '系統升級備份文件',
|
||||
cache: '系統緩存文件',
|
||||
snapshot: '系統快照臨時文件',
|
||||
snapshotTmp: '系統快照上傳臨時文件',
|
||||
snapshotLocal: '系統快照製作臨時文件',
|
||||
unused: '系統廢棄目錄',
|
||||
oldUpgrade: '廢棄升級前備份目錄',
|
||||
oldOriginal: '廢棄快照恢復前備份目錄',
|
||||
oldAppsBak: '廢棄應用備份目錄',
|
||||
|
||||
upload: '臨時上傳文件',
|
||||
uploadHelper: '掃描臨時上傳目錄(具體包括:系統上傳備份列表中上傳的臨時文件)',
|
||||
download: '臨時下載文件',
|
||||
downloadHelper: '掃描臨時下載目錄(具體包括:系統從第三方備份賬號下載的臨時文件)',
|
||||
website: '網站',
|
||||
app: '應用',
|
||||
database: '數據庫',
|
||||
directory: '應用',
|
||||
|
||||
systemLog: '系統日誌文件',
|
||||
systemLogHelper:
|
||||
'掃描系統垃圾(具體包括:系統日誌信息、容器構建或鏡像拉取等日誌信息以及計劃任務中產生的日誌文件)',
|
||||
dockerLog: '容器操作日誌文件',
|
||||
taskLog: '計劃任務執行日誌文件',
|
||||
shell: 'Shell 腳本計劃任務',
|
||||
containerShell: '容器內執行 Shell 腳本計劃任務',
|
||||
curl: 'CURL 計劃任務',
|
||||
},
|
||||
app: {
|
||||
app: '應用',
|
||||
installName: '安裝名稱',
|
||||
|
@ -89,7 +89,6 @@ const message = {
|
||||
loadingText: {
|
||||
Upgrading: '系统升级中,请稍候...',
|
||||
Restarting: '系统重启中,请稍候...',
|
||||
Snapshoting: '制作快照中,请稍候...',
|
||||
Recovering: '从快照恢复中,请稍候...',
|
||||
Rollbacking: '快照回滚中,请稍候...',
|
||||
},
|
||||
@ -996,6 +995,7 @@ const message = {
|
||||
newPassword: '新密码',
|
||||
retryPassword: '确认密码',
|
||||
duplicatePassword: '新密码不能与原始密码一致,请重新输入!',
|
||||
diskClean: '磁盘清理',
|
||||
|
||||
thirdParty: '第三方账号',
|
||||
createBackupAccount: '添加 {0}',
|
||||
@ -1144,6 +1144,53 @@ const message = {
|
||||
doc2: '文档',
|
||||
currentVersion: '当前运行版本:',
|
||||
},
|
||||
clean: {
|
||||
scan: '开始扫描',
|
||||
clean: '立即清理',
|
||||
reScan: '重新扫描',
|
||||
cleanHelper: '已勾选文件及目录清理后无法回滚(系统缓存文件清理需要重启服务),是否继续?',
|
||||
statusSuggest: '( 建议清理 )',
|
||||
statusClean: '( 很干净 )',
|
||||
statusEmpty: '非常干净,无需清理!',
|
||||
statusWarning: '( 谨慎操作 )',
|
||||
lastCleanTime: '上次清理时间: {0}',
|
||||
lastCleanHelper: '清理文件及目录:{0} 个, 总计清理:{1}',
|
||||
cleanSuccessful: '清理成功!',
|
||||
currentCleanHelper: '本次清理文件及目录:{0} 个, 总计清理:{1}',
|
||||
totalScan: '待清理垃圾文件共计: ',
|
||||
selectScan: '已选中垃圾文件共计: ',
|
||||
|
||||
system: '系统垃圾',
|
||||
systemHelper: '扫描系统垃圾(具体包括:快照、升级等过程中产生的临时文件以及版本迭代过程中废弃的文件内容)',
|
||||
panelOriginal: '系统快照恢复前备份文件',
|
||||
upgrade: '系统升级备份文件',
|
||||
cache: '系统缓存文件',
|
||||
snapshot: '系统快照临时文件',
|
||||
snapshotTmp: '系统快照上传临时文件',
|
||||
snapshotLocal: '系统快照制作临时文件',
|
||||
unused: '系统废弃目录',
|
||||
oldUpgrade: '废弃升级前备份目录',
|
||||
oldOriginal: '废弃快照恢复前备份目录',
|
||||
oldAppsBak: '废弃应用备份目录',
|
||||
|
||||
upload: '临时上传文件',
|
||||
uploadHelper: '扫描临时上传目录(具体包括:系统上传备份列表中上传的临时文件)',
|
||||
download: '临时下载文件',
|
||||
downloadHelper: '扫描临时下载目录(具体包括:系统从第三方备份账号下载的临时文件)',
|
||||
website: '网站',
|
||||
app: '应用',
|
||||
database: '数据库',
|
||||
directory: '应用',
|
||||
|
||||
systemLog: '系统日志文件',
|
||||
systemLogHelper:
|
||||
'扫描系统垃圾(具体包括:系统日志信息、容器构建或镜像拉取等日志信息以及计划任务中产生的日志文件)',
|
||||
dockerLog: '容器操作日志文件',
|
||||
taskLog: '计划任务执行日志文件',
|
||||
shell: 'Shell 脚本计划任务',
|
||||
containerShell: '容器内执行 Shell 脚本计划任务',
|
||||
curl: 'CURL 计划任务',
|
||||
},
|
||||
app: {
|
||||
app: '应用',
|
||||
installName: '安装名称',
|
||||
|
534
frontend/src/views/setting/panel/clean/index.vue
Normal file
534
frontend/src/views/setting/panel/clean/index.vue
Normal file
@ -0,0 +1,534 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-drawer v-model="drawerVisible" :destroy-on-close="true" :close-on-click-modal="false" size="50%">
|
||||
<template #header>
|
||||
<DrawerHeader :header="$t('setting.diskClean')" :back="handleClose" />
|
||||
</template>
|
||||
<div v-loading="loading">
|
||||
<div v-if="scanStatus !== 'scanned'">
|
||||
<div v-if="scanStatus === 'beforeScan'">
|
||||
<el-text class="clean_title" type="success">
|
||||
{{ $t('clean.lastCleanTime', [form.lastCleanTime || '-']) }}
|
||||
</el-text>
|
||||
<div class="mt-4">
|
||||
<el-text type="success">
|
||||
{{
|
||||
$t('clean.lastCleanHelper', [
|
||||
form.lastCleanData || '-',
|
||||
form.lastCleanSize ? computeSize(Number(form.lastCleanSize)) : '-',
|
||||
])
|
||||
}}
|
||||
</el-text>
|
||||
</div>
|
||||
<div class="large_button">
|
||||
<el-button type="primary" size="large" @click="scanData">{{ $t('clean.scan') }}</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="scanStatus === 'afterScan'">
|
||||
<el-text class="clean_title" type="success">{{ $t('clean.cleanSuccessful') }}</el-text>
|
||||
<div class="mt-4">
|
||||
<el-text type="success">
|
||||
{{
|
||||
$t('clean.currentCleanHelper', [
|
||||
form.lastCleanData,
|
||||
computeSize(Number(form.lastCleanSize)),
|
||||
])
|
||||
}}
|
||||
</el-text>
|
||||
</div>
|
||||
<div class="large_button">
|
||||
<el-button type="primary" size="large" @click="scanData">
|
||||
{{ $t('clean.reScan') }}
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="app-card">
|
||||
<el-card class="e-card">
|
||||
<el-row>
|
||||
<el-col :span="3">
|
||||
<el-button icon="Setting" link class="card_icon" />
|
||||
</el-col>
|
||||
<el-col :span="21">
|
||||
<div>
|
||||
<el-text class="mx-1 card_title" type="primary">
|
||||
{{ $t('clean.system') }}
|
||||
</el-text>
|
||||
</div>
|
||||
<span>{{ $t('clean.systemHelper') }}</span>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-card>
|
||||
<el-card class="e-card">
|
||||
<el-row>
|
||||
<el-col :span="3">
|
||||
<el-button icon="Upload" link class="card_icon" />
|
||||
</el-col>
|
||||
<el-col :span="21">
|
||||
<div>
|
||||
<el-text class="mx-1 card_title" type="primary">
|
||||
{{ $t('clean.upload') }}
|
||||
</el-text>
|
||||
</div>
|
||||
<span>{{ $t('clean.uploadHelper') }}</span>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-card>
|
||||
<el-card class="e-card">
|
||||
<el-row>
|
||||
<el-col :span="3">
|
||||
<el-button icon="Download" link class="card_icon" />
|
||||
</el-col>
|
||||
<el-col :span="21">
|
||||
<div>
|
||||
<el-text class="mx-1 card_title" type="primary">
|
||||
{{ $t('clean.download') }}
|
||||
</el-text>
|
||||
</div>
|
||||
<span>{{ $t('clean.downloadHelper') }}</span>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-card>
|
||||
<el-card class="e-card">
|
||||
<el-row>
|
||||
<el-col :span="3">
|
||||
<el-button icon="Document" link class="card_icon" />
|
||||
</el-col>
|
||||
<el-col :span="21">
|
||||
<div>
|
||||
<el-text class="mx-1 card_title" type="primary">
|
||||
{{ $t('clean.systemLog') }}
|
||||
</el-text>
|
||||
</div>
|
||||
<span>
|
||||
{{ $t('clean.systemLogHelper') }}
|
||||
</span>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-card>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="scanStatus === 'scanned'">
|
||||
<div>
|
||||
<el-text class="clean_title" type="primary">
|
||||
{{ $t('clean.totalScan') }} {{ computeSize(totalSize) }}
|
||||
</el-text>
|
||||
<div class="mt-4">
|
||||
<el-text type="info">{{ $t('clean.selectScan') }} {{ computeSize(selectSize) }}</el-text>
|
||||
</div>
|
||||
<div class="large_button">
|
||||
<el-button type="primary" size="large" @click="onSubmitClean">
|
||||
{{ $t('clean.clean') }}
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<el-collapse class="mt-4" v-model="activeNames">
|
||||
<el-collapse-item :title="$t('clean.system')" name="system">
|
||||
<el-tree
|
||||
ref="systemRef"
|
||||
:data="cleanData.systemClean"
|
||||
node-key="id"
|
||||
:default-checked-keys="systemDefaultCheck"
|
||||
show-checkbox
|
||||
:props="defaultProps"
|
||||
@check-change="onChange"
|
||||
>
|
||||
<template #default="{ node, data }">
|
||||
<div class="float-left">
|
||||
<span>{{ load18n(data.label) }}</span>
|
||||
</div>
|
||||
<div class="ml-4 float-left">
|
||||
<span v-if="data.size">{{ computeSize(data.size) }}</span>
|
||||
</div>
|
||||
<div class="ml-4 float-left">
|
||||
<span>{{ loadTag(node, data) }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-tree>
|
||||
</el-collapse-item>
|
||||
<el-collapse-item :title="$t('clean.upload')" name="upload">
|
||||
<el-tree
|
||||
ref="uploadRef"
|
||||
:data="cleanData.uploadClean"
|
||||
node-key="id"
|
||||
:default-checked-keys="uploadDefaultCheck"
|
||||
show-checkbox
|
||||
:props="defaultProps"
|
||||
@check-change="onChange"
|
||||
>
|
||||
<template #empty>
|
||||
<el-empty :image-size="60" :description="$t('clean.statusEmpty')" />
|
||||
</template>
|
||||
<template #default="{ node, data }">
|
||||
<div class="float-left">
|
||||
<span>{{ load18n(data.label) }}</span>
|
||||
</div>
|
||||
<div class="ml-4 float-left">
|
||||
<span v-if="data.size">{{ computeSize(data.size) }}</span>
|
||||
</div>
|
||||
<div class="ml-4 float-left">
|
||||
<span>{{ loadTag(node, data) }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-tree>
|
||||
</el-collapse-item>
|
||||
<el-collapse-item :title="$t('clean.download')" name="download">
|
||||
<el-tree
|
||||
ref="downloadRef"
|
||||
:data="cleanData.downloadClean"
|
||||
node-key="id"
|
||||
:default-checked-keys="downloadDefaultCheck"
|
||||
show-checkbox
|
||||
:props="defaultProps"
|
||||
@check-change="onChange"
|
||||
>
|
||||
<template #empty>
|
||||
<el-empty :image-size="60" :description="$t('clean.statusEmpty')" />
|
||||
</template>
|
||||
<template #default="{ node, data }">
|
||||
<div class="float-left">
|
||||
<span>{{ load18n(data.label) }}</span>
|
||||
</div>
|
||||
<div class="ml-4 float-left">
|
||||
<span v-if="data.size">{{ computeSize(data.size) }}</span>
|
||||
</div>
|
||||
<div class="ml-4 float-left">
|
||||
<span>{{ loadTag(node, data) }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-tree>
|
||||
</el-collapse-item>
|
||||
<el-collapse-item :title="$t('clean.systemLog')" name="system_log">
|
||||
<el-tree
|
||||
ref="systemLogRef"
|
||||
:data="cleanData.systemLogClean"
|
||||
node-key="id"
|
||||
:default-checked-keys="systemLogDefaultCheck"
|
||||
show-checkbox
|
||||
:props="defaultProps"
|
||||
@check-change="onChange"
|
||||
>
|
||||
<template #default="{ node, data }">
|
||||
<div class="float-left">
|
||||
<span>{{ load18n(data.label) }}</span>
|
||||
</div>
|
||||
<div class="ml-4 float-left">
|
||||
<span v-if="data.size">{{ computeSize(data.size) }}</span>
|
||||
</div>
|
||||
<div class="ml-4 float-left">
|
||||
<span>{{ loadTag(node, data) }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-tree>
|
||||
</el-collapse-item>
|
||||
</el-collapse>
|
||||
</div>
|
||||
</div>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="onCancel">{{ $t('commons.button.cancel') }}</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-drawer>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { reactive, ref } from 'vue';
|
||||
import { computeSize } from '@/utils/util';
|
||||
import DrawerHeader from '@/components/drawer-header/index.vue';
|
||||
import { cleanSystem, scanSystem } from '@/api/modules/setting';
|
||||
import i18n from '@/lang';
|
||||
import { MsgSuccess } from '@/utils/message';
|
||||
|
||||
const emit = defineEmits<{ (e: 'search'): void }>();
|
||||
const drawerVisible = ref();
|
||||
const loading = ref();
|
||||
const totalSize = ref<number>(0);
|
||||
const selectSize = ref<number>(0);
|
||||
|
||||
const scanStatus = ref<string>('beforeScan');
|
||||
|
||||
const defaultProps = {
|
||||
children: 'children',
|
||||
label: 'label',
|
||||
};
|
||||
const cleanData = reactive({
|
||||
systemClean: [],
|
||||
uploadClean: [],
|
||||
downloadClean: [],
|
||||
systemLogClean: [],
|
||||
});
|
||||
const systemRef = ref();
|
||||
const systemDefaultCheck = ref([]);
|
||||
const uploadRef = ref();
|
||||
const uploadDefaultCheck = ref([]);
|
||||
const downloadRef = ref();
|
||||
const downloadDefaultCheck = ref([]);
|
||||
const systemLogRef = ref();
|
||||
const systemLogDefaultCheck = ref([]);
|
||||
const activeNames = ref(['system', 'upload', 'download', 'system_log']);
|
||||
|
||||
const submitCleans = ref();
|
||||
|
||||
const form = reactive({
|
||||
lastCleanTime: '',
|
||||
lastCleanSize: '',
|
||||
lastCleanData: '',
|
||||
});
|
||||
interface DialogProps {
|
||||
lastCleanTime: string;
|
||||
lastCleanSize: string;
|
||||
lastCleanData: string;
|
||||
}
|
||||
const acceptParams = (params: DialogProps): void => {
|
||||
scanStatus.value = 'beforeScan';
|
||||
form.lastCleanTime = params.lastCleanTime;
|
||||
console.log(form.lastCleanTime);
|
||||
form.lastCleanSize = params.lastCleanSize;
|
||||
form.lastCleanData = params.lastCleanData;
|
||||
drawerVisible.value = true;
|
||||
};
|
||||
|
||||
const scanData = async () => {
|
||||
loading.value = true;
|
||||
await scanSystem()
|
||||
.then((res) => {
|
||||
loading.value = false;
|
||||
selectSize.value = 0;
|
||||
totalSize.value = 0;
|
||||
cleanData.systemClean = res.data.systemClean || [];
|
||||
for (const item of cleanData.systemClean) {
|
||||
totalSize.value += item.size;
|
||||
}
|
||||
cleanData.uploadClean = res.data.uploadClean || [];
|
||||
for (const item of cleanData.uploadClean) {
|
||||
totalSize.value += item.size;
|
||||
}
|
||||
cleanData.downloadClean = res.data.downloadClean || [];
|
||||
for (const item of cleanData.downloadClean) {
|
||||
totalSize.value += item.size;
|
||||
}
|
||||
cleanData.systemLogClean = res.data.systemLogClean || [];
|
||||
for (const item of cleanData.systemLogClean) {
|
||||
totalSize.value += item.size;
|
||||
}
|
||||
loadCheck(cleanData.systemClean, systemDefaultCheck.value);
|
||||
loadCheck(cleanData.uploadClean, uploadDefaultCheck.value);
|
||||
loadCheck(cleanData.downloadClean, downloadDefaultCheck.value);
|
||||
loadCheck(cleanData.systemLogClean, systemLogDefaultCheck.value);
|
||||
scanStatus.value = 'scanned';
|
||||
})
|
||||
.catch(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
};
|
||||
|
||||
const onSubmitClean = async () => {
|
||||
ElMessageBox.confirm(i18n.global.t('clean.cleanHelper'), i18n.global.t('clean.clean'), {
|
||||
confirmButtonText: i18n.global.t('commons.button.confirm'),
|
||||
cancelButtonText: i18n.global.t('commons.button.cancel'),
|
||||
type: 'info',
|
||||
}).then(async () => {
|
||||
loading.value = true;
|
||||
submitCleans.value = [];
|
||||
loadSubmitCheck(cleanData.systemClean);
|
||||
loadSubmitCheck(cleanData.uploadClean);
|
||||
loadSubmitCheck(cleanData.downloadClean);
|
||||
loadSubmitCheck(cleanData.systemLogClean);
|
||||
await cleanSystem(submitCleans.value)
|
||||
.then(() => {
|
||||
form.lastCleanSize = selectSize.value + '';
|
||||
form.lastCleanData = submitCleans.value.length + '';
|
||||
scanStatus.value = 'afterScan';
|
||||
MsgSuccess(i18n.global.t('commons.msg.operationSuccess'));
|
||||
loading.value = false;
|
||||
})
|
||||
.catch(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
const onCancel = async () => {
|
||||
drawerVisible.value = false;
|
||||
emit('search');
|
||||
};
|
||||
|
||||
const loadSubmitCheck = (data: any) => {
|
||||
if (data.children === null) {
|
||||
if (data.isCheck) {
|
||||
submitCleans.value.push({ treeType: data.type, name: data.name, size: data.size });
|
||||
}
|
||||
return;
|
||||
}
|
||||
for (const item of data) {
|
||||
if (item.isCheck) {
|
||||
submitCleans.value.push({ treeType: item.type, name: item.name, size: item.size });
|
||||
continue;
|
||||
}
|
||||
if (item.children) {
|
||||
loadSubmitCheck(item.children);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const changeCheckStatus = (data: any, isCheck: boolean) => {
|
||||
data.isCheck = isCheck;
|
||||
if (data.children) {
|
||||
for (const item of data.children) {
|
||||
changeCheckStatus(item, isCheck);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function onChange(data: any, isCheck: boolean) {
|
||||
changeCheckStatus(data, isCheck);
|
||||
selectSize.value = 0;
|
||||
let systemSelects = systemRef.value.getCheckedNodes(false, true);
|
||||
for (const item of systemSelects) {
|
||||
if (item.children === null) {
|
||||
selectSize.value = selectSize.value + Number(item.size);
|
||||
}
|
||||
}
|
||||
let uploadSelects = uploadRef.value.getCheckedNodes(false, true);
|
||||
for (const item of uploadSelects) {
|
||||
if (item.children === null) {
|
||||
selectSize.value = selectSize.value + Number(item.size);
|
||||
}
|
||||
}
|
||||
let downloadSelects = downloadRef.value.getCheckedNodes(false, true);
|
||||
for (const item of downloadSelects) {
|
||||
if (item.children === null) {
|
||||
selectSize.value = selectSize.value + Number(item.size);
|
||||
}
|
||||
}
|
||||
let systemLogSelects = systemLogRef.value.getCheckedNodes(false, true);
|
||||
for (const item of systemLogSelects) {
|
||||
if (item.children === null) {
|
||||
selectSize.value = selectSize.value + Number(item.size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function loadCheck(data: any, checkList: any) {
|
||||
if (data.children === null) {
|
||||
if (data.isCheck) {
|
||||
checkList.push(data.id);
|
||||
}
|
||||
return;
|
||||
}
|
||||
for (const item of data) {
|
||||
if (item.isCheck) {
|
||||
selectSize.value = selectSize.value + Number(item.size);
|
||||
checkList.push(item.id);
|
||||
continue;
|
||||
}
|
||||
if (item.children) {
|
||||
loadCheck(item.children, checkList);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function loadTag(node: any, data: any) {
|
||||
if (node.level !== 1) {
|
||||
return '';
|
||||
}
|
||||
if (data.size === 0) {
|
||||
return i18n.global.t('clean.statusClean');
|
||||
}
|
||||
return data.isRecommend ? i18n.global.t('clean.statusSuggest') : i18n.global.t('clean.statusWarning');
|
||||
}
|
||||
|
||||
function load18n(label: string) {
|
||||
switch (label) {
|
||||
case '1panel_original':
|
||||
return i18n.global.t('clean.panelOriginal');
|
||||
case 'upgrade':
|
||||
return i18n.global.t('clean.upgrade');
|
||||
case 'cache':
|
||||
return i18n.global.t('clean.cache');
|
||||
case 'snapshot':
|
||||
return i18n.global.t('clean.snapshot');
|
||||
case 'snapshot_tmp':
|
||||
return i18n.global.t('clean.snapshotTmp');
|
||||
case 'snapshot_local':
|
||||
return i18n.global.t('clean.snapshotLocal');
|
||||
case 'unused':
|
||||
return i18n.global.t('clean.unused');
|
||||
case 'old_original':
|
||||
return i18n.global.t('clean.oldOriginal');
|
||||
case 'old_apps_bak':
|
||||
return i18n.global.t('clean.oldAppsBak');
|
||||
case 'old_upgrade':
|
||||
return i18n.global.t('clean.oldUpgrade');
|
||||
case 'upload':
|
||||
return i18n.global.t('clean.upload');
|
||||
case 'download':
|
||||
return i18n.global.t('clean.download');
|
||||
case 'website':
|
||||
return i18n.global.t('clean.website');
|
||||
case 'app':
|
||||
return i18n.global.t('clean.app');
|
||||
case 'database':
|
||||
return i18n.global.t('clean.database');
|
||||
case 'directory':
|
||||
return i18n.global.t('clean.directory');
|
||||
case 'system_log':
|
||||
return i18n.global.t('clean.systemLog');
|
||||
case 'docker_log':
|
||||
return i18n.global.t('clean.dockerLog');
|
||||
case 'task_log':
|
||||
return i18n.global.t('clean.taskLog');
|
||||
case 'shell':
|
||||
return i18n.global.t('clean.shell');
|
||||
case 'containerShell':
|
||||
return i18n.global.t('clean.containerShell');
|
||||
case 'curl':
|
||||
return i18n.global.t('clean.curl');
|
||||
default:
|
||||
return label;
|
||||
}
|
||||
}
|
||||
|
||||
const handleClose = () => {
|
||||
emit('search');
|
||||
drawerVisible.value = false;
|
||||
};
|
||||
|
||||
defineExpose({
|
||||
acceptParams,
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.app-card {
|
||||
cursor: pointer;
|
||||
width: 100%;
|
||||
&:hover .app-icon {
|
||||
transform: scale(1.2);
|
||||
}
|
||||
.e-card {
|
||||
margin-top: 30px;
|
||||
cursor: pointer;
|
||||
border: var(--panel-border) !important;
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
border: 1px solid var(--el-color-primary) !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
.card_icon {
|
||||
font-size: 36px;
|
||||
float: right;
|
||||
margin-right: 15px;
|
||||
}
|
||||
.card_title {
|
||||
font-size: 18px;
|
||||
}
|
||||
.clean_title {
|
||||
font-size: 22px;
|
||||
}
|
||||
.large_button {
|
||||
float: right;
|
||||
margin-top: -40px;
|
||||
}
|
||||
</style>
|
@ -117,6 +117,15 @@
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('setting.diskClean')">
|
||||
<el-input disabled v-model="form.lastCleanTime">
|
||||
<template #append>
|
||||
<el-button v-show="!show" @click="onClean" icon="Setting">
|
||||
{{ $t('commons.button.set') }}
|
||||
</el-button>
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
@ -130,7 +139,8 @@
|
||||
<Timeout ref="timeoutRef" @search="search()" />
|
||||
<TimeZone ref="timezoneRef" @search="search()" />
|
||||
<Ntp ref="ntpRef" @search="search()" />
|
||||
<Netwrok ref="netwrokRef" @search="search()" />
|
||||
<Network ref="networkRef" @search="search()" />
|
||||
<Clean ref="cleanRef" @search="search()" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -148,7 +158,8 @@ import Timeout from '@/views/setting/panel/timeout/index.vue';
|
||||
import PanelName from '@/views/setting/panel/name/index.vue';
|
||||
import SystemIP from '@/views/setting/panel/systemip/index.vue';
|
||||
import TimeZone from '@/views/setting/panel/timezone/index.vue';
|
||||
import Netwrok from '@/views/setting/panel/default-network/index.vue';
|
||||
import Network from '@/views/setting/panel/default-network/index.vue';
|
||||
import Clean from '@/views/setting/panel/clean/index.vue';
|
||||
import Ntp from '@/views/setting/panel/ntp/index.vue';
|
||||
|
||||
const loading = ref(false);
|
||||
@ -172,6 +183,10 @@ const form = reactive({
|
||||
complexityVerification: '',
|
||||
defaultNetwork: '',
|
||||
defaultNetworkVal: '',
|
||||
|
||||
lastCleanTime: '',
|
||||
lastCleanSize: '',
|
||||
lastCleanData: '',
|
||||
});
|
||||
|
||||
const show = ref();
|
||||
@ -183,7 +198,8 @@ const systemIPRef = ref();
|
||||
const timeoutRef = ref();
|
||||
const ntpRef = ref();
|
||||
const timezoneRef = ref();
|
||||
const netwrokRef = ref();
|
||||
const networkRef = ref();
|
||||
const cleanRef = ref();
|
||||
const unset = ref(i18n.t('setting.unSetting'));
|
||||
|
||||
const search = async () => {
|
||||
@ -201,6 +217,10 @@ const search = async () => {
|
||||
form.complexityVerification = res.data.complexityVerification;
|
||||
form.defaultNetwork = res.data.defaultNetwork;
|
||||
form.defaultNetworkVal = res.data.defaultNetwork === 'all' ? i18n.t('commons.table.all') : res.data.defaultNetwork;
|
||||
|
||||
form.lastCleanTime = res.data.lastCleanTime;
|
||||
form.lastCleanSize = res.data.lastCleanSize;
|
||||
form.lastCleanData = res.data.lastCleanData;
|
||||
};
|
||||
|
||||
const onChangePassword = () => {
|
||||
@ -225,7 +245,14 @@ const onChangeNtp = () => {
|
||||
ntpRef.value.acceptParams({ localTime: form.localTime, ntpSite: form.ntpSite });
|
||||
};
|
||||
const onChangeNetwork = () => {
|
||||
netwrokRef.value.acceptParams({ defaultNetwork: form.defaultNetwork });
|
||||
networkRef.value.acceptParams({ defaultNetwork: form.defaultNetwork });
|
||||
};
|
||||
const onClean = () => {
|
||||
cleanRef.value.acceptParams({
|
||||
lastCleanTime: form.lastCleanTime,
|
||||
lastCleanSize: form.lastCleanSize,
|
||||
lastCleanData: form.lastCleanData,
|
||||
});
|
||||
};
|
||||
|
||||
const onSave = async (key: string, val: any) => {
|
||||
|
Loading…
x
Reference in New Issue
Block a user