1
0
mirror of https://github.com/1Panel-dev/1Panel.git synced 2025-01-31 14:08:06 +08:00

fix: 完善 info、error 级别日志打印

This commit is contained in:
ssongliu 2022-12-28 18:35:53 +08:00
parent b4ff5463a0
commit 78a437d0ca
14 changed files with 87 additions and 41 deletions

View File

@ -67,6 +67,7 @@ func ErrorWithDetail(ctx *gin.Context, code int, msgKey string, err error) {
} else {
res.Message = i18n.GetMsgWithMap(msgKey, map[string]interface{}{"detail": err})
}
global.LOG.Error(res.Message)
ctx.JSON(http.StatusOK, res)
ctx.Abort()
}

View File

@ -94,7 +94,7 @@ func (b *BaseApi) SyncTime(c *gin.Context) {
}
system := runtime.GOOS
if system == "linux" {
cmd := exec.Command("timedatectl", "set-time", ntime.Format("2006-01-02 15:04:05"))
cmd := exec.Command("date", "-s", ntime.Format("2006-01-02 15:04:05"))
stdout, err := cmd.CombinedOutput()
if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, errors.New(string(stdout)))
@ -102,7 +102,7 @@ func (b *BaseApi) SyncTime(c *gin.Context) {
}
}
helper.SuccessWithData(c, ntime.Format("2006-01-02 15:04 MST -0700"))
helper.SuccessWithData(c, ntime.Format("2006-01-02 15:04:05 MST -0700"))
}
func (b *BaseApi) CleanMonitor(c *gin.Context) {

View File

@ -14,6 +14,7 @@ import (
"github.com/1Panel-dev/1Panel/backend/app/dto"
"github.com/1Panel-dev/1Panel/backend/constant"
"github.com/1Panel-dev/1Panel/backend/global"
"github.com/1Panel-dev/1Panel/backend/utils/docker"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"
@ -159,11 +160,14 @@ func (u *ContainerService) ContainerCreate(req dto.ContainerCreate) error {
hostConf.Binds = append(hostConf.Binds, fmt.Sprintf("%s:%s:%s", volume.SourceDir, volume.ContainerDir, volume.Mode))
}
}
global.LOG.Infof("new container info %s has been made, now start to create", req.Name)
container, err := client.ContainerCreate(context.TODO(), config, hostConf, &network.NetworkingConfig{}, &v1.Platform{}, req.Name)
if err != nil {
_ = client.ContainerRemove(context.Background(), req.Name, types.ContainerRemoveOptions{RemoveVolumes: true, Force: true})
return err
}
global.LOG.Infof("create container successful! now check if the container is started and delete the container information if it is not.", req.Name)
if err := client.ContainerStart(context.TODO(), container.ID, types.ContainerStartOptions{}); err != nil {
_ = client.ContainerRemove(context.Background(), req.Name, types.ContainerRemoveOptions{RemoveVolumes: true, Force: true})
return fmt.Errorf("create successful but start failed, err: %v", err)
@ -178,6 +182,7 @@ func (u *ContainerService) ContainerOperation(req dto.ContainerOperation) error
if err != nil {
return err
}
global.LOG.Infof("start container %s operation %s", req.Name, req.Operation)
switch req.Operation {
case constant.ContainerOpStart:
err = client.ContainerStart(ctx, req.Name, types.ContainerStartOptions{})

View File

@ -140,10 +140,10 @@ func (u *ContainerService) CreateCompose(req dto.ComposeCreate) error {
write.Flush()
req.Path = path
}
global.LOG.Infof("docker-compose.yml %s create successful, start to docker-compose up", req.Name)
if stdout, err := compose.Up(req.Path); err != nil {
return errors.New(string(stdout))
}
global.LOG.Debugf("docker-compose up %s successful", req.Name)
_ = composeRepo.CreateRecord(&model.Compose{Name: req.Name})
return nil
@ -156,7 +156,7 @@ func (u *ContainerService) ComposeOperation(req dto.ComposeOperation) error {
if stdout, err := compose.Operate(req.Path, req.Operation); err != nil {
return errors.New(string(stdout))
}
global.LOG.Debugf("docker-compose %s %s successful", req.Operation, req.Name)
global.LOG.Infof("docker-compose %s %s successful", req.Operation, req.Name)
if req.Operation == "down" {
_ = composeRepo.DeleteRecord(commonRepo.WithByName(req.Name))
_ = os.RemoveAll(strings.ReplaceAll(req.Path, req.Name+"/docker-compose.yml", ""))
@ -178,6 +178,7 @@ func (u *ContainerService) ComposeUpdate(req dto.ComposeUpdate) error {
_, _ = write.WriteString(req.Content)
write.Flush()
global.LOG.Infof("docker-compose.yml %s has been replaced, now start to docker-compose restart", req.Path)
if stdout, err := compose.Down(req.Path); err != nil {
return errors.New(string(stdout))
}

View File

@ -92,6 +92,8 @@ func (u *CronjobService) Download(down dto.CronjobDownload) (string, error) {
if cronjob.ID == 0 {
return "", constant.ErrRecordNotFound
}
global.LOG.Infof("start to download records %s from %s", cronjob.Type, backup.Type)
varMap := make(map[string]interface{})
if err := json.Unmarshal([]byte(backup.Vars), &varMap); err != nil {
return "", err
@ -101,25 +103,30 @@ func (u *CronjobService) Download(down dto.CronjobDownload) (string, error) {
varMap["bucket"] = backup.Bucket
switch backup.Type {
case constant.Sftp:
varMap["username"] = backup.AccessKey
varMap["password"] = backup.Credential
case constant.OSS, constant.S3, constant.MinIo:
varMap["accessKey"] = backup.AccessKey
varMap["secretKey"] = backup.Credential
}
backClient, err := cloud_storage.NewCloudStorageClient(varMap)
if err != nil {
return "", fmt.Errorf("new cloud storage client failed, err: %v", err)
}
global.LOG.Info("new backup client successful")
commonDir := fmt.Sprintf("%s/%s/", cronjob.Type, cronjob.Name)
name := fmt.Sprintf("%s%s.tar.gz", commonDir, record.StartTime.Format("20060102150405"))
if cronjob.Type == "database" {
name = fmt.Sprintf("%s%s.gz", commonDir, record.StartTime.Format("20060102150405"))
}
tempPath := fmt.Sprintf("%s%s", constant.DownloadDir, commonDir)
tempPath := fmt.Sprintf("%s/%s", constant.DownloadDir, commonDir)
if _, err := os.Stat(tempPath); err != nil && os.IsNotExist(err) {
if err = os.MkdirAll(tempPath, os.ModePerm); err != nil {
fmt.Println(err)
}
}
global.LOG.Infof("download records %s from %s to %s", name, commonDir, tempPath)
targetPath := tempPath + strings.ReplaceAll(name, commonDir, "")
if _, err = os.Stat(targetPath); err != nil && os.IsNotExist(err) {
isOK, err := backClient.Download(name, targetPath)
@ -132,6 +139,7 @@ func (u *CronjobService) Download(down dto.CronjobDownload) (string, error) {
if _, ok := varMap["dir"]; !ok {
return "", errors.New("load local backup dir failed")
}
global.LOG.Infof("record is save in local dir %s", varMap["dir"])
switch cronjob.Type {
case "website":
@ -172,6 +180,7 @@ func (u *CronjobService) Create(cronjobDto dto.CronjobCreate) error {
if err := cronjobRepo.Create(&cronjob); err != nil {
return err
}
global.LOG.Infof("create cronjob %s successful, spec: %s", cronjob.Name, cronjob.Spec)
if err := u.StartJob(&cronjob); err != nil {
return err
}
@ -180,6 +189,7 @@ func (u *CronjobService) Create(cronjobDto dto.CronjobCreate) error {
func (u *CronjobService) StartJob(cronjob *model.Cronjob) error {
global.Cron.Remove(cron.EntryID(cronjob.EntryID))
global.LOG.Infof("stop cronjob entryID: %d", cronjob.EntryID)
entryID, err := u.AddCronJob(cronjob)
if err != nil {
return err
@ -245,6 +255,7 @@ func (u *CronjobService) UpdateStatus(id uint, status string) error {
}
} else {
global.Cron.Remove(cron.EntryID(cronjob.EntryID))
global.LOG.Infof("stop cronjob entryID: %d", cronjob.EntryID)
}
return cronjobRepo.Update(cronjob.ID, map[string]interface{}{"status": status})
}
@ -258,6 +269,7 @@ func (u *CronjobService) AddCronJob(cronjob *model.Cronjob) (int, error) {
if err != nil {
return 0, err
}
global.LOG.Infof("start cronjob entryID: %d", entryID)
return int(entryID), nil
}
@ -270,6 +282,7 @@ func mkdirAndWriteFile(cronjob *model.Cronjob, startTime time.Time, msg []byte)
}
path := fmt.Sprintf("%s/%s.log", dir, startTime.Format("20060102150405"))
global.LOG.Infof("cronjob %s has generated some logs %s", cronjob.Name, path)
file, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE, 0666)
if err != nil {
return "", err

View File

@ -82,6 +82,8 @@ func (u *CronjobService) HandleBackup(cronjob *model.Cronjob, startTime time.Tim
if err != nil {
return "", err
}
global.LOG.Infof("start to backup %s %s to %s", cronjob.Type, cronjob.Name, backup.Type)
if cronjob.KeepLocal || cronjob.Type != "LOCAL" {
localDir, err := loadLocalDir()
if err != nil {
@ -113,6 +115,7 @@ func (u *CronjobService) HandleBackup(cronjob *model.Cronjob, startTime time.Tim
default:
fileName = fmt.Sprintf("%s.tar.gz", startTime.Format("20060102150405"))
backupDir = fmt.Sprintf("%s/%s", cronjob.Type, cronjob.Name)
global.LOG.Infof("handle tar %s to %s", backupDir, fileName)
if err := handleTar(cronjob.SourceDir, baseDir+"/"+backupDir, fileName, cronjob.ExclusionRules); err != nil {
return "", err
}
@ -145,6 +148,7 @@ func (u *CronjobService) HandleDelete(id uint) error {
}
commonDir := fmt.Sprintf("%s/%s/", cronjob.Type, cronjob.Name)
global.Cron.Remove(cron.EntryID(cronjob.EntryID))
global.LOG.Infof("stop cronjob entryID: %d", cronjob.EntryID)
_ = cronjobRepo.DeleteRecord(cronjobRepo.WithByJobID(int(id)))
dir := fmt.Sprintf("%s/%s/%s", constant.TaskDir, cronjob.Type, cronjob.Name)
@ -157,6 +161,7 @@ func (u *CronjobService) HandleDelete(id uint) error {
}
func (u *CronjobService) HandleRmExpired(backType, baseDir, backupDir string, cronjob *model.Cronjob, backClient cloud_storage.CloudStorageClient) {
global.LOG.Infof("start to handle remove expired, retain copies: %d", cronjob.RetainCopies)
if backType != "LOCAL" {
currentObjs, err := backClient.ListObjects(backupDir + "/")
if err != nil {

View File

@ -32,7 +32,7 @@ type MysqlService struct{}
type IMysqlService interface {
SearchWithPage(search dto.PageInfo) (int64, interface{}, error)
ListDBName() ([]string, error)
Create(ctx context.Context, mysqlDto dto.MysqlDBCreate) (*model.DatabaseMysql, error)
Create(ctx context.Context, req dto.MysqlDBCreate) (*model.DatabaseMysql, error)
ChangeAccess(info dto.ChangeDBInfo) error
ChangePassword(info dto.ChangeDBInfo) error
UpdateVariables(updatas []dto.MysqlVariablesUpdate) error
@ -73,15 +73,11 @@ func (u *MysqlService) RecoverByUpload(req dto.UploadRecover) error {
if err != nil {
return err
}
localDir, err := loadLocalDir()
if err != nil {
return err
}
file := req.FileDir + "/" + req.FileName
if !strings.HasSuffix(req.FileName, ".sql") && !strings.HasSuffix(req.FileName, ".gz") {
fileOp := files.NewFileOp()
fileNameItem := time.Now().Format("20060102150405")
dstDir := fmt.Sprintf("%s/database/mysql/%s/upload/tmp/%s", localDir, req.MysqlName, fileNameItem)
dstDir := fmt.Sprintf("%s/%s", req.FileDir, fileNameItem)
if _, err := os.Stat(dstDir); err != nil && os.IsNotExist(err) {
if err = os.MkdirAll(dstDir, os.ModePerm); err != nil {
if err != nil {
@ -100,6 +96,7 @@ func (u *MysqlService) RecoverByUpload(req dto.UploadRecover) error {
_ = os.RemoveAll(dstDir)
return err
}
global.LOG.Infof("decompress file %s successful, now start to check test.sql is exist", req.FileDir+"/"+req.FileName)
hasTestSql := false
_ = filepath.Walk(dstDir, func(path string, info os.FileInfo, err error) error {
if err != nil {
@ -120,6 +117,7 @@ func (u *MysqlService) RecoverByUpload(req dto.UploadRecover) error {
}()
}
global.LOG.Info("start to do recover from uploads")
fi, _ := os.Open(file)
defer fi.Close()
cmd := exec.Command("docker", "exec", "-i", app.ContainerName, "mysql", "-uroot", "-p"+app.Password, req.DBName)
@ -143,6 +141,7 @@ func (u *MysqlService) RecoverByUpload(req dto.UploadRecover) error {
if err != nil || strings.HasPrefix(string(stdStr), "ERROR ") {
return errors.New(stdStr)
}
global.LOG.Info("recover from uploads successful!")
return nil
}
@ -155,36 +154,38 @@ func (u *MysqlService) ListDBName() ([]string, error) {
return dbNames, err
}
func (u *MysqlService) Create(ctx context.Context, mysqlDto dto.MysqlDBCreate) (*model.DatabaseMysql, error) {
if mysqlDto.Username == "root" {
func (u *MysqlService) Create(ctx context.Context, req dto.MysqlDBCreate) (*model.DatabaseMysql, error) {
if req.Username == "root" {
return nil, errors.New("Cannot set root as user name")
}
app, err := appInstallRepo.LoadBaseInfo("mysql", "")
if err != nil {
return nil, err
}
mysql, _ := mysqlRepo.Get(commonRepo.WithByName(mysqlDto.Name))
mysql, _ := mysqlRepo.Get(commonRepo.WithByName(req.Name))
if mysql.ID != 0 {
return nil, constant.ErrRecordExist
}
if err := copier.Copy(&mysql, &mysqlDto); err != nil {
if err := copier.Copy(&mysql, &req); err != nil {
return nil, errors.WithMessage(constant.ErrStructTransform, err.Error())
}
if err := excuteSql(app.ContainerName, app.Password, fmt.Sprintf("create database if not exists `%s` character set=%s", mysqlDto.Name, mysqlDto.Format)); err != nil {
if err := excuteSql(app.ContainerName, app.Password, fmt.Sprintf("create database if not exists `%s` character set=%s", req.Name, req.Format)); err != nil {
return nil, err
}
tmpPermission := mysqlDto.Permission
if err := excuteSql(app.ContainerName, app.Password, fmt.Sprintf("create user if not exists '%s'@'%s' identified by '%s';", mysqlDto.Username, tmpPermission, mysqlDto.Password)); err != nil {
tmpPermission := req.Permission
if err := excuteSql(app.ContainerName, app.Password, fmt.Sprintf("create user if not exists '%s'@'%s' identified by '%s';", req.Username, tmpPermission, req.Password)); err != nil {
return nil, err
}
grantStr := fmt.Sprintf("grant all privileges on `%s`.* to '%s'@'%s'", mysqlDto.Name, mysqlDto.Username, tmpPermission)
grantStr := fmt.Sprintf("grant all privileges on `%s`.* to '%s'@'%s'", req.Name, req.Username, tmpPermission)
if app.Version == "5.7.39" {
grantStr = fmt.Sprintf("%s identified by '%s' with grant option;", grantStr, mysqlDto.Password)
grantStr = fmt.Sprintf("%s identified by '%s' with grant option;", grantStr, req.Password)
}
if err := excuteSql(app.ContainerName, app.Password, grantStr); err != nil {
return nil, err
}
global.LOG.Infof("create database %s successful!", req.Name)
mysql.MysqlName = app.Name
if err := mysqlRepo.Create(ctx, &mysql); err != nil {
return nil, err
@ -209,12 +210,14 @@ func (u *MysqlService) Backup(db dto.BackupDB) error {
return nil
}
func (u *MysqlService) Recover(db dto.RecoverDB) error {
func (u *MysqlService) Recover(req dto.RecoverDB) error {
app, err := appInstallRepo.LoadBaseInfo("mysql", "")
if err != nil {
return err
}
gzipFile, err := os.Open(db.BackupName)
global.LOG.Infof("recover database %s-%s from backup file %s", req.MysqlName, req.DBName, req.BackupName)
gzipFile, err := os.Open(req.BackupName)
if err != nil {
return err
}
@ -224,7 +227,7 @@ func (u *MysqlService) Recover(db dto.RecoverDB) error {
return err
}
defer gzipReader.Close()
cmd := exec.Command("docker", "exec", "-i", app.ContainerName, "mysql", "-uroot", "-p"+app.Password, db.DBName)
cmd := exec.Command("docker", "exec", "-i", app.ContainerName, "mysql", "-uroot", "-p"+app.Password, req.DBName)
cmd.Stdin = gzipReader
stdout, err := cmd.CombinedOutput()
stdStr := strings.ReplaceAll(string(stdout), "mysql: [Warning] Using a password on the command line interface can be insecure.\n", "")
@ -273,6 +276,7 @@ func (u *MysqlService) Delete(ctx context.Context, req dto.MysqlDBDelete) error
if err := excuteSql(app.ContainerName, app.Password, fmt.Sprintf("drop database if exists `%s`", db.Name)); err != nil && !req.ForceDelete {
return err
}
global.LOG.Info("execute delete database sql successful, now start to drop uploads and records")
uploadDir := fmt.Sprintf("%s/uploads/database/mysql/%s/%s", constant.DefaultDataDir, app.Name, db.Name)
if _, err := os.Stat(uploadDir); err == nil {
@ -287,6 +291,7 @@ func (u *MysqlService) Delete(ctx context.Context, req dto.MysqlDBDelete) error
if _, err := os.Stat(backupDir); err == nil {
_ = os.RemoveAll(backupDir)
}
global.LOG.Infof("delete database %s-%s backups successful", app.Name, db.Name)
}
_ = backupRepo.DeleteRecord(ctx, commonRepo.WithByType("database-mysql"), commonRepo.WithByName(app.Name), backupRepo.WithByDetailName(db.Name))
@ -325,6 +330,8 @@ func (u *MysqlService) ChangePassword(info dto.ChangeDBInfo) error {
if err != nil {
return err
}
global.LOG.Infof("start to update mysql password used by app %s-%s", appModel.Key, appInstall.Name)
if err := updateInstallInfoInDB(appModel.Key, appInstall.Name, "user-password", true, info.Value); err != nil {
return err
}
@ -332,6 +339,7 @@ func (u *MysqlService) ChangePassword(info dto.ChangeDBInfo) error {
if err := excuteSql(app.ContainerName, app.Password, passwordChangeCMD); err != nil {
return err
}
global.LOG.Info("excute password change sql successful")
_ = mysqlRepo.Update(mysql.ID, map[string]interface{}{"password": info.Value})
return nil
}
@ -344,7 +352,7 @@ func (u *MysqlService) ChangePassword(info dto.ChangeDBInfo) error {
if host == "%" || host == "localhost" {
passwordRootChangeCMD := fmt.Sprintf("set password for 'root'@'%s' = password('%s')", host, info.Value)
if app.Version != "5.7.39" {
passwordRootChangeCMD = fmt.Sprintf("ALTER USER 'root'@'%s' IDENTIFIED WITH mysql_native_password BY '%s';", host, info.Value)
passwordRootChangeCMD = fmt.Sprintf("alter user 'root'@'%s' identified with mysql_native_password BY '%s';", host, info.Value)
}
if err := excuteSql(app.ContainerName, app.Password, passwordRootChangeCMD); err != nil {
return err
@ -625,6 +633,7 @@ func backupMysql(backupType, baseDir, backupDir, mysqlName, dbName, fileName str
}
}
outfile, _ := os.OpenFile(fullDir+"/"+fileName, os.O_RDWR|os.O_CREATE, 0755)
global.LOG.Infof("start to mysqldump | gzip > %s.gzip", outfile)
cmd := exec.Command("docker", "exec", app.ContainerName, "mysqldump", "-uroot", "-p"+app.Password, dbName)
gzipCmd := exec.Command("gzip", "-cf")
gzipCmd.Stdin, _ = cmd.StdoutPipe()

View File

@ -13,6 +13,7 @@ import (
"github.com/1Panel-dev/1Panel/backend/app/dto"
"github.com/1Panel-dev/1Panel/backend/constant"
"github.com/1Panel-dev/1Panel/backend/global"
"github.com/1Panel-dev/1Panel/backend/utils/compose"
_ "github.com/go-sql-driver/mysql"
)
@ -182,6 +183,8 @@ func (u *RedisService) Backup() error {
if err != nil {
return err
}
global.LOG.Infof("appendonly in redis conf is %s", appendonly)
if appendonly == "yes" {
redisDataDir := fmt.Sprintf("%s/%s/%s/data", constant.AppInstallDir, "redis", redisInfo.Name)
name := fmt.Sprintf("%s.tar.gz", time.Now().Format("20060102150405"))
@ -208,6 +211,7 @@ func (u *RedisService) Recover(req dto.RedisBackupRecover) error {
if err != nil {
return err
}
global.LOG.Infof("appendonly in redis conf is %s", appendonly)
composeDir := fmt.Sprintf("%s/redis/%s", constant.AppInstallDir, redisInfo.Name)
if _, err := compose.Down(composeDir + "/docker-compose.yml"); err != nil {

View File

@ -43,7 +43,7 @@ func (u *SettingService) GetSettingInfo() (*dto.SettingInfo, error) {
if err := json.Unmarshal(arr, &info); err != nil {
return nil, err
}
info.LocalTime = time.Now().Format("2006-01-02 15:04 MST -0700")
info.LocalTime = time.Now().Format("2006-01-02 15:04:05 MST -0700")
return &info, err
}

View File

@ -403,9 +403,12 @@ func handleWebsiteBackup(backupType, baseDir, backupDir, domain, backupName stri
}
}
}
global.LOG.Infof("make a tmp dir %s for website files successful", tmpDir)
if err := saveWebsiteJson(&website, tmpDir); err != nil {
return err
}
global.LOG.Info("put website into tmp dir successful")
nginxInfo, err := appInstallRepo.LoadBaseInfo(constant.AppNginx, "")
if err != nil {
@ -416,6 +419,7 @@ func handleWebsiteBackup(backupType, baseDir, backupDir, domain, backupName stri
if err := fileOp.CopyFile(nginxConfFile, tmpDir); err != nil {
return err
}
global.LOG.Info("put nginx conf into tmp dir successful")
if website.Type == constant.Deployment {
if err := mysqlOperation(&website, "backup", tmpDir); err != nil {
@ -429,11 +433,13 @@ func handleWebsiteBackup(backupType, baseDir, backupDir, domain, backupName stri
if err := handleTar(websiteDir, tmpDir, fmt.Sprintf("%s.app.tar.gz", website.Alias), ""); err != nil {
return err
}
global.LOG.Info("put app tar into tmp dir successful")
}
websiteDir := path.Join(constant.AppInstallDir, "nginx", nginxInfo.Name, "www", "sites", website.Alias)
if err := handleTar(websiteDir, tmpDir, fmt.Sprintf("%s.web.tar.gz", website.Alias), ""); err != nil {
return err
}
global.LOG.Info("put website tar into tmp dir successful, now start to tar tmp dir")
if err := handleTar(tmpDir, fmt.Sprintf("%s/%s", baseDir, backupDir), backupName+".tar.gz", ""); err != nil {
return err
}

View File

@ -1,7 +0,0 @@
package constant
const (
TmpDir = "/opt/1Panel/data/tmp"
TaskDir = "/opt/1Panel/data/task"
DownloadDir = "/opt/1Panel/download"
)

View File

@ -10,3 +10,10 @@ var (
AppResourceDir = path.Join(ResourceDir, "apps")
AppInstallDir = path.Join(DefaultDataDir, "apps")
)
const (
TmpDir = "/opt/1Panel/data/tmp"
TaskDir = "/opt/1Panel/data/task"
DownloadDir = "/opt/1Panel/data/download"
UploadDir = "/opt/1Panel/data/uploads"
)

View File

@ -5,7 +5,7 @@
width="30%"
:close-on-click-modal="false"
>
<el-form ref="deleteForm">
<el-form ref="deleteForm" v-loading="loading">
<el-form-item>
<el-checkbox v-model="deleteReq.forceDelete" :label="$t('app.forceDelete')" />
<span class="input-help">
@ -29,10 +29,10 @@
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="dialogVisiable = false" :loading="loading">
<el-button @click="dialogVisiable = false" :disabled="loading">
{{ $t('commons.button.cancel') }}
</el-button>
<el-button type="primary" @click="submit" :loading="loading" :disabled="deleteInfo != dbName">
<el-button type="primary" @click="submit" :disabled="deleteInfo != dbName || loading">
{{ $t('commons.button.confirm') }}
</el-button>
</span>

View File

@ -46,16 +46,16 @@
>
<template #default="{ node, data }">
<span class="custom-tree-node" @mouseover="hover = data.id" @mouseleave="hover = null">
<span v-if="node.label !== currentGroup">
<a @click="onEdit(node, data)">{{ node.label }}</a>
</span>
<el-input v-else v-model="currentGroupValue" @blur="onUpdateGroup()"></el-input>
<span v-if="node.label !== currentGroup || !data.onEdit">{{ node.label }}</span>
<el-input v-else v-model="currentGroupValue"></el-input>
<div
style="margin-left: 10px"
v-if="!(node.level === 1 && data.label === 'default') && data.id === hover"
>
<el-button icon="Edit" link @click="onEdit(node, data)" />
<el-button icon="Delete" link @click="onDelete(node, data)" />
<el-button v-if="!data.onEdit" icon="Edit" link @click="onEdit(node, data)" />
<el-button v-if="!data.onEdit" icon="Delete" link @click="onDelete(node, data)" />
<el-button v-if="data.onEdit" icon="Check" link @click="onUpdateGroup()" />
<el-button v-if="data.onEdit" icon="Close" link @click="data.onEdit = false" />
</div>
</span>
</template>
@ -184,6 +184,7 @@ interface Tree {
id: number;
label: string;
children?: Tree[];
onEdit: boolean;
}
let searcConfig = reactive<Host.ReqSearch>({
@ -308,6 +309,7 @@ const onEdit = async (node: Node, data: Tree) => {
currentGroupValue.value = data.label;
currentGroupID.value = data.id - 10000;
groupOperation.value = 'edit';
data.onEdit = true;
return;
} else {
const res = await getHostInfo(data.id);