feat: Cache cleanup supports cleaning up unassociated backups

This commit is contained in:
ssongliu 2025-12-25 11:58:36 +08:00
parent 41bae1e636
commit 0010855175
15 changed files with 746 additions and 497 deletions

View file

@ -37,6 +37,7 @@ type SyncTime struct {
type CleanData struct {
SystemClean []CleanTree `json:"systemClean"`
BackupClean []CleanTree `json:"backupClean"`
UploadClean []CleanTree `json:"uploadClean"`
DownloadClean []CleanTree `json:"downloadClean"`
SystemLogClean []CleanTree `json:"systemLogClean"`

View file

@ -11,36 +11,29 @@ import (
"strings"
"time"
"github.com/1Panel-dev/1Panel/agent/constant"
"github.com/1Panel-dev/1Panel/agent/i18n"
"github.com/1Panel-dev/1Panel/agent/utils/controller"
"github.com/1Panel-dev/1Panel/agent/utils/docker"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/build"
"github.com/docker/docker/api/types/filters"
"github.com/1Panel-dev/1Panel/agent/app/dto"
"github.com/1Panel-dev/1Panel/agent/app/model"
"github.com/1Panel-dev/1Panel/agent/app/repo"
"github.com/1Panel-dev/1Panel/agent/app/task"
"github.com/1Panel-dev/1Panel/agent/constant"
"github.com/1Panel-dev/1Panel/agent/global"
"github.com/1Panel-dev/1Panel/agent/i18n"
"github.com/1Panel-dev/1Panel/agent/utils/common"
"github.com/1Panel-dev/1Panel/agent/utils/controller"
"github.com/1Panel-dev/1Panel/agent/utils/docker"
fileUtils "github.com/1Panel-dev/1Panel/agent/utils/files"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/build"
"github.com/docker/docker/api/types/filters"
"github.com/google/uuid"
)
const (
upgradePath = "1panel/tmp/upgrade"
snapshotTmpPath = "1panel/tmp/system"
rollbackPath = "1panel/tmp"
cachePath = "1panel/cache"
oldOriginalPath = "original"
oldAppBackupPath = "1panel/resource/apps_bak"
oldDownloadPath = "1panel/tmp/download"
oldUpgradePath = "1panel/tmp"
tmpUploadPath = "1panel/tmp/upload"
uploadPath = "1panel/uploads"
downloadPath = "1panel/download"
rollbackPath = "1panel/tmp"
cachePath = "1panel/cache"
upgradePath = "1panel/tmp/upgrade"
uploadPath = "1panel/uploads"
downloadPath = "1panel/download"
)
func (u *DeviceService) Scan() dto.CleanData {
@ -61,55 +54,21 @@ func (u *DeviceService) Scan() dto.CleanData {
Type: "1panel_original",
Children: loadTreeWithDir(true, "1panel_original", originalPath, fileOp),
})
upgradePath := path.Join(global.Dir.BaseDir, upgradePath)
upgradeSize, _ := fileOp.GetDirSize(upgradePath)
upgradeTree := dto.CleanTree{
ID: uuid.NewString(),
Label: "upgrade",
Size: uint64(upgradeSize),
IsCheck: false,
IsRecommend: true,
Type: "upgrade",
Children: loadTreeWithDir(true, "upgrade", upgradePath, fileOp),
}
if len(upgradeTree.Children) != 0 {
sort.Slice(upgradeTree.Children, func(i, j int) bool {
return common.CompareVersion(upgradeTree.Children[i].Label, upgradeTree.Children[j].Label)
})
if global.IsMaster {
var copiesSetting model.Setting
_ = global.CoreDB.Where("key = ?", "UpgradeBackupCopies").First(&copiesSetting).Error
copies, _ := strconv.Atoi(copiesSetting.Value)
if copies == 0 || copies > len(upgradeTree.Children) {
copies = len(upgradeTree.Children)
}
for i := 0; i < copies; i++ {
upgradeTree.Children[i].IsCheck = false
upgradeTree.Children[i].IsRecommend = false
}
} else {
upgradeTree.Children[0].IsCheck = false
upgradeTree.Children[0].IsRecommend = false
}
}
treeData = append(treeData, upgradeTree)
tmpBackupTree := loadTmpBackupTree(fileOp)
tmpBackupSize := uint64(0)
for _, tmp := range tmpBackupTree {
tmpBackupSize += tmp.Size
}
treeData = append(treeData, loadUpgradeTree(fileOp))
treeData = append(treeData, loadAgentPackage(fileOp))
cachePath := path.Join(global.Dir.BaseDir, cachePath)
cacheSize, _ := fileOp.GetDirSize(cachePath)
treeData = append(treeData, dto.CleanTree{
ID: uuid.NewString(),
Label: "backup",
Size: tmpBackupSize,
IsCheck: tmpBackupSize > 0,
IsRecommend: true,
Type: "backup",
Children: tmpBackupTree,
Label: "cache",
Size: uint64(cacheSize),
IsCheck: false,
IsRecommend: false,
Type: "cache",
})
SystemClean.BackupClean = loadBackupTree(fileOp)
rollBackTree := loadRollBackTree(fileOp)
rollbackSize := uint64(0)
for _, rollback := range rollBackTree {
@ -124,17 +83,6 @@ func (u *DeviceService) Scan() dto.CleanData {
Type: "rollback",
Children: rollBackTree,
})
cachePath := path.Join(global.Dir.BaseDir, cachePath)
cacheSize, _ := fileOp.GetDirSize(cachePath)
treeData = append(treeData, dto.CleanTree{
ID: uuid.NewString(),
Label: "cache",
Size: uint64(cacheSize),
IsCheck: false,
IsRecommend: false,
Type: "cache",
})
SystemClean.SystemClean = treeData
uploadTreeData := loadUploadTree(fileOp)
@ -164,13 +112,13 @@ func (u *DeviceService) Clean(req []dto.Clean) {
case "upgrade":
dropFileOrDir(path.Join(global.Dir.BaseDir, upgradePath, item.Name))
case "backup":
dropFileOrDir(path.Join(global.Dir.LocalBackupDir, "tmp/app"))
dropFileOrDir(path.Join(global.Dir.LocalBackupDir, "tmp/database"))
dropFileOrDir(path.Join(global.Dir.LocalBackupDir, "tmp/website"))
dropFileOrDir(path.Join(global.Dir.LocalBackupDir, "tmp/directory"))
dropFileOrDir(path.Join(global.Dir.LocalBackupDir, "tmp/log"))
dropFileOrDir(path.Join(global.Dir.LocalBackupDir, "tmp/system"))
case "agent":
dropFileOrDir(path.Join(global.Dir.BaseDir, "1panel/agent/package", item.Name))
case "tmp_backup":
dropFileOrDir(path.Join(global.Dir.LocalBackupDir, "tmp"))
case "unknown_backup":
dropFileOrDir(item.Name)
case "rollback":
dropFileOrDir(path.Join(global.Dir.BaseDir, rollbackPath, "app"))
@ -189,19 +137,12 @@ func (u *DeviceService) Clean(req []dto.Clean) {
case "upload":
dropFileOrDir(path.Join(global.Dir.BaseDir, uploadPath, item.Name))
if len(item.Name) == 0 {
dropFileOrDir(path.Join(global.Dir.BaseDir, tmpUploadPath))
}
case "upload_tmp":
dropFileOrDir(path.Join(global.Dir.BaseDir, tmpUploadPath, item.Name))
case "upload_app":
dropFileOrDir(path.Join(global.Dir.BaseDir, uploadPath, "app", item.Name))
case "upload_database":
dropFileOrDir(path.Join(global.Dir.BaseDir, uploadPath, "database", item.Name))
case "upload_website":
dropFileOrDir(path.Join(global.Dir.BaseDir, uploadPath, "website", item.Name))
case "upload_directory":
dropFileOrDir(path.Join(global.Dir.BaseDir, uploadPath, "directory", item.Name))
case "download":
dropFileOrDir(path.Join(global.Dir.BaseDir, downloadPath, item.Name))
case "download_app":
@ -210,8 +151,6 @@ func (u *DeviceService) Clean(req []dto.Clean) {
dropFileOrDir(path.Join(global.Dir.BaseDir, downloadPath, "database", item.Name))
case "download_website":
dropFileOrDir(path.Join(global.Dir.BaseDir, downloadPath, "website", item.Name))
case "download_directory":
dropFileOrDir(path.Join(global.Dir.BaseDir, downloadPath, "directory", item.Name))
case "system_log":
if len(item.Name) == 0 {
@ -284,25 +223,20 @@ func doSystemClean(taskItem *task.Task) func(t *task.Task) error {
}
}
dropWithTask(path.Join(global.Dir.BaseDir, snapshotTmpPath), taskItem, &size, &fileCount)
dropWithTask(path.Join(global.Dir.LocalBackupDir, "tmp/system"), taskItem, &size, &fileCount)
dropWithTask(path.Join(global.Dir.BaseDir, rollbackPath, "app"), taskItem, &size, &fileCount)
dropWithTask(path.Join(global.Dir.BaseDir, rollbackPath, "website"), taskItem, &size, &fileCount)
dropWithTask(path.Join(global.Dir.BaseDir, rollbackPath, "database"), taskItem, &size, &fileCount)
dropWithTask(path.Join(global.Dir.BaseDir, oldOriginalPath), taskItem, &size, &fileCount)
dropWithTask(path.Join(global.Dir.BaseDir, oldAppBackupPath), taskItem, &size, &fileCount)
dropWithTask(path.Join(global.Dir.BaseDir, oldDownloadPath), taskItem, &size, &fileCount)
oldUpgradePath := path.Join(global.Dir.BaseDir, oldUpgradePath)
oldUpgradeFiles, _ := os.ReadDir(oldUpgradePath)
upgrades := path.Join(global.Dir.BaseDir, upgradePath)
oldUpgradeFiles, _ := os.ReadDir(upgrades)
if len(oldUpgradeFiles) != 0 {
for i := 0; i < len(oldUpgradeFiles); i++ {
dropWithTask(path.Join(oldUpgradePath, oldUpgradeFiles[i].Name()), taskItem, &size, &fileCount)
dropWithTask(path.Join(upgrades, oldUpgradeFiles[i].Name()), taskItem, &size, &fileCount)
}
}
dropWithTask(path.Join(global.Dir.BaseDir, tmpUploadPath), taskItem, &size, &fileCount)
dropWithExclude(path.Join(global.Dir.BaseDir, uploadPath), []string{"theme"}, taskItem, &size, &fileCount)
dropWithTask(path.Join(global.Dir.BaseDir, downloadPath), taskItem, &size, &fileCount)
@ -338,17 +272,312 @@ func doSystemClean(taskItem *task.Task) func(t *task.Task) error {
}
}
func loadTmpBackupTree(fileOp fileUtils.FileOp) []dto.CleanTree {
func loadUpgradeTree(fileOp fileUtils.FileOp) dto.CleanTree {
upgradePath := path.Join(global.Dir.BaseDir, upgradePath)
upgradeSize, _ := fileOp.GetDirSize(upgradePath)
upgradeTree := dto.CleanTree{
ID: uuid.NewString(),
Label: "upgrade",
Size: uint64(upgradeSize),
IsCheck: false,
IsRecommend: true,
Type: "upgrade",
Children: loadTreeWithDir(true, "upgrade", upgradePath, fileOp),
}
if len(upgradeTree.Children) != 0 {
sort.Slice(upgradeTree.Children, func(i, j int) bool {
return common.CompareVersion(upgradeTree.Children[i].Label, upgradeTree.Children[j].Label)
})
if global.IsMaster {
var copiesSetting model.Setting
_ = global.CoreDB.Where("key = ?", "UpgradeBackupCopies").First(&copiesSetting).Error
copies, _ := strconv.Atoi(copiesSetting.Value)
if copies == 0 || copies > len(upgradeTree.Children) {
copies = len(upgradeTree.Children)
}
for i := 0; i < copies; i++ {
upgradeTree.Children[i].IsCheck = false
upgradeTree.Children[i].IsRecommend = false
}
} else {
upgradeTree.Children[0].IsCheck = false
upgradeTree.Children[0].IsRecommend = false
}
}
return upgradeTree
}
func loadAgentPackage(fileOp fileUtils.FileOp) dto.CleanTree {
pathItem := path.Join(global.Dir.BaseDir, "1panel/agent/package")
itemTree := dto.CleanTree{
ID: uuid.NewString(),
Label: "agent_packages",
IsCheck: true,
IsRecommend: true,
Type: "agent",
}
files, _ := os.ReadDir(pathItem)
for _, file := range files {
if file.IsDir() {
itemSize, _ := fileOp.GetDirSize(path.Join(pathItem, file.Name()))
itemTree.Size += uint64(itemSize)
itemTree.Children = append(itemTree.Children, dto.CleanTree{
ID: uuid.NewString(),
Name: file.Name(),
Size: uint64(itemSize),
IsCheck: true,
IsRecommend: true,
Type: "agent",
})
} else {
if strings.HasPrefix(file.Name(), fmt.Sprintf("1panel-agent_%s_a", global.CONF.Base.Version)) {
continue
}
itemSize, _ := file.Info()
itemTree.Size += uint64(itemSize.Size())
itemTree.Children = append(itemTree.Children, dto.CleanTree{
ID: uuid.NewString(),
Label: file.Name(),
Size: uint64(itemSize.Size()),
IsCheck: true,
IsRecommend: true,
Type: "agent",
})
}
}
if itemTree.Size == 0 {
itemTree.IsCheck = false
}
return itemTree
}
func loadBackupTree(fileOp fileUtils.FileOp) []dto.CleanTree {
var treeData []dto.CleanTree
treeData = loadTreeWithCheck(treeData, path.Join(global.Dir.LocalBackupDir, "tmp/app"), "tmp_backup_app", fileOp)
treeData = loadTreeWithCheck(treeData, path.Join(global.Dir.LocalBackupDir, "tmp/website"), "tmp_backup_website", fileOp)
treeData = loadTreeWithCheck(treeData, path.Join(global.Dir.LocalBackupDir, "tmp/database"), "tmp_backup_database", fileOp)
treeData = loadTreeWithCheck(treeData, path.Join(global.Dir.LocalBackupDir, "tmp/system"), "tmp_backup_snapshot", fileOp)
treeData = loadTreeWithCheck(treeData, path.Join(global.Dir.LocalBackupDir, "tmp/directory"), "tmp_backup_directory", fileOp)
treeData = loadTreeWithCheck(treeData, path.Join(global.Dir.LocalBackupDir, "tmp/log"), "tmp_backup_log", fileOp)
tmpSize, _ := fileOp.GetDirSize(path.Join(global.Dir.LocalBackupDir, "tmp"))
treeData = append(treeData, dto.CleanTree{
ID: uuid.NewString(),
Label: "tmp_backup",
Size: uint64(tmpSize),
IsCheck: tmpSize != 0,
IsRecommend: true,
Type: "tmp_backup",
})
backupRecords, _ := backupRepo.ListRecord()
var recordMap = make(map[string][]string)
for _, record := range backupRecords {
if val, ok := recordMap[record.FileDir]; ok {
val = append(val, record.FileName)
recordMap[record.FileDir] = val
} else {
recordMap[record.FileDir] = []string{record.FileName}
}
}
treeData = append(treeData, loadUnknownApps(fileOp, recordMap))
treeData = append(treeData, loadUnknownDbs(fileOp, recordMap))
treeData = append(treeData, loadUnknownWebsites(fileOp, recordMap))
treeData = append(treeData, loadUnknownSnapshot(fileOp))
return treeData
}
func loadUnknownApps(fileOp fileUtils.FileOp, recordMap map[string][]string) dto.CleanTree {
apps, _ := appInstallRepo.ListBy(context.Background())
var excludePaths []string
for _, app := range apps {
itemName := fmt.Sprintf("app/%s/%s", app.App.Key, app.Name)
if val, ok := recordMap[itemName]; ok {
for _, item := range val {
excludePaths = append(excludePaths, path.Join(global.Dir.LocalBackupDir, itemName, item))
}
} else {
excludePaths = append(excludePaths, path.Join(global.Dir.LocalBackupDir, itemName))
}
}
treeData := dto.CleanTree{
ID: uuid.NewString(),
Label: "unknown_app",
IsCheck: false,
IsRecommend: false,
Type: "unknown_backup",
}
_ = loadFileOrDirWithExclude(fileOp, 0, path.Join(global.Dir.LocalBackupDir, "app"), &treeData, excludePaths)
loadBackupIsCheck(&treeData)
return treeData
}
func loadUnknownDbs(fileOp fileUtils.FileOp, recordMap map[string][]string) dto.CleanTree {
apps, _ := appInstallRepo.ListBy(context.Background())
var excludePaths []string
appMap := make(map[string]struct{})
for _, app := range apps {
appMap[fmt.Sprintf("database/%s/%s", app.App.Key, app.Name)] = struct{}{}
}
for key, val := range recordMap {
itemName := path.Dir(key)
if _, ok := appMap[itemName]; ok {
for _, item := range val {
excludePaths = append(excludePaths, path.Join(global.Dir.LocalBackupDir, key, item))
}
}
}
treeData := dto.CleanTree{
ID: uuid.NewString(),
Label: "unknown_database",
IsCheck: false,
IsRecommend: false,
Type: "unknown_backup",
}
_ = loadFileOrDirWithExclude(fileOp, 0, path.Join(global.Dir.LocalBackupDir, "database"), &treeData, excludePaths)
loadBackupIsCheck(&treeData)
return treeData
}
func loadUnknownWebsites(fileOp fileUtils.FileOp, recordMap map[string][]string) dto.CleanTree {
websites, _ := websiteRepo.List()
var excludePaths []string
for _, website := range websites {
itemName := fmt.Sprintf("website/%s", website.PrimaryDomain)
if val, ok := recordMap[itemName]; ok {
for _, item := range val {
excludePaths = append(excludePaths, path.Join(global.Dir.LocalBackupDir, itemName, item))
}
} else {
excludePaths = append(excludePaths, path.Join(global.Dir.LocalBackupDir, itemName))
}
}
treeData := dto.CleanTree{
ID: uuid.NewString(),
Label: "unknown_website",
IsCheck: false,
IsRecommend: false,
Type: "unknown_backup",
}
_ = loadFileOrDirWithExclude(fileOp, 0, path.Join(global.Dir.LocalBackupDir, "website"), &treeData, excludePaths)
loadBackupIsCheck(&treeData)
return treeData
}
func loadUnknownSnapshot(fileOp fileUtils.FileOp) dto.CleanTree {
snaps, _ := snapshotRepo.GetList()
var excludePaths []string
for _, item := range snaps {
excludePaths = append(excludePaths, path.Join(global.Dir.LocalBackupDir, "system_snapshot", item.Name+".tar.gz"))
}
treeData := dto.CleanTree{
ID: uuid.NewString(),
Label: "unknown_snapshot",
IsCheck: false,
IsRecommend: false,
Type: "unknown_backup",
}
dir := path.Join(global.Dir.LocalBackupDir, "system_snapshot")
entries, _ := os.ReadDir(dir)
for _, entry := range entries {
childPath := filepath.Join(dir, entry.Name())
if isExactPathMatch(childPath, excludePaths) {
continue
}
childNode := dto.CleanTree{
ID: uuid.NewString(),
Label: entry.Name(),
IsCheck: false,
IsRecommend: false,
Name: childPath,
Type: "unknown_backup",
}
if entry.IsDir() {
itemSize, _ := fileOp.GetDirSize(childPath)
childNode.Size = uint64(itemSize)
childNode.IsCheck = true
childNode.IsRecommend = true
treeData.Size += childNode.Size
} else {
info, _ := entry.Info()
childNode.Size = uint64(info.Size())
treeData.Size += childNode.Size
}
treeData.Children = append(treeData.Children, childNode)
}
return treeData
}
func loadFileOrDirWithExclude(fileOp fileUtils.FileOp, index uint, dir string, rootTree *dto.CleanTree, excludes []string) error {
index++
entries, err := os.ReadDir(dir)
if err != nil {
return err
}
for _, entry := range entries {
childPath := filepath.Join(dir, entry.Name())
if isExactPathMatch(childPath, excludes) {
continue
}
childNode := dto.CleanTree{
ID: uuid.NewString(),
Label: entry.Name(),
IsCheck: false,
IsRecommend: false,
Name: childPath,
Type: "unknown_backup",
}
if entry.IsDir() {
if index < 4 {
if err = loadFileOrDirWithExclude(fileOp, index, childPath, &childNode, excludes); err != nil {
return err
}
childNode.Size = 0
for _, child := range childNode.Children {
childNode.Size += child.Size
}
rootTree.Size += childNode.Size
} else {
itemSize, _ := fileOp.GetDirSize(childPath)
childNode.Size = uint64(itemSize)
rootTree.Size += childNode.Size
}
} else {
info, _ := entry.Info()
childNode.Size = uint64(info.Size())
rootTree.Size += childNode.Size
}
rootTree.Children = append(rootTree.Children, childNode)
}
return nil
}
func loadBackupIsCheck(treeData *dto.CleanTree) {
for i := 0; i < len(treeData.Children); i++ {
if len(treeData.Children[i].Children) == 0 {
treeData.Children[i].IsCheck = true
treeData.Children[i].IsRecommend = true
continue
}
for j := 0; j < len(treeData.Children[i].Children); j++ {
if len(treeData.Children[i].Children[j].Children) == 0 {
treeData.Children[i].Children[j].IsCheck = true
treeData.Children[i].Children[j].IsRecommend = true
continue
}
}
}
}
func isExactPathMatch(path string, excludePaths []string) bool {
cleanPath := filepath.Clean(path)
for _, excludePath := range excludePaths {
cleanExclude := filepath.Clean(excludePath)
if cleanPath == cleanExclude {
return true
}
}
return false
}
func loadRollBackTree(fileOp fileUtils.FileOp) []dto.CleanTree {
var treeData []dto.CleanTree
treeData = loadTreeWithCheck(treeData, path.Join(global.Dir.BaseDir, rollbackPath, "app"), "rollback_app", fileOp)
@ -360,7 +589,6 @@ func loadRollBackTree(fileOp fileUtils.FileOp) []dto.CleanTree {
func loadUploadTree(fileOp fileUtils.FileOp) []dto.CleanTree {
var treeData []dto.CleanTree
treeData = loadTreeWithCheck(treeData, path.Join(global.Dir.BaseDir, tmpUploadPath), "upload_tmp", fileOp)
treeData = loadTreeWithCheck(treeData, path.Join(global.Dir.BaseDir, uploadPath, "app"), "upload_app", fileOp)
treeData = loadTreeWithCheck(treeData, path.Join(global.Dir.BaseDir, uploadPath, "website"), "upload_website", fileOp)
treeData = loadTreeWithCheck(treeData, path.Join(global.Dir.BaseDir, uploadPath, "database"), "upload_database", fileOp)

View file

@ -41,6 +41,7 @@ func initGlobalData() {
if len(node.Version) != 0 {
_ = settingRepo.Update("SystemVersion", node.Version)
}
global.CONF.Base.Version = node.Version
global.CONF.Base.EncryptKey, _ = settingRepo.GetValueByKey("EncryptKey")
}

View file

@ -36,6 +36,7 @@ export namespace Toolbox {
export interface CleanData {
systemClean: Array<CleanTree>;
backupClean: Array<CleanTree>;
uploadClean: Array<CleanTree>;
downloadClean: Array<CleanTree>;
systemLogClean: Array<CleanTree>;

View file

@ -2196,17 +2196,25 @@ const message = {
selectScan: 'Total selected junk files: ',
system: 'System Junk Files',
systemHelper:
'Temporary files generated during snapshots, upgrades, and obsolete file contents during version iterations',
panelOriginal: 'System snapshot recovery backup files',
backup: 'Temporary backup directory',
systemHelper: 'Temporary files generated during snapshot, upgrade, and other processes',
panelOriginal: 'Backup files before system snapshot restore',
upgrade: 'System upgrade backup files',
agentPackages: 'Historical version child node upgrade/installation packages',
upgradeHelper: '(Recommend keeping the latest upgrade backup for system rollback)',
cache: 'System cache files',
cacheHelper: '(Proceed with caution, cleaning requires a service restart)',
snapshot: 'System snapshot temporary files',
rollback: 'Backup files before recover',
backup: 'System Backup',
backupHelper: 'Backup files not associated with local backup accounts',
unknownBackup: 'System Backup',
tmpBackup: 'Temporary Backup',
unknownApp: 'Unassociated App Backup',
unknownDatabase: 'Unassociated Database Backup',
unknownWebsite: 'Unassociated Website Backup',
unknownSnapshot: 'Unassociated Snapshot Backup',
upload: 'Temporary Upload Files',
uploadHelper: 'Temporary files uploaded from the system backup list',
download: 'Temporary Download Files',
@ -2214,15 +2222,15 @@ const message = {
directory: 'Directory',
systemLog: 'System Log Files',
systemLogHelper:
'System log information, container build or image pull log information, and log files generated in scheduled tasks',
systemLogHelper: 'System log and task log files',
dockerLog: 'Container operation log files',
taskLog: 'Scheduled task execution log files',
shell: 'Shell script scheduled tasks',
containerShell: 'Container internal Shell script scheduled tasks',
containerShell: 'Shell script scheduled tasks executed inside containers',
curl: 'CURL scheduled tasks',
containerTrash: 'Container Trash',
docker: 'Container garbage',
dockerHelper: 'Files such as containers, images, volumes, build cache, etc.',
volumes: 'Volumes',
buildCache: 'Container Build Cache',
},

View file

@ -2209,28 +2209,40 @@ const message = {
totalScan: 'Total a limpiar: ',
selectScan: 'Total seleccionado: ',
system: 'Archivos basura del sistema',
systemHelper: 'Archivos temporales de instantáneas, actualizaciones, archivos obsoletos, etc.',
panelOriginal: 'Archivos de recuperación de instantáneas',
backup: 'Temporary backup directory',
upgrade: 'Archivos de actualización',
systemHelper: 'Archivos temporales generados durante instantáneas, actualizaciones y otros procesos',
panelOriginal: 'Archivos de copia de seguridad antes de restaurar instantánea del sistema',
upgrade: 'Archivos de copia de seguridad de actualización del sistema',
agentPackages: 'Paquetes de actualización/instalación de nodos secundarios de versiones históricas',
upgradeHelper: '(Mantenga el último respaldo para restaurar el sistema)',
cache: 'Archivos de caché',
cacheHelper: '(Precaución, limpiar requiere reiniciar servicios)',
snapshot: 'Archivos temporales de instantáneas',
rollback: 'Archivos de respaldo antes de recuperación',
backup: 'Copia de Seguridad del Sistema',
backupHelper: 'Archivos de copia de seguridad no asociados con cuentas de copia de seguridad locales',
unknownBackup: 'Copia de Seguridad del Sistema',
tmpBackup: 'Copia de Seguridad Temporal',
unknownApp: 'Copia de Seguridad de Aplicación no Asociada',
unknownDatabase: 'Copia de Seguridad de Base de Datos no Asociada',
unknownWebsite: 'Copia de Seguridad de Sitio Web no Asociada',
unknownSnapshot: 'Copia de Seguridad de Instantánea no Asociada',
upload: 'Archivos temporales de carga',
uploadHelper: 'Archivos temporales subidos en la lista de respaldos',
download: 'Archivos temporales de descarga',
downloadHelper: 'Archivos temporales descargados desde respaldos externos',
directory: 'Directorio',
systemLog: 'Archivos de log del sistema',
systemLogHelper: 'Logs del sistema, construcción de contenedores, pulls, tareas programadas',
dockerLog: 'Logs de operaciones de contenedores',
taskLog: 'Logs de tareas programadas',
shell: 'Tareas programadas de shell',
containerShell: 'Tareas de shell dentro de contenedor',
curl: 'Tareas programadas CURL',
containerTrash: 'Papelera de contenedores',
systemLogHelper: 'Archivos de registro del sistema y de tareas',
dockerLog: 'Archivos de registro de operaciones de contenedores',
taskLog: 'Archivos de registro de ejecución de tareas programadas',
shell: 'Tareas programadas de script de shell',
containerShell: 'Tareas programadas de script de shell ejecutadas dentro de contenedores',
curl: 'Tareas programadas de CURL',
docker: 'Basura de contenedores',
dockerHelper: 'Archivos como contenedores, imágenes, volúmenes, caché de construcción, etc.',
volumes: 'Volúmenes',
buildCache: 'Caché de build de contenedores',
},

View file

@ -2117,16 +2117,24 @@ const message = {
selectScan: '選択したジャンクファイルの合計:',
system: 'システムジャンクファイル',
systemHelper:
'スナップショット中に生成された一時ファイルアップグレードおよびバージョンの反復中にファイルのコンテンツが廃止されました',
panelOriginal: 'システムスナップショットリカバリバックアップファイル',
backup: '一時バックアップディレクトリ',
upgrade: 'システムアップグレードバックアップファイル',
systemHelper: 'スナップショットアップグレードなどのプロセスで生成された一時ファイル',
panelOriginal: 'システムスナップショット復元前のバックアップファイル',
upgrade: 'システムアップグレードのバックアップファイル',
agentPackages: '履歴バージョンの子ノードアップグレード/インストールパッケージ',
upgradeHelper: 'システムロールバックのために最新のアップグレードバックアップを保持することをお勧めします',
cache: 'システムキャッシュファイル',
cacheHelper: '注意を払って進むにはクリーニングにはサービスの再起動が必要です',
rollback: '回復する前にファイルをバックアップします',
backup: 'システムバックアップ',
backupHelper: 'ローカルバックアップアカウントに関連付けられていないバックアップファイル',
unknownBackup: 'システムバックアップ',
tmpBackup: '一時バックアップ',
unknownApp: '関連付けられていないアプリバックアップ',
unknownDatabase: '関連付けられていないデータベースバックアップ',
unknownWebsite: '関連付けられていないWebサイトバックアップ',
unknownSnapshot: '関連付けられていないスナップショットバックアップ',
upload: '一時的なアップロードファイル',
uploadHelper: 'システムバックアップリストからアップロードされた一時ファイル',
download: '一時的なダウンロードファイル',
@ -2134,13 +2142,15 @@ const message = {
directory: 'ディレクトリ',
systemLog: 'システムログファイル',
systemLogHelper:
'システムログ情報コンテナビルドまたは画像プルログ情報およびスケジュールされたタスクで生成されたログファイル',
systemLogHelper: 'システムログタスクログファイル',
dockerLog: 'コンテナ操作ログファイル',
taskLog: 'スケジュールされたタスク実行ログファイル',
containerShell: 'コンテナ内部シェルスクリプトスケジュールされたタスク',
taskLog: 'スケジュールタスク実行ログファイル',
shell: 'シェルスクリプトスケジュールタスク',
containerShell: 'コンテナ内で実行するシェルスクリプトスケジュールタスク',
curl: 'CURLスケジュールタスク',
containerTrash: 'コンテナのゴミ',
docker: 'コンテナゴミ',
dockerHelper: 'コンテナイメージボリュームビルドキャッシュなどのファイル',
volumes: 'ボリューム',
buildCache: 'コンテナビルドキャッシュ',
},

View file

@ -2081,15 +2081,24 @@ const message = {
selectScan: '선택된 불필요 파일 총합: ',
system: '시스템 불필요 파일',
systemHelper: '스냅샷, 업그레이드 중에 생성된 임시 파일과 버전 업데이트 중에 불필요해진 파일 내용',
panelOriginal: '시스템 스냅샷 복구 백업 파일',
backup: '임시 백업 디렉터리',
systemHelper: '스냅샷, 업그레이드 기타 프로세스 중에 생성된 임시 파일',
panelOriginal: '시스템 스냅샷 복원 백업 파일',
upgrade: '시스템 업그레이드 백업 파일',
agentPackages: '이전 버전 자식 노드 업그레이드/설치 패키지',
upgradeHelper: '(시스템 롤백을 위해 최신 업그레이드 백업을 유지하는 것이 좋습니다)',
cache: '시스템 캐시 파일',
cacheHelper: '(주의하여 진행, 정리 서비스 재시작 필요)',
rollback: '복구 백업 파일',
backup: '시스템 백업',
backupHelper: '로컬 백업 계정에 연결되지 않은 백업 파일',
unknownBackup: '시스템 백업',
tmpBackup: '임시 백업',
unknownApp: '연결되지 않은 백업',
unknownDatabase: '연결되지 않은 데이터베이스 백업',
unknownWebsite: '연결되지 않은 웹사이트 백업',
unknownSnapshot: '연결되지 않은 스냅샷 백업',
upload: '임시 업로드 파일',
uploadHelper: '시스템 백업 리스트에서 업로드된 임시 파일',
download: '임시 다운로드 파일',
@ -2097,12 +2106,15 @@ const message = {
directory: '디렉터리',
systemLog: '시스템 로그 파일',
systemLogHelper: '시스템 로그 정보, 컨테이너 빌드 또는 이미지 로그 정보, 예약된 작업에서 생성된 로그 파일',
dockerLog: '컨테이너 운영 로그 파일',
taskLog: '예약된 작업 실행 로그 파일',
containerShell: '컨테이너 스크립트 예약 작업',
systemLogHelper: '시스템 로그, 작업 로그 파일',
dockerLog: '컨테이너 작업 로그 파일',
taskLog: '예약 작업 실행 로그 파일',
shell: ' 스크립트 예약 작업',
containerShell: '컨테이너 내에서 실행하는 스크립트 예약 작업',
curl: 'CURL 예약 작업',
containerTrash: '컨테이너 휴지통',
docker: '컨테이너 쓰레기',
dockerHelper: '컨테이너, 이미지, 볼륨, 빌드 캐시 등의 파일',
volumes: '볼륨',
buildCache: '컨테이너 빌드 캐시',
},

View file

@ -2176,16 +2176,24 @@ const message = {
selectScan: 'Jumlah fail sampah yang dipilih: ',
system: 'Fail Sampah Sistem',
systemHelper:
'Fail sementara yang dihasilkan semasa snapshot, peningkatan, dan kandungan fail usang semasa iterasi versi',
panelOriginal: 'Fail sandaran pemulihan snapshot sistem',
backup: 'Direktori sandaran sementara',
upgrade: 'Fail sandaran peningkatan sistem',
systemHelper: 'Fail sementara dijana semasa snapshot, naik taraf, dan proses lain',
panelOriginal: 'Fail sandaran sebelum pemulihan snapshot sistem',
upgrade: 'Fail sandaran naik taraf sistem',
agentPackages: 'Pakej naik taraf/pemasangan nod anak versi sejarah',
upgradeHelper: '(Disarankan untuk mengekalkan sandaran peningkatan terbaru untuk pemulihan sistem)',
cache: 'Fail cache sistem',
cacheHelper: '(Berhati-hati, pembersihan memerlukan permulaan semula perkhidmatan)',
rollback: 'Fail sandaran sebelum pemulihan',
backup: 'Sandaran Sistem',
backupHelper: 'Fail sandaran tidak dikaitkan dengan akaun sandaran tempatan',
unknownBackup: 'Sandaran Sistem',
tmpBackup: 'Sandaran Sementara',
unknownApp: 'Sandaran Apl Tidak Dikaitkan',
unknownDatabase: 'Sandaran Pangkalan Data Tidak Dikaitkan',
unknownWebsite: 'Sandaran Laman Web Tidak Dikaitkan',
unknownSnapshot: 'Sandaran Snapshot Tidak Dikaitkan',
upload: 'Fail Muat Naik Sementara',
uploadHelper: 'Fail sementara dimuat naik dari senarai sandaran sistem',
download: 'Fail Muat Turun Sementara',
@ -2193,13 +2201,15 @@ const message = {
directory: 'Direktori',
systemLog: 'Fail Log Sistem',
systemLogHelper:
'Maklumat log sistem, maklumat log pembinaan kontena atau muat turun imej, dan fail log yang dihasilkan dalam tugas berjadual',
dockerLog: 'Fail log operasi kontena',
systemLogHelper: 'Fail log sistem dan log tugas',
dockerLog: 'Fail log operasi bekas',
taskLog: 'Fail log pelaksanaan tugas berjadual',
containerShell: 'Tugas berjadual skrip Shell dalam kontena',
shell: 'Tugas berjadual skrip Shell',
containerShell: 'Tugas berjadual skrip Shell dilaksanakan di dalam bekas',
curl: 'Tugas berjadual CURL',
containerTrash: 'Tong Sampah Kontena',
docker: 'Sampah bekas',
dockerHelper: 'Fail seperti bekas, imej, isipadu, cache binaan, dsb.',
volumes: 'Isipadu',
buildCache: 'Cache Pembinaan Kontena',
},

View file

@ -2170,16 +2170,24 @@ const message = {
selectScan: 'Total de arquivos inúteis selecionados: ',
system: 'Arquivos inúteis do sistema',
systemHelper:
'Arquivos temporários gerados durante snapshots, atualizações e conteúdos obsoletos durante iterações de versão',
panelOriginal: 'Arquivos de backup de recuperação de snapshot do sistema',
backup: 'Diretório de backup temporário',
upgrade: 'Arquivos de backup de atualização do sistema',
systemHelper: 'Arquivos temporários gerados durante processos como snapshots e atualizações.',
panelOriginal: 'Arquivos de backup antes da restauração do snapshot do sistema.',
upgrade: 'Arquivos de backup de atualização do sistema.',
agentPackages: 'Pacotes de atualização/instalação de nós filhos de versões históricas.',
upgradeHelper: '(Recomenda-se manter o backup de atualização mais recente para rollback do sistema)',
cache: 'Arquivos de cache do sistema',
cacheHelper: '(Prossiga com cautela, a limpeza exige reinício do serviço)',
rollback: 'Arquivos de backup antes da recuperação',
backup: 'Backup do Sistema',
backupHelper: 'Arquivos de backup não associados a contas de backup locais',
unknownBackup: 'Backup do Sistema',
tmpBackup: 'Backup Temporário',
unknownApp: 'Backup de Aplicativo não Associado',
unknownDatabase: 'Backup de Banco de Dados não Associado',
unknownWebsite: 'Backup de Site não Associado',
unknownSnapshot: 'Backup de Instantâneo não Associado',
upload: 'Arquivos temporários de upload',
uploadHelper: 'Arquivos temporários enviados da lista de backup do sistema',
download: 'Arquivos temporários de download',
@ -2187,13 +2195,15 @@ const message = {
directory: 'Diretório',
systemLog: 'Arquivos de log do sistema',
systemLogHelper:
'Informações de log do sistema, logs de construção de container ou pull de imagem, e logs gerados em tarefas agendadas',
dockerLog: 'Arquivos de log de operação de container',
systemLogHelper: 'Arquivos de log do sistema e de tarefas',
dockerLog: 'Arquivos de log de operação de contêineres',
taskLog: 'Arquivos de log de execução de tarefas agendadas',
containerShell: 'Tarefas agendadas de script Shell interno do container',
shell: 'Tarefas agendadas de script de shell',
containerShell: 'Tarefas agendadas de script de shell executadas dentro de contêineres',
curl: 'Tarefas agendadas de CURL',
containerTrash: 'Lixeira do container',
docker: 'Lixo de contêineres',
dockerHelper: 'Arquivos como contêineres, imagens, volumes, cache de compilação, etc.',
volumes: 'Volumes',
buildCache: 'Cache de construção do container',
},

View file

@ -2165,16 +2165,24 @@ const message = {
selectScan: 'Всего выбранных мусорных файлов: ',
system: 'Системные мусорные файлы',
systemHelper:
'Временные файлы, созданные во время снапшотов, обновлений, и устаревшее содержимое файлов при итерациях версий',
panelOriginal: 'Файлы резервных копий восстановления системных снапшотов',
backup: 'Временный резервный каталог',
upgrade: 'Файлы резервных копий системных обновлений',
systemHelper: 'Временные файлы, созданные во время снимков, обновлений и других процессов',
panelOriginal: 'Файлы резервных копий перед восстановлением снимка системы',
upgrade: 'Файлы резервных копий обновления системы',
agentPackages: 'Пакеты обновления/установки дочерних узлов исторических версий',
upgradeHelper: '(Рекомендуется сохранять последнюю резервную копию обновления для отката системы)',
cache: 'Системные файлы кэша',
cacheHelper: '(Действуйте с осторожностью, очистка требует перезапуска службы)',
rollback: 'Файлы резервных копий перед восстановлением',
backup: 'Резервная Копия Системы',
backupHelper: 'Файлы резервных копий, не связанные с локальными учетными записями резервного копирования',
unknownBackup: 'Резервная Копия Системы',
tmpBackup: 'Временная Резервная Копия',
unknownApp: 'Несвязанная Резервная Копия Приложения',
unknownDatabase: 'Несвязанная Резервная Копия Базы Данных',
unknownWebsite: 'Несвязанная Резервная Копия Веб-сайта',
unknownSnapshot: 'Несвязанная Резервная Копия Снимка',
upload: 'Временные файлы загрузки',
uploadHelper: 'Временные файлы, загруженные из списка системных резервных копий',
download: 'Временные файлы скачивания',
@ -2182,13 +2190,15 @@ const message = {
directory: 'Директория',
systemLog: 'Системные файлы логов',
systemLogHelper:
'Системная информация логов, логи сборки контейнеров или загрузки образов, и файлы логов, созданные в запланированных задачах',
dockerLog: 'Файлы логов операций с контейнерами',
taskLog: 'Файлы логов выполнения запланированных задач',
containerShell: 'Запланированные задачи Shell-скриптов внутри контейнера',
systemLogHelper: 'Файлы системных журналов и журналов задач',
dockerLog: 'Файлы журналов операций с контейнерами',
taskLog: 'Файлы журналов выполнения запланированных задач',
shell: 'Запланированные задачи скриптов оболочки',
containerShell: 'Запланированные задачи скриптов оболочки, выполняемые внутри контейнеров',
curl: 'Запланированные задачи CURL',
containerTrash: 'Корзина контейнеров',
docker: 'Мусор контейнеров',
dockerHelper: 'Файлы, такие как контейнеры, образы, тома, кэш сборки и т.д.',
volumes: 'Тома',
buildCache: 'Кэш сборки контейнеров',
},

View file

@ -2221,17 +2221,25 @@ const message = {
selectScan: 'Seçilen toplam gereksiz dosya: ',
system: 'Sistem Gereksiz Dosyaları',
systemHelper:
'Anlık görüntüler, yükseltmeler ve sürüm iterasyonları sırasında eski dosya içerikleri sırasında üretilen geçici dosyalar',
panelOriginal: 'Sistem anlık görüntü kurtarma yedek dosyaları',
backup: 'Geçici yedekleme dizini',
upgrade: 'Sistem yükseltme yedek dosyaları',
systemHelper: 'Anlık görüntü, yükseltme ve diğer işlemler sırasında oluşturulan geçici dosyalar',
panelOriginal: 'Sistem anlık görüntüsü geri yükleme öncesi yedekleme dosyaları',
upgrade: 'Sistem yükseltme yedekleme dosyaları',
agentPackages: 'Geçmiş sürüm alt düğüm yükseltme/kurulum paketleri',
upgradeHelper: '(Sistem geri alımı için en son yükseltme yedeğini tutmanız önerilir)',
cache: 'Sistem önbellek dosyaları',
cacheHelper: '(Dikkatli ilerleyin, temizleme servis yeniden başlatılmasını gerektirir)',
snapshot: 'Sistem anlık görüntü geçici dosyaları',
rollback: 'Kurtarma öncesi yedek dosyaları',
backup: 'Sistem Yedekleme',
backupHelper: 'Yerel yedekleme hesaplarıyla ilişkili olmayan yedekleme dosyaları',
unknownBackup: 'Sistem Yedekleme',
tmpBackup: 'Geçici Yedekleme',
unknownApp: 'İlişkili Olmayan Uygulama Yedeklemesi',
unknownDatabase: 'İlişkili Olmayan Veritabanı Yedeklemesi',
unknownWebsite: 'İlişkili Olmayan Web Sitesi Yedeklemesi',
unknownSnapshot: 'İlişkili Olmayan Anlık Görüntü Yedeklemesi',
upload: 'Geçici Yükleme Dosyaları',
uploadHelper: 'Sistem yedek listesinden yüklenen geçici dosyalar',
download: 'Geçici İndirme Dosyaları',
@ -2239,15 +2247,15 @@ const message = {
directory: 'Dizin',
systemLog: 'Sistem Günlük Dosyaları',
systemLogHelper:
'Sistem günlük bilgileri, konteyner oluşturma veya görüntü çekme günlük bilgileri ve zamanlanmış görevlerde üretilen günlük dosyaları',
dockerLog: 'Konteyner işlem günlük dosyaları',
taskLog: 'Zamanlanmış görev yürütme günlük dosyaları',
shell: 'Shell betik zamanlanmış görevler',
containerShell: 'Konteyner içi Shell betik zamanlanmış görevler',
systemLogHelper: 'Sistem günlüğü ve görev günlüğü dosyaları',
dockerLog: 'Konteyner işlem günlüğü dosyaları',
taskLog: 'Zamanlanmış görev yürütme günlüğü dosyaları',
shell: 'Shell script zamanlanmış görevler',
containerShell: 'Konteynerler içinde yürütülen shell script zamanlanmış görevler',
curl: 'CURL zamanlanmış görevler',
containerTrash: 'Konteyner Çöpü',
docker: 'Konteyner çöpü',
dockerHelper: 'Konteynerler, görüntüler, hacimler, derleme önbelleği vb. dosyalar',
volumes: 'Birimler',
buildCache: 'Konteyner Oluşturma Önbelleği',
},

View file

@ -2045,16 +2045,25 @@ const message = {
selectScan: '已選中垃圾文件共計 ',
system: '系統垃圾',
systemHelper: '快照升級等過程中產生的暫存檔以及版本疊代過程中廢棄的文件內容',
panelOriginal: '系統快照復原前備份文件',
backup: '臨時備份目錄',
upgrade: '系統升級備份文',
systemHelper: '快照升級等過程中產生的臨時檔案',
panelOriginal: '系統快照恢復前備份檔案',
upgrade: '系統升級備份檔案',
agentPackages: '歷史版本子節點升級/安裝套',
upgradeHelper: '( 建議保留最新的升級備份用於系統回滾 )',
cache: '系統快取文件',
cacheHelper: '( 謹慎操作清理需要重啟服務 )',
snapshot: '系統快照暫存檔',
rollback: '復原前備份目錄',
backup: '系統備份',
backupHelper: '本地備份帳號中未關聯的備份檔案',
unknownBackup: '系統備份',
tmpBackup: '臨時備份',
unknownApp: '未關聯應用備份',
unknownDatabase: '未關聯資料庫備份',
unknownWebsite: '未關聯網站備份',
unknownSnapshot: '未關聯快照備份',
upload: '臨時上傳文件',
uploadHelper: '系統上傳備份列表中上傳的暫存檔',
download: '臨時下載文件',
@ -2062,14 +2071,15 @@ const message = {
directory: '資料夾',
systemLog: '系統日誌檔案',
systemLogHelper: '系統日誌資訊容器構建或鏡像拉取等日誌資訊以及計劃任務中產生的日誌檔案',
systemLogHelper: '系統日誌任務日誌檔案',
dockerLog: '容器操作日誌檔案',
taskLog: '計劃任務執行日誌檔案',
shell: 'Shell 腳本計劃任務',
containerShell: '容器內執行 Shell 腳本計劃任務',
curl: 'CURL 計劃任務',
containerTrash: '容器垃圾',
docker: '容器垃圾',
dockerHelper: '容器映像儲存卷建置快取等檔案',
volumes: '磁碟區',
buildCache: '容器建置快取',
},

View file

@ -2042,16 +2042,25 @@ const message = {
selectScan: '已选中垃圾文件共计 ',
system: '系统垃圾',
systemHelper: '快照升级等过程中产生的临时文件以及版本迭代过程中废弃的文件内容',
systemHelper: '快照升级等过程中产生的临时文件',
panelOriginal: '系统快照恢复前备份文件',
backup: '临时备份目录',
upgrade: '系统升级备份文件',
agentPackages: '历史版本子节点升级 / 安装包',
upgradeHelper: '( 建议保留最新的升级备份用于系统回滚 )',
cache: '系统缓存文件',
cacheHelper: '( 谨慎操作清理需要重启服务 )',
snapshot: '系统快照临时文件',
rollback: '恢复前备份目录',
backup: '系统备份',
backupHelper: '本地备份账号中未关联的备份文件',
unknownBackup: '系统备份',
tmpBackup: '临时备份',
unknownApp: '未关联应用备份',
unknownDatabase: '未关联数据库备份',
unknownWebsite: '未关联网站备份',
unknownSnapshot: '未关联快照备份',
upload: '临时上传文件',
uploadHelper: '系统上传备份列表中上传的临时文件',
download: '临时下载文件',
@ -2059,14 +2068,15 @@ const message = {
directory: '文件夹',
systemLog: '系统日志文件',
systemLogHelper: '系统日志信息容器构建或镜像拉取等日志信息以及计划任务中产生的日志文件',
systemLogHelper: '系统日志任务日志文件',
dockerLog: '容器操作日志文件',
taskLog: '计划任务执行日志文件',
shell: 'Shell 脚本计划任务',
containerShell: '容器内执行 Shell 脚本计划任务',
curl: 'CURL 计划任务',
containerTrash: '容器垃圾',
docker: '容器垃圾',
dockerHelper: '容器镜像存储卷构建缓存等文件',
volumes: '存储卷',
buildCache: '构建缓存',
},

View file

@ -7,153 +7,90 @@
</el-button>
</template>
<template #main>
<el-row class="mt-5 mb-5">
<el-col :xs="22" :sm="20" :md="20" :lg="10" :xl="10" :offset="1">
<div v-if="scanStatus !== 'scanned'">
<div v-if="scanStatus === 'beforeScan'">
<div v-if="form.lastCleanTime">
<el-text class="clean_title">
{{ $t('clean.lastCleanTime', [form.lastCleanTime || '-']) }}
</el-text>
<div class="mt-4">
<el-text>
{{
$t('clean.lastCleanHelper', [
form.lastCleanData || '-',
form.lastCleanSize ? computeSize(Number(form.lastCleanSize)) : '-',
])
}}
</el-text>
</div>
</div>
<div v-else>
<el-text class="clean_title">
<el-icon>
<MagicStick />
</el-icon>
{{ $t('clean.scanHelper') }}
</el-text>
</div>
<div class="app-card">
<el-card class="e-card">
<el-row>
<el-col :span="4">
<el-button icon="Setting" link class="card_icon" />
</el-col>
<el-col :span="20">
<div>
<el-text class="mx-1 card_title" type="primary">
{{ $t('clean.system') }}
</el-text>
</div>
<span class="input-help">{{ $t('clean.systemHelper') }}</span>
</el-col>
</el-row>
</el-card>
<el-card class="e-card">
<el-row>
<el-col :span="4">
<svg-icon iconName="p-docker1" class="svg-icon"></svg-icon>
<el-button link class="card_icon" />
</el-col>
<el-col :span="20">
<div>
<el-text class="mx-1 card_title" type="primary">
{{ $t('clean.containerTrash') }}
</el-text>
</div>
<span class="input-help">
{{ $t('container.cleanDockerDiskZone') }}
</span>
</el-col>
</el-row>
</el-card>
<el-card class="e-card">
<el-row>
<el-col :span="4">
<el-button icon="Upload" link class="card_icon" />
</el-col>
<el-col :span="20">
<div>
<el-text class="mx-1 card_title" type="primary">
{{ $t('clean.upload') }}
</el-text>
</div>
<span class="input-help">{{ $t('clean.uploadHelper') }}</span>
</el-col>
</el-row>
</el-card>
<el-card class="e-card">
<el-row>
<el-col :span="4">
<el-button icon="Download" link class="card_icon" />
</el-col>
<el-col :span="20">
<div>
<el-text class="mx-1 card_title" type="primary">
{{ $t('clean.download') }}
</el-text>
</div>
<span class="input-help">{{ $t('clean.downloadHelper') }}</span>
</el-col>
</el-row>
</el-card>
<el-card class="e-card">
<el-row>
<el-col :span="4">
<el-button icon="Document" link class="card_icon" />
</el-col>
<el-col :span="20">
<div>
<el-text class="mx-1 card_title" type="primary">
{{ $t('clean.systemLog') }}
</el-text>
</div>
<span class="input-help">
{{ $t('clean.systemLogHelper') }}
</span>
</el-col>
</el-row>
</el-card>
</div>
</div>
<div v-if="scanStatus === 'afterScan'">
<el-text class="clean_title">{{ $t('clean.cleanSuccessful') }}</el-text>
<div class="mt-4">
<el-text>
{{
$t('clean.currentCleanHelper', [
form.lastCleanData,
computeSize(Number(form.lastCleanSize)),
])
}}
</el-text>
</div>
</div>
<div v-if="scanStatus === 'beforeScan'" class="ml-5">
<div v-if="form.lastCleanTime">
<el-text class="clean_title">
{{ $t('clean.lastCleanTime', [form.lastCleanTime || '-']) }}
</el-text>
<div class="mt-4">
<el-text>
{{
$t('clean.lastCleanHelper', [
form.lastCleanData || '-',
form.lastCleanSize ? computeSize(Number(form.lastCleanSize)) : '-',
])
}}
</el-text>
</div>
<div v-if="scanStatus === 'scanned'">
<div class="flex flex-row justify-between items-center gap-2">
<div>
<el-text class="clean_title">
{{ $t('clean.totalScan') }} {{ computeSize(totalSize) }}
</el-text>
<div class="mt-4">
<el-text type="info">
{{ $t('clean.selectScan') }} {{ computeSize(selectSize) }}
</el-text>
</div>
</div>
<div class="large_button">
<el-button
type="primary"
size="large"
:disabled="selectSize <= 0"
@click="onSubmitClean"
>
{{ $t('clean.clean') }}
</el-button>
</div>
</div>
</div>
<div v-else>
<el-text class="clean_title">
<el-icon>
<MagicStick />
</el-icon>
{{ $t('clean.scanHelper') }}
</el-text>
</div>
<el-row type="flex" justify="center" :gutter="20" class="mb-10">
<el-col :xs="24" :sm="24" :md="24" :lg="12" :xl="12" v-for="item in cleanTag" :key="item.title">
<el-card class="clean-card">
<el-row>
<el-col :span="4">
<el-button
v-if="item.icon.indexOf('p-') === -1"
:icon="item.icon"
link
class="card_icon"
/>
<template v-else>
<el-button link class="svg-icon">
<svg-icon :iconName="item.icon"></svg-icon>
</el-button>
</template>
</el-col>
<el-col :span="20">
<div>
<el-text class="mx-1 card_title" type="primary">
{{ $t(item.title) }}
</el-text>
</div>
<span class="input-help">{{ $t(item.description) }}</span>
</el-col>
</el-row>
</el-card>
</el-col>
</el-row>
</div>
<div v-if="scanStatus === 'afterScan'" class="ml-5">
<el-text class="clean_title">{{ $t('clean.cleanSuccessful') }}</el-text>
<div class="mt-4">
<el-text>
{{
$t('clean.currentCleanHelper', [
form.lastCleanData,
computeSize(Number(form.lastCleanSize)),
])
}}
</el-text>
</div>
</div>
<div v-if="scanStatus === 'scanned'" class="ml-5">
<div>
<el-text class="clean_title">{{ $t('clean.totalScan') }} {{ computeSize(totalSize) }}</el-text>
<el-button
type="primary"
class="-mt-2 ml-20"
:disabled="selectSize <= 0"
@click="onSubmitClean"
>
{{ $t('clean.clean') }}
</el-button>
<div class="mt-4">
<el-text type="info">{{ $t('clean.selectScan') }} {{ computeSize(selectSize) }}</el-text>
</div>
</div>
<el-row type="flex" :gutter="20" class="mb-10">
<el-col :xs="24" :sm="24" :md="24" :lg="16" :xl="16">
<div class="tree-container">
<el-collapse v-model="activeNames" class="tree-collapse">
<el-collapse-item :title="$t('clean.system')" name="system">
@ -169,32 +106,46 @@
:empty-text="$t('clean.statusEmpty')"
>
<template #default="{ node, data }">
<div class="tree-node">
<el-tooltip
effect="dark"
:content="load18n(data.label)"
placement="top"
>
<span class="tree-node-label">{{ load18n(data.label) }}</span>
</el-tooltip>
<span class="tree-node-size" v-if="data.size">
{{ computeSize(data.size) }}
</span>
<el-tooltip
effect="dark"
:content="loadTag(node, data)"
placement="top"
>
<span class="tree-node-tooltip">
{{ loadTag(node, data) }}
</span>
</el-tooltip>
</div>
<el-text>
{{
load18n(data.label) +
' ' +
computeSize(data.size) +
' ' +
loadTag(node, data)
}}
</el-text>
</template>
</el-tree>
</el-collapse-item>
<el-collapse-item :title="$t('clean.containerTrash')" name="container_trash">
<el-collapse-item :title="$t('clean.unknownBackup')" name="backup">
<el-tree
ref="backupRef"
:data="cleanData.backupClean"
node-key="id"
:default-checked-keys="backupDefaultCheck"
show-checkbox
:props="defaultProps"
@check-change="onChange"
class="responsive-tree"
:empty-text="$t('clean.statusEmpty')"
>
<template #default="{ node, data }">
<el-text>
{{
load18n(data.label) +
' ' +
computeSize(data.size) +
' ' +
loadTag(node, data)
}}
</el-text>
</template>
</el-tree>
</el-collapse-item>
<el-collapse-item :title="$t('clean.docker')" name="docker">
<el-tree
ref="containerRef"
:data="cleanData.containerClean"
@ -207,27 +158,15 @@
:empty-text="$t('clean.statusEmpty')"
>
<template #default="{ node, data }">
<div class="tree-node">
<el-tooltip
effect="dark"
:content="load18n(data.label)"
placement="top"
>
<span class="tree-node-label">{{ load18n(data.label) }}</span>
</el-tooltip>
<span class="tree-node-size" v-if="data.size">
{{ computeSize(data.size) }}
</span>
<el-tooltip
effect="dark"
:content="loadTag(node, data)"
placement="top"
>
<span class="tree-node-tooltip">
{{ loadTag(node, data) }}
</span>
</el-tooltip>
</div>
<el-text>
{{
load18n(data.label) +
' ' +
computeSize(data.size) +
' ' +
loadTag(node, data)
}}
</el-text>
</template>
</el-tree>
</el-collapse-item>
@ -244,27 +183,15 @@
:empty-text="$t('clean.statusEmpty')"
>
<template #default="{ node, data }">
<div class="tree-node">
<el-tooltip
effect="dark"
:content="load18n(data.label)"
placement="top"
>
<span class="tree-node-label">{{ load18n(data.label) }}</span>
</el-tooltip>
<span class="tree-node-size" v-if="data.size">
{{ computeSize(data.size) }}
</span>
<el-tooltip
effect="dark"
:content="loadTag(node, data)"
placement="top"
>
<span class="tree-node-tooltip">
{{ loadTag(node, data) }}
</span>
</el-tooltip>
</div>
<el-text>
{{
load18n(data.label) +
' ' +
computeSize(data.size) +
' ' +
loadTag(node, data)
}}
</el-text>
</template>
</el-tree>
</el-collapse-item>
@ -281,27 +208,15 @@
:empty-text="$t('clean.statusEmpty')"
>
<template #default="{ node, data }">
<div class="tree-node">
<el-tooltip
effect="dark"
:content="load18n(data.label)"
placement="top"
>
<span class="tree-node-label">{{ load18n(data.label) }}</span>
</el-tooltip>
<span class="tree-node-size" v-if="data.size">
{{ computeSize(data.size) }}
</span>
<el-tooltip
effect="dark"
:content="loadTag(node, data)"
placement="top"
>
<span class="tree-node-tooltip">
{{ loadTag(node, data) }}
</span>
</el-tooltip>
</div>
<el-text>
{{
load18n(data.label) +
' ' +
computeSize(data.size) +
' ' +
loadTag(node, data)
}}
</el-text>
</template>
</el-tree>
</el-collapse-item>
@ -318,35 +233,23 @@
:empty-text="$t('clean.statusEmpty')"
>
<template #default="{ node, data }">
<div class="tree-node">
<el-tooltip
effect="dark"
:content="load18n(data.label)"
placement="top"
>
<span class="tree-node-label">{{ load18n(data.label) }}</span>
</el-tooltip>
<span class="tree-node-size" v-if="data.size">
{{ computeSize(data.size) }}
</span>
<el-tooltip
effect="dark"
:content="loadTag(node, data)"
placement="top"
>
<span class="tree-node-tooltip">
{{ loadTag(node, data) }}
</span>
</el-tooltip>
</div>
<el-text>
{{
load18n(data.label) +
' ' +
computeSize(data.size) +
' ' +
loadTag(node, data)
}}
</el-text>
</template>
</el-tree>
</el-collapse-item>
</el-collapse>
</div>
</div>
</el-col>
</el-row>
</el-col>
</el-row>
</div>
</template>
</LayoutContent>
</div>
@ -374,6 +277,7 @@ const defaultProps = {
};
const cleanData = reactive({
systemClean: [],
backupClean: [],
uploadClean: [],
downloadClean: [],
systemLogClean: [],
@ -381,6 +285,8 @@ const cleanData = reactive({
});
const systemRef = ref();
const systemDefaultCheck = ref([]);
const backupRef = ref();
const backupDefaultCheck = ref([]);
const uploadRef = ref();
const uploadDefaultCheck = ref([]);
const downloadRef = ref();
@ -389,7 +295,20 @@ const systemLogRef = ref();
const systemLogDefaultCheck = ref([]);
const containerRef = ref();
const containerDefaultCheck = ref([]);
const activeNames = ref(['system', 'upload', 'download', 'system_log', 'container_trash']);
const activeNames = ref(['system', 'backup', 'upload', 'download', 'system_log', 'docker']);
const cleanTag = [
{ icon: 'Setting', title: i18n.global.t('clean.system'), description: i18n.global.t('clean.systemHelper') },
{ icon: 'Upload', title: i18n.global.t('clean.upload'), description: i18n.global.t('clean.uploadHelper') },
{ icon: 'Files', title: i18n.global.t('clean.backup'), description: i18n.global.t('clean.backupHelper') },
{ icon: 'Download', title: i18n.global.t('clean.download'), description: i18n.global.t('clean.downloadHelper') },
{
icon: 'p-docker1',
title: i18n.global.t('clean.docker'),
description: i18n.global.t('clean.dockerHelper'),
},
{ icon: 'Document', title: i18n.global.t('clean.systemLog'), description: i18n.global.t('clean.systemLogHelper') },
];
const submitCleans = ref();
@ -410,6 +329,10 @@ const scanData = async () => {
for (const item of cleanData.systemClean) {
totalSize.value += item.size;
}
cleanData.backupClean = res.data.backupClean || [];
for (const item of cleanData.backupClean) {
totalSize.value += item.size;
}
cleanData.uploadClean = res.data.uploadClean || [];
for (const item of cleanData.uploadClean) {
totalSize.value += item.size;
@ -427,6 +350,7 @@ const scanData = async () => {
totalSize.value += item.size;
}
loadCheck(cleanData.systemClean, systemDefaultCheck.value);
loadCheck(cleanData.backupClean, backupDefaultCheck.value);
loadCheck(cleanData.uploadClean, uploadDefaultCheck.value);
loadCheck(cleanData.downloadClean, downloadDefaultCheck.value);
loadCheck(cleanData.systemLogClean, systemLogDefaultCheck.value);
@ -448,6 +372,7 @@ const onSubmitClean = async () => {
submitCleans.value = [];
let restart = false;
loadSubmitCheck(cleanData.systemClean);
loadSubmitCheck(cleanData.backupClean);
loadSubmitCheck(cleanData.uploadClean);
loadSubmitCheck(cleanData.downloadClean);
loadSubmitCheck(cleanData.systemLogClean);
@ -498,7 +423,13 @@ const loadSubmitCheck = (data: any) => {
return;
}
for (const item of data) {
if (item.isCheck) {
if (
item.isCheck &&
item.label !== 'unknown_app' &&
item.label !== 'unknown_database' &&
item.label !== 'unknown_website' &&
item.label !== 'unknown_snapshot'
) {
submitCleans.value.push({ treeType: item.type, name: item.name, size: item.size });
continue;
}
@ -526,6 +457,12 @@ function onChange(data: any, isCheck: boolean) {
selectSize.value = selectSize.value + Number(item.size);
}
}
let backupSelects = backupRef.value.getCheckedNodes(false, true);
for (const item of backupSelects) {
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) {
@ -600,16 +537,26 @@ function load18n(label: string) {
switch (label) {
case '1panel_original':
return i18n.global.t('clean.panelOriginal');
case 'backup':
return i18n.global.t('clean.backup');
case 'upgrade':
return i18n.global.t('clean.upgrade');
case 'agent_packages':
return i18n.global.t('clean.agentPackages');
case 'cache':
return i18n.global.t('clean.cache');
case 'snapshot':
return i18n.global.t('clean.snapshot');
case 'rollback':
return i18n.global.t('clean.rollback');
case 'tmp_backup':
return i18n.global.t('clean.tmpBackup');
case 'unknown_app':
return i18n.global.t('clean.unknownApp');
case 'unknown_database':
return i18n.global.t('clean.unknownDatabase');
case 'unknown_website':
return i18n.global.t('clean.unknownWebsite');
case 'unknown_snapshot':
return i18n.global.t('clean.unknownSnapshot');
case 'upload':
case 'upload_tmp':
return i18n.global.t('clean.upload');
@ -695,23 +642,14 @@ onMounted(() => {
</script>
<style lang="scss" scoped>
.app-card {
.clean-card {
margin-top: 20px;
cursor: pointer;
width: 100%;
border: var(--panel-border) !important;
&:hover .app-icon {
transform: scale(1.2);
}
.e-card {
margin-top: 20px;
&:hover {
cursor: pointer;
border: var(--panel-border) !important;
&:hover {
cursor: pointer;
border: 1px solid var(--el-color-primary) !important;
}
border: 1px solid var(--el-color-primary) !important;
}
}
@ -737,7 +675,7 @@ onMounted(() => {
.svg-icon {
font-size: 14px;
float: right;
margin-right: 15px;
margin-right: 5px;
}
.tree-container {
@ -755,31 +693,11 @@ onMounted(() => {
width: 100%;
max-height: 100%;
overflow: auto;
}
.tree-node {
display: flex;
align-items: center;
justify-content: start;
gap: 1rem;
width: 100%;
overflow: hidden;
}
.tree-node-label {
flex-shrink: 0;
max-width: 60%;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.tree-node-size {
flex-shrink: 0;
max-width: 25%;
white-space: nowrap;
}
.tree-node-tooltip {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
display: inline-block;
:deep(.el-tree-node .el-tree-node__content) {
width: fit-content;
overflow: auto;
min-width: 300px;
}
}
</style>