mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2026-10-10 00:00:30 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
04edce94f9 | ||
|
|
ccb81365f2 | ||
|
|
acf608cb7e | ||
|
|
2724708539 | ||
|
|
50589a8d8d | ||
|
|
f06f487e8a | ||
|
|
42dd668e1e | ||
|
|
6cd00a072d | ||
|
|
8faa3b6e51 | ||
|
|
52198e9c0c | ||
|
|
173e3e9cc1 | ||
|
|
40c751cde2 | ||
|
|
a3bf4513e1 | ||
|
|
4e7350aaae | ||
|
|
9ae935d06a | ||
|
|
b6055eb058 | ||
|
|
0e158ffa2b | ||
|
|
cc7260e121 | ||
|
|
43b3ef47f3 | ||
|
|
21755223e1 | ||
|
|
08f0147d81 |
@@ -153,24 +153,6 @@ type DBBaseInfo struct {
|
||||
Port int64 `json:"port"`
|
||||
}
|
||||
|
||||
type BackupDB struct {
|
||||
MysqlName string `json:"mysqlName" validate:"required"`
|
||||
DBName string `json:"dbName" validate:"required"`
|
||||
}
|
||||
|
||||
type RecoverDB struct {
|
||||
MysqlName string `json:"mysqlName" validate:"required"`
|
||||
DBName string `json:"dbName" validate:"required"`
|
||||
BackupName string `json:"backupName" validate:"required"`
|
||||
}
|
||||
|
||||
type UploadRecover struct {
|
||||
MysqlName string `json:"mysqlName" validate:"required"`
|
||||
DBName string `json:"dbName" validate:"required"`
|
||||
FileName string `json:"fileName"`
|
||||
FileDir string `json:"fileDir"`
|
||||
}
|
||||
|
||||
// redis
|
||||
type ChangeRedisPass struct {
|
||||
Value string `json:"value" validate:"required"`
|
||||
|
||||
@@ -17,6 +17,7 @@ type RuntimeCreate struct {
|
||||
Image string `json:"image"`
|
||||
Type string `json:"type"`
|
||||
Version string `json:"version"`
|
||||
Source string `json:"source"`
|
||||
}
|
||||
|
||||
type RuntimeDelete struct {
|
||||
@@ -30,4 +31,5 @@ type RuntimeUpdate struct {
|
||||
Image string `json:"image"`
|
||||
Version string `json:"version"`
|
||||
Rebuild bool `json:"rebuild"`
|
||||
Source string `json:"source"`
|
||||
}
|
||||
|
||||
@@ -6,4 +6,5 @@ type RuntimeRes struct {
|
||||
model.Runtime
|
||||
AppParams []AppParam `json:"appParams"`
|
||||
AppID uint `json:"appId"`
|
||||
Source string `json:"source"`
|
||||
}
|
||||
|
||||
@@ -42,6 +42,7 @@ type WebsiteLog struct {
|
||||
Enable bool `json:"enable"`
|
||||
Content string `json:"content"`
|
||||
End bool `json:"end"`
|
||||
Path string `json:"path"`
|
||||
}
|
||||
|
||||
type PHPConfig struct {
|
||||
|
||||
@@ -5,6 +5,14 @@ import (
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/backend/app/dto"
|
||||
"github.com/1Panel-dev/1Panel/backend/app/dto/request"
|
||||
"github.com/1Panel-dev/1Panel/backend/app/dto/response"
|
||||
@@ -19,13 +27,6 @@ import (
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/files"
|
||||
http2 "github.com/1Panel-dev/1Panel/backend/utils/http"
|
||||
"gopkg.in/yaml.v3"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type AppService struct {
|
||||
|
||||
@@ -255,7 +255,7 @@ func handleAppRecover(install *model.AppInstall, recoverFile string, isRollback
|
||||
func reCreateDB(dbID uint, app model.AppInstall, oldEnv string) (*model.DatabaseMysql, map[string]interface{}, error) {
|
||||
mysqlService := NewIMysqlService()
|
||||
ctx := context.Background()
|
||||
_ = mysqlService.Delete(ctx, dto.MysqlDBDelete{ID: dbID, Database: app.Name, Type: app.App.Key, DeleteBackup: true, ForceDelete: true})
|
||||
_ = mysqlService.Delete(ctx, dto.MysqlDBDelete{ID: dbID, Database: app.Name, Type: app.App.Key, DeleteBackup: false, ForceDelete: true})
|
||||
|
||||
envMap := make(map[string]interface{})
|
||||
if err := json.Unmarshal([]byte(oldEnv), &envMap); err != nil {
|
||||
|
||||
@@ -150,7 +150,7 @@ func (u *MysqlService) LoadFromRemote(req dto.MysqlLoadDB) error {
|
||||
return err
|
||||
}
|
||||
|
||||
databases, err := mysqlRepo.List(databaseRepo.WithByFrom(req.From))
|
||||
databases, err := mysqlRepo.List(mysqlRepo.WithByMysqlName(req.Database))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -235,11 +235,11 @@ func (u *MysqlService) Delete(ctx context.Context, req dto.MysqlDBDelete) error
|
||||
return err
|
||||
}
|
||||
|
||||
uploadDir := path.Join(global.CONF.System.BaseDir, fmt.Sprintf("1panel/uploads/database/%s/%s/%s", req.Type, req.Database, db.Name))
|
||||
if _, err := os.Stat(uploadDir); err == nil {
|
||||
_ = os.RemoveAll(uploadDir)
|
||||
}
|
||||
if req.DeleteBackup {
|
||||
uploadDir := path.Join(global.CONF.System.BaseDir, fmt.Sprintf("1panel/uploads/database/%s/%s/%s", req.Type, req.Database, db.Name))
|
||||
if _, err := os.Stat(uploadDir); err == nil {
|
||||
_ = os.RemoveAll(uploadDir)
|
||||
}
|
||||
localDir, err := loadLocalDir()
|
||||
if err != nil && !req.ForceDelete {
|
||||
return err
|
||||
@@ -248,9 +248,9 @@ func (u *MysqlService) Delete(ctx context.Context, req dto.MysqlDBDelete) error
|
||||
if _, err := os.Stat(backupDir); err == nil {
|
||||
_ = os.RemoveAll(backupDir)
|
||||
}
|
||||
_ = backupRepo.DeleteRecord(ctx, commonRepo.WithByType(req.Type), commonRepo.WithByName(req.Database), backupRepo.WithByDetailName(db.Name))
|
||||
global.LOG.Infof("delete database %s-%s backups successful", req.Database, db.Name)
|
||||
}
|
||||
_ = backupRepo.DeleteRecord(ctx, commonRepo.WithByType(req.Type), commonRepo.WithByName(req.Database), backupRepo.WithByDetailName(db.Name))
|
||||
|
||||
_ = mysqlRepo.Delete(ctx, commonRepo.WithByID(db.ID))
|
||||
return nil
|
||||
|
||||
@@ -267,6 +267,7 @@ func (u *FirewallService) OperatePortRule(req dto.PortRuleOperate, reload bool)
|
||||
_ = u.addPortRecord(req)
|
||||
}(req)
|
||||
}
|
||||
wg.Wait()
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -343,6 +344,7 @@ func (u *FirewallService) OperateAddressRule(req dto.AddrRuleOperate, reload boo
|
||||
_ = u.addAddressRecord(req)
|
||||
}(req)
|
||||
}
|
||||
wg.Wait()
|
||||
if reload {
|
||||
return client.Reload()
|
||||
}
|
||||
|
||||
@@ -94,7 +94,7 @@ func (r *RuntimeService) Create(create request.RuntimeCreate) (err error) {
|
||||
return
|
||||
}
|
||||
}
|
||||
composeContent, envContent, forms, err := handleParams(create.Image, create.Type, newNameDir, create.Params)
|
||||
composeContent, envContent, forms, err := handleParams(create.Image, create.Type, newNameDir, create.Source, create.Params)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@@ -197,6 +197,9 @@ func (r *RuntimeService) Get(id uint) (*response.RuntimeRes, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if v, ok := envs["CONTAINER_PACKAGE_URL"]; ok {
|
||||
res.Source = v
|
||||
}
|
||||
for _, form := range appForm.FormFields {
|
||||
if v, ok := envs[form.EnvKey]; ok {
|
||||
appParam := response.AppParam{
|
||||
@@ -252,7 +255,7 @@ func (r *RuntimeService) Update(req request.RuntimeUpdate) error {
|
||||
return buserr.New(constant.ErrImageExist)
|
||||
}
|
||||
runtimeDir := path.Join(constant.RuntimeDir, runtime.Type, runtime.Name)
|
||||
composeContent, envContent, _, err := handleParams(req.Image, runtime.Type, runtimeDir, req.Params)
|
||||
composeContent, envContent, _, err := handleParams(req.Image, runtime.Type, runtimeDir, req.Source, req.Params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -89,7 +89,7 @@ func buildRuntime(runtime *model.Runtime, oldImageID string, rebuild bool) {
|
||||
_ = runtimeRepo.Save(runtime)
|
||||
}
|
||||
|
||||
func handleParams(image, runtimeType, runtimeDir string, params map[string]interface{}) (composeContent []byte, envContent []byte, forms []byte, err error) {
|
||||
func handleParams(image, runtimeType, runtimeDir, source string, params map[string]interface{}) (composeContent []byte, envContent []byte, forms []byte, err error) {
|
||||
fileOp := files.NewFileOp()
|
||||
composeContent, err = fileOp.GetContent(path.Join(runtimeDir, "docker-compose.yml"))
|
||||
if err != nil {
|
||||
@@ -114,6 +114,7 @@ func handleParams(image, runtimeType, runtimeDir string, params map[string]inter
|
||||
params["PHP_EXTENSIONS"] = strings.Join(strArray, ",")
|
||||
}
|
||||
}
|
||||
params["CONTAINER_PACKAGE_URL"] = source
|
||||
}
|
||||
newMap := make(map[string]string)
|
||||
handleMap(params, newMap)
|
||||
|
||||
@@ -884,9 +884,10 @@ func updateRollbackStatus(id uint, status string, message string) {
|
||||
}
|
||||
|
||||
func cpBinary(src []string, dst string) error {
|
||||
stderr, err := cmd.Exec(fmt.Sprintf("\\cp -f %s %s", strings.Join(src, " "), dst))
|
||||
global.LOG.Debugf(fmt.Sprintf("\\cp -f %s %s", strings.Join(src, " "), dst))
|
||||
stdout, err := cmd.Exec(fmt.Sprintf("\\cp -f %s %s", strings.Join(src, " "), dst))
|
||||
if err != nil {
|
||||
return errors.New(stderr)
|
||||
return fmt.Errorf("cp file failed, stdout: %v, err: %v", stdout, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -168,7 +168,7 @@ func snapCompress(snap snapHelper, rootDir string) {
|
||||
_ = snapshotRepo.UpdateStatus(snap.Status.ID, map[string]interface{}{"compress": err.Error()})
|
||||
return
|
||||
}
|
||||
size := common.LoadSizeUnit(float64(stat.Size()))
|
||||
size := common.LoadSizeUnit2F(float64(stat.Size()))
|
||||
global.LOG.Debugf("compress successful! size of file: %s", size)
|
||||
snap.Status.Compress = constant.StatusDone
|
||||
snap.Status.Size = size
|
||||
|
||||
@@ -132,25 +132,25 @@ func (u *UpgradeService) Upgrade(req dto.Upgrade) error {
|
||||
global.LOG.Info("backup original data successful, now start to upgrade!")
|
||||
|
||||
if err := cpBinary([]string{tmpDir + "/1panel"}, "/usr/local/bin/1panel"); err != nil {
|
||||
u.handleRollback(fileOp, originalDir, 1)
|
||||
global.LOG.Errorf("upgrade 1panel failed, err: %v", err)
|
||||
u.handleRollback(fileOp, originalDir, 1)
|
||||
return
|
||||
}
|
||||
|
||||
if err := cpBinary([]string{tmpDir + "/1pctl"}, "/usr/local/bin/1pctl"); err != nil {
|
||||
u.handleRollback(fileOp, originalDir, 2)
|
||||
global.LOG.Errorf("upgrade 1pctl failed, err: %v", err)
|
||||
u.handleRollback(fileOp, originalDir, 2)
|
||||
return
|
||||
}
|
||||
if _, err := cmd.Execf("sed -i -e 's#BASE_DIR=.*#BASE_DIR=%s#g' /usr/local/bin/1pctl", global.CONF.System.BaseDir); err != nil {
|
||||
u.handleRollback(fileOp, originalDir, 2)
|
||||
global.LOG.Errorf("upgrade basedir in 1pctl failed, err: %v", err)
|
||||
u.handleRollback(fileOp, originalDir, 2)
|
||||
return
|
||||
}
|
||||
|
||||
if err := cpBinary([]string{tmpDir + "/1panel.service"}, "/etc/systemd/system/1panel.service"); err != nil {
|
||||
u.handleRollback(fileOp, originalDir, 3)
|
||||
global.LOG.Errorf("upgrade 1panel.service failed, err: %v", err)
|
||||
u.handleRollback(fileOp, originalDir, 3)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -941,6 +941,7 @@ func (w WebsiteService) OpWebsiteLog(req request.WebsiteLogReq) (*response.Websi
|
||||
return nil, err
|
||||
}
|
||||
res.End = end
|
||||
res.Path = filePath
|
||||
res.Content = strings.Join(lines, "\n")
|
||||
return res, nil
|
||||
case constant.DisableLog:
|
||||
@@ -1210,6 +1211,9 @@ func (w WebsiteService) UpdatePHPConfigFile(req request.WebsitePHPFileUpdate) er
|
||||
if err := files.NewFileOp().WriteFile(configPath, strings.NewReader(req.Content), 0755); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := compose.Restart(runtimeInstall.GetComposePath()); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -42,6 +42,7 @@ func Init() {
|
||||
migrations.AddDatabases,
|
||||
migrations.UpdateDatabase,
|
||||
migrations.UpdateAppInstallResource,
|
||||
migrations.DropDatabaseLocal,
|
||||
})
|
||||
if err := m.Migrate(); err != nil {
|
||||
global.LOG.Error(err)
|
||||
|
||||
@@ -572,103 +572,40 @@ var AddDatabases = &gormigrate.Migration{
|
||||
ID: "20230831-add-databases",
|
||||
Migrate: func(tx *gorm.DB) error {
|
||||
installRepo := repo.NewIAppInstallRepo()
|
||||
mysqlInfo, err := installRepo.LoadBaseInfo("mysql", "")
|
||||
if err == nil {
|
||||
var mysqlDb model.Database
|
||||
_ = tx.Where("name = ?", mysqlInfo.Name).First(&mysqlDb).Error
|
||||
if mysqlDb.ID == 0 {
|
||||
if err := tx.Create(&model.Database{
|
||||
AppInstallID: mysqlInfo.ID,
|
||||
Name: mysqlInfo.Name,
|
||||
Type: "mysql",
|
||||
Version: mysqlInfo.Version,
|
||||
From: "local",
|
||||
Address: mysqlInfo.ServiceName,
|
||||
Port: service.DatabaseKeys["mysql"],
|
||||
Username: "root",
|
||||
Password: mysqlInfo.Password,
|
||||
}).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
mariadbInfo, err := installRepo.LoadBaseInfo("mariadb", "")
|
||||
if err == nil {
|
||||
if err := tx.Create(&model.Database{
|
||||
AppInstallID: mariadbInfo.ID,
|
||||
Name: mariadbInfo.Name,
|
||||
Type: "mariadb",
|
||||
Version: mariadbInfo.Version,
|
||||
From: "local",
|
||||
Address: mariadbInfo.ServiceName,
|
||||
Port: service.DatabaseKeys["mariadb"],
|
||||
Username: "root",
|
||||
Password: mariadbInfo.Password,
|
||||
}).Error; err != nil {
|
||||
_ = tx.Where("name = ? AND address = ?", "local", "127.0.0.1").Delete(&model.Database{}).Error
|
||||
mysql := addDatabaseData(tx, installRepo, "mysql")
|
||||
if mysql.AppInstallID != 0 {
|
||||
if err := tx.Create(mysql).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
redisInfo, err := installRepo.LoadBaseInfo("redis", "")
|
||||
if err == nil {
|
||||
if err := tx.Create(&model.Database{
|
||||
AppInstallID: redisInfo.ID,
|
||||
Name: redisInfo.Name,
|
||||
Type: "redis",
|
||||
Version: redisInfo.Version,
|
||||
From: "local",
|
||||
Address: redisInfo.ServiceName,
|
||||
Port: service.DatabaseKeys["redis"],
|
||||
Username: "root",
|
||||
Password: redisInfo.Password,
|
||||
}).Error; err != nil {
|
||||
mariadb := addDatabaseData(tx, installRepo, "mariadb")
|
||||
if mariadb.AppInstallID != 0 {
|
||||
if err := tx.Create(mariadb).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
pgInfo, err := installRepo.LoadBaseInfo("postgresql", "")
|
||||
if err == nil {
|
||||
if err := tx.Create(&model.Database{
|
||||
AppInstallID: pgInfo.ID,
|
||||
Name: pgInfo.Name,
|
||||
Type: "postgresql",
|
||||
Version: pgInfo.Version,
|
||||
From: "local",
|
||||
Address: pgInfo.ServiceName,
|
||||
Port: service.DatabaseKeys["postgresql"],
|
||||
Username: pgInfo.UserName,
|
||||
Password: pgInfo.Password,
|
||||
}).Error; err != nil {
|
||||
redis := addDatabaseData(tx, installRepo, "redis")
|
||||
if redis.AppInstallID != 0 {
|
||||
if err := tx.Create(redis).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
mongodbInfo, err := installRepo.LoadBaseInfo("mongodb", "")
|
||||
if err == nil {
|
||||
if err := tx.Create(&model.Database{
|
||||
AppInstallID: mongodbInfo.ID,
|
||||
Name: mongodbInfo.Name,
|
||||
Type: "mongodb",
|
||||
Version: mongodbInfo.Version,
|
||||
From: "local",
|
||||
Address: mongodbInfo.ServiceName,
|
||||
Port: service.DatabaseKeys["mongodb"],
|
||||
Username: mongodbInfo.UserName,
|
||||
Password: mongodbInfo.Password,
|
||||
}).Error; err != nil {
|
||||
postgresql := addDatabaseData(tx, installRepo, "postgresql")
|
||||
if postgresql.AppInstallID != 0 {
|
||||
if err := tx.Create(postgresql).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
memcachedInfo, err := installRepo.LoadBaseInfo("memcached", "")
|
||||
if err == nil {
|
||||
if err := tx.Create(&model.Database{
|
||||
AppInstallID: memcachedInfo.ID,
|
||||
Name: memcachedInfo.Name,
|
||||
Type: "memcached",
|
||||
Version: memcachedInfo.Version,
|
||||
From: "local",
|
||||
Address: memcachedInfo.ServiceName,
|
||||
Port: service.DatabaseKeys["memcached"],
|
||||
Username: "root",
|
||||
Password: memcachedInfo.Password,
|
||||
}).Error; err != nil {
|
||||
mongodb := addDatabaseData(tx, installRepo, "mongodb")
|
||||
if mongodb.AppInstallID != 0 {
|
||||
if err := tx.Create(mongodb).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
memcached := addDatabaseData(tx, installRepo, "memcached")
|
||||
if memcached.AppInstallID != 0 {
|
||||
if err := tx.Create(memcached).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -691,37 +628,15 @@ var UpdateDatabase = &gormigrate.Migration{
|
||||
return nil
|
||||
}
|
||||
for _, data := range datas {
|
||||
if data.Name == "local" && data.Address == "127.0.0.1" && data.Type == "mysql" {
|
||||
installRepo := repo.NewIAppInstallRepo()
|
||||
mysqlInfo, err := installRepo.LoadBaseInfo("mysql", "")
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
pass, err := encrypt.StringEncrypt(data.Password)
|
||||
if err != nil {
|
||||
global.LOG.Errorf("encrypt database %s password failed, err: %v", data.Name, err)
|
||||
continue
|
||||
}
|
||||
if err := tx.Model(&model.Database{}).Where("id = ?", data.ID).Updates(map[string]interface{}{
|
||||
"app_install_id": mysqlInfo.ID,
|
||||
"name": mysqlInfo.Name,
|
||||
"password": pass,
|
||||
"port": service.DatabaseKeys["mysql"],
|
||||
"address": mysqlInfo.ServiceName,
|
||||
}).Error; err != nil {
|
||||
global.LOG.Errorf("updata database %s info failed, err: %v", data.Name, err)
|
||||
}
|
||||
} else {
|
||||
pass, err := encrypt.StringEncrypt(data.Password)
|
||||
if err != nil {
|
||||
global.LOG.Errorf("encrypt database %s password failed, err: %v", data.Name, err)
|
||||
continue
|
||||
}
|
||||
if err := tx.Model(&model.Database{}).Where("id = ?", data.ID).Updates(map[string]interface{}{
|
||||
"password": pass,
|
||||
}).Error; err != nil {
|
||||
global.LOG.Errorf("updata database %s info failed, err: %v", data.Name, err)
|
||||
}
|
||||
pass, err := encrypt.StringEncrypt(data.Password)
|
||||
if err != nil {
|
||||
global.LOG.Errorf("encrypt database %s password failed, err: %v", data.Name, err)
|
||||
continue
|
||||
}
|
||||
if err := tx.Model(&model.Database{}).Where("id = ?", data.ID).Updates(map[string]interface{}{
|
||||
"password": pass,
|
||||
}).Error; err != nil {
|
||||
global.LOG.Errorf("updata database %s info failed, err: %v", data.Name, err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -759,3 +674,70 @@ var UpdateAppInstallResource = &gormigrate.Migration{
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
var DropDatabaseLocal = &gormigrate.Migration{
|
||||
ID: "20230914-drop-database-local",
|
||||
Migrate: func(tx *gorm.DB) error {
|
||||
_ = tx.Where("name = ? AND address = ?", "local", "127.0.0.1").Delete(&model.Database{}).Error
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
func addDatabaseData(tx *gorm.DB, installRepo repo.IAppInstallRepo, appType string) *model.Database {
|
||||
dbInfo, err := installRepo.LoadBaseInfo(appType, "")
|
||||
if err != nil {
|
||||
return &model.Database{}
|
||||
}
|
||||
|
||||
if appType == "mysql" || appType == "redis" || appType == "mariadb" || appType == "memcached" {
|
||||
dbInfo.UserName = "root"
|
||||
}
|
||||
database := &model.Database{
|
||||
AppInstallID: dbInfo.ID,
|
||||
Name: dbInfo.Name,
|
||||
Type: appType,
|
||||
Version: dbInfo.Version,
|
||||
From: "local",
|
||||
Address: dbInfo.ServiceName,
|
||||
Port: service.DatabaseKeys[appType],
|
||||
Username: dbInfo.UserName,
|
||||
Password: dbInfo.Password,
|
||||
}
|
||||
var dbItem model.Database
|
||||
_ = global.DB.Where("name = ?", dbInfo.Name).First(&dbItem).Error
|
||||
if dbItem.ID != 0 {
|
||||
if appType == "mysql" {
|
||||
var (
|
||||
backups []model.BackupRecord
|
||||
mysqls []model.DatabaseMysql
|
||||
)
|
||||
_ = tx.Where("name = ? AND type = ?", dbItem.Name, "mysql").Find(&backups)
|
||||
_ = tx.Where("`from` = ?", "local").Find(&mysqls)
|
||||
for _, item := range backups {
|
||||
isLocal := false
|
||||
for _, mysql := range mysqls {
|
||||
if item.Name == mysql.MysqlName && item.DetailName == mysql.Name {
|
||||
isLocal = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !isLocal {
|
||||
_ = tx.Model(&model.BackupRecord{}).Where("id = ?", item.ID).Updates(map[string]interface{}{
|
||||
"name": "remote-" + dbItem.Name,
|
||||
}).Error
|
||||
}
|
||||
}
|
||||
}
|
||||
if err := tx.Debug().Model(&model.DatabaseMysql{}).Where("mysql_name = ? AND `from` != ?", dbItem.Name, "local").Updates(map[string]interface{}{
|
||||
"mysql_name": "remote-" + dbItem.Name,
|
||||
}).Error; err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
if err := tx.Debug().Model(&model.Database{}).Where("name = ?", dbItem.Name).Updates(map[string]interface{}{
|
||||
"name": "remote-" + dbItem.Name,
|
||||
}).Error; err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
}
|
||||
return database
|
||||
}
|
||||
|
||||
@@ -24,6 +24,17 @@ func CompareVersion(version1 string, version2 string) bool {
|
||||
version1s := strings.Split(version1, ".")
|
||||
version2s := strings.Split(version2, ".")
|
||||
|
||||
if len(version2s) > len(version1s) {
|
||||
for i := 0; i < len(version2s)-len(version1s); i++ {
|
||||
version1s = append(version1s, "0")
|
||||
}
|
||||
}
|
||||
if len(version1s) > len(version2s) {
|
||||
for i := 0; i < len(version1s)-len(version2s); i++ {
|
||||
version2s = append(version2s, "0")
|
||||
}
|
||||
}
|
||||
|
||||
n := min(len(version1s), len(version2s))
|
||||
re := regexp.MustCompile("[0-9]+")
|
||||
for i := 0; i < n; i++ {
|
||||
@@ -147,6 +158,16 @@ func RemoveRepeatElement(a interface{}) (ret []interface{}) {
|
||||
}
|
||||
|
||||
func LoadSizeUnit(value float64) string {
|
||||
if value > 1048576 {
|
||||
return fmt.Sprintf("%vM", value/1048576)
|
||||
}
|
||||
if value > 1024 {
|
||||
return fmt.Sprintf("%vK", value/1024)
|
||||
}
|
||||
return fmt.Sprintf("%v", value)
|
||||
}
|
||||
|
||||
func LoadSizeUnit2F(value float64) string {
|
||||
if value > 1073741824 {
|
||||
return fmt.Sprintf("%.2fG", value/1073741824)
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
mathRand "math/rand"
|
||||
"strings"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/backend/utils/common"
|
||||
@@ -113,26 +112,5 @@ func randomPassword(user string) string {
|
||||
if len(user) > 6 {
|
||||
passwdItem = user[:6]
|
||||
}
|
||||
num := []rune("1234567890")
|
||||
uppercase := []rune("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
|
||||
lowercase := []rune("abcdefghijklmnopqrstuvwxyz")
|
||||
special := []rune(".%@!~_-")
|
||||
|
||||
b := make([]rune, 10)
|
||||
for i := 0; i < 2; i++ {
|
||||
b[i] = lowercase[mathRand.Intn(len(lowercase))]
|
||||
}
|
||||
for i := 2; i < 4; i++ {
|
||||
b[i] = uppercase[mathRand.Intn(len(uppercase))]
|
||||
}
|
||||
b[4] = special[mathRand.Intn(len(special))]
|
||||
for i := 5; i < 9; i++ {
|
||||
b[i] = num[mathRand.Intn(len(num))]
|
||||
}
|
||||
|
||||
for i := len(b) - 1; i > 0; i-- {
|
||||
j := mathRand.Intn(i + 1)
|
||||
b[i], b[j] = b[j], b[i]
|
||||
}
|
||||
return passwdItem + "-" + (string(b))
|
||||
return passwdItem + "@" + common.RandStrAndNum(8)
|
||||
}
|
||||
|
||||
@@ -17688,6 +17688,9 @@ const docTemplate = `{
|
||||
},
|
||||
"end": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"path": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -17681,6 +17681,9 @@
|
||||
},
|
||||
"end": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"path": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -4016,6 +4016,8 @@ definitions:
|
||||
type: boolean
|
||||
end:
|
||||
type: boolean
|
||||
path:
|
||||
type: string
|
||||
type: object
|
||||
response.WebsiteNginxConfig:
|
||||
properties:
|
||||
|
||||
@@ -23,6 +23,7 @@ export namespace Runtime {
|
||||
export interface RuntimeDTO extends Runtime {
|
||||
appParams: App.InstallParams[];
|
||||
appId: number;
|
||||
source?: string;
|
||||
}
|
||||
|
||||
export interface RuntimeCreate {
|
||||
@@ -36,6 +37,7 @@ export namespace Runtime {
|
||||
appId?: number;
|
||||
version?: string;
|
||||
rebuild?: boolean;
|
||||
source?: string;
|
||||
}
|
||||
|
||||
export interface RuntimeUpdate {
|
||||
|
||||
@@ -90,6 +90,7 @@ export namespace Website {
|
||||
enable: boolean;
|
||||
content: string;
|
||||
end: boolean;
|
||||
path: string;
|
||||
}
|
||||
|
||||
export interface Domain {
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
</div>
|
||||
</el-card>
|
||||
</div>
|
||||
<div v-else>
|
||||
<div v-if="!data.isExist && !isDB()">
|
||||
<LayoutContent :title="getTitle(key)" :divider="true">
|
||||
<template #main>
|
||||
<div class="app-warn">
|
||||
@@ -134,6 +134,10 @@ const goRouter = async (key: string) => {
|
||||
router.push({ name: 'AppAll', query: { install: key } });
|
||||
};
|
||||
|
||||
const isDB = () => {
|
||||
return key.value === 'mysql' || key.value === 'mariadb';
|
||||
};
|
||||
|
||||
const onCheck = async () => {
|
||||
await CheckAppInstalled(key.value, name.value)
|
||||
.then((res) => {
|
||||
|
||||
@@ -1658,6 +1658,15 @@ const message = {
|
||||
phpPluginHelper:
|
||||
'<a target="_blank" href="https://1panel.cn/docs/user_manual/websites/php/#php_1">View PHP extension list</a> ',
|
||||
rebuild: 'Rebuild PHP App',
|
||||
source: 'PHP extension source',
|
||||
ustc: 'University of Science and Technology of China',
|
||||
netease: 'Netease',
|
||||
aliyun: 'Alibaba Cloud',
|
||||
default: 'default',
|
||||
tsinghua: 'Tsinghua University',
|
||||
xtomhk: 'XTOM Mirror Station (Hong Kong)',
|
||||
xtom: 'XTOM Mirror Station (Global)',
|
||||
phpsourceHelper: 'Choose the appropriate source according to your network environment',
|
||||
},
|
||||
process: {
|
||||
pid: 'Process ID',
|
||||
|
||||
@@ -1569,6 +1569,15 @@ const message = {
|
||||
phpPluginHelper:
|
||||
"<a target=“_blank” href='https://1panel.cn/docs/user_manual/websites/php/#php_1'>查看 PHP 擴展列表</a> ",
|
||||
rebuild: '重建 PHP 應用',
|
||||
source: 'PHP 擴展源',
|
||||
ustc: '中國科學技術大學',
|
||||
netease: '網易',
|
||||
aliyun: '阿里雲',
|
||||
default: '默認',
|
||||
tsinghua: '清華大學',
|
||||
xtomhk: 'XTOM 鏡像站(香港)',
|
||||
xtom: 'XTOM 鏡像站(全球)',
|
||||
phpsourceHelper: '根據你的網絡環境選擇合適的源',
|
||||
},
|
||||
process: {
|
||||
pid: '進程ID',
|
||||
|
||||
@@ -1569,6 +1569,15 @@ const message = {
|
||||
phpPluginHelper:
|
||||
"<a target=“_blank” href='https://1panel.cn/docs/user_manual/websites/php/#php_1'>查看 PHP 扩展列表</a> ",
|
||||
rebuild: '重建 PHP 应用',
|
||||
source: 'PHP 扩展源',
|
||||
ustc: '中国科学技术大学',
|
||||
netease: '网易',
|
||||
aliyun: '阿里云',
|
||||
default: '默认',
|
||||
tsinghua: '清华大学',
|
||||
xtomhk: 'XTOM 镜像站(香港)',
|
||||
xtom: 'XTOM 镜像站(全球)',
|
||||
phpsourceHelper: '根据你的网络环境选择合适的源',
|
||||
},
|
||||
process: {
|
||||
pid: '进程ID',
|
||||
|
||||
@@ -180,11 +180,13 @@ html.dark {
|
||||
|
||||
.router_card_button {
|
||||
.el-radio-button__inner {
|
||||
background: none;
|
||||
background: none !important;
|
||||
}
|
||||
.el-radio-button__original-radio:checked + .el-radio-button__inner {
|
||||
color: #ffffff;
|
||||
background-color: var(--panel-button-active) !important;
|
||||
box-shadow: none !important;
|
||||
border: none !important;
|
||||
}
|
||||
}
|
||||
// content-box
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<el-dialog v-model="open" :title="$t('app.delete')" width="30%" :close-on-click-modal="false">
|
||||
<el-dialog v-model="open" :title="$t('container.' + operation)" width="30%" :close-on-click-modal="false">
|
||||
<el-row>
|
||||
<el-col :span="20" :offset="2">
|
||||
<el-alert :title="msg" show-icon type="error" :closable="false"></el-alert>
|
||||
@@ -64,7 +64,7 @@ const onConfirm = () => {
|
||||
open.value = false;
|
||||
loading.value = false;
|
||||
em('search');
|
||||
MsgSuccess(i18n.global.t('commons.msg.deleteSuccess'));
|
||||
MsgSuccess(i18n.global.t('commons.msg.operationSuccess'));
|
||||
})
|
||||
.finally(() => {
|
||||
open.value = false;
|
||||
|
||||
@@ -401,18 +401,20 @@ const onSubmit = async (formEl: FormInstance | undefined) => {
|
||||
dialogData.value.rowData!.labels = dialogData.value.rowData!.labelsStr.split('\n');
|
||||
}
|
||||
dialogData.value.rowData!.cmd = [];
|
||||
if (dialogData.value.rowData?.cmdStr.indexOf(`'`) !== -1) {
|
||||
let itemCmd = dialogData.value.rowData!.cmdStr.split(`'`);
|
||||
for (const cmd of itemCmd) {
|
||||
if (cmd && cmd !== ' ') {
|
||||
if (dialogData.value.rowData?.cmdStr) {
|
||||
if (dialogData.value.rowData?.cmdStr.indexOf(`'`) !== -1) {
|
||||
let itemCmd = dialogData.value.rowData!.cmdStr.split(`'`);
|
||||
for (const cmd of itemCmd) {
|
||||
if (cmd && cmd !== ' ') {
|
||||
dialogData.value.rowData!.cmd.push(cmd);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let itemCmd = dialogData.value.rowData!.cmdStr.split(` `);
|
||||
for (const cmd of itemCmd) {
|
||||
dialogData.value.rowData!.cmd.push(cmd);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let itemCmd = dialogData.value.rowData!.cmdStr.split(` `);
|
||||
for (const cmd of itemCmd) {
|
||||
dialogData.value.rowData!.cmd.push(cmd);
|
||||
}
|
||||
}
|
||||
if (dialogData.value.rowData!.entrypointStr) {
|
||||
dialogData.value.rowData!.entrypoint = dialogData.value.rowData!.entrypointStr.split(' ');
|
||||
|
||||
@@ -164,7 +164,7 @@
|
||||
</template>
|
||||
</LayoutContent>
|
||||
|
||||
<div v-if="!currentDB?.id">
|
||||
<div v-if="dbOptionsLocal.length === 0 && dbOptionsRemote.length === 0">
|
||||
<LayoutContent :title="'MySQL ' + $t('menu.database')" :divider="true">
|
||||
<template #main>
|
||||
<div class="app-warn">
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
plain
|
||||
round
|
||||
size="small"
|
||||
:disabled="app.limit == 1 && app.installed"
|
||||
@click="goInstall(app.key)"
|
||||
>
|
||||
{{ $t('app.install') }}
|
||||
@@ -57,7 +58,7 @@ let req = reactive({
|
||||
});
|
||||
|
||||
let loading = ref(false);
|
||||
let apps = ref<App.App[]>([]);
|
||||
let apps = ref<App.AppDTO[]>([]);
|
||||
|
||||
const acceptParams = (): void => {
|
||||
search(req);
|
||||
|
||||
@@ -228,7 +228,7 @@ const search = async () => {
|
||||
needLoadStatus = true;
|
||||
}
|
||||
}
|
||||
if (needLoadStatus) {
|
||||
if (supervisorStatus.value.isRunning && needLoadStatus) {
|
||||
setTimeout(loadStatus, 1000);
|
||||
}
|
||||
} catch (error) {}
|
||||
@@ -252,7 +252,7 @@ const loadStatus = async () => {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (needLoadStatus) {
|
||||
if (supervisorStatus.value.isRunning && needLoadStatus) {
|
||||
setTimeout(loadStatus, 2000);
|
||||
}
|
||||
} catch (error) {}
|
||||
|
||||
@@ -63,44 +63,60 @@
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('runtime.image')" prop="image">
|
||||
<el-input v-model="runtime.image"></el-input>
|
||||
</el-form-item>
|
||||
<div v-if="initParam">
|
||||
<el-form-item v-if="runtime.type === 'php'">
|
||||
<el-alert :title="$t('runtime.buildHelper')" type="warning" :closable="false" />
|
||||
</el-form-item>
|
||||
<Params
|
||||
v-if="mode === 'create'"
|
||||
v-model:form="runtime.params"
|
||||
v-model:params="appParams"
|
||||
v-model:rules="rules"
|
||||
></Params>
|
||||
<EditParams
|
||||
v-if="mode === 'edit'"
|
||||
v-model:form="runtime.params"
|
||||
v-model:params="editParams"
|
||||
v-model:rules="rules"
|
||||
></EditParams>
|
||||
<el-form-item v-if="runtime.type === 'php'">
|
||||
<el-alert type="info" :closable="false">
|
||||
<span>{{ $t('runtime.extendHelper') }}</span>
|
||||
<span v-html="$t('runtime.phpPluginHelper')"></span>
|
||||
<br />
|
||||
</el-alert>
|
||||
</el-form-item>
|
||||
<div v-if="runtime.type === 'php' && mode == 'edit'">
|
||||
<div v-if="runtime.type === 'php'">
|
||||
<el-form-item :label="$t('runtime.image')" prop="image">
|
||||
<el-input v-model="runtime.image"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('runtime.source')" prop="source">
|
||||
<el-select v-model="runtime.source" filterable allow-create default-first-option>
|
||||
<el-option
|
||||
v-for="(source, index) in phpSources"
|
||||
:key="index"
|
||||
:label="source.label + ' [' + source.value + ']'"
|
||||
:value="source.value"
|
||||
></el-option>
|
||||
</el-select>
|
||||
<span class="input-help">
|
||||
{{ $t('runtime.phpsourceHelper') }}
|
||||
</span>
|
||||
</el-form-item>
|
||||
|
||||
<Params
|
||||
v-if="mode === 'create'"
|
||||
v-model:form="runtime.params"
|
||||
v-model:params="appParams"
|
||||
v-model:rules="rules"
|
||||
></Params>
|
||||
<EditParams
|
||||
v-if="mode === 'edit'"
|
||||
v-model:form="runtime.params"
|
||||
v-model:params="editParams"
|
||||
v-model:rules="rules"
|
||||
></EditParams>
|
||||
<el-form-item>
|
||||
<el-checkbox v-model="runtime.rebuild">
|
||||
{{ $t('runtime.rebuild') }}
|
||||
</el-checkbox>
|
||||
<el-alert :title="$t('runtime.buildHelper')" type="warning" :closable="false" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-alert type="info" :closable="false">
|
||||
<span>{{ $t('runtime.rebuildHelper') }}</span>
|
||||
<span>{{ $t('runtime.extendHelper') }}</span>
|
||||
<span v-html="$t('runtime.phpPluginHelper')"></span>
|
||||
<br />
|
||||
</el-alert>
|
||||
</el-form-item>
|
||||
<div v-if="mode == 'edit'">
|
||||
<el-form-item>
|
||||
<el-checkbox v-model="runtime.rebuild">
|
||||
{{ $t('runtime.rebuild') }}
|
||||
</el-checkbox>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-alert type="info" :closable="false">
|
||||
<span>{{ $t('runtime.rebuildHelper') }}</span>
|
||||
<br />
|
||||
</el-alert>
|
||||
</el-form-item>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -160,23 +176,59 @@ const appReq = reactive({
|
||||
page: 1,
|
||||
pageSize: 20,
|
||||
});
|
||||
const runtime = ref<Runtime.RuntimeCreate>({
|
||||
const initData = (type: string) => ({
|
||||
name: '',
|
||||
appDetailId: undefined,
|
||||
image: '',
|
||||
params: {},
|
||||
type: 'php',
|
||||
type: type,
|
||||
resource: 'appstore',
|
||||
rebuild: false,
|
||||
source: 'mirrors.ustc.edu.cn',
|
||||
});
|
||||
|
||||
let runtime = reactive<Runtime.RuntimeCreate>(initData('php'));
|
||||
|
||||
const rules = ref<any>({
|
||||
name: [Rules.appName],
|
||||
resource: [Rules.requiredInput],
|
||||
appId: [Rules.requiredSelect],
|
||||
version: [Rules.requiredInput, Rules.paramCommon],
|
||||
image: [Rules.requiredInput, Rules.imageName],
|
||||
source: [Rules.requiredSelect],
|
||||
});
|
||||
|
||||
const phpSources = [
|
||||
{
|
||||
label: i18n.global.t('runtime.ustc'),
|
||||
value: 'mirrors.ustc.edu.cn',
|
||||
},
|
||||
{
|
||||
label: i18n.global.t('runtime.netease'),
|
||||
value: 'mirrors.163.com',
|
||||
},
|
||||
{
|
||||
label: i18n.global.t('runtime.aliyun'),
|
||||
value: 'mirrors.aliyun.com',
|
||||
},
|
||||
{
|
||||
label: i18n.global.t('runtime.tsinghua'),
|
||||
value: 'mirrors.tuna.tsinghua.edu.cn',
|
||||
},
|
||||
{
|
||||
label: i18n.global.t('runtime.xtomhk'),
|
||||
value: 'mirrors.xtom.com.hk',
|
||||
},
|
||||
{
|
||||
label: i18n.global.t('runtime.xtom'),
|
||||
value: 'mirrors.xtom.com',
|
||||
},
|
||||
{
|
||||
label: i18n.global.t('runtime.default'),
|
||||
value: 'dl-cdn.alpinelinux.org',
|
||||
},
|
||||
];
|
||||
|
||||
const em = defineEmits(['close']);
|
||||
|
||||
const handleClose = () => {
|
||||
@@ -186,12 +238,12 @@ const handleClose = () => {
|
||||
|
||||
const changeResource = (resource: string) => {
|
||||
if (resource === 'local') {
|
||||
runtime.value.appDetailId = undefined;
|
||||
runtime.value.version = '';
|
||||
runtime.value.params = {};
|
||||
runtime.value.image = '';
|
||||
runtime.appDetailId = undefined;
|
||||
runtime.version = '';
|
||||
runtime.params = {};
|
||||
runtime.image = '';
|
||||
} else {
|
||||
runtime.value.version = '';
|
||||
runtime.version = '';
|
||||
searchApp(null);
|
||||
}
|
||||
};
|
||||
@@ -201,7 +253,7 @@ const searchApp = (appId: number) => {
|
||||
apps.value = res.data.items || [];
|
||||
if (res.data && res.data.items && res.data.items.length > 0) {
|
||||
if (appId == null) {
|
||||
runtime.value.appId = res.data.items[0].id;
|
||||
runtime.appId = res.data.items[0].id;
|
||||
getApp(res.data.items[0].key, mode.value);
|
||||
} else {
|
||||
res.data.items.forEach((item) => {
|
||||
@@ -227,10 +279,10 @@ const changeApp = (appId: number) => {
|
||||
const changeVersion = () => {
|
||||
loading.value = true;
|
||||
initParam.value = false;
|
||||
GetAppDetail(runtime.value.appId, runtime.value.version, 'runtime')
|
||||
GetAppDetail(runtime.appId, runtime.version, 'runtime')
|
||||
.then((res) => {
|
||||
runtime.value.appDetailId = res.data.id;
|
||||
runtime.value.image = res.data.image + ':' + runtime.value.version;
|
||||
runtime.appDetailId = res.data.id;
|
||||
runtime.image = res.data.image + ':' + runtime.version;
|
||||
appParams.value = res.data.params;
|
||||
initParam.value = true;
|
||||
})
|
||||
@@ -243,7 +295,7 @@ const getApp = (appkey: string, mode: string) => {
|
||||
GetApp(appkey).then((res) => {
|
||||
appVersions.value = res.data.versions || [];
|
||||
if (res.data.versions.length > 0) {
|
||||
runtime.value.version = res.data.versions[0];
|
||||
runtime.version = res.data.versions[0];
|
||||
if (mode === 'create') {
|
||||
changeVersion();
|
||||
} else {
|
||||
@@ -261,7 +313,7 @@ const submit = async (formEl: FormInstance | undefined) => {
|
||||
}
|
||||
if (mode.value == 'create') {
|
||||
loading.value = true;
|
||||
CreateRuntime(runtime.value)
|
||||
CreateRuntime(runtime)
|
||||
.then(() => {
|
||||
MsgSuccess(i18n.global.t('commons.msg.createSuccess'));
|
||||
handleClose();
|
||||
@@ -271,7 +323,7 @@ const submit = async (formEl: FormInstance | undefined) => {
|
||||
});
|
||||
} else {
|
||||
loading.value = true;
|
||||
UpdateRuntime(runtime.value)
|
||||
UpdateRuntime(runtime)
|
||||
.then(() => {
|
||||
MsgSuccess(i18n.global.t('commons.msg.updateSuccess'));
|
||||
handleClose();
|
||||
@@ -287,7 +339,7 @@ const getRuntime = async (id: number) => {
|
||||
try {
|
||||
const res = await GetRuntime(id);
|
||||
const data = res.data;
|
||||
runtime.value = {
|
||||
Object.assign(runtime, {
|
||||
id: data.id,
|
||||
name: data.name,
|
||||
appDetailId: data.appDetailId,
|
||||
@@ -298,7 +350,8 @@ const getRuntime = async (id: number) => {
|
||||
appId: data.appId,
|
||||
version: data.version,
|
||||
rebuild: true,
|
||||
};
|
||||
source: data.source,
|
||||
});
|
||||
editParams.value = data.appParams;
|
||||
if (mode.value == 'create') {
|
||||
searchApp(data.appId);
|
||||
@@ -312,16 +365,10 @@ const acceptParams = async (props: OperateRrops) => {
|
||||
mode.value = props.mode;
|
||||
initParam.value = false;
|
||||
if (props.mode === 'create') {
|
||||
runtime.value = {
|
||||
name: '',
|
||||
appDetailId: undefined,
|
||||
image: '',
|
||||
params: {},
|
||||
type: props.type,
|
||||
resource: 'appstore',
|
||||
};
|
||||
Object.assign(runtime, initData(props.type));
|
||||
searchApp(null);
|
||||
} else {
|
||||
searchApp(null);
|
||||
getRuntime(props.id);
|
||||
}
|
||||
open.value = true;
|
||||
|
||||
@@ -4,19 +4,14 @@
|
||||
<el-form-item :label="$t('website.enable')">
|
||||
<el-switch v-model="data.enable" @change="updateEnable"></el-switch>
|
||||
</el-form-item>
|
||||
<div style="margin-top: 10px">
|
||||
<el-checkbox border v-model="tailLog" style="float: left" @change="changeTail">
|
||||
<div class="mt-2.5">
|
||||
<el-checkbox border v-model="tailLog" class="float-left" @change="changeTail">
|
||||
{{ $t('commons.button.watch') }}
|
||||
</el-checkbox>
|
||||
<el-button
|
||||
style="margin-left: 20px"
|
||||
@click="onDownload"
|
||||
icon="Download"
|
||||
:disabled="data.content === ''"
|
||||
>
|
||||
<el-button class="ml-5" @click="onDownload" icon="Download" :disabled="data.content === ''">
|
||||
{{ $t('file.download') }}
|
||||
</el-button>
|
||||
<el-button style="margin-left: 20px" @click="cleanLog" icon="Delete" :disabled="data.content === ''">
|
||||
<el-button class="ml-5" @click="cleanLog" icon="Delete" :disabled="data.content === ''">
|
||||
{{ $t('commons.button.clean') }}
|
||||
</el-button>
|
||||
</div>
|
||||
@@ -46,8 +41,8 @@ import { javascript } from '@codemirror/lang-javascript';
|
||||
import { oneDark } from '@codemirror/theme-one-dark';
|
||||
import { computed, nextTick, onMounted, onUnmounted, reactive, ref, shallowRef } from 'vue';
|
||||
import { OpWebsiteLog } from '@/api/modules/website';
|
||||
import { dateFormatForName, downloadWithContent } from '@/utils/util';
|
||||
import { useDeleteData } from '@/hooks/use-delete-data';
|
||||
import { downloadFile } from '@/utils/util';
|
||||
|
||||
const extensions = [javascript(), oneDark];
|
||||
const props = defineProps({
|
||||
@@ -70,6 +65,7 @@ const loading = ref(false);
|
||||
const data = ref({
|
||||
enable: false,
|
||||
content: '',
|
||||
path: '',
|
||||
});
|
||||
const tailLog = ref(false);
|
||||
let timer: NodeJS.Timer | null = null;
|
||||
@@ -165,7 +161,7 @@ const cleanLog = async () => {
|
||||
};
|
||||
|
||||
const onDownload = async () => {
|
||||
downloadWithContent(data.value.content, logType.value + '-' + dateFormatForName(new Date()) + '.log');
|
||||
downloadFile(data.value.path);
|
||||
};
|
||||
|
||||
const onCloseLog = async () => {
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
:placeholder="$t('commons.msg.noneData')"
|
||||
:indent-with-tab="true"
|
||||
:tabSize="4"
|
||||
style="margin-top: 10px; max-height: 700px"
|
||||
style="max-height: 700px"
|
||||
:lineWrapping="true"
|
||||
:matchBrackets="true"
|
||||
theme="cobalt"
|
||||
@@ -13,11 +13,9 @@
|
||||
:extensions="extensions"
|
||||
v-model="content"
|
||||
/>
|
||||
<div style="margin-top: 10px">
|
||||
<el-button type="primary" @click="submit()">
|
||||
{{ $t('nginx.saveAndReload') }}
|
||||
</el-button>
|
||||
</div>
|
||||
<el-button type="primary" @click="submit()" class="mt-2.5">
|
||||
{{ $t('nginx.saveAndReload') }}
|
||||
</el-button>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
:placeholder="$t('commons.msg.noneData')"
|
||||
:indent-with-tab="true"
|
||||
:tabSize="4"
|
||||
style="margin-top: 10px; max-height: 700px"
|
||||
style="max-height: 700px"
|
||||
:lineWrapping="true"
|
||||
:matchBrackets="true"
|
||||
theme="cobalt"
|
||||
@@ -13,11 +13,10 @@
|
||||
:extensions="extensions"
|
||||
v-model="content"
|
||||
/>
|
||||
<div style="margin-top: 10px">
|
||||
<el-button type="primary" @click="submit()">
|
||||
{{ $t('nginx.saveAndReload') }}
|
||||
</el-button>
|
||||
</div>
|
||||
<el-button type="primary" @click="openUpdate()" class="mt-2.5">
|
||||
{{ $t('nginx.saveAndReload') }}
|
||||
</el-button>
|
||||
<ConfirmDialog ref="confirmDialogRef" @confirm="submit()"></ConfirmDialog>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
@@ -52,9 +51,10 @@ const id = computed(() => {
|
||||
return props.id;
|
||||
});
|
||||
|
||||
let data = ref<File.File>();
|
||||
let loading = ref(false);
|
||||
let content = ref('');
|
||||
const data = ref<File.File>();
|
||||
const loading = ref(false);
|
||||
const content = ref('');
|
||||
const confirmDialogRef = ref();
|
||||
|
||||
const get = () => {
|
||||
loading.value = true;
|
||||
@@ -68,6 +68,14 @@ const get = () => {
|
||||
});
|
||||
};
|
||||
|
||||
const openUpdate = async () => {
|
||||
confirmDialogRef.value!.acceptParams({
|
||||
header: i18n.global.t('database.confChange'),
|
||||
operationInfo: i18n.global.t('database.restartNowHelper'),
|
||||
submitInputInfo: i18n.global.t('database.restartNow'),
|
||||
});
|
||||
};
|
||||
|
||||
const submit = async () => {
|
||||
loading.value = true;
|
||||
UpdatePHPFile({
|
||||
|
||||
Reference in New Issue
Block a user