feat: qqwry 文件嵌入二进制

This commit is contained in:
ssongliu 2022-11-18 16:14:23 +08:00 committed by ssongliu
parent 0a109b594b
commit e6142a403c
46 changed files with 477 additions and 571 deletions

View File

@ -1,12 +1,14 @@
package v1 package v1
import ( import (
"errors"
"reflect"
"github.com/1Panel-dev/1Panel/backend/app/api/v1/helper" "github.com/1Panel-dev/1Panel/backend/app/api/v1/helper"
"github.com/1Panel-dev/1Panel/backend/app/dto" "github.com/1Panel-dev/1Panel/backend/app/dto"
"github.com/1Panel-dev/1Panel/backend/constant" "github.com/1Panel-dev/1Panel/backend/constant"
"github.com/1Panel-dev/1Panel/backend/global" "github.com/1Panel-dev/1Panel/backend/global"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"reflect"
) )
func (b *BaseApi) SearchAppInstalled(c *gin.Context) { func (b *BaseApi) SearchAppInstalled(c *gin.Context) {
@ -37,6 +39,20 @@ func (b *BaseApi) SearchAppInstalled(c *gin.Context) {
} }
} }
func (b *BaseApi) CheckAppInstalld(c *gin.Context) {
key, ok := c.Params.Get("key")
if !ok {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, errors.New("error key in path"))
return
}
checkData, err := appInstallService.CheckExist(key)
if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
helper.SuccessWithData(c, checkData)
}
func (b *BaseApi) SyncInstalled(c *gin.Context) { func (b *BaseApi) SyncInstalled(c *gin.Context) {
if err := appInstallService.SyncAll(); err != nil { if err := appInstallService.SyncAll(); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)

View File

@ -95,13 +95,7 @@ func (b *BaseApi) UpdateMysqlVariables(c *gin.Context) {
return return
} }
mysqlName, ok := c.Params.Get("mysqlName") if err := mysqlService.UpdateVariables(req); err != nil {
if !ok {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, errors.New("error mysqlName in path"))
return
}
if err := mysqlService.UpdateVariables(mysqlName, req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return return
} }
@ -124,7 +118,7 @@ func (b *BaseApi) UpdateMysqlConfByFile(c *gin.Context) {
} }
func (b *BaseApi) SearchMysql(c *gin.Context) { func (b *BaseApi) SearchMysql(c *gin.Context) {
var req dto.SearchDBWithPage var req dto.PageInfo
if err := c.ShouldBindJSON(&req); err != nil { if err := c.ShouldBindJSON(&req); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return return
@ -142,14 +136,8 @@ func (b *BaseApi) SearchMysql(c *gin.Context) {
}) })
} }
func (b *BaseApi) ListDBNameByVersion(c *gin.Context) { func (b *BaseApi) ListDBName(c *gin.Context) {
name, ok := c.Params.Get("name") list, err := mysqlService.ListDBName()
if !ok {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, errors.New("error name in path"))
return
}
list, err := mysqlService.ListDBByVersion(name)
if err != nil { if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return return
@ -232,37 +220,16 @@ func (b *BaseApi) DeleteMysql(c *gin.Context) {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err) helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, err)
return return
} }
name, ok := c.Params.Get("name")
if !ok {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, errors.New("error name in path"))
return
}
if err := mysqlService.Delete(name, req.Ids); err != nil { if err := mysqlService.Delete(req.Ids); err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return return
} }
helper.SuccessWithData(c, nil) helper.SuccessWithData(c, nil)
} }
func (b *BaseApi) LoadVersions(c *gin.Context) {
data, err := mysqlService.LoadRunningVersion()
if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return
}
helper.SuccessWithData(c, data)
}
func (b *BaseApi) LoadBaseinfo(c *gin.Context) { func (b *BaseApi) LoadBaseinfo(c *gin.Context) {
name, ok := c.Params.Get("name") data, err := mysqlService.LoadBaseInfo()
if !ok {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, errors.New("error name in path"))
return
}
data, err := mysqlService.LoadBaseInfo(name)
if err != nil { if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return return
@ -272,13 +239,7 @@ func (b *BaseApi) LoadBaseinfo(c *gin.Context) {
} }
func (b *BaseApi) LoadStatus(c *gin.Context) { func (b *BaseApi) LoadStatus(c *gin.Context) {
name, ok := c.Params.Get("name") data, err := mysqlService.LoadStatus()
if !ok {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, errors.New("error name in path"))
return
}
data, err := mysqlService.LoadStatus(name)
if err != nil { if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return return
@ -288,12 +249,7 @@ func (b *BaseApi) LoadStatus(c *gin.Context) {
} }
func (b *BaseApi) LoadVariables(c *gin.Context) { func (b *BaseApi) LoadVariables(c *gin.Context) {
name, ok := c.Params.Get("name") data, err := mysqlService.LoadVariables()
if !ok {
helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, errors.New("error name in path"))
return
}
data, err := mysqlService.LoadVariables(name)
if err != nil { if err != nil {
helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err)
return return

View File

@ -39,6 +39,12 @@ type AppInstallRequest struct {
Services map[string]string `json:"services"` Services map[string]string `json:"services"`
} }
type CheckInstalled struct {
IsExist bool `json:"isExist"`
Name string `json:"name"`
Version string `json:"version"`
}
type AppInstalled struct { type AppInstalled struct {
model.AppInstall model.AppInstall
Total int `json:"total"` Total int `json:"total"`

View File

@ -14,7 +14,6 @@ type CronjobCreate struct {
Script string `json:"script"` Script string `json:"script"`
Website string `json:"website"` Website string `json:"website"`
ExclusionRules string `json:"exclusionRules"` ExclusionRules string `json:"exclusionRules"`
Database string `json:"database"`
DBName string `json:"dbName"` DBName string `json:"dbName"`
URL string `json:"url"` URL string `json:"url"`
SourceDir string `json:"sourceDir"` SourceDir string `json:"sourceDir"`
@ -34,7 +33,6 @@ type CronjobUpdate struct {
Script string `json:"script"` Script string `json:"script"`
Website string `json:"website"` Website string `json:"website"`
ExclusionRules string `json:"exclusionRules"` ExclusionRules string `json:"exclusionRules"`
Database string `json:"database"`
DBName string `json:"dbName"` DBName string `json:"dbName"`
URL string `json:"url"` URL string `json:"url"`
SourceDir string `json:"sourceDir"` SourceDir string `json:"sourceDir"`
@ -66,7 +64,6 @@ type CronjobInfo struct {
Script string `json:"script"` Script string `json:"script"`
Website string `json:"website"` Website string `json:"website"`
ExclusionRules string `json:"exclusionRules"` ExclusionRules string `json:"exclusionRules"`
Database string `json:"database"`
DBName string `json:"dbName"` DBName string `json:"dbName"`
URL string `json:"url"` URL string `json:"url"`
SourceDir string `json:"sourceDir"` SourceDir string `json:"sourceDir"`

View File

@ -16,7 +16,6 @@ type MysqlDBInfo struct {
type MysqlDBCreate struct { type MysqlDBCreate struct {
Name string `json:"name" validate:"required"` Name string `json:"name" validate:"required"`
MysqlName string `json:"mysqlName" validate:"required"`
Format string `json:"format" validate:"required,oneof=utf8mb4 utf-8 gbk big5"` Format string `json:"format" validate:"required,oneof=utf8mb4 utf-8 gbk big5"`
Username string `json:"username" validate:"required"` Username string `json:"username" validate:"required"`
Password string `json:"password" validate:"required"` Password string `json:"password" validate:"required"`
@ -106,7 +105,6 @@ type DBBaseInfo struct {
Port int64 `json:"port"` Port int64 `json:"port"`
Password string `json:"password"` Password string `json:"password"`
RemoteConn bool `json:"remoteConn"` RemoteConn bool `json:"remoteConn"`
MysqlKey string `json:"mysqlKey"`
} }
type SearchDBWithPage struct { type SearchDBWithPage struct {

View File

@ -16,7 +16,6 @@ type Cronjob struct {
Script string `gorm:"longtext" json:"script"` Script string `gorm:"longtext" json:"script"`
Website string `gorm:"type:varchar(64)" json:"website"` Website string `gorm:"type:varchar(64)" json:"website"`
Database string `gorm:"type:varchar(64)" json:"database"`
DBName string `gorm:"type:varchar(64)" json:"dbName"` DBName string `gorm:"type:varchar(64)" json:"dbName"`
URL string `gorm:"type:varchar(256)" json:"url"` URL string `gorm:"type:varchar(256)" json:"url"`
SourceDir string `gorm:"type:varchar(256)" json:"sourceDir"` SourceDir string `gorm:"type:varchar(256)" json:"sourceDir"`

View File

@ -20,9 +20,7 @@ type IMysqlRepo interface {
Create(ctx context.Context, mysql *model.DatabaseMysql) error Create(ctx context.Context, mysql *model.DatabaseMysql) error
Delete(ctx context.Context, opts ...DBOption) error Delete(ctx context.Context, opts ...DBOption) error
Update(id uint, vars map[string]interface{}) error Update(id uint, vars map[string]interface{}) error
LoadRunningVersion(keys []string) ([]string, error) LoadBaseInfoByKey(key string) (*RootInfo, error)
LoadBaseInfoByName(name string) (*RootInfo, error)
LoadRedisBaseInfo() (*RootInfo, error)
UpdateDatabaseInfo(id uint, vars map[string]interface{}) error UpdateDatabaseInfo(id uint, vars map[string]interface{}) error
} }
@ -62,26 +60,6 @@ func (u *MysqlRepo) Page(page, size int, opts ...DBOption) (int64, []model.Datab
return count, users, err return count, users, err
} }
func (u *MysqlRepo) LoadRunningVersion(keys []string) ([]string, error) {
var (
apps []model.App
appInstall []model.AppInstall
results []string
)
if err := global.DB.Where("name in (?)", keys).Find(&apps).Error; err != nil {
return nil, err
}
for _, app := range apps {
if err := global.DB.Where("app_id = ?", app.ID).Find(&appInstall).Error; err != nil {
return nil, err
}
for _, item := range appInstall {
results = append(results, item.Name)
}
}
return results, nil
}
type RootInfo struct { type RootInfo struct {
ID uint `json:"id"` ID uint `json:"id"`
Name string `json:"name"` Name string `json:"name"`
@ -91,52 +69,16 @@ type RootInfo struct {
Param string `json:"param"` Param string `json:"param"`
Env string `json:"env"` Env string `json:"env"`
Key string `json:"key"` Key string `json:"key"`
Version string `json:"version"`
} }
func (u *MysqlRepo) LoadBaseInfoByName(name string) (*RootInfo, error) { func (u *MysqlRepo) LoadBaseInfoByKey(key string) (*RootInfo, error) {
var ( var (
app model.App app model.App
appInstall model.AppInstall appInstall model.AppInstall
info RootInfo info RootInfo
) )
if err := global.DB.Where("name = ?", name).First(&appInstall).Error; err != nil { if err := global.DB.Where("key = ?", key).First(&app).Error; err != nil {
return nil, err
}
if err := global.DB.Where("id = ?", appInstall.AppId).First(&app).Error; err != nil {
return nil, err
}
envMap := make(map[string]interface{})
if err := json.Unmarshal([]byte(appInstall.Env), &envMap); err != nil {
return nil, err
}
password, ok := envMap["PANEL_DB_ROOT_PASSWORD"].(string)
if ok {
info.Password = password
} else {
return nil, errors.New("error password in db")
}
port, ok := envMap["PANEL_APP_PORT_HTTP"].(float64)
if ok {
info.Port = int64(port)
} else {
return nil, errors.New("error port in db")
}
info.ID = appInstall.ID
info.Key = app.Key
info.ContainerName = appInstall.ContainerName
info.Name = appInstall.Name
info.Env = appInstall.Env
info.Param = appInstall.Param
return &info, nil
}
func (u *MysqlRepo) LoadRedisBaseInfo() (*RootInfo, error) {
var (
app model.App
appInstall model.AppInstall
info RootInfo
)
if err := global.DB.Where("key = ?", "redis").First(&app).Error; err != nil {
return nil, err return nil, err
} }
if err := global.DB.Where("app_id = ?", app.ID).First(&appInstall).Error; err != nil { if err := global.DB.Where("app_id = ?", app.ID).First(&appInstall).Error; err != nil {
@ -163,6 +105,7 @@ func (u *MysqlRepo) LoadRedisBaseInfo() (*RootInfo, error) {
info.Name = appInstall.Name info.Name = appInstall.Name
info.Env = appInstall.Env info.Env = appInstall.Env
info.Param = appInstall.Param info.Param = appInstall.Param
info.Version = appInstall.Version
return &info, nil return &info, nil
} }

View File

@ -3,6 +3,12 @@ package service
import ( import (
"context" "context"
"fmt" "fmt"
"io/ioutil"
"os"
"path"
"strconv"
"strings"
"github.com/1Panel-dev/1Panel/backend/app/dto" "github.com/1Panel-dev/1Panel/backend/app/dto"
"github.com/1Panel-dev/1Panel/backend/app/model" "github.com/1Panel-dev/1Panel/backend/app/model"
"github.com/1Panel-dev/1Panel/backend/constant" "github.com/1Panel-dev/1Panel/backend/constant"
@ -12,11 +18,6 @@ import (
"github.com/1Panel-dev/1Panel/backend/utils/docker" "github.com/1Panel-dev/1Panel/backend/utils/docker"
"github.com/1Panel-dev/1Panel/backend/utils/files" "github.com/1Panel-dev/1Panel/backend/utils/files"
"github.com/pkg/errors" "github.com/pkg/errors"
"io/ioutil"
"os"
"path"
"strconv"
"strings"
) )
type AppInstallService struct { type AppInstallService struct {
@ -38,6 +39,18 @@ func (a AppInstallService) Page(req dto.AppInstalledRequest) (int64, []dto.AppIn
return total, installDTOs, nil return total, installDTOs, nil
} }
func (a AppInstallService) CheckExist(key string) (*dto.CheckInstalled, error) {
app, err := appRepo.GetFirst(appRepo.WithKey(key))
if err != nil {
return nil, err
}
appInstall, _ := appInstallRepo.GetFirst(appInstallRepo.WithAppId(app.ID))
if appInstall.ID != 0 {
return &dto.CheckInstalled{Name: appInstall.Name, IsExist: true, Version: appInstall.Version}, nil
}
return &dto.CheckInstalled{IsExist: false}, nil
}
func (a AppInstallService) Search(req dto.AppInstalledRequest) ([]dto.AppInstalled, error) { func (a AppInstallService) Search(req dto.AppInstalledRequest) ([]dto.AppInstalled, error) {
var installs []model.AppInstall var installs []model.AppInstall
var err error var err error
@ -221,7 +234,7 @@ func (a AppInstallService) ChangeAppPort(req dto.PortUpdate) error {
files []string files []string
newFiles []string newFiles []string
) )
app, err := mysqlRepo.LoadBaseInfoByName(req.Name) app, err := mysqlRepo.LoadBaseInfoByKey(req.Key)
if err != nil { if err != nil {
return err return err
} }

View File

@ -216,7 +216,6 @@ func (u *CronjobService) Update(id uint, req dto.CronjobUpdate) error {
upMap["minute"] = req.Minute upMap["minute"] = req.Minute
upMap["website"] = req.Website upMap["website"] = req.Website
upMap["exclusion_rules"] = req.ExclusionRules upMap["exclusion_rules"] = req.ExclusionRules
upMap["database"] = req.Database
upMap["db_name"] = req.DBName upMap["db_name"] = req.DBName
upMap["url"] = req.URL upMap["url"] = req.URL
upMap["source_dir"] = req.SourceDir upMap["source_dir"] = req.SourceDir

View File

@ -78,7 +78,7 @@ func (u *CronjobService) HandleBackup(cronjob *model.Cronjob, startTime time.Tim
if err != nil { if err != nil {
return "", err return "", err
} }
app, err := mysqlRepo.LoadBaseInfoByName(cronjob.Database) app, err := mysqlRepo.LoadBaseInfoByKey("mysql")
if err != nil { if err != nil {
return "", err return "", err
} }
@ -94,8 +94,8 @@ func (u *CronjobService) HandleBackup(cronjob *model.Cronjob, startTime time.Tim
if cronjob.Type == "database" { if cronjob.Type == "database" {
fileName = fmt.Sprintf("db_%s_%s.sql.gz", cronjob.DBName, time.Now().Format("20060102150405")) fileName = fmt.Sprintf("db_%s_%s.sql.gz", cronjob.DBName, time.Now().Format("20060102150405"))
backupDir = fmt.Sprintf("database/%s/%s/%s", app.Key, cronjob.Database, cronjob.DBName) backupDir = fmt.Sprintf("database/mysql/%s/%s", app.Name, cronjob.DBName)
err = backupMysql(backup.Type, baseDir, backupDir, cronjob.Database, cronjob.DBName, fileName) err = backupMysql(backup.Type, baseDir, backupDir, app.Name, cronjob.DBName, fileName)
if err != nil { if err != nil {
return "", err return "", err
} }

View File

@ -31,12 +31,12 @@ import (
type MysqlService struct{} type MysqlService struct{}
type IMysqlService interface { type IMysqlService interface {
SearchWithPage(search dto.SearchDBWithPage) (int64, interface{}, error) SearchWithPage(search dto.PageInfo) (int64, interface{}, error)
ListDBByVersion(name string) ([]string, error) ListDBName() ([]string, error)
SearchBackupsWithPage(search dto.SearchBackupsWithPage) (int64, interface{}, error) SearchBackupsWithPage(search dto.SearchBackupsWithPage) (int64, interface{}, error)
Create(mysqlDto dto.MysqlDBCreate) error Create(mysqlDto dto.MysqlDBCreate) error
ChangeInfo(info dto.ChangeDBInfo) error ChangeInfo(info dto.ChangeDBInfo) error
UpdateVariables(mysqlName string, updatas []dto.MysqlVariablesUpdate) error UpdateVariables(updatas []dto.MysqlVariablesUpdate) error
UpdateConfByFile(info dto.MysqlConfUpdateByFile) error UpdateConfByFile(info dto.MysqlConfUpdateByFile) error
UpFile(mysqlName string, files []*multipart.FileHeader) error UpFile(mysqlName string, files []*multipart.FileHeader) error
@ -45,19 +45,18 @@ type IMysqlService interface {
Backup(db dto.BackupDB) error Backup(db dto.BackupDB) error
Recover(db dto.RecoverDB) error Recover(db dto.RecoverDB) error
Delete(name string, ids []uint) error Delete(ids []uint) error
LoadStatus(name string) (*dto.MysqlStatus, error) LoadStatus() (*dto.MysqlStatus, error)
LoadVariables(vernamesion string) (*dto.MysqlVariables, error) LoadVariables() (*dto.MysqlVariables, error)
LoadRunningVersion() ([]string, error) LoadBaseInfo() (*dto.DBBaseInfo, error)
LoadBaseInfo(name string) (*dto.DBBaseInfo, error)
} }
func NewIMysqlService() IMysqlService { func NewIMysqlService() IMysqlService {
return &MysqlService{} return &MysqlService{}
} }
func (u *MysqlService) SearchWithPage(search dto.SearchDBWithPage) (int64, interface{}, error) { func (u *MysqlService) SearchWithPage(search dto.PageInfo) (int64, interface{}, error) {
total, mysqls, err := mysqlRepo.Page(search.Page, search.PageSize, mysqlRepo.WithByMysqlName(search.MysqlName)) total, mysqls, err := mysqlRepo.Page(search.Page, search.PageSize)
var dtoMysqls []dto.MysqlDBInfo var dtoMysqls []dto.MysqlDBInfo
for _, mysql := range mysqls { for _, mysql := range mysqls {
var item dto.MysqlDBInfo var item dto.MysqlDBInfo
@ -74,11 +73,11 @@ func (u *MysqlService) SearchUpListWithPage(req dto.SearchDBWithPage) (int64, in
list []dto.DatabaseFileRecords list []dto.DatabaseFileRecords
backDatas []dto.DatabaseFileRecords backDatas []dto.DatabaseFileRecords
) )
localDir, appKey, err := loadBackupDirAndKey(req.MysqlName) localDir, err := loadLocalDir()
if err != nil { if err != nil {
return 0, list, nil return 0, list, nil
} }
uploadDir := fmt.Sprintf("%s/database/%s/%s/upload", localDir, appKey, req.MysqlName) uploadDir := fmt.Sprintf("%s/database/mysql/%s/upload", localDir, req.MysqlName)
if _, err := os.Stat(uploadDir); err != nil { if _, err := os.Stat(uploadDir); err != nil {
return 0, list, nil return 0, list, nil
} }
@ -109,11 +108,11 @@ func (u *MysqlService) SearchUpListWithPage(req dto.SearchDBWithPage) (int64, in
} }
func (u *MysqlService) UpFile(mysqlName string, files []*multipart.FileHeader) error { func (u *MysqlService) UpFile(mysqlName string, files []*multipart.FileHeader) error {
localDir, appKey, err := loadBackupDirAndKey(mysqlName) localDir, err := loadLocalDir()
if err != nil { if err != nil {
return err return err
} }
dstDir := fmt.Sprintf("%s/database/%s/%s/upload", localDir, appKey, mysqlName) dstDir := fmt.Sprintf("%s/database/mysql/%s/upload", localDir, mysqlName)
if _, err := os.Stat(dstDir); err != nil && os.IsNotExist(err) { if _, err := os.Stat(dstDir); err != nil && os.IsNotExist(err) {
if err = os.MkdirAll(dstDir, os.ModePerm); err != nil { if err = os.MkdirAll(dstDir, os.ModePerm); err != nil {
if err != nil { if err != nil {
@ -138,7 +137,7 @@ func (u *MysqlService) UpFile(mysqlName string, files []*multipart.FileHeader) e
} }
func (u *MysqlService) RecoverByUpload(req dto.UploadRecover) error { func (u *MysqlService) RecoverByUpload(req dto.UploadRecover) error {
app, err := mysqlRepo.LoadBaseInfoByName(req.MysqlName) app, err := mysqlRepo.LoadBaseInfoByKey("mysql")
if err != nil { if err != nil {
return err return err
} }
@ -150,7 +149,7 @@ func (u *MysqlService) RecoverByUpload(req dto.UploadRecover) error {
if !strings.HasSuffix(req.FileName, ".sql") && !strings.HasSuffix(req.FileName, ".gz") { if !strings.HasSuffix(req.FileName, ".sql") && !strings.HasSuffix(req.FileName, ".gz") {
fileOp := files.NewFileOp() fileOp := files.NewFileOp()
fileNameItem := time.Now().Format("20060102150405") fileNameItem := time.Now().Format("20060102150405")
dstDir := fmt.Sprintf("%s/database/%s/%s/upload/tmp/%s", localDir, app.Key, req.MysqlName, fileNameItem) dstDir := fmt.Sprintf("%s/database/mysql/%s/upload/tmp/%s", localDir, req.MysqlName, fileNameItem)
if _, err := os.Stat(dstDir); err != nil && os.IsNotExist(err) { if _, err := os.Stat(dstDir); err != nil && os.IsNotExist(err) {
if err = os.MkdirAll(dstDir, os.ModePerm); err != nil { if err = os.MkdirAll(dstDir, os.ModePerm); err != nil {
if err != nil { if err != nil {
@ -215,8 +214,8 @@ func (u *MysqlService) RecoverByUpload(req dto.UploadRecover) error {
return nil return nil
} }
func (u *MysqlService) ListDBByVersion(name string) ([]string, error) { func (u *MysqlService) ListDBName() ([]string, error) {
mysqls, err := mysqlRepo.List(mysqlRepo.WithByMysqlName(name)) mysqls, err := mysqlRepo.List()
var dbNames []string var dbNames []string
for _, mysql := range mysqls { for _, mysql := range mysqls {
dbNames = append(dbNames, mysql.Name) dbNames = append(dbNames, mysql.Name)
@ -225,7 +224,7 @@ func (u *MysqlService) ListDBByVersion(name string) ([]string, error) {
} }
func (u *MysqlService) SearchBackupsWithPage(search dto.SearchBackupsWithPage) (int64, interface{}, error) { func (u *MysqlService) SearchBackupsWithPage(search dto.SearchBackupsWithPage) (int64, interface{}, error) {
app, err := mysqlRepo.LoadBaseInfoByName(search.MysqlName) app, err := mysqlRepo.LoadBaseInfoByKey("mysql")
if err != nil { if err != nil {
return 0, nil, err return 0, nil, err
} }
@ -239,19 +238,15 @@ func (u *MysqlService) SearchBackupsWithPage(search dto.SearchBackupsWithPage) (
return NewIBackupService().SearchRecordWithPage(searchDto) return NewIBackupService().SearchRecordWithPage(searchDto)
} }
func (u *MysqlService) LoadRunningVersion() ([]string, error) {
return mysqlRepo.LoadRunningVersion([]string{"Mysql5.7", "Mysql8.0"})
}
func (u *MysqlService) Create(mysqlDto dto.MysqlDBCreate) error { func (u *MysqlService) Create(mysqlDto dto.MysqlDBCreate) error {
if mysqlDto.Username == "root" { if mysqlDto.Username == "root" {
return errors.New("Cannot set root as user name") return errors.New("Cannot set root as user name")
} }
app, err := mysqlRepo.LoadBaseInfoByName(mysqlDto.MysqlName) app, err := mysqlRepo.LoadBaseInfoByKey("mysql")
if err != nil { if err != nil {
return err return err
} }
mysql, _ := mysqlRepo.Get(commonRepo.WithByName(mysqlDto.Name), mysqlRepo.WithByMysqlName(app.Key)) mysql, _ := mysqlRepo.Get(commonRepo.WithByName(mysqlDto.Name))
if mysql.ID != 0 { if mysql.ID != 0 {
return constant.ErrRecordExist return constant.ErrRecordExist
} }
@ -267,12 +262,13 @@ func (u *MysqlService) Create(mysqlDto dto.MysqlDBCreate) error {
return err return 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'", mysqlDto.Name, mysqlDto.Username, tmpPermission)
if app.Key == "mysql5.7" { 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, mysqlDto.Password)
} }
if err := excuteSql(app.ContainerName, app.Password, grantStr); err != nil { if err := excuteSql(app.ContainerName, app.Password, grantStr); err != nil {
return err return err
} }
mysql.MysqlName = app.Name
if err := mysqlRepo.Create(context.TODO(), &mysql); err != nil { if err := mysqlRepo.Create(context.TODO(), &mysql); err != nil {
return err return err
} }
@ -280,11 +276,11 @@ func (u *MysqlService) Create(mysqlDto dto.MysqlDBCreate) error {
} }
func (u *MysqlService) Backup(db dto.BackupDB) error { func (u *MysqlService) Backup(db dto.BackupDB) error {
localDir, appKey, err := loadBackupDirAndKey(db.MysqlName) localDir, err := loadLocalDir()
if err != nil { if err != nil {
return err return err
} }
backupDir := fmt.Sprintf("database/%s/%s/%s", appKey, db.MysqlName, db.DBName) backupDir := fmt.Sprintf("database/mysql/%s/%s", db.MysqlName, db.DBName)
fileName := fmt.Sprintf("%s_%s.sql.gz", db.DBName, time.Now().Format("20060102150405")) fileName := fmt.Sprintf("%s_%s.sql.gz", db.DBName, time.Now().Format("20060102150405"))
if err := backupMysql("LOCAL", localDir, backupDir, db.MysqlName, db.DBName, fileName); err != nil { if err := backupMysql("LOCAL", localDir, backupDir, db.MysqlName, db.DBName, fileName); err != nil {
return err return err
@ -293,7 +289,7 @@ func (u *MysqlService) Backup(db dto.BackupDB) error {
} }
func (u *MysqlService) Recover(db dto.RecoverDB) error { func (u *MysqlService) Recover(db dto.RecoverDB) error {
app, err := mysqlRepo.LoadBaseInfoByName(db.MysqlName) app, err := mysqlRepo.LoadBaseInfoByKey("mysql")
if err != nil { if err != nil {
return err return err
} }
@ -317,8 +313,8 @@ func (u *MysqlService) Recover(db dto.RecoverDB) error {
return nil return nil
} }
func (u *MysqlService) Delete(name string, ids []uint) error { func (u *MysqlService) Delete(ids []uint) error {
app, err := mysqlRepo.LoadBaseInfoByName(name) app, err := mysqlRepo.LoadBaseInfoByKey("mysql")
if err != nil { if err != nil {
return err return err
} }
@ -353,7 +349,7 @@ func (u *MysqlService) ChangeInfo(info dto.ChangeDBInfo) error {
return err return err
} }
} }
app, err := mysqlRepo.LoadBaseInfoByName(info.MysqlName) app, err := mysqlRepo.LoadBaseInfoByKey("mysql")
if err != nil { if err != nil {
return err return err
} }
@ -402,7 +398,7 @@ func (u *MysqlService) ChangeInfo(info dto.ChangeDBInfo) error {
return err return err
} }
grantStr := fmt.Sprintf("grant all privileges on %s.* to '%s'@'%s'", mysql.Name, mysql.Username, info.Value) grantStr := fmt.Sprintf("grant all privileges on %s.* to '%s'@'%s'", mysql.Name, mysql.Username, info.Value)
if app.Key == "mysql5.7" { if app.Version == "5.7.39" {
grantStr = fmt.Sprintf("%s identified by '%s' with grant option;", grantStr, mysql.Password) grantStr = fmt.Sprintf("%s identified by '%s' with grant option;", grantStr, mysql.Password)
} }
if err := excuteSql(app.ContainerName, app.Password, grantStr); err != nil { if err := excuteSql(app.ContainerName, app.Password, grantStr); err != nil {
@ -421,11 +417,11 @@ func (u *MysqlService) ChangeInfo(info dto.ChangeDBInfo) error {
} }
func (u *MysqlService) UpdateConfByFile(info dto.MysqlConfUpdateByFile) error { func (u *MysqlService) UpdateConfByFile(info dto.MysqlConfUpdateByFile) error {
app, err := mysqlRepo.LoadBaseInfoByName(info.MysqlName) app, err := mysqlRepo.LoadBaseInfoByKey("mysql")
if err != nil { if err != nil {
return err return err
} }
path := fmt.Sprintf("%s/%s/%s/conf/my.cnf", constant.AppInstallDir, app.Key, app.Name) path := fmt.Sprintf("%s/mysql/%s/conf/my.cnf", constant.AppInstallDir, app.Name)
file, err := os.OpenFile(path, os.O_WRONLY|os.O_TRUNC, 0640) file, err := os.OpenFile(path, os.O_WRONLY|os.O_TRUNC, 0640)
if err != nil { if err != nil {
return err return err
@ -434,20 +430,20 @@ func (u *MysqlService) UpdateConfByFile(info dto.MysqlConfUpdateByFile) error {
write := bufio.NewWriter(file) write := bufio.NewWriter(file)
_, _ = write.WriteString(info.File) _, _ = write.WriteString(info.File)
write.Flush() write.Flush()
if _, err := compose.Restart(fmt.Sprintf("%s/%s/%s/docker-compose.yml", constant.AppInstallDir, app.Key, app.Name)); err != nil { if _, err := compose.Restart(fmt.Sprintf("%s/mysql/%s/docker-compose.yml", constant.AppInstallDir, app.Name)); err != nil {
return err return err
} }
return nil return nil
} }
func (u *MysqlService) UpdateVariables(mysqlName string, updatas []dto.MysqlVariablesUpdate) error { func (u *MysqlService) UpdateVariables(updatas []dto.MysqlVariablesUpdate) error {
app, err := mysqlRepo.LoadBaseInfoByName(mysqlName) app, err := mysqlRepo.LoadBaseInfoByKey("mysql")
if err != nil { if err != nil {
return err return err
} }
var files []string var files []string
path := fmt.Sprintf("%s/%s/%s/conf/my.cnf", constant.AppInstallDir, app.Key, app.Name) path := fmt.Sprintf("%s/mysql/%s/conf/my.cnf", constant.AppInstallDir, app.Name)
lineBytes, err := ioutil.ReadFile(path) lineBytes, err := ioutil.ReadFile(path)
if err != nil { if err != nil {
return err return err
@ -474,16 +470,16 @@ func (u *MysqlService) UpdateVariables(mysqlName string, updatas []dto.MysqlVari
return err return err
} }
if _, err := compose.Restart(fmt.Sprintf("%s/%s/%s/docker-compose.yml", constant.AppInstallDir, app.Key, app.Name)); err != nil { if _, err := compose.Restart(fmt.Sprintf("%s/mysql/%s/docker-compose.yml", constant.AppInstallDir, app.Name)); err != nil {
return err return err
} }
return nil return nil
} }
func (u *MysqlService) LoadBaseInfo(name string) (*dto.DBBaseInfo, error) { func (u *MysqlService) LoadBaseInfo() (*dto.DBBaseInfo, error) {
var data dto.DBBaseInfo var data dto.DBBaseInfo
app, err := mysqlRepo.LoadBaseInfoByName(name) app, err := mysqlRepo.LoadBaseInfoByKey("mysql")
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -491,7 +487,6 @@ func (u *MysqlService) LoadBaseInfo(name string) (*dto.DBBaseInfo, error) {
data.Name = app.Name data.Name = app.Name
data.Port = int64(app.Port) data.Port = int64(app.Port)
data.Password = app.Password data.Password = app.Password
data.MysqlKey = app.Key
hosts, err := excuteSqlForRows(app.ContainerName, app.Password, "select host from mysql.user where user='root';") hosts, err := excuteSqlForRows(app.ContainerName, app.Password, "select host from mysql.user where user='root';")
if err != nil { if err != nil {
@ -506,8 +501,8 @@ func (u *MysqlService) LoadBaseInfo(name string) (*dto.DBBaseInfo, error) {
return &data, nil return &data, nil
} }
func (u *MysqlService) LoadVariables(name string) (*dto.MysqlVariables, error) { func (u *MysqlService) LoadVariables() (*dto.MysqlVariables, error) {
app, err := mysqlRepo.LoadBaseInfoByName(name) app, err := mysqlRepo.LoadBaseInfoByKey("mysql")
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -524,8 +519,8 @@ func (u *MysqlService) LoadVariables(name string) (*dto.MysqlVariables, error) {
return &info, nil return &info, nil
} }
func (u *MysqlService) LoadStatus(name string) (*dto.MysqlStatus, error) { func (u *MysqlService) LoadStatus() (*dto.MysqlStatus, error) {
app, err := mysqlRepo.LoadBaseInfoByName(name) app, err := mysqlRepo.LoadBaseInfoByKey("mysql")
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -609,7 +604,7 @@ func excuteSql(containerName, password, command string) error {
} }
func backupMysql(backupType, baseDir, backupDir, mysqlName, dbName, fileName string) error { func backupMysql(backupType, baseDir, backupDir, mysqlName, dbName, fileName string) error {
app, err := mysqlRepo.LoadBaseInfoByName(mysqlName) app, err := mysqlRepo.LoadBaseInfoByKey("mysql")
if err != nil { if err != nil {
return err return err
} }
@ -690,15 +685,3 @@ func updateMyCnf(oldFiles []string, group string, param string, value interface{
} }
return newFiles return newFiles
} }
func loadBackupDirAndKey(mysqlName string) (string, string, error) {
app, err := mysqlRepo.LoadBaseInfoByName(mysqlName)
if err != nil {
return "", "", err
}
localDir, err := loadLocalDir()
if err != nil {
return "", "", err
}
return localDir, app.Key, nil
}

View File

@ -37,7 +37,7 @@ func NewIRedisService() IRedisService {
} }
func (u *RedisService) UpdateConf(req dto.RedisConfUpdate) error { func (u *RedisService) UpdateConf(req dto.RedisConfUpdate) error {
redisInfo, err := mysqlRepo.LoadRedisBaseInfo() redisInfo, err := mysqlRepo.LoadBaseInfoByKey("redis")
if err != nil { if err != nil {
return err return err
} }
@ -70,7 +70,7 @@ func (u *RedisService) UpdateConf(req dto.RedisConfUpdate) error {
} }
func (u *RedisService) UpdatePersistenceConf(req dto.RedisConfPersistenceUpdate) error { func (u *RedisService) UpdatePersistenceConf(req dto.RedisConfPersistenceUpdate) error {
redisInfo, err := mysqlRepo.LoadRedisBaseInfo() redisInfo, err := mysqlRepo.LoadBaseInfoByKey("redis")
if err != nil { if err != nil {
return err return err
} }
@ -97,7 +97,7 @@ func (u *RedisService) UpdatePersistenceConf(req dto.RedisConfPersistenceUpdate)
} }
func (u *RedisService) LoadStatus() (*dto.RedisStatus, error) { func (u *RedisService) LoadStatus() (*dto.RedisStatus, error) {
redisInfo, err := mysqlRepo.LoadRedisBaseInfo() redisInfo, err := mysqlRepo.LoadBaseInfoByKey("redis")
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -125,7 +125,7 @@ func (u *RedisService) LoadStatus() (*dto.RedisStatus, error) {
} }
func (u *RedisService) LoadConf() (*dto.RedisConf, error) { func (u *RedisService) LoadConf() (*dto.RedisConf, error) {
redisInfo, err := mysqlRepo.LoadRedisBaseInfo() redisInfo, err := mysqlRepo.LoadBaseInfoByKey("redis")
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -150,7 +150,7 @@ func (u *RedisService) LoadConf() (*dto.RedisConf, error) {
} }
func (u *RedisService) LoadPersistenceConf() (*dto.RedisPersistence, error) { func (u *RedisService) LoadPersistenceConf() (*dto.RedisPersistence, error) {
redisInfo, err := mysqlRepo.LoadRedisBaseInfo() redisInfo, err := mysqlRepo.LoadBaseInfoByKey("redis")
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -169,7 +169,7 @@ func (u *RedisService) LoadPersistenceConf() (*dto.RedisPersistence, error) {
} }
func (u *RedisService) Backup() error { func (u *RedisService) Backup() error {
redisInfo, err := mysqlRepo.LoadRedisBaseInfo() redisInfo, err := mysqlRepo.LoadBaseInfoByKey("redis")
if err != nil { if err != nil {
return err return err
} }
@ -214,7 +214,7 @@ func (u *RedisService) Backup() error {
} }
func (u *RedisService) Recover(req dto.RedisBackupRecover) error { func (u *RedisService) Recover(req dto.RedisBackupRecover) error {
redisInfo, err := mysqlRepo.LoadRedisBaseInfo() redisInfo, err := mysqlRepo.LoadBaseInfoByKey("redis")
if err != nil { if err != nil {
return err return err
} }
@ -254,7 +254,7 @@ func (u *RedisService) SearchBackupListWithPage(req dto.PageInfo) (int64, interf
list []dto.DatabaseFileRecords list []dto.DatabaseFileRecords
backDatas []dto.DatabaseFileRecords backDatas []dto.DatabaseFileRecords
) )
redisInfo, err := mysqlRepo.LoadRedisBaseInfo() redisInfo, err := mysqlRepo.LoadBaseInfoByKey("redis")
if err != nil { if err != nil {
return 0, nil, err return 0, nil, err
} }

View File

@ -5,9 +5,12 @@ import (
"encoding/json" "encoding/json"
"io/ioutil" "io/ioutil"
"os" "os"
"os/exec"
"strings" "strings"
"github.com/1Panel-dev/1Panel/backend/app/dto" "github.com/1Panel-dev/1Panel/backend/app/dto"
"github.com/1Panel-dev/1Panel/backend/constant"
"github.com/pkg/errors"
) )
type DockerService struct{} type DockerService struct{}
@ -32,7 +35,7 @@ type daemonJsonItem struct {
} }
func (u *DockerService) LoadDockerConf() (*dto.DaemonJsonConf, error) { func (u *DockerService) LoadDockerConf() (*dto.DaemonJsonConf, error) {
file, err := ioutil.ReadFile("/opt/1Panel/docker/daemon.json") file, err := ioutil.ReadFile(constant.DaemonJsonDir)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -68,7 +71,7 @@ func (u *DockerService) LoadDockerConf() (*dto.DaemonJsonConf, error) {
} }
func (u *DockerService) UpdateConf(req dto.DaemonJsonConf) error { func (u *DockerService) UpdateConf(req dto.DaemonJsonConf) error {
file, err := ioutil.ReadFile("/opt/1Panel/docker/daemon.json") file, err := ioutil.ReadFile(constant.DaemonJsonDir)
if err != nil { if err != nil {
return err return err
} }
@ -100,9 +103,15 @@ func (u *DockerService) UpdateConf(req dto.DaemonJsonConf) error {
if err != nil { if err != nil {
return err return err
} }
if err := ioutil.WriteFile("/opt/1Panel/docker/daemon.json", newJson, 0640); err != nil { if err := ioutil.WriteFile(constant.DaemonJsonDir, newJson, 0640); err != nil {
return err return err
} }
cmd := exec.Command("systemctl", "restart", "docker")
stdout, err := cmd.CombinedOutput()
if err != nil {
return errors.New(string(stdout))
}
return nil return nil
} }
@ -116,10 +125,10 @@ func (u *DockerService) UpdateConfByFile(req dto.DaemonJsonUpdateByFile) error {
_, _ = write.WriteString(req.File) _, _ = write.WriteString(req.File)
write.Flush() write.Flush()
// cmd := exec.Command("systemctl", "restart", "docker") cmd := exec.Command("systemctl", "restart", "docker")
// stdout, err := cmd.CombinedOutput() stdout, err := cmd.CombinedOutput()
// if err != nil { if err != nil {
// return errors.New(string(stdout)) return errors.New(string(stdout))
// } }
return nil return nil
} }

View File

@ -1,32 +0,0 @@
package service
import (
"encoding/json"
"fmt"
"io/ioutil"
"strings"
"testing"
)
func TestDocker(t *testing.T) {
file, err := ioutil.ReadFile("/opt/1Panel/docker/daemon.json")
if err != nil {
fmt.Println(err)
}
var conf daemonJsonItem
deamonMap := make(map[string]interface{})
if err := json.Unmarshal(file, &deamonMap); err != nil {
fmt.Println(err)
}
arr, err := json.Marshal(deamonMap)
if err != nil {
fmt.Println(err)
}
_ = json.Unmarshal(arr, &conf)
for _, opt := range conf.ExecOpts {
if strings.HasPrefix(opt, "native.cgroupdriver=") {
fmt.Println(strings.ReplaceAll(opt, "native.cgroupdriver=", ""))
}
}
}

View File

@ -14,7 +14,7 @@ const (
ComposeOpRestart = "restart" ComposeOpRestart = "restart"
ComposeOpRemove = "remove" ComposeOpRemove = "remove"
DaemonJsonDir = "/System/Volumes/Data/Users/slooop/.docker/daemon.json" DaemonJsonDir = "/opt/1Panel/docker/config/daemon.json"
TmpDockerBuildDir = "/opt/1Panel/data/docker/build" TmpDockerBuildDir = "/opt/1Panel/data/docker/build"
TmpComposeBuildDir = "/opt/1Panel/data/docker/compose" TmpComposeBuildDir = "/opt/1Panel/data/docker/compose"
) )

View File

@ -21,6 +21,7 @@ func (a *AppRouter) InitAppRouter(Router *gin.RouterGroup) {
appRouter.GET("/detail/:appId/:version", baseApi.GetAppDetail) appRouter.GET("/detail/:appId/:version", baseApi.GetAppDetail)
appRouter.POST("/install", baseApi.InstallApp) appRouter.POST("/install", baseApi.InstallApp)
appRouter.GET("/installed/:appInstallId/versions", baseApi.GetUpdateVersions) appRouter.GET("/installed/:appInstallId/versions", baseApi.GetUpdateVersions)
appRouter.GET("/installed/check/:key", baseApi.CheckAppInstalld)
appRouter.POST("/installed", baseApi.SearchAppInstalled) appRouter.POST("/installed", baseApi.SearchAppInstalled)
appRouter.POST("/installed/op", baseApi.OperateInstalled) appRouter.POST("/installed/op", baseApi.OperateInstalled)
appRouter.POST("/installed/sync", baseApi.SyncInstalled) appRouter.POST("/installed/sync", baseApi.SyncInstalled)

View File

@ -30,14 +30,13 @@ func (s *DatabaseRouter) InitDatabaseRouter(Router *gin.RouterGroup) {
withRecordRouter.POST("/recover", baseApi.RecoverMysql) withRecordRouter.POST("/recover", baseApi.RecoverMysql)
withRecordRouter.POST("/backups/search", baseApi.SearchDBBackups) withRecordRouter.POST("/backups/search", baseApi.SearchDBBackups)
withRecordRouter.POST("/del", baseApi.DeleteMysql) withRecordRouter.POST("/del", baseApi.DeleteMysql)
withRecordRouter.POST("/variables/update/:mysqlName", baseApi.UpdateMysqlVariables) withRecordRouter.POST("/variables/update", baseApi.UpdateMysqlVariables)
withRecordRouter.POST("/conf/update/byfile", baseApi.UpdateMysqlConfByFile) withRecordRouter.POST("/conf/update/byfile", baseApi.UpdateMysqlConfByFile)
cmdRouter.POST("/search", baseApi.SearchMysql) cmdRouter.POST("/search", baseApi.SearchMysql)
cmdRouter.GET("/variables/:name", baseApi.LoadVariables) cmdRouter.GET("/variables", baseApi.LoadVariables)
cmdRouter.GET("/status/:name", baseApi.LoadStatus) cmdRouter.GET("/status", baseApi.LoadStatus)
cmdRouter.GET("/baseinfo/:name", baseApi.LoadBaseinfo) cmdRouter.GET("/baseinfo", baseApi.LoadBaseinfo)
cmdRouter.GET("/versions", baseApi.LoadVersions) cmdRouter.GET("/dbs", baseApi.ListDBName)
cmdRouter.GET("/dbs/:name", baseApi.ListDBNameByVersion)
cmdRouter.GET("/redis/persistence/conf", baseApi.LoadPersistenceConf) cmdRouter.GET("/redis/persistence/conf", baseApi.LoadPersistenceConf)
cmdRouter.GET("/redis/status", baseApi.LoadRedisStatus) cmdRouter.GET("/redis/status", baseApi.LoadRedisStatus)

View File

@ -2,10 +2,10 @@ package qqwry
import ( import (
"encoding/binary" "encoding/binary"
"io/ioutil"
"net" "net"
"strings" "strings"
"github.com/1Panel-dev/1Panel/cmd/server/qqwry"
"golang.org/x/text/encoding/simplifiedchinese" "golang.org/x/text/encoding/simplifiedchinese"
) )
@ -23,10 +23,7 @@ type QQwry struct {
} }
func NewQQwry() (*QQwry, error) { func NewQQwry() (*QQwry, error) {
IpCommonDictionary, err := ioutil.ReadFile("/opt/1Panel/conf/qqwry.dat") IpCommonDictionary := qqwry.QQwryByte
if err != nil {
return nil, err
}
return &QQwry{Data: IpCommonDictionary}, nil return &QQwry{Data: IpCommonDictionary}, nil
} }

View File

@ -0,0 +1,6 @@
package qqwry
import _ "embed"
//go:embed qqwry.dat
var QQwryByte []byte

BIN
cmd/server/qqwry/qqwry.dat Normal file

Binary file not shown.

View File

@ -82,6 +82,12 @@ export namespace App {
app: App; app: App;
} }
export interface CheckInstalled {
name: string;
version: string;
isExist: boolean;
}
export interface AppInstalledOp { export interface AppInstalledOp {
installId: number; installId: number;
operate: string; operate: string;

View File

@ -14,7 +14,6 @@ export namespace Cronjob {
script: string; script: string;
website: string; website: string;
exclusionRules: string; exclusionRules: string;
database: string;
dbName: string; dbName: string;
url: string; url: string;
sourceDir: string; sourceDir: string;
@ -36,7 +35,6 @@ export namespace Cronjob {
script: string; script: string;
website: string; website: string;
exclusionRules: string; exclusionRules: string;
database: string;
dbName: string; dbName: string;
url: string; url: string;
sourceDir: string; sourceDir: string;
@ -55,7 +53,6 @@ export namespace Cronjob {
script: string; script: string;
website: string; website: string;
exclusionRules: string; exclusionRules: string;
database: string;
dbName: string; dbName: string;
url: string; url: string;
sourceDir: string; sourceDir: string;

View File

@ -1,9 +1,6 @@
import { ReqPage } from '.'; import { ReqPage } from '.';
export namespace Database { export namespace Database {
export interface Search extends ReqPage {
mysqlName: string;
}
export interface SearchBackupRecord extends ReqPage { export interface SearchBackupRecord extends ReqPage {
mysqlName: string; mysqlName: string;
dbName: string; dbName: string;
@ -47,7 +44,6 @@ export namespace Database {
} }
export interface MysqlDBCreate { export interface MysqlDBCreate {
name: string; name: string;
mysqlName: string;
format: string; format: string;
username: string; username: string;
password: string; password: string;

View File

@ -30,6 +30,10 @@ export const GetAppInstalled = (info: ReqPage) => {
return http.post<ResPage<App.AppInstalled>>('apps/installed', info); return http.post<ResPage<App.AppInstalled>>('apps/installed', info);
}; };
export const CheckAppInstalled = (key: string) => {
return http.get<App.CheckInstalled>(`apps/installed/check/${key}`);
};
export const SearchAppInstalled = (search: App.AppInstalledSearch) => { export const SearchAppInstalled = (search: App.AppInstalledSearch) => {
return http.post<App.AppInstalled[]>('apps/installed', search); return http.post<App.AppInstalled[]>('apps/installed', search);
}; };

View File

@ -4,14 +4,11 @@ import { Backup } from '../interface/backup';
import { Database } from '../interface/database'; import { Database } from '../interface/database';
import { File } from '@/api/interface/file'; import { File } from '@/api/interface/file';
export const searchMysqlDBs = (params: Database.Search) => { export const searchMysqlDBs = (params: ReqPage) => {
return http.post<ResPage<Database.MysqlDBInfo>>(`/databases/search`, params); return http.post<ResPage<Database.MysqlDBInfo>>(`/databases/search`, params);
}; };
export const listDBByVersion = (params: string) => {
return http.get(`/databases/dbs/${params}`);
};
export const searchUpList = (params: Database.Search) => { export const searchUpList = (params: ReqPage) => {
return http.post<ResPage<Database.FileRecord>>(`/databases/uplist`, params); return http.post<ResPage<Database.FileRecord>>(`/databases/uplist`, params);
}; };
export const uploadFile = (mysqlName: string, params: FormData) => { export const uploadFile = (mysqlName: string, params: FormData) => {
@ -36,8 +33,8 @@ export const addMysqlDB = (params: Database.MysqlDBCreate) => {
export const updateMysqlDBInfo = (params: Database.ChangeInfo) => { export const updateMysqlDBInfo = (params: Database.ChangeInfo) => {
return http.put(`/databases/${params.id}`, params); return http.put(`/databases/${params.id}`, params);
}; };
export const updateMysqlVariables = (mysqlName: string, params: Array<Database.VariablesUpdate>) => { export const updateMysqlVariables = (params: Array<Database.VariablesUpdate>) => {
return http.post(`/databases/variables/update/${mysqlName}`, params); return http.post(`/databases/variables/update`, params);
}; };
export const updateMysqlConfByFile = (params: Database.MysqlConfUpdateByFile) => { export const updateMysqlConfByFile = (params: Database.MysqlConfUpdateByFile) => {
return http.post(`/databases/conf/update/byfile`, params); return http.post(`/databases/conf/update/byfile`, params);
@ -46,17 +43,17 @@ export const deleteMysqlDB = (params: { ids: number[] }) => {
return http.post(`/databases/del`, params); return http.post(`/databases/del`, params);
}; };
export const loadMysqlBaseInfo = (param: string) => { export const loadMysqlBaseInfo = () => {
return http.get<Database.BaseInfo>(`/databases/baseinfo/${param}`); return http.get<Database.BaseInfo>(`/databases/baseinfo`);
}; };
export const loadMysqlVariables = (param: string) => { export const loadMysqlVariables = () => {
return http.get<Database.MysqlVariables>(`/databases/variables/${param}`); return http.get<Database.MysqlVariables>(`/databases/variables`);
}; };
export const loadMysqlStatus = (param: string) => { export const loadMysqlStatus = () => {
return http.get<Database.MysqlStatus>(`/databases/status/${param}`); return http.get<Database.MysqlStatus>(`/databases/status`);
}; };
export const loadVersions = () => { export const loadDBNames = () => {
return http.get(`/databases/versions`); return http.get<Array<string>>(`/databases/dbs`);
}; };
// redis // redis

View File

@ -0,0 +1,53 @@
<template>
<el-dialog v-model="codeVisiable" :destroy-on-close="true" width="70%">
<template #header>
<div class="card-header">
<span>{{ header }}</span>
</div>
</template>
<codemirror
ref="mymirror"
:autofocus="true"
placeholder="None data"
:indent-with-tab="true"
:tabSize="4"
style="max-height: 500px"
:lineWrapping="true"
:matchBrackets="true"
theme="cobalt"
:styleActiveLine="true"
:extensions="extensions"
v-model="detailInfo"
:readOnly="true"
/>
</el-dialog>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
import { Codemirror } from 'vue-codemirror';
import { javascript } from '@codemirror/lang-javascript';
import { oneDark } from '@codemirror/theme-one-dark';
const mymirror = ref();
const extensions = [javascript(), oneDark];
const header = ref();
const detailInfo = ref();
const codeVisiable = ref(false);
interface DialogProps {
header: string;
detailInfo: string;
}
const acceptParams = (props: DialogProps): void => {
header.value = props.header;
detailInfo.value = props.detailInfo;
codeVisiable.value = true;
};
defineExpose({
acceptParams,
});
</script>

View File

@ -157,6 +157,8 @@ export default {
logout: 'Logout', logout: 'Logout',
}, },
database: { database: {
noMysql: 'No {0} database is detected, please go to App Store and click Install!',
goInstall: 'Go to install',
source: 'Source', source: 'Source',
backup: 'Database backup', backup: 'Database backup',
permission: 'Permission', permission: 'Permission',
@ -637,7 +639,7 @@ export default {
issue: 'Feedback', issue: 'Feedback',
chat: 'Community Discussion', chat: 'Community Discussion',
star: 'Star', star: 'Star',
description: 'A modern Linux panel tool', description: '1Panel, A modern open source Linux panel.',
}, },
app: { app: {
installed: 'installed', installed: 'installed',

View File

@ -157,6 +157,8 @@ export default {
logout: '退出登录', logout: '退出登录',
}, },
database: { database: {
noMysql: '当前未检测到 {0} 数据库请进入应用商店点击安装',
goInstall: '去安装',
source: '来源', source: '来源',
backup: '备份数据库', backup: '备份数据库',
permission: '权限', permission: '权限',
@ -649,7 +651,7 @@ export default {
issue: '问题反馈', issue: '问题反馈',
chat: '参与讨论', chat: '参与讨论',
star: '点亮 Star', star: '点亮 Star',
description: '一个现代化的 Linux 面板工具', description: '1Panel一款现代化的开源 Linux 面板',
}, },
app: { app: {
app: '应用', app: '应用',

View File

@ -1,7 +1,7 @@
import { Layout } from '@/routers/constant'; import { Layout } from '@/routers/constant';
const logsRouter = { const logsRouter = {
sort: 10, sort: 7,
path: '/logs', path: '/logs',
component: Layout, component: Layout,
redirect: '/logs', redirect: '/logs',
@ -12,17 +12,17 @@ const logsRouter = {
children: [ children: [
{ {
path: '', path: '',
name: 'LoginLog', name: 'OperationLog',
component: () => import('@/views/log/login/index.vue'), component: () => import('@/views/log/operation/index.vue'),
hidden: true, hidden: true,
meta: { meta: {
activeMenu: '/logs', activeMenu: '/logs',
}, },
}, },
{ {
path: 'operation', path: 'login',
name: 'OperationLog', name: 'LoginLog',
component: () => import('@/views/log/operation/index.vue'), component: () => import('@/views/log/login/index.vue'),
hidden: true, hidden: true,
meta: { meta: {
activeMenu: '/logs', activeMenu: '/logs',

View File

@ -1,7 +1,7 @@
import { Layout } from '@/routers/constant'; import { Layout } from '@/routers/constant';
const settingRouter = { const settingRouter = {
sort: 7, sort: 8,
path: '/settings', path: '/settings',
component: Layout, component: Layout,
redirect: '/setting', redirect: '/setting',

View File

@ -50,33 +50,7 @@
</ComplexTable> </ComplexTable>
</el-card> </el-card>
<el-dialog v-model="detailVisiable" :destroy-on-close="true" :close-on-click-modal="false" width="70%"> <CodemirrorDialog ref="codemirror" />
<template #header>
<div class="card-header">
<span>{{ $t('commons.button.view') }}</span>
</div>
</template>
<codemirror
:autofocus="true"
placeholder="None data"
:indent-with-tab="true"
:tabSize="4"
style="max-height: 500px"
:lineWrapping="true"
:matchBrackets="true"
theme="cobalt"
:styleActiveLine="true"
:extensions="extensions"
v-model="detailInfo"
:readOnly="true"
/>
<template #footer>
<span class="dialog-footer">
<el-button @click="detailVisiable = false">{{ $t('commons.button.cancel') }}</el-button>
</span>
</template>
</el-dialog>
<CreateDialog @search="search" ref="dialogCreateRef" /> <CreateDialog @search="search" ref="dialogCreateRef" />
</div> </div>
</template> </template>
@ -84,10 +58,8 @@
<script lang="ts" setup> <script lang="ts" setup>
import ComplexTable from '@/components/complex-table/index.vue'; import ComplexTable from '@/components/complex-table/index.vue';
import CreateDialog from '@/views/container/network/create/index.vue'; import CreateDialog from '@/views/container/network/create/index.vue';
import CodemirrorDialog from '@/components/codemirror-dialog/codemirror.vue';
import Submenu from '@/views/container/index.vue'; import Submenu from '@/views/container/index.vue';
import { Codemirror } from 'vue-codemirror';
import { javascript } from '@codemirror/lang-javascript';
import { oneDark } from '@codemirror/theme-one-dark';
import { reactive, onMounted, ref } from 'vue'; import { reactive, onMounted, ref } from 'vue';
import { dateFromat } from '@/utils/util'; import { dateFromat } from '@/utils/util';
import { deleteNetwork, searchNetwork, inspect } from '@/api/modules/container'; import { deleteNetwork, searchNetwork, inspect } from '@/api/modules/container';
@ -95,9 +67,8 @@ import { Container } from '@/api/interface/container';
import i18n from '@/lang'; import i18n from '@/lang';
import { useDeleteData } from '@/hooks/use-delete-data'; import { useDeleteData } from '@/hooks/use-delete-data';
const detailVisiable = ref<boolean>(false);
const detailInfo = ref(); const detailInfo = ref();
const extensions = [javascript(), oneDark]; const codemirror = ref();
const data = ref(); const data = ref();
const selects = ref<any>([]); const selects = ref<any>([]);
@ -145,7 +116,11 @@ const batchDelete = async (row: Container.NetworkInfo | null) => {
const onInspect = async (id: string) => { const onInspect = async (id: string) => {
const res = await inspect({ id: id, type: 'network' }); const res = await inspect({ id: id, type: 'network' });
detailInfo.value = JSON.stringify(JSON.parse(res.data), null, 2); detailInfo.value = JSON.stringify(JSON.parse(res.data), null, 2);
detailVisiable.value = true; let param = {
header: i18n.global.t('commons.button.view'),
detailInfo: detailInfo.value,
};
codemirror.value!.acceptParams(param);
}; };
const buttons = [ const buttons = [

View File

@ -2,11 +2,11 @@
<div> <div>
<Submenu activeName="setting" /> <Submenu activeName="setting" />
<el-card style="margin-top: 20px"> <el-card style="margin-top: 20px">
<el-radio-group v-model="confShowType"> <el-radio-group v-model="confShowType" @change="changeMode">
<el-radio-button label="base">{{ $t('database.baseConf') }}</el-radio-button> <el-radio-button label="base">{{ $t('database.baseConf') }}</el-radio-button>
<el-radio-button label="all">{{ $t('database.allConf') }}</el-radio-button> <el-radio-button label="all">{{ $t('database.allConf') }}</el-radio-button>
</el-radio-group> </el-radio-group>
<el-form v-if="confShowType === 'base'" :model="form" ref="formRef" :rules="rules" label-width="120px"> <el-form v-if="confShowType === 'base'" :model="form" ref="formRef" label-width="120px">
<el-row style="margin-top: 20px"> <el-row style="margin-top: 20px">
<el-col :span="1"><br /></el-col> <el-col :span="1"><br /></el-col>
<el-col :span="10"> <el-col :span="10">
@ -27,7 +27,7 @@
v-model="form.registries" v-model="form.registries"
/> />
</el-form-item> </el-form-item>
<el-form-item label="bip" prop="bip"> <el-form-item label="bip">
<el-input clearable v-model="form.bip" /> <el-input clearable v-model="form.bip" />
</el-form-item> </el-form-item>
<el-form-item label="live-restore" prop="liveRestore"> <el-form-item label="live-restore" prop="liveRestore">
@ -84,7 +84,6 @@ import { LoadFile } from '@/api/modules/files';
import ConfirmDialog from '@/components/confirm-dialog/index.vue'; import ConfirmDialog from '@/components/confirm-dialog/index.vue';
import i18n from '@/lang'; import i18n from '@/lang';
import { loadDaemonJson, updateDaemonJson, updateDaemonJsonByfile } from '@/api/modules/container'; import { loadDaemonJson, updateDaemonJson, updateDaemonJsonByfile } from '@/api/modules/container';
import { Rules } from '@/global/form-rules';
const extensions = [javascript(), oneDark]; const extensions = [javascript(), oneDark];
const confShowType = ref('base'); const confShowType = ref('base');
@ -98,10 +97,6 @@ const form = reactive({
cgroupDriver: '', cgroupDriver: '',
}); });
const rules = reactive({
bip: [Rules.requiredInput],
});
const formRef = ref<FormInstance>(); const formRef = ref<FormInstance>();
const dockerConf = ref(); const dockerConf = ref();
const confirmDialogRef = ref(); const confirmDialogRef = ref();
@ -132,7 +127,7 @@ const onSubmitSave = async () => {
if (confShowType.value === 'all') { if (confShowType.value === 'all') {
let param = { let param = {
file: dockerConf.value, file: dockerConf.value,
path: '/opt/1Panel/docker/daemon.json', path: '/opt/1Panel/docker/config/daemon.json',
}; };
await updateDaemonJsonByfile(param); await updateDaemonJsonByfile(param);
ElMessage.success(i18n.global.t('commons.msg.operationSuccess')); ElMessage.success(i18n.global.t('commons.msg.operationSuccess'));
@ -151,10 +146,18 @@ const onSubmitSave = async () => {
}; };
const loadMysqlConf = async () => { const loadMysqlConf = async () => {
const res = await LoadFile({ path: '/opt/1Panel/docker/daemon.json' }); const res = await LoadFile({ path: '/opt/1Panel/docker/config/daemon.json' });
dockerConf.value = res.data; dockerConf.value = res.data;
}; };
const changeMode = async () => {
if (confShowType.value === 'all') {
loadMysqlConf();
} else {
search();
}
};
const search = async () => { const search = async () => {
const res = await loadDaemonJson(); const res = await loadDaemonJson();
form.bip = res.data.bip; form.bip = res.data.bip;
@ -167,6 +170,5 @@ const search = async () => {
onMounted(() => { onMounted(() => {
search(); search();
loadMysqlConf();
}); });
</script> </script>

View File

@ -34,33 +34,7 @@
</ComplexTable> </ComplexTable>
</el-card> </el-card>
<el-dialog v-model="detailVisiable" :destroy-on-close="true" :close-on-click-modal="false" width="70%"> <CodemirrorDialog ref="codemirror" />
<template #header>
<div class="card-header">
<span>{{ $t('commons.button.view') }}</span>
</div>
</template>
<codemirror
:autofocus="true"
placeholder="None data"
:indent-with-tab="true"
:tabSize="4"
style="max-height: 500px"
:lineWrapping="true"
:matchBrackets="true"
theme="cobalt"
:styleActiveLine="true"
:extensions="extensions"
v-model="detailInfo"
:readOnly="true"
/>
<template #footer>
<span class="dialog-footer">
<el-button @click="detailVisiable = false">{{ $t('commons.button.cancel') }}</el-button>
</span>
</template>
</el-dialog>
<CreateDialog @search="search" ref="dialogCreateRef" /> <CreateDialog @search="search" ref="dialogCreateRef" />
</div> </div>
</template> </template>
@ -69,9 +43,7 @@
import ComplexTable from '@/components/complex-table/index.vue'; import ComplexTable from '@/components/complex-table/index.vue';
import CreateDialog from '@/views/container/volume/create/index.vue'; import CreateDialog from '@/views/container/volume/create/index.vue';
import Submenu from '@/views/container/index.vue'; import Submenu from '@/views/container/index.vue';
import { Codemirror } from 'vue-codemirror'; import CodemirrorDialog from '@/components/codemirror-dialog/codemirror.vue';
import { javascript } from '@codemirror/lang-javascript';
import { oneDark } from '@codemirror/theme-one-dark';
import { reactive, onMounted, ref } from 'vue'; import { reactive, onMounted, ref } from 'vue';
import { dateFromat } from '@/utils/util'; import { dateFromat } from '@/utils/util';
import { deleteVolume, searchVolume, inspect } from '@/api/modules/container'; import { deleteVolume, searchVolume, inspect } from '@/api/modules/container';
@ -79,9 +51,8 @@ import { Container } from '@/api/interface/container';
import i18n from '@/lang'; import i18n from '@/lang';
import { useDeleteData } from '@/hooks/use-delete-data'; import { useDeleteData } from '@/hooks/use-delete-data';
const detailVisiable = ref<boolean>(false);
const detailInfo = ref(); const detailInfo = ref();
const extensions = [javascript(), oneDark]; const codemirror = ref();
const data = ref(); const data = ref();
const selects = ref<any>([]); const selects = ref<any>([]);
@ -116,7 +87,11 @@ const search = async () => {
const onInspect = async (id: string) => { const onInspect = async (id: string) => {
const res = await inspect({ id: id, type: 'volume' }); const res = await inspect({ id: id, type: 'volume' });
detailInfo.value = JSON.stringify(JSON.parse(res.data), null, 2); detailInfo.value = JSON.stringify(JSON.parse(res.data), null, 2);
detailVisiable.value = true; let param = {
header: i18n.global.t('commons.button.view'),
detailInfo: detailInfo.value,
};
codemirror.value!.acceptParams(param);
}; };
const batchDelete = async (row: Container.VolumeInfo | null) => { const batchDelete = async (row: Container.VolumeInfo | null) => {

View File

@ -12,7 +12,11 @@
style="width: 100%" style="width: 100%"
v-model="dialogData.rowData!.type" v-model="dialogData.rowData!.type"
> >
<el-option v-for="item in typeOptions" :key="item.label" :value="item.value" :label="item.label" /> <el-option value="shell" :label="$t('cronjob.shell')" />
<el-option value="website" :label="$t('cronjob.website')" />
<el-option value="database" :label="$t('cronjob.database')" />
<el-option value="directory" :label="$t('cronjob.directory')" />
<el-option value="curl" :label="$t('cronjob.curl')" />
</el-select> </el-select>
</el-form-item> </el-form-item>
@ -76,14 +80,9 @@
</el-form-item> </el-form-item>
<div v-if="dialogData.rowData!.type === 'database'"> <div v-if="dialogData.rowData!.type === 'database'">
<el-form-item :label="$t('cronjob.database')" prop="database">
<el-radio-group v-model="dialogData.rowData!.database" @change="changeDBVersion" class="ml-4">
<el-radio v-for="item in mysqlVersionOptions" :key="item" :label="item" :value="item" />
</el-radio-group>
</el-form-item>
<el-form-item :label="$t('cronjob.database')" prop="dbName"> <el-form-item :label="$t('cronjob.database')" prop="dbName">
<el-select style="width: 100%" clearable v-model="dialogData.rowData!.dbName"> <el-select style="width: 100%" clearable v-model="dialogData.rowData!.dbName">
<el-option v-for="item in dbOptions" :key="item" :label="item" :value="item" /> <el-option v-for="item in mysqlInfo.dbNames" :key="item" :label="item" :value="item" />
</el-select> </el-select>
</el-form-item> </el-form-item>
</div> </div>
@ -170,7 +169,8 @@ import i18n from '@/lang';
import { ElForm, ElMessage } from 'element-plus'; import { ElForm, ElMessage } from 'element-plus';
import { Cronjob } from '@/api/interface/cronjob'; import { Cronjob } from '@/api/interface/cronjob';
import { addCronjob, editCronjob } from '@/api/modules/cronjob'; import { addCronjob, editCronjob } from '@/api/modules/cronjob';
import { listDBByVersion, loadVersions } from '@/api/modules/database'; import { loadDBNames } from '@/api/modules/database';
import { CheckAppInstalled } from '@/api/modules/app';
interface DialogProps { interface DialogProps {
title: string; title: string;
@ -186,12 +186,10 @@ const acceptParams = (params: DialogProps): void => {
dialogData.value = params; dialogData.value = params;
title.value = i18n.global.t('commons.button.' + dialogData.value.title); title.value = i18n.global.t('commons.button.' + dialogData.value.title);
cronjobVisiable.value = true; cronjobVisiable.value = true;
loadRunningOptions(); checkMysqlInstalled();
loadBackups(); loadBackups();
}; };
const mysqlVersionOptions = ref();
const dbOptions = ref();
const localDirID = ref(); const localDirID = ref();
const websiteOptions = ref([ const websiteOptions = ref([
@ -203,6 +201,13 @@ const backupOptions = ref();
const emit = defineEmits<{ (e: 'search'): void }>(); const emit = defineEmits<{ (e: 'search'): void }>();
const mysqlInfo = reactive({
isExist: false,
name: '',
version: '',
dbNames: [] as Array<string>,
});
const varifySpec = (rule: any, value: any, callback: any) => { const varifySpec = (rule: any, value: any, callback: any) => {
switch (dialogData.value.rowData!.specType) { switch (dialogData.value.rowData!.specType) {
case 'perMonth': case 'perMonth':
@ -247,13 +252,6 @@ const varifySpec = (rule: any, value: any, callback: any) => {
} }
callback(); callback();
}; };
const typeOptions = [
{ label: i18n.global.t('cronjob.shell'), value: 'shell' },
{ label: i18n.global.t('cronjob.website'), value: 'website' },
{ label: i18n.global.t('cronjob.database'), value: 'database' },
{ label: i18n.global.t('cronjob.directory'), value: 'directory' },
{ label: i18n.global.t('cronjob.curl') + ' URL', value: 'curl' },
];
const specOptions = [ const specOptions = [
{ label: i18n.global.t('cronjob.perMonth'), value: 'perMonth' }, { label: i18n.global.t('cronjob.perMonth'), value: 'perMonth' },
@ -287,7 +285,6 @@ const rules = reactive({
script: [Rules.requiredInput], script: [Rules.requiredInput],
website: [Rules.requiredSelect], website: [Rules.requiredSelect],
database: [Rules.requiredSelect],
dbName: [Rules.requiredSelect], dbName: [Rules.requiredSelect],
url: [Rules.requiredInput], url: [Rules.requiredInput],
sourceDir: [Rules.requiredSelect], sourceDir: [Rules.requiredSelect],
@ -313,20 +310,14 @@ const loadBackups = async () => {
} }
}; };
const loadRunningOptions = async () => { const checkMysqlInstalled = async () => {
const res = await loadVersions(); const res = await CheckAppInstalled('mysql');
mysqlVersionOptions.value = res.data; mysqlInfo.isExist = res.data.isExist;
if (mysqlVersionOptions.value.length != 0) { mysqlInfo.name = res.data.name;
dialogData.value.rowData!.database = mysqlVersionOptions.value[0]; mysqlInfo.version = res.data.version;
changeDBVersion(); if (mysqlInfo.isExist) {
} const data = await loadDBNames();
}; mysqlInfo.dbNames = data.data;
const changeDBVersion = async () => {
dialogData.value.rowData!.dbName = '';
const res = await listDBByVersion(dialogData.value.rowData!.database);
dbOptions.value = res.data;
if (dbOptions.value.length != 0) {
dialogData.value.rowData!.dbName = dbOptions.value[0];
} }
}; };

View File

@ -114,7 +114,7 @@
</el-col> </el-col>
<el-col :span="8" v-if="dialogData.rowData!.type === 'database'"> <el-col :span="8" v-if="dialogData.rowData!.type === 'database'">
<el-form-item :label="$t('cronjob.database')"> <el-form-item :label="$t('cronjob.database')">
{{ dialogData.rowData!.database }} {{ dialogData.rowData!.dbName }}
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="8" v-if="dialogData.rowData!.type === 'directory'"> <el-col :span="8" v-if="dialogData.rowData!.type === 'directory'">

View File

@ -1,86 +1,77 @@
<template> <template>
<div> <div>
<Submenu activeName="mysql" /> <Submenu activeName="mysql" />
<el-dropdown size="default" split-button style="margin-top: 20px; margin-bottom: 5px"> <div v-if="!mysqlInfo.isExist" style="margin-top: 20px">
{{ mysqlName }} <el-alert :closable="false" :title="$t('database.noMysql', ['Mysql'])" type="info">
<template #dropdown> <el-link icon="Position" @click="goRouter('/apps')" type="primary">
<el-dropdown-menu v-model="mysqlName"> {{ $t('database.goInstall') }}
<el-dropdown-item v-for="item in mysqlVersions" :key="item" @click="onChangeVersion(item)"> </el-link>
{{ item }} </el-alert>
</el-dropdown-item> </div>
</el-dropdown-menu> <div v-else>
</template> <el-button v-if="!isOnSetting" style="margin-top: 20px" size="default" icon="Setting" @click="onSetting">
</el-dropdown> {{ $t('database.setting') }}
<el-button </el-button>
v-if="!isOnSetting" <el-button v-if="isOnSetting" style="margin-top: 20px" size="default" icon="Back" @click="onBacklist">
style="margin-top: 20px; margin-left: 10px" {{ $t('database.backList') }}
size="default" </el-button>
icon="Setting"
@click="onSetting"
>
{{ $t('database.setting') }}
</el-button>
<el-button
v-if="isOnSetting"
style="margin-top: 20px; margin-left: 10px"
size="default"
icon="Back"
@click="onBacklist"
>
{{ $t('database.backList') }}
</el-button>
<Setting ref="settingRef"></Setting> <Setting ref="settingRef"></Setting>
<el-card v-if="!isOnSetting"> <el-card v-if="!isOnSetting" style="margin-top: 5px">
<ComplexTable :pagination-config="paginationConfig" v-model:selects="selects" @search="search" :data="data"> <ComplexTable
<template #toolbar> :pagination-config="paginationConfig"
<el-button type="primary" @click="onOpenDialog()">{{ $t('commons.button.create') }}</el-button> v-model:selects="selects"
<el-button>phpMyAdmin</el-button> @search="search"
<el-button type="danger" plain :disabled="selects.length === 0" @click="onBatchDelete(null)"> :data="data"
{{ $t('commons.button.delete') }} >
</el-button> <template #toolbar>
</template> <el-button type="primary" @click="onOpenDialog()">{{ $t('commons.button.create') }}</el-button>
<el-table-column type="selection" fix /> <el-button>phpMyAdmin</el-button>
<el-table-column :label="$t('commons.table.name')" prop="name" /> <el-button type="danger" plain :disabled="selects.length === 0" @click="onBatchDelete(null)">
<el-table-column :label="$t('auth.username')" prop="username" /> {{ $t('commons.button.delete') }}
<el-table-column :label="$t('auth.password')" prop="password"> </el-button>
<template #default="{ row }">
<div v-if="!row.showPassword">
<span style="float: left">***********</span>
<div style="margin-top: 2px; cursor: pointer">
<el-icon style="margin-left: 5px" @click="row.showPassword = true" :size="16">
<View />
</el-icon>
</div>
</div>
<div v-else>
<span style="float: left">{{ row.password }}</span>
<div style="margin-top: 4px; cursor: pointer">
<el-icon style="margin-left: 5px" @click="row.showPassword = false" :size="16">
<Hide />
</el-icon>
</div>
</div>
</template> </template>
</el-table-column> <el-table-column type="selection" fix />
<el-table-column :label="$t('commons.table.description')" prop="description" /> <el-table-column :label="$t('commons.table.name')" prop="name" />
<el-table-column <el-table-column :label="$t('auth.username')" prop="username" />
prop="createdAt" <el-table-column :label="$t('auth.password')" prop="password">
:label="$t('commons.table.date')" <template #default="{ row }">
:formatter="dateFromat" <div v-if="!row.showPassword">
show-overflow-tooltip <span style="float: left">***********</span>
/> <div style="margin-top: 2px; cursor: pointer">
<fu-table-operations <el-icon style="margin-left: 5px" @click="row.showPassword = true" :size="16">
width="300px" <View />
:buttons="buttons" </el-icon>
:ellipsis="10" </div>
:label="$t('commons.table.operate')" </div>
fix <div v-else>
/> <span style="float: left">{{ row.password }}</span>
</ComplexTable> <div style="margin-top: 4px; cursor: pointer">
</el-card> <el-icon style="margin-left: 5px" @click="row.showPassword = false" :size="16">
<Hide />
</el-icon>
</div>
</div>
</template>
</el-table-column>
<el-table-column :label="$t('commons.table.description')" prop="description" />
<el-table-column
prop="createdAt"
:label="$t('commons.table.date')"
:formatter="dateFromat"
show-overflow-tooltip
/>
<fu-table-operations
width="300px"
:buttons="buttons"
:ellipsis="10"
:label="$t('commons.table.operate')"
fix
/>
</ComplexTable>
</el-card>
</div>
<el-dialog v-model="changeVisiable" :destroy-on-close="true" width="30%"> <el-dialog v-model="changeVisiable" :destroy-on-close="true" width="30%">
<template #header> <template #header>
<div class="card-header"> <div class="card-header">
@ -140,16 +131,22 @@ import Setting from '@/views/database/mysql/setting/index.vue';
import Submenu from '@/views/database/index.vue'; import Submenu from '@/views/database/index.vue';
import { dateFromat } from '@/utils/util'; import { dateFromat } from '@/utils/util';
import { onMounted, reactive, ref } from 'vue'; import { onMounted, reactive, ref } from 'vue';
import { deleteMysqlDB, loadVersions, searchMysqlDBs, updateMysqlDBInfo } from '@/api/modules/database'; import { deleteMysqlDB, searchMysqlDBs, updateMysqlDBInfo } from '@/api/modules/database';
import i18n from '@/lang'; import i18n from '@/lang';
import { useDeleteData } from '@/hooks/use-delete-data'; import { useDeleteData } from '@/hooks/use-delete-data';
import { ElForm, ElMessage } from 'element-plus'; import { ElForm, ElMessage } from 'element-plus';
import { Database } from '@/api/interface/database'; import { Database } from '@/api/interface/database';
import { Rules } from '@/global/form-rules'; import { Rules } from '@/global/form-rules';
import { CheckAppInstalled } from '@/api/modules/app';
import { useRouter } from 'vue-router';
const router = useRouter();
const selects = ref<any>([]); const selects = ref<any>([]);
const mysqlVersions = ref(); const mysqlInfo = reactive({
const mysqlName = ref<string>('5.7'); name: '',
version: '',
isExist: false,
});
const isOnSetting = ref<boolean>(); const isOnSetting = ref<boolean>();
const data = ref(); const data = ref();
@ -162,7 +159,7 @@ const paginationConfig = reactive({
const dialogRef = ref(); const dialogRef = ref();
const onOpenDialog = async () => { const onOpenDialog = async () => {
let params = { let params = {
mysqlName: mysqlName.value, mysqlName: mysqlInfo.name,
}; };
dialogRef.value!.acceptParams(params); dialogRef.value!.acceptParams(params);
}; };
@ -170,7 +167,7 @@ const onOpenDialog = async () => {
const dialogBackupRef = ref(); const dialogBackupRef = ref();
const onOpenBackupDialog = async (dbName: string) => { const onOpenBackupDialog = async (dbName: string) => {
let params = { let params = {
mysqlName: mysqlName.value, mysqlName: mysqlInfo.name,
dbName: dbName, dbName: dbName,
}; };
dialogBackupRef.value!.acceptParams(params); dialogBackupRef.value!.acceptParams(params);
@ -182,7 +179,7 @@ const settingRef = ref();
const onSetting = async () => { const onSetting = async () => {
isOnSetting.value = true; isOnSetting.value = true;
let params = { let params = {
mysqlName: mysqlName.value, mysqlName: mysqlInfo.name,
}; };
settingRef.value!.acceptParams(params); settingRef.value!.acceptParams(params);
}; };
@ -210,7 +207,7 @@ const submitChangeInfo = async (formEl: FormInstance | undefined) => {
formEl.validate(async (valid) => { formEl.validate(async (valid) => {
if (!valid) return; if (!valid) return;
changeForm.value = changeForm.operation === 'password' ? changeForm.password : changeForm.privilege; changeForm.value = changeForm.operation === 'password' ? changeForm.password : changeForm.privilege;
changeForm.mysqlName = mysqlName.value; changeForm.mysqlName = mysqlInfo.name;
await updateMysqlDBInfo(changeForm); await updateMysqlDBInfo(changeForm);
ElMessage.success(i18n.global.t('commons.msg.operationSuccess')); ElMessage.success(i18n.global.t('commons.msg.operationSuccess'));
search(); search();
@ -218,31 +215,24 @@ const submitChangeInfo = async (formEl: FormInstance | undefined) => {
}); });
}; };
const loadRunningOptions = async () => { const checkMysqlInstalled = async () => {
const res = await loadVersions(); const res = await CheckAppInstalled('mysql');
mysqlVersions.value = res.data; mysqlInfo.isExist = res.data.isExist;
if (mysqlVersions.value.length != 0) { mysqlInfo.name = res.data.name;
mysqlName.value = mysqlVersions.value[0]; mysqlInfo.version = res.data.version;
if (mysqlInfo.isExist) {
search(); search();
} }
}; };
const onChangeVersion = async (val: string) => { const goRouter = async (path: string) => {
mysqlName.value = val; router.push({ path: path });
search();
if (isOnSetting.value) {
let params = {
mysqlName: mysqlName.value,
};
settingRef.value!.acceptParams(params);
}
}; };
const search = async () => { const search = async () => {
let params = { let params = {
page: paginationConfig.currentPage, page: paginationConfig.currentPage,
pageSize: paginationConfig.pageSize, pageSize: paginationConfig.pageSize,
mysqlName: mysqlName.value,
}; };
const res = await searchMysqlDBs(params); const res = await searchMysqlDBs(params);
data.value = res.data.items || []; data.value = res.data.items || [];
@ -295,7 +285,7 @@ const buttons = [
label: i18n.global.t('database.loadBackup'), label: i18n.global.t('database.loadBackup'),
click: (row: Database.MysqlDBInfo) => { click: (row: Database.MysqlDBInfo) => {
let params = { let params = {
mysqlName: mysqlName.value, mysqlName: mysqlInfo.name,
dbName: row.name, dbName: row.name,
}; };
uploadRef.value!.acceptParams(params); uploadRef.value!.acceptParams(params);
@ -310,6 +300,6 @@ const buttons = [
]; ];
onMounted(() => { onMounted(() => {
loadRunningOptions(); checkMysqlInstalled();
}); });
</script> </script>

View File

@ -1,6 +1,6 @@
<template> <template>
<div class="demo-collapse" v-show="onSetting"> <div class="demo-collapse" v-show="onSetting">
<el-card> <el-card style="margin-top: 5px">
<el-collapse v-model="activeName" accordion> <el-collapse v-model="activeName" accordion>
<el-collapse-item :title="$t('database.baseSetting')" name="1"> <el-collapse-item :title="$t('database.baseSetting')" name="1">
<el-form :model="baseInfo" ref="panelFormRef" label-width="120px"> <el-form :model="baseInfo" ref="panelFormRef" label-width="120px">
@ -116,7 +116,6 @@ const baseInfo = reactive({
port: 3306, port: 3306,
password: '', password: '',
remoteConn: false, remoteConn: false,
mysqlKey: '',
containerID: '', containerID: '',
}); });
const panelFormRef = ref<FormInstance>(); const panelFormRef = ref<FormInstance>();
@ -137,7 +136,6 @@ interface DialogProps {
const dialogContainerLogRef = ref(); const dialogContainerLogRef = ref();
const acceptParams = (params: DialogProps): void => { const acceptParams = (params: DialogProps): void => {
onSetting.value = true; onSetting.value = true;
mysqlName.value = params.mysqlName;
loadBaseInfo(); loadBaseInfo();
loadVariables(); loadVariables();
loadSlowLogs(); loadSlowLogs();
@ -155,7 +153,7 @@ const onSave = async (formEl: FormInstance | undefined, key: string, val: any) =
} }
if (key === 'port') { if (key === 'port') {
let params = { let params = {
key: baseInfo.mysqlKey, key: 'mysql',
name: mysqlName.value, name: mysqlName.value,
port: val, port: val,
}; };
@ -197,19 +195,19 @@ const loadContainerLog = async (containerID: string) => {
}; };
const loadBaseInfo = async () => { const loadBaseInfo = async () => {
const res = await loadMysqlBaseInfo(mysqlName.value); const res = await loadMysqlBaseInfo();
mysqlName.value = res.data?.name;
baseInfo.name = res.data?.name; baseInfo.name = res.data?.name;
baseInfo.port = res.data?.port; baseInfo.port = res.data?.port;
baseInfo.password = res.data?.password; baseInfo.password = res.data?.password;
baseInfo.remoteConn = res.data?.remoteConn; baseInfo.remoteConn = res.data?.remoteConn;
baseInfo.mysqlKey = res.data?.mysqlKey;
baseInfo.containerID = res.data?.containerName; baseInfo.containerID = res.data?.containerName;
loadMysqlConf(`/opt/1Panel/data/apps/${baseInfo.mysqlKey}/${baseInfo.name}/conf/my.cnf`); loadMysqlConf(`/opt/1Panel/data/apps/mysql/${baseInfo.name}/conf/my.cnf`);
loadContainerLog(baseInfo.containerID); loadContainerLog(baseInfo.containerID);
}; };
const loadVariables = async () => { const loadVariables = async () => {
const res = await loadMysqlVariables(mysqlName.value); const res = await loadMysqlVariables();
variables.value = res.data; variables.value = res.data;
variablesRef.value!.acceptParams({ mysqlName: mysqlName.value, variables: res.data }); variablesRef.value!.acceptParams({ mysqlName: mysqlName.value, variables: res.data });
}; };
@ -218,7 +216,6 @@ const loadSlowLogs = async () => {
await Promise.all([loadBaseInfo(), loadVariables()]); await Promise.all([loadBaseInfo(), loadVariables()]);
let param = { let param = {
mysqlName: mysqlName.value, mysqlName: mysqlName.value,
mysqlKey: baseInfo.mysqlKey,
variables: variables.value, variables: variables.value,
}; };
slowLogRef.value!.acceptParams(param); slowLogRef.value!.acceptParams(param);

View File

@ -52,7 +52,6 @@ const slowLogs = ref();
const confirmDialogRef = ref(); const confirmDialogRef = ref();
const mysqlName = ref(); const mysqlName = ref();
const mysqlKey = ref();
const variables = reactive({ const variables = reactive({
slow_query_log: 'OFF', slow_query_log: 'OFF',
long_query_time: 10, long_query_time: 10,
@ -61,17 +60,15 @@ const oldVariables = ref();
interface DialogProps { interface DialogProps {
mysqlName: string; mysqlName: string;
mysqlKey: string;
variables: Database.MysqlVariables; variables: Database.MysqlVariables;
} }
const acceptParams = (params: DialogProps): void => { const acceptParams = (params: DialogProps): void => {
mysqlName.value = params.mysqlName; mysqlName.value = params.mysqlName;
mysqlKey.value = params.mysqlKey;
variables.slow_query_log = params.variables.slow_query_log; variables.slow_query_log = params.variables.slow_query_log;
variables.long_query_time = Number(params.variables.long_query_time); variables.long_query_time = Number(params.variables.long_query_time);
if (variables.slow_query_log === 'ON') { if (variables.slow_query_log === 'ON') {
let path = `/opt/1Panel/data/apps/${mysqlKey.value}/${mysqlName.value}/data/1Panel-slow.log`; let path = `/opt/1Panel/data/apps/mysql/${mysqlName.value}/data/1Panel-slow.log`;
loadMysqlSlowlogs(path); loadMysqlSlowlogs(path);
} }
oldVariables.value = { ...variables }; oldVariables.value = { ...variables };
@ -95,7 +92,7 @@ const onSave = async () => {
param.push({ param: 'long_query_time', value: variables.long_query_time }); param.push({ param: 'long_query_time', value: variables.long_query_time });
param.push({ param: 'slow_query_log_file', value: '/var/lib/mysql/1Panel-slow.log' }); param.push({ param: 'slow_query_log_file', value: '/var/lib/mysql/1Panel-slow.log' });
} }
await updateMysqlVariables(mysqlName.value, param); await updateMysqlVariables(param);
ElMessage.success(i18n.global.t('commons.msg.operationSuccess')); ElMessage.success(i18n.global.t('commons.msg.operationSuccess'));
}; };

View File

@ -110,7 +110,7 @@
<script lang="ts" setup> <script lang="ts" setup>
import { loadMysqlStatus } from '@/api/modules/database'; import { loadMysqlStatus } from '@/api/modules/database';
import { computeSize } from '@/utils/util'; import { computeSize } from '@/utils/util';
import { reactive, ref } from 'vue'; import { reactive } from 'vue';
let mysqlStatus = reactive({ let mysqlStatus = reactive({
run: 0, run: 0,
@ -136,17 +136,12 @@ let mysqlStatus = reactive({
tableLocksWaited: 0, tableLocksWaited: 0,
}); });
const mysqlName = ref(); const acceptParams = (): void => {
interface DialogProps {
mysqlName: string;
}
const acceptParams = (params: DialogProps): void => {
mysqlName.value = params.mysqlName;
loadStatus(); loadStatus();
}; };
const loadStatus = async () => { const loadStatus = async () => {
const res = await loadMysqlStatus(mysqlName.value); const res = await loadMysqlStatus();
let queryPerSecond = res.data.Questions / res.data.Uptime; let queryPerSecond = res.data.Questions / res.data.Uptime;
let txPerSecond = (res.data!.Com_commit + res.data.Com_rollback) / res.data.Uptime; let txPerSecond = (res.data!.Com_commit + res.data.Com_rollback) / res.data.Uptime;

View File

@ -1,23 +1,32 @@
<template> <template>
<div> <div>
<Submenu activeName="redis" /> <Submenu activeName="redis" />
<el-button style="margin-top: 20px" size="default" icon="Tickets" @click="changeView('status')"> <div v-show="!redisInfo.isExist" style="margin-top: 20px">
{{ $t('database.status') }} <el-alert :closable="false" :title="$t('database.noMysql', ['Redis'])" type="info">
</el-button> <el-link icon="Position" @click="goRouter('/apps')" type="primary">
<el-button style="margin-top: 20px" size="default" icon="Setting" @click="changeView('setting')"> {{ $t('database.goInstall') }}
{{ $t('database.setting') }} </el-link>
</el-button> </el-alert>
<el-button style="margin-top: 20px" size="default" icon="Files" @click="changeView('persistence')"> </div>
{{ $t('database.persistence') }} <div v-show="redisInfo.isExist">
</el-button> <el-button style="margin-top: 20px" size="default" icon="Tickets" @click="changeView('status')">
<el-button style="margin-top: 20px" size="default" icon="Setting" @click="changeView('terminal')"> {{ $t('database.status') }}
{{ $t('database.terminal') }} </el-button>
</el-button> <el-button style="margin-top: 20px" size="default" icon="Setting" @click="changeView('setting')">
{{ $t('database.setting') }}
</el-button>
<el-button style="margin-top: 20px" size="default" icon="Files" @click="changeView('persistence')">
{{ $t('database.persistence') }}
</el-button>
<el-button style="margin-top: 20px" size="default" icon="Setting" @click="changeView('terminal')">
{{ $t('database.terminal') }}
</el-button>
<Status ref="statusRef"></Status> <Status ref="statusRef"></Status>
<Setting ref="settingRef"></Setting> <Setting ref="settingRef"></Setting>
<Persistence ref="persistenceRef"></Persistence> <Persistence ref="persistenceRef"></Persistence>
<Terminal ref="terminalRef"></Terminal> <Terminal ref="terminalRef"></Terminal>
</div>
</div> </div>
</template> </template>
@ -27,13 +36,22 @@ import Status from '@/views/database/redis/status/index.vue';
import Setting from '@/views/database/redis/setting/index.vue'; import Setting from '@/views/database/redis/setting/index.vue';
import Persistence from '@/views/database/redis/persistence/index.vue'; import Persistence from '@/views/database/redis/persistence/index.vue';
import Terminal from '@/views/database/redis/terminal/index.vue'; import Terminal from '@/views/database/redis/terminal/index.vue';
import { onMounted, ref } from 'vue'; import { onMounted, reactive, ref } from 'vue';
import { CheckAppInstalled } from '@/api/modules/app';
import { useRouter } from 'vue-router';
const router = useRouter();
const statusRef = ref(); const statusRef = ref();
const settingRef = ref(); const settingRef = ref();
const persistenceRef = ref(); const persistenceRef = ref();
const terminalRef = ref(); const terminalRef = ref();
const redisInfo = reactive({
name: '',
version: '',
isExist: false,
});
const changeView = async (params: string) => { const changeView = async (params: string) => {
switch (params) { switch (params) {
case 'status': case 'status':
@ -62,8 +80,21 @@ const changeView = async (params: string) => {
break; break;
} }
}; };
const checkRedisInstalled = async () => {
const res = await CheckAppInstalled('redis');
redisInfo.isExist = res.data.isExist;
redisInfo.name = res.data.name;
redisInfo.version = res.data.version;
if (redisInfo.isExist) {
changeView('status');
}
};
const goRouter = async (path: string) => {
router.push({ path: path });
};
onMounted(() => { onMounted(() => {
changeView('status'); checkRedisInstalled();
}); });
</script> </script>

View File

@ -1,7 +1,7 @@
<template> <template>
<div v-if="settingShow"> <div v-if="settingShow">
<el-card style="margin-top: 5px"> <el-card style="margin-top: 5px">
<el-radio-group v-model="confShowType"> <el-radio-group v-model="confShowType" @change="onChangeMode">
<el-radio-button label="base">{{ $t('database.baseConf') }}</el-radio-button> <el-radio-button label="base">{{ $t('database.baseConf') }}</el-radio-button>
<el-radio-button label="all">{{ $t('database.allConf') }}</el-radio-button> <el-radio-button label="all">{{ $t('database.allConf') }}</el-radio-button>
</el-radio-group> </el-radio-group>
@ -135,6 +135,14 @@ function callback(error: any) {
} }
} }
const onChangeMode = async () => {
if (confShowType.value === 'all') {
loadMysqlConf();
} else {
loadform();
}
};
const onSave = async (formEl: FormInstance | undefined) => { const onSave = async (formEl: FormInstance | undefined) => {
if (confShowType.value === 'all') { if (confShowType.value === 'all') {
onSaveFile(); onSaveFile();
@ -149,6 +157,7 @@ const onSave = async (formEl: FormInstance | undefined) => {
maxmemory: form.maxmemory + '', maxmemory: form.maxmemory + '',
}; };
await updateRedisConf(param); await updateRedisConf(param);
loadform();
ElMessage.success(i18n.global.t('commons.msg.operationSuccess')); ElMessage.success(i18n.global.t('commons.msg.operationSuccess'));
}); });
}; };
@ -179,10 +188,10 @@ const loadform = async () => {
form.requirepass = res.data?.requirepass; form.requirepass = res.data?.requirepass;
form.maxmemory = Number(res.data?.maxmemory); form.maxmemory = Number(res.data?.maxmemory);
form.port = Number(res.data?.port); form.port = Number(res.data?.port);
loadMysqlConf(`/opt/1Panel/data/apps/redis/${form.name}/conf/redis.conf`);
}; };
const loadMysqlConf = async (path: string) => { const loadMysqlConf = async () => {
let path = `/opt/1Panel/data/apps/redis/${form.name}/conf/redis.conf`;
const res = await LoadFile({ path: path }); const res = await LoadFile({ path: path });
mysqlConf.value = res.data; mysqlConf.value = res.data;
}; };

View File

@ -2,12 +2,12 @@
<div> <div>
<el-card class="topCard"> <el-card class="topCard">
<el-radio-group v-model="active"> <el-radio-group v-model="active">
<el-radio-button class="topButton" size="large" @click="routerTo('/logs')" label="login"> <el-radio-button class="topButton" size="large" @click="routerTo('/logs')" label="operation">
{{ $t('logs.login') }}
</el-radio-button>
<el-radio-button class="topButton" size="large" @click="routerTo('/logs/operation')" label="operation">
{{ $t('logs.operation') }} {{ $t('logs.operation') }}
</el-radio-button> </el-radio-button>
<el-radio-button class="topButton" size="large" @click="routerTo('/logs/login')" label="login">
{{ $t('logs.login') }}
</el-radio-button>
<el-radio-button class="topButton" size="large" @click="routerTo('/logs/system')" label="system"> <el-radio-button class="topButton" size="large" @click="routerTo('/logs/system')" label="system">
{{ $t('logs.system') }} {{ $t('logs.system') }}
</el-radio-button> </el-radio-button>

View File

@ -18,8 +18,18 @@
</el-radio-button> </el-radio-button>
</el-radio-group> </el-radio-group>
</el-card> </el-card>
<Panel v-if="activeNames === 'all' || activeNames === 'panel'" :settingInfo="form" @on-save="SaveSetting" /> <Panel
<Safe v-if="activeNames === 'all' || activeNames === 'safe'" :settingInfo="form" @on-save="SaveSetting" /> v-if="activeNames === 'all' || activeNames === 'panel'"
:settingInfo="form"
@on-save="SaveSetting"
@search="search"
/>
<Safe
v-if="activeNames === 'all' || activeNames === 'safe'"
:settingInfo="form"
@on-save="SaveSetting"
@search="search"
/>
<Backup v-if="activeNames === 'all' || activeNames === 'backup'" :settingInfo="form" @on-save="SaveSetting" /> <Backup v-if="activeNames === 'all' || activeNames === 'backup'" :settingInfo="form" @on-save="SaveSetting" />
<Monitor v-if="activeNames === 'all' || activeNames === 'monitor'" :settingInfo="form" @on-save="SaveSetting" /> <Monitor v-if="activeNames === 'all' || activeNames === 'monitor'" :settingInfo="form" @on-save="SaveSetting" />
<About v-if="activeNames === 'all' || activeNames === 'about'" /> <About v-if="activeNames === 'all' || activeNames === 'about'" />

View File

@ -9,24 +9,23 @@
<div style="justify-self: center"> <div style="justify-self: center">
<img style="width: 80px" src="@/assets/images/ko_image.png" /> <img style="width: 80px" src="@/assets/images/ko_image.png" />
</div> </div>
<h1>1Panel</h1>
<h3>{{ $t('setting.description') }}</h3> <h3>{{ $t('setting.description') }}</h3>
<h3>v0.0.1</h3> <h3>v1.0.0</h3>
<div style="margin-top: 10px"> <div style="margin-top: 10px">
<svg-icon style="font-size: 9px" iconName="p-huaban88"></svg-icon>
<el-link @click="toGithub"> <el-link @click="toGithub">
<span>{{ $t('setting.project') }}</span> <svg-icon style="font-size: 9px; margin-bottom: 8px" iconName="p-huaban88"></svg-icon>
<span style="line-height: 20px">{{ $t('setting.project') }}</span>
</el-link> </el-link>
<svg-icon style="font-size: 9px; margin-left: 15px" iconName="p-bug"></svg-icon> <el-link @click="toIssue" style="margin-left: 15px">
<el-link @click="toIssue"> <svg-icon style="font-size: 9px; margin-bottom: 8px" iconName="p-bug"></svg-icon>
<span>{{ $t('setting.issue') }}</span> <span>{{ $t('setting.issue') }}</span>
</el-link> </el-link>
<svg-icon style="font-size: 9px; margin-left: 15px" iconName="p-taolun"></svg-icon> <el-link @click="toTalk" style="margin-left: 15px">
<el-link @click="toTalk"> <svg-icon style="font-size: 9px; margin-bottom: 8px" iconName="p-taolun"></svg-icon>
<span>{{ $t('setting.chat') }}</span> <span>{{ $t('setting.chat') }}</span>
</el-link> </el-link>
<svg-icon style="font-size: 9px; margin-left: 15px" iconName="p-star"></svg-icon> <el-link @click="toGithubStar" style="margin-left: 15px">
<el-link @click="toGithubStar"> <svg-icon style="font-size: 9px; margin-bottom: 6px" iconName="p-star"></svg-icon>
<span>{{ $t('setting.star') }}</span> <span>{{ $t('setting.star') }}</span>
</el-link> </el-link>
</div> </div>

View File

@ -32,22 +32,6 @@
</el-input> </el-input>
</el-form-item> </el-form-item>
<el-form-item :label="$t('auth.email')" :rules="Rules.email" prop="settingInfo.email">
<el-input clearable v-model="form.settingInfo.email">
<template #append>
<el-button
@click="onSave(panelFormRef, 'Email', form.settingInfo.email)"
icon="Collection"
>
{{ $t('commons.button.save') }}
</el-button>
</template>
</el-input>
<div>
<span class="input-help">{{ $t('setting.emailHelper') }}</span>
</div>
</el-form-item>
<el-form-item <el-form-item
:label="$t('setting.title')" :label="$t('setting.title')"
:rules="Rules.requiredInput" :rules="Rules.requiredInput"
@ -180,7 +164,7 @@ import i18n from '@/lang';
import { GlobalStore } from '@/store'; import { GlobalStore } from '@/store';
const globalStore = GlobalStore(); const globalStore = GlobalStore();
const emit = defineEmits<{ (e: 'on-save', formEl: FormInstance | undefined, key: string, val: any): void }>(); const emit = defineEmits(['on-save', 'search']);
type FormInstance = InstanceType<typeof ElForm>; type FormInstance = InstanceType<typeof ElForm>;
const passFormRef = ref<FormInstance>(); const passFormRef = ref<FormInstance>();
@ -251,6 +235,7 @@ const submitChangePassword = async (formEl: FormInstance | undefined) => {
const onSyncTime = async () => { const onSyncTime = async () => {
const res = await syncTime(); const res = await syncTime();
emit('search');
form.settingInfo.localTime = res.data; form.settingInfo.localTime = res.data;
ElMessage.success(i18n.global.t('commons.msg.operationSuccess')); ElMessage.success(i18n.global.t('commons.msg.operationSuccess'));
}; };

View File

@ -175,7 +175,7 @@ import i18n from '@/lang';
import { Rules } from '@/global/form-rules'; import { Rules } from '@/global/form-rules';
import { dateFromat } from '@/utils/util'; import { dateFromat } from '@/utils/util';
const emit = defineEmits<{ (e: 'on-save', formEl: FormInstance | undefined, key: string, val: any): void }>(); const emit = defineEmits(['on-save', 'search']);
interface Props { interface Props {
settingInfo: any; settingInfo: any;
@ -217,12 +217,14 @@ const handleMFA = async () => {
isMFAShow.value = true; isMFAShow.value = true;
} else { } else {
await updateSetting({ key: 'MFAStatus', value: 'disable' }); await updateSetting({ key: 'MFAStatus', value: 'disable' });
emit('search');
ElMessage.success(i18n.global.t('commons.msg.operationSuccess')); ElMessage.success(i18n.global.t('commons.msg.operationSuccess'));
} }
}; };
const onBind = async () => { const onBind = async () => {
await bindMFA({ code: mfaCode.value, secret: otp.secret }); await bindMFA({ code: mfaCode.value, secret: otp.secret });
emit('search');
ElMessage.success(i18n.global.t('commons.msg.operationSuccess')); ElMessage.success(i18n.global.t('commons.msg.operationSuccess'));
isMFAShow.value = false; isMFAShow.value = false;
}; };
@ -238,6 +240,7 @@ const submitTimeout = async (formEl: FormInstance | undefined) => {
if (!valid) return; if (!valid) return;
let time = new Date(new Date().getTime() + 3600 * 1000 * 24 * timeoutForm.days); let time = new Date(new Date().getTime() + 3600 * 1000 * 24 * timeoutForm.days);
await updateSetting({ key: 'ExpirationDays', value: timeoutForm.days + '' }); await updateSetting({ key: 'ExpirationDays', value: timeoutForm.days + '' });
emit('search');
form.settingInfo.expirationTime = dateFromat(0, 0, time); form.settingInfo.expirationTime = dateFromat(0, 0, time);
timeoutVisiable.value = false; timeoutVisiable.value = false;
}); });