mirror of
https://github.com/acepanel/panel.git
synced 2026-02-04 01:57:19 +08:00
feat: 支持更多运行环境
This commit is contained in:
@@ -96,7 +96,11 @@ func initWeb() (*app.Web, error) {
|
||||
certAccountService := service.NewCertAccountService(certAccountRepo)
|
||||
appService := service.NewAppService(locale, appRepo, cacheRepo, settingRepo)
|
||||
environmentService := service.NewEnvironmentService(locale, environmentRepo, taskRepo)
|
||||
environmentGoService := service.NewEnvironmentGoService(locale, environmentRepo)
|
||||
environmentJavaService := service.NewEnvironmentJavaService(locale, environmentRepo)
|
||||
environmentNodejsService := service.NewEnvironmentNodejsService(locale, environmentRepo)
|
||||
environmentPHPService := service.NewEnvironmentPHPService(locale, config, environmentRepo, taskRepo)
|
||||
environmentPythonService := service.NewEnvironmentPythonService(locale, environmentRepo)
|
||||
cronService := service.NewCronService(cronRepo)
|
||||
processService := service.NewProcessService()
|
||||
safeRepo := data.NewSafeRepo(logger)
|
||||
@@ -152,7 +156,7 @@ func initWeb() (*app.Web, error) {
|
||||
s3fsApp := s3fs.NewApp(locale)
|
||||
supervisorApp := supervisor.NewApp(locale)
|
||||
loader := bootstrap.NewLoader(apacheApp, codeserverApp, dockerApp, fail2banApp, frpApp, giteaApp, mariadbApp, memcachedApp, minioApp, mysqlApp, nginxApp, openrestyApp, perconaApp, phpmyadminApp, podmanApp, postgresqlApp, pureftpdApp, redisApp, rsyncApp, s3fsApp, supervisorApp)
|
||||
http := route.NewHttp(config, userService, userTokenService, homeService, taskService, websiteService, projectService, databaseService, databaseServerService, databaseUserService, backupService, certService, certDNSService, certAccountService, appService, environmentService, environmentPHPService, cronService, processService, safeService, firewallService, sshService, containerService, containerComposeService, containerNetworkService, containerImageService, containerVolumeService, fileService, logService, monitorService, settingService, systemctlService, toolboxSystemService, toolboxBenchmarkService, toolboxSSHService, toolboxDiskService, toolboxLogService, webHookService, templateService, loader)
|
||||
http := route.NewHttp(config, userService, userTokenService, homeService, taskService, websiteService, projectService, databaseService, databaseServerService, databaseUserService, backupService, certService, certDNSService, certAccountService, appService, environmentService, environmentGoService, environmentJavaService, environmentNodejsService, environmentPHPService, environmentPythonService, cronService, processService, safeService, firewallService, sshService, containerService, containerComposeService, containerNetworkService, containerImageService, containerVolumeService, fileService, logService, monitorService, settingService, systemctlService, toolboxSystemService, toolboxBenchmarkService, toolboxSSHService, toolboxDiskService, toolboxLogService, webHookService, templateService, loader)
|
||||
wsService := service.NewWsService(locale, config, logger, sshRepo)
|
||||
ws := route.NewWs(wsService)
|
||||
mux, err := bootstrap.NewRouter(locale, middlewares, http, ws)
|
||||
|
||||
7
go.sum
7
go.sum
@@ -125,6 +125,8 @@ github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXi
|
||||
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||
github.com/google/subcommands v1.2.0 h1:vWQspBTo2nEqTUFita5/KeEWlUL8kQObDFbub/EN9oE=
|
||||
github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk=
|
||||
github.com/google/wire v0.7.0 h1:JxUKI6+CVBgCO2WToKy/nQk0sS+amI9z9EjVmdaocj4=
|
||||
github.com/google/wire v0.7.0/go.mod h1:n6YbUQD9cPKTnHXEBN2DXlOp/mVADhVErcMFb0v3J18=
|
||||
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
||||
@@ -276,6 +278,7 @@ github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/9
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
|
||||
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 h1:o4JXh1EVt9k/+g42oCprj/FisM4qX9L3sZB3upGN2ZU=
|
||||
@@ -386,6 +389,8 @@ golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU
|
||||
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
|
||||
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
||||
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
|
||||
golang.org/x/mod v0.31.0 h1:HaW9xtz0+kOcWKwli0ZXy79Ix+UW/vOfmWI5QVd2tgI=
|
||||
golang.org/x/mod v0.31.0/go.mod h1:43JraMp9cGx1Rx3AqioxrbrhNsLl2l/iNAvuBkrezpg=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
@@ -459,6 +464,8 @@ golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtn
|
||||
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.40.0 h1:yLkxfA+Qnul4cs9QA3KnlFu0lVmd8JJfoq+E41uSutA=
|
||||
golang.org/x/tools v0.40.0/go.mod h1:Ik/tzLRlbscWpqqMRjyWYDisX8bG13FrdXp3o4Sr9lc=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
|
||||
|
||||
@@ -36,7 +36,11 @@ func NewEnvironmentRepo(t *gotext.Locale, conf *config.Config, cache biz.CacheRe
|
||||
|
||||
func (r *environmentRepo) Types() []types.LV {
|
||||
return []types.LV{
|
||||
{Label: "Go", Value: "go"},
|
||||
{Label: "Java", Value: "java"},
|
||||
{Label: "Node.js", Value: "nodejs"},
|
||||
{Label: "PHP", Value: "php"},
|
||||
{Label: "Python", Value: "python"},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,8 +76,16 @@ func (r *environmentRepo) IsInstalled(typ, slug string) bool {
|
||||
path := filepath.Join(app.Root, "server", typ, slug)
|
||||
var binFile string
|
||||
switch typ {
|
||||
case "go":
|
||||
binFile = filepath.Join(path, "bin", "go")
|
||||
case "java":
|
||||
binFile = filepath.Join(path, "bin", "java")
|
||||
case "nodejs":
|
||||
binFile = filepath.Join(path, "bin", "node")
|
||||
case "php":
|
||||
binFile = filepath.Join(path, "bin", "php")
|
||||
case "python":
|
||||
binFile = filepath.Join(path, "bin", "python3")
|
||||
default:
|
||||
return false
|
||||
}
|
||||
@@ -102,17 +114,33 @@ func (r *environmentRepo) InstalledVersion(typ, slug string) string {
|
||||
}
|
||||
|
||||
var basePath = filepath.Join(app.Root, "server", typ, slug)
|
||||
var version string
|
||||
var err error
|
||||
|
||||
switch typ {
|
||||
case "go":
|
||||
// go version go1.21.0 linux/amd64 -> 1.21.0
|
||||
version, err = shell.Exec(filepath.Join(basePath, "bin", "go") + " version | awk '{print $3}' | sed 's/go//'")
|
||||
case "java":
|
||||
// openjdk version "17.0.8" 2023-07-18 LTS -> 17.0.8
|
||||
version, err = shell.Exec(filepath.Join(basePath, "bin", "java") + " -version 2>&1 | head -n 1 | awk -F'\"' '{print $2}'")
|
||||
case "nodejs":
|
||||
// v20.10.0 -> 20.10.0
|
||||
version, err = shell.Exec(filepath.Join(basePath, "bin", "node") + " -v | sed 's/v//'")
|
||||
case "php":
|
||||
version, err := shell.Exec(filepath.Join(basePath, "bin", "php") + " -v | head -n 1 | awk '{print $2}'")
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return version
|
||||
// PHP 8.3.0 (cli) -> 8.3.0
|
||||
version, err = shell.Exec(filepath.Join(basePath, "bin", "php") + " -v | head -n 1 | awk '{print $2}'")
|
||||
case "python":
|
||||
// Python 3.11.5 -> 3.11.5
|
||||
version, err = shell.Exec(filepath.Join(basePath, "bin", "python3") + " --version | awk '{print $2}'")
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return version
|
||||
}
|
||||
|
||||
func (r *environmentRepo) HasUpdate(typ, slug string) bool {
|
||||
|
||||
24
internal/http/request/environment_common.go
Normal file
24
internal/http/request/environment_common.go
Normal file
@@ -0,0 +1,24 @@
|
||||
package request
|
||||
|
||||
// EnvironmentSlug 环境版本请求(通用)
|
||||
type EnvironmentSlug struct {
|
||||
Slug string `json:"slug"`
|
||||
}
|
||||
|
||||
// EnvironmentProxy Go 代理设置请求
|
||||
type EnvironmentProxy struct {
|
||||
Slug string `json:"slug"`
|
||||
Proxy string `form:"proxy" json:"proxy" validate:"required"`
|
||||
}
|
||||
|
||||
// EnvironmentRegistry Node.js 镜像设置请求
|
||||
type EnvironmentRegistry struct {
|
||||
Slug string `json:"slug"`
|
||||
Registry string `form:"registry" json:"registry" validate:"required"`
|
||||
}
|
||||
|
||||
// EnvironmentMirror Python 镜像设置请求
|
||||
type EnvironmentMirror struct {
|
||||
Slug string `json:"slug"`
|
||||
Mirror string `form:"mirror" json:"mirror" validate:"required"`
|
||||
}
|
||||
@@ -16,46 +16,50 @@ import (
|
||||
)
|
||||
|
||||
type Http struct {
|
||||
conf *config.Config
|
||||
user *service.UserService
|
||||
userToken *service.UserTokenService
|
||||
home *service.HomeService
|
||||
task *service.TaskService
|
||||
website *service.WebsiteService
|
||||
project *service.ProjectService
|
||||
database *service.DatabaseService
|
||||
databaseServer *service.DatabaseServerService
|
||||
databaseUser *service.DatabaseUserService
|
||||
backup *service.BackupService
|
||||
cert *service.CertService
|
||||
certDNS *service.CertDNSService
|
||||
certAccount *service.CertAccountService
|
||||
app *service.AppService
|
||||
environment *service.EnvironmentService
|
||||
environmentPHP *service.EnvironmentPHPService
|
||||
cron *service.CronService
|
||||
process *service.ProcessService
|
||||
safe *service.SafeService
|
||||
firewall *service.FirewallService
|
||||
ssh *service.SSHService
|
||||
container *service.ContainerService
|
||||
containerCompose *service.ContainerComposeService
|
||||
containerNetwork *service.ContainerNetworkService
|
||||
containerImage *service.ContainerImageService
|
||||
containerVolume *service.ContainerVolumeService
|
||||
file *service.FileService
|
||||
log *service.LogService
|
||||
monitor *service.MonitorService
|
||||
setting *service.SettingService
|
||||
systemctl *service.SystemctlService
|
||||
toolboxSystem *service.ToolboxSystemService
|
||||
toolboxBenchmark *service.ToolboxBenchmarkService
|
||||
toolboxSSH *service.ToolboxSSHService
|
||||
toolboxDisk *service.ToolboxDiskService
|
||||
toolboxLog *service.ToolboxLogService
|
||||
webhook *service.WebHookService
|
||||
template *service.TemplateService
|
||||
apps *apploader.Loader
|
||||
conf *config.Config
|
||||
user *service.UserService
|
||||
userToken *service.UserTokenService
|
||||
home *service.HomeService
|
||||
task *service.TaskService
|
||||
website *service.WebsiteService
|
||||
project *service.ProjectService
|
||||
database *service.DatabaseService
|
||||
databaseServer *service.DatabaseServerService
|
||||
databaseUser *service.DatabaseUserService
|
||||
backup *service.BackupService
|
||||
cert *service.CertService
|
||||
certDNS *service.CertDNSService
|
||||
certAccount *service.CertAccountService
|
||||
app *service.AppService
|
||||
environment *service.EnvironmentService
|
||||
environmentGo *service.EnvironmentGoService
|
||||
environmentJava *service.EnvironmentJavaService
|
||||
environmentNodejs *service.EnvironmentNodejsService
|
||||
environmentPHP *service.EnvironmentPHPService
|
||||
environmentPython *service.EnvironmentPythonService
|
||||
cron *service.CronService
|
||||
process *service.ProcessService
|
||||
safe *service.SafeService
|
||||
firewall *service.FirewallService
|
||||
ssh *service.SSHService
|
||||
container *service.ContainerService
|
||||
containerCompose *service.ContainerComposeService
|
||||
containerNetwork *service.ContainerNetworkService
|
||||
containerImage *service.ContainerImageService
|
||||
containerVolume *service.ContainerVolumeService
|
||||
file *service.FileService
|
||||
log *service.LogService
|
||||
monitor *service.MonitorService
|
||||
setting *service.SettingService
|
||||
systemctl *service.SystemctlService
|
||||
toolboxSystem *service.ToolboxSystemService
|
||||
toolboxBenchmark *service.ToolboxBenchmarkService
|
||||
toolboxSSH *service.ToolboxSSHService
|
||||
toolboxDisk *service.ToolboxDiskService
|
||||
toolboxLog *service.ToolboxLogService
|
||||
webhook *service.WebHookService
|
||||
template *service.TemplateService
|
||||
apps *apploader.Loader
|
||||
}
|
||||
|
||||
func NewHttp(
|
||||
@@ -75,7 +79,11 @@ func NewHttp(
|
||||
certAccount *service.CertAccountService,
|
||||
app *service.AppService,
|
||||
environment *service.EnvironmentService,
|
||||
environmentGo *service.EnvironmentGoService,
|
||||
environmentJava *service.EnvironmentJavaService,
|
||||
environmentNodejs *service.EnvironmentNodejsService,
|
||||
environmentPHP *service.EnvironmentPHPService,
|
||||
environmentPython *service.EnvironmentPythonService,
|
||||
cron *service.CronService,
|
||||
process *service.ProcessService,
|
||||
safe *service.SafeService,
|
||||
@@ -101,46 +109,50 @@ func NewHttp(
|
||||
apps *apploader.Loader,
|
||||
) *Http {
|
||||
return &Http{
|
||||
conf: conf,
|
||||
user: user,
|
||||
userToken: userToken,
|
||||
home: home,
|
||||
task: task,
|
||||
website: website,
|
||||
project: project,
|
||||
database: database,
|
||||
databaseServer: databaseServer,
|
||||
databaseUser: databaseUser,
|
||||
backup: backup,
|
||||
cert: cert,
|
||||
certDNS: certDNS,
|
||||
certAccount: certAccount,
|
||||
app: app,
|
||||
environment: environment,
|
||||
environmentPHP: environmentPHP,
|
||||
cron: cron,
|
||||
process: process,
|
||||
safe: safe,
|
||||
firewall: firewall,
|
||||
ssh: ssh,
|
||||
container: container,
|
||||
containerCompose: containerCompose,
|
||||
containerNetwork: containerNetwork,
|
||||
containerImage: containerImage,
|
||||
containerVolume: containerVolume,
|
||||
file: file,
|
||||
log: log,
|
||||
monitor: monitor,
|
||||
setting: setting,
|
||||
systemctl: systemctl,
|
||||
toolboxSystem: toolboxSystem,
|
||||
toolboxBenchmark: toolboxBenchmark,
|
||||
toolboxSSH: toolboxSSH,
|
||||
toolboxDisk: toolboxDisk,
|
||||
toolboxLog: toolboxLog,
|
||||
webhook: webhook,
|
||||
template: template,
|
||||
apps: apps,
|
||||
conf: conf,
|
||||
user: user,
|
||||
userToken: userToken,
|
||||
home: home,
|
||||
task: task,
|
||||
website: website,
|
||||
project: project,
|
||||
database: database,
|
||||
databaseServer: databaseServer,
|
||||
databaseUser: databaseUser,
|
||||
backup: backup,
|
||||
cert: cert,
|
||||
certDNS: certDNS,
|
||||
certAccount: certAccount,
|
||||
app: app,
|
||||
environment: environment,
|
||||
environmentGo: environmentGo,
|
||||
environmentJava: environmentJava,
|
||||
environmentNodejs: environmentNodejs,
|
||||
environmentPHP: environmentPHP,
|
||||
environmentPython: environmentPython,
|
||||
cron: cron,
|
||||
process: process,
|
||||
safe: safe,
|
||||
firewall: firewall,
|
||||
ssh: ssh,
|
||||
container: container,
|
||||
containerCompose: containerCompose,
|
||||
containerNetwork: containerNetwork,
|
||||
containerImage: containerImage,
|
||||
containerVolume: containerVolume,
|
||||
file: file,
|
||||
log: log,
|
||||
monitor: monitor,
|
||||
setting: setting,
|
||||
systemctl: systemctl,
|
||||
toolboxSystem: toolboxSystem,
|
||||
toolboxBenchmark: toolboxBenchmark,
|
||||
toolboxSSH: toolboxSSH,
|
||||
toolboxDisk: toolboxDisk,
|
||||
toolboxLog: toolboxLog,
|
||||
webhook: webhook,
|
||||
template: template,
|
||||
apps: apps,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -306,6 +318,19 @@ func (route *Http) Register(r *chi.Mux) {
|
||||
r.Get("/uninstall", route.environment.Uninstall)
|
||||
r.Put("/update", route.environment.Update)
|
||||
r.Get("/is_installed", route.environment.IsInstalled)
|
||||
r.Route("/go", func(r chi.Router) {
|
||||
r.Post("/{slug}/set_cli", route.environmentGo.SetCli)
|
||||
r.Get("/{slug}/proxy", route.environmentGo.GetProxy)
|
||||
r.Post("/{slug}/proxy", route.environmentGo.SetProxy)
|
||||
})
|
||||
r.Route("/java", func(r chi.Router) {
|
||||
r.Post("/{slug}/set_cli", route.environmentJava.SetCli)
|
||||
})
|
||||
r.Route("/nodejs", func(r chi.Router) {
|
||||
r.Post("/{slug}/set_cli", route.environmentNodejs.SetCli)
|
||||
r.Get("/{slug}/registry", route.environmentNodejs.GetRegistry)
|
||||
r.Post("/{slug}/registry", route.environmentNodejs.SetRegistry)
|
||||
})
|
||||
r.Route("/php", func(r chi.Router) {
|
||||
r.Post("/{version}/set_cli", route.environmentPHP.SetCli)
|
||||
r.Get("/{version}/phpinfo", route.environmentPHP.PHPInfo)
|
||||
@@ -322,6 +347,11 @@ func (route *Http) Register(r *chi.Mux) {
|
||||
r.Post("/{version}/modules", route.environmentPHP.InstallModule)
|
||||
r.Delete("/{version}/modules", route.environmentPHP.UninstallModule)
|
||||
})
|
||||
r.Route("/python", func(r chi.Router) {
|
||||
r.Post("/{slug}/set_cli", route.environmentPython.SetCli)
|
||||
r.Get("/{slug}/mirror", route.environmentPython.GetMirror)
|
||||
r.Post("/{slug}/mirror", route.environmentPython.SetMirror)
|
||||
})
|
||||
})
|
||||
|
||||
r.Route("/cron", func(r chi.Router) {
|
||||
|
||||
90
internal/service/environment_go.go
Normal file
90
internal/service/environment_go.go
Normal file
@@ -0,0 +1,90 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/leonelquinteros/gotext"
|
||||
|
||||
"github.com/acepanel/panel/internal/app"
|
||||
"github.com/acepanel/panel/internal/biz"
|
||||
"github.com/acepanel/panel/internal/http/request"
|
||||
"github.com/acepanel/panel/pkg/shell"
|
||||
)
|
||||
|
||||
type EnvironmentGoService struct {
|
||||
t *gotext.Locale
|
||||
environmentRepo biz.EnvironmentRepo
|
||||
}
|
||||
|
||||
func NewEnvironmentGoService(t *gotext.Locale, environmentRepo biz.EnvironmentRepo) *EnvironmentGoService {
|
||||
return &EnvironmentGoService{
|
||||
t: t,
|
||||
environmentRepo: environmentRepo,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *EnvironmentGoService) SetCli(w http.ResponseWriter, r *http.Request) {
|
||||
req, err := Bind[request.EnvironmentSlug](r)
|
||||
if err != nil {
|
||||
Error(w, http.StatusUnprocessableEntity, "%v", err)
|
||||
return
|
||||
}
|
||||
if !s.environmentRepo.IsInstalled("go", req.Slug) {
|
||||
Error(w, http.StatusUnprocessableEntity, s.t.Get("Go-%s is not installed", req.Slug))
|
||||
return
|
||||
}
|
||||
|
||||
binPath := fmt.Sprintf("%s/server/go/%s/bin", app.Root, req.Slug)
|
||||
if _, err = shell.Execf("ln -sf %s/go /usr/local/bin/go", binPath); err != nil {
|
||||
Error(w, http.StatusInternalServerError, "%v", err)
|
||||
return
|
||||
}
|
||||
if _, err = shell.Execf("ln -sf %s/gofmt /usr/local/bin/gofmt", binPath); err != nil {
|
||||
Error(w, http.StatusInternalServerError, "%v", err)
|
||||
return
|
||||
}
|
||||
|
||||
Success(w, nil)
|
||||
}
|
||||
|
||||
func (s *EnvironmentGoService) GetProxy(w http.ResponseWriter, r *http.Request) {
|
||||
req, err := Bind[request.EnvironmentSlug](r)
|
||||
if err != nil {
|
||||
Error(w, http.StatusUnprocessableEntity, "%v", err)
|
||||
return
|
||||
}
|
||||
if !s.environmentRepo.IsInstalled("go", req.Slug) {
|
||||
Error(w, http.StatusUnprocessableEntity, s.t.Get("Go-%s is not installed", req.Slug))
|
||||
return
|
||||
}
|
||||
|
||||
goBin := fmt.Sprintf("%s/server/go/%s/bin/go", app.Root, req.Slug)
|
||||
proxy, err := shell.Execf("%s env GOPROXY", goBin)
|
||||
if err != nil {
|
||||
proxy = "https://proxy.golang.org,direct"
|
||||
}
|
||||
|
||||
Success(w, strings.TrimSpace(proxy))
|
||||
}
|
||||
|
||||
func (s *EnvironmentGoService) SetProxy(w http.ResponseWriter, r *http.Request) {
|
||||
req, err := Bind[request.EnvironmentProxy](r)
|
||||
if err != nil {
|
||||
Error(w, http.StatusUnprocessableEntity, "%v", err)
|
||||
return
|
||||
}
|
||||
if !s.environmentRepo.IsInstalled("go", req.Slug) {
|
||||
Error(w, http.StatusUnprocessableEntity, s.t.Get("Go-%s is not installed", req.Slug))
|
||||
return
|
||||
}
|
||||
|
||||
goBin := fmt.Sprintf("%s/server/go/%s/bin/go", app.Root, req.Slug)
|
||||
if _, err = shell.Execf("%s env -w GOPROXY=%s", goBin, req.Proxy); err != nil {
|
||||
Error(w, http.StatusInternalServerError, "%v", err)
|
||||
return
|
||||
}
|
||||
|
||||
Success(w, nil)
|
||||
}
|
||||
48
internal/service/environment_java.go
Normal file
48
internal/service/environment_java.go
Normal file
@@ -0,0 +1,48 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/leonelquinteros/gotext"
|
||||
|
||||
"github.com/acepanel/panel/internal/app"
|
||||
"github.com/acepanel/panel/internal/biz"
|
||||
"github.com/acepanel/panel/internal/http/request"
|
||||
"github.com/acepanel/panel/pkg/shell"
|
||||
)
|
||||
|
||||
type EnvironmentJavaService struct {
|
||||
t *gotext.Locale
|
||||
environmentRepo biz.EnvironmentRepo
|
||||
}
|
||||
|
||||
func NewEnvironmentJavaService(t *gotext.Locale, environmentRepo biz.EnvironmentRepo) *EnvironmentJavaService {
|
||||
return &EnvironmentJavaService{
|
||||
t: t,
|
||||
environmentRepo: environmentRepo,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *EnvironmentJavaService) SetCli(w http.ResponseWriter, r *http.Request) {
|
||||
req, err := Bind[request.EnvironmentSlug](r)
|
||||
if err != nil {
|
||||
Error(w, http.StatusUnprocessableEntity, "%v", err)
|
||||
return
|
||||
}
|
||||
if !s.environmentRepo.IsInstalled("java", req.Slug) {
|
||||
Error(w, http.StatusUnprocessableEntity, s.t.Get("Java-%s is not installed", req.Slug))
|
||||
return
|
||||
}
|
||||
|
||||
binPath := fmt.Sprintf("%s/server/java/%s/bin", app.Root, req.Slug)
|
||||
binaries := []string{"java", "javac", "jar", "jshell"}
|
||||
for _, bin := range binaries {
|
||||
if _, err = shell.Execf("ln -sf %s/%s /usr/local/bin/%s", binPath, bin, bin); err != nil {
|
||||
Error(w, http.StatusInternalServerError, "%v", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
Success(w, nil)
|
||||
}
|
||||
89
internal/service/environment_nodejs.go
Normal file
89
internal/service/environment_nodejs.go
Normal file
@@ -0,0 +1,89 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/leonelquinteros/gotext"
|
||||
|
||||
"github.com/acepanel/panel/internal/app"
|
||||
"github.com/acepanel/panel/internal/biz"
|
||||
"github.com/acepanel/panel/internal/http/request"
|
||||
"github.com/acepanel/panel/pkg/shell"
|
||||
)
|
||||
|
||||
type EnvironmentNodejsService struct {
|
||||
t *gotext.Locale
|
||||
environmentRepo biz.EnvironmentRepo
|
||||
}
|
||||
|
||||
func NewEnvironmentNodejsService(t *gotext.Locale, environmentRepo biz.EnvironmentRepo) *EnvironmentNodejsService {
|
||||
return &EnvironmentNodejsService{
|
||||
t: t,
|
||||
environmentRepo: environmentRepo,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *EnvironmentNodejsService) SetCli(w http.ResponseWriter, r *http.Request) {
|
||||
req, err := Bind[request.EnvironmentSlug](r)
|
||||
if err != nil {
|
||||
Error(w, http.StatusUnprocessableEntity, "%v", err)
|
||||
return
|
||||
}
|
||||
if !s.environmentRepo.IsInstalled("nodejs", req.Slug) {
|
||||
Error(w, http.StatusUnprocessableEntity, s.t.Get("Node.js-%s is not installed", req.Slug))
|
||||
return
|
||||
}
|
||||
|
||||
binPath := fmt.Sprintf("%s/server/nodejs/%s/bin", app.Root, req.Slug)
|
||||
binaries := []string{"node", "npm", "npx", "corepack"}
|
||||
for _, bin := range binaries {
|
||||
if _, err = shell.Execf("ln -sf %s/%s /usr/local/bin/%s", binPath, bin, bin); err != nil {
|
||||
Error(w, http.StatusInternalServerError, "%v", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
Success(w, nil)
|
||||
}
|
||||
|
||||
func (s *EnvironmentNodejsService) GetRegistry(w http.ResponseWriter, r *http.Request) {
|
||||
req, err := Bind[request.EnvironmentSlug](r)
|
||||
if err != nil {
|
||||
Error(w, http.StatusUnprocessableEntity, "%v", err)
|
||||
return
|
||||
}
|
||||
if !s.environmentRepo.IsInstalled("nodejs", req.Slug) {
|
||||
Error(w, http.StatusUnprocessableEntity, s.t.Get("Node.js-%s is not installed", req.Slug))
|
||||
return
|
||||
}
|
||||
|
||||
npmBin := fmt.Sprintf("%s/server/nodejs/%s/bin/npm", app.Root, req.Slug)
|
||||
registry, err := shell.Execf("%s config get --global registry", npmBin)
|
||||
if err != nil {
|
||||
registry = "https://registry.npmjs.org/"
|
||||
}
|
||||
|
||||
Success(w, strings.TrimSpace(registry))
|
||||
}
|
||||
|
||||
func (s *EnvironmentNodejsService) SetRegistry(w http.ResponseWriter, r *http.Request) {
|
||||
req, err := Bind[request.EnvironmentRegistry](r)
|
||||
if err != nil {
|
||||
Error(w, http.StatusUnprocessableEntity, "%v", err)
|
||||
return
|
||||
}
|
||||
if !s.environmentRepo.IsInstalled("nodejs", req.Slug) {
|
||||
Error(w, http.StatusUnprocessableEntity, s.t.Get("Node.js-%s is not installed", req.Slug))
|
||||
return
|
||||
}
|
||||
|
||||
npmBin := fmt.Sprintf("%s/server/nodejs/%s/bin/npm", app.Root, req.Slug)
|
||||
if _, err = shell.Execf("%s config set --global registry %s", npmBin, req.Registry); err != nil {
|
||||
Error(w, http.StatusInternalServerError, "%v", err)
|
||||
return
|
||||
}
|
||||
|
||||
Success(w, nil)
|
||||
}
|
||||
@@ -88,13 +88,13 @@ func (s *EnvironmentPHPService) GetConfig(w http.ResponseWriter, r *http.Request
|
||||
return
|
||||
}
|
||||
|
||||
config, err := io.Read(fmt.Sprintf("%s/server/php/%d/etc/php.ini", app.Root, req.Version))
|
||||
ini, err := io.Read(fmt.Sprintf("%s/server/php/%d/etc/php.ini", app.Root, req.Version))
|
||||
if err != nil {
|
||||
Error(w, http.StatusInternalServerError, "%v", err)
|
||||
return
|
||||
}
|
||||
|
||||
Success(w, config)
|
||||
Success(w, ini)
|
||||
}
|
||||
|
||||
func (s *EnvironmentPHPService) UpdateConfig(w http.ResponseWriter, r *http.Request) {
|
||||
@@ -127,13 +127,13 @@ func (s *EnvironmentPHPService) GetFPMConfig(w http.ResponseWriter, r *http.Requ
|
||||
return
|
||||
}
|
||||
|
||||
config, err := io.Read(fmt.Sprintf("%s/server/php/%d/etc/php-fpm.conf", app.Root, req.Version))
|
||||
ini, err := io.Read(fmt.Sprintf("%s/server/php/%d/etc/php-fpm.conf", app.Root, req.Version))
|
||||
if err != nil {
|
||||
Error(w, http.StatusInternalServerError, "%v", err)
|
||||
return
|
||||
}
|
||||
|
||||
Success(w, config)
|
||||
Success(w, ini)
|
||||
}
|
||||
|
||||
func (s *EnvironmentPHPService) UpdateFPMConfig(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
89
internal/service/environment_python.go
Normal file
89
internal/service/environment_python.go
Normal file
@@ -0,0 +1,89 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/leonelquinteros/gotext"
|
||||
|
||||
"github.com/acepanel/panel/internal/app"
|
||||
"github.com/acepanel/panel/internal/biz"
|
||||
"github.com/acepanel/panel/internal/http/request"
|
||||
"github.com/acepanel/panel/pkg/shell"
|
||||
)
|
||||
|
||||
type EnvironmentPythonService struct {
|
||||
t *gotext.Locale
|
||||
environmentRepo biz.EnvironmentRepo
|
||||
}
|
||||
|
||||
func NewEnvironmentPythonService(t *gotext.Locale, environmentRepo biz.EnvironmentRepo) *EnvironmentPythonService {
|
||||
return &EnvironmentPythonService{
|
||||
t: t,
|
||||
environmentRepo: environmentRepo,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *EnvironmentPythonService) SetCli(w http.ResponseWriter, r *http.Request) {
|
||||
req, err := Bind[request.EnvironmentSlug](r)
|
||||
if err != nil {
|
||||
Error(w, http.StatusUnprocessableEntity, "%v", err)
|
||||
return
|
||||
}
|
||||
if !s.environmentRepo.IsInstalled("python", req.Slug) {
|
||||
Error(w, http.StatusUnprocessableEntity, s.t.Get("Python-%s is not installed", req.Slug))
|
||||
return
|
||||
}
|
||||
|
||||
binPath := fmt.Sprintf("%s/server/python/%s/bin", app.Root, req.Slug)
|
||||
binaries := []string{"python3", "pip3"}
|
||||
for _, bin := range binaries {
|
||||
if _, err = shell.Execf("ln -sf %s/%s /usr/local/bin/%s", binPath, bin, bin); err != nil {
|
||||
Error(w, http.StatusInternalServerError, "%v", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
Success(w, nil)
|
||||
}
|
||||
|
||||
func (s *EnvironmentPythonService) GetMirror(w http.ResponseWriter, r *http.Request) {
|
||||
req, err := Bind[request.EnvironmentSlug](r)
|
||||
if err != nil {
|
||||
Error(w, http.StatusUnprocessableEntity, "%v", err)
|
||||
return
|
||||
}
|
||||
if !s.environmentRepo.IsInstalled("python", req.Slug) {
|
||||
Error(w, http.StatusUnprocessableEntity, s.t.Get("Python-%s is not installed", req.Slug))
|
||||
return
|
||||
}
|
||||
|
||||
pipBin := fmt.Sprintf("%s/server/python/%s/bin/pip3", app.Root, req.Slug)
|
||||
mirror, err := shell.Execf("%s config --global get global.index-url", pipBin)
|
||||
if err != nil {
|
||||
mirror = "https://pypi.org/simple"
|
||||
}
|
||||
|
||||
Success(w, strings.TrimSpace(mirror))
|
||||
}
|
||||
|
||||
func (s *EnvironmentPythonService) SetMirror(w http.ResponseWriter, r *http.Request) {
|
||||
req, err := Bind[request.EnvironmentMirror](r)
|
||||
if err != nil {
|
||||
Error(w, http.StatusUnprocessableEntity, "%v", err)
|
||||
return
|
||||
}
|
||||
if !s.environmentRepo.IsInstalled("python", req.Slug) {
|
||||
Error(w, http.StatusUnprocessableEntity, s.t.Get("Python-%s is not installed", req.Slug))
|
||||
return
|
||||
}
|
||||
|
||||
pipBin := fmt.Sprintf("%s/server/python/%s/bin/pip3", app.Root, req.Slug)
|
||||
if _, err = shell.Execf("%s config --global set global.index-url %s", pipBin, req.Mirror); err != nil {
|
||||
Error(w, http.StatusInternalServerError, "%v", err)
|
||||
return
|
||||
}
|
||||
|
||||
Success(w, nil)
|
||||
}
|
||||
@@ -20,7 +20,11 @@ var ProviderSet = wire.NewSet(
|
||||
NewDatabaseServerService,
|
||||
NewDatabaseUserService,
|
||||
NewEnvironmentService,
|
||||
NewEnvironmentGoService,
|
||||
NewEnvironmentJavaService,
|
||||
NewEnvironmentNodejsService,
|
||||
NewEnvironmentPHPService,
|
||||
NewEnvironmentPythonService,
|
||||
NewFileService,
|
||||
NewFirewallService,
|
||||
NewHomeService,
|
||||
|
||||
@@ -8,7 +8,6 @@ type Environment struct {
|
||||
Name string `json:"name"`
|
||||
Version string `json:"version"`
|
||||
Description string `json:"description"`
|
||||
Order int `json:"order"`
|
||||
}
|
||||
|
||||
type Environments []*Environment
|
||||
|
||||
11
web/src/api/panel/environment/go/index.ts
Normal file
11
web/src/api/panel/environment/go/index.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { http } from '@/utils'
|
||||
|
||||
export default {
|
||||
// 设为 CLI 版本
|
||||
setCli: (slug: string): any => http.Post(`/environment/go/${slug}/set_cli`),
|
||||
// 获取代理
|
||||
getProxy: (slug: string): any => http.Get(`/environment/go/${slug}/proxy`),
|
||||
// 设置代理
|
||||
setProxy: (slug: string, proxy: string): any =>
|
||||
http.Post(`/environment/go/${slug}/proxy`, { proxy })
|
||||
}
|
||||
6
web/src/api/panel/environment/java/index.ts
Normal file
6
web/src/api/panel/environment/java/index.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
import { http } from '@/utils'
|
||||
|
||||
export default {
|
||||
// 设为 CLI 版本
|
||||
setCli: (slug: string): any => http.Post(`/environment/java/${slug}/set_cli`)
|
||||
}
|
||||
11
web/src/api/panel/environment/nodejs/index.ts
Normal file
11
web/src/api/panel/environment/nodejs/index.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { http } from '@/utils'
|
||||
|
||||
export default {
|
||||
// 设为 CLI 版本
|
||||
setCli: (slug: string): any => http.Post(`/environment/nodejs/${slug}/set_cli`),
|
||||
// 获取镜像
|
||||
getRegistry: (slug: string): any => http.Get(`/environment/nodejs/${slug}/registry`),
|
||||
// 设置镜像
|
||||
setRegistry: (slug: string, registry: string): any =>
|
||||
http.Post(`/environment/nodejs/${slug}/registry`, { registry })
|
||||
}
|
||||
11
web/src/api/panel/environment/python/index.ts
Normal file
11
web/src/api/panel/environment/python/index.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { http } from '@/utils'
|
||||
|
||||
export default {
|
||||
// 设为 CLI 版本
|
||||
setCli: (slug: string): any => http.Post(`/environment/python/${slug}/set_cli`),
|
||||
// 获取镜像
|
||||
getMirror: (slug: string): any => http.Get(`/environment/python/${slug}/mirror`),
|
||||
// 设置镜像
|
||||
setMirror: (slug: string, mirror: string): any =>
|
||||
http.Post(`/environment/python/${slug}/mirror`, { mirror })
|
||||
}
|
||||
90
web/src/views/environment/GoView.vue
Normal file
90
web/src/views/environment/GoView.vue
Normal file
@@ -0,0 +1,90 @@
|
||||
<script setup lang="ts">
|
||||
import { useGettext } from 'vue3-gettext'
|
||||
|
||||
import goApi from '@/api/panel/environment/go'
|
||||
|
||||
const route = useRoute()
|
||||
const slug = route.params.slug as string
|
||||
|
||||
const { $gettext } = useGettext()
|
||||
|
||||
const proxy = ref('')
|
||||
const proxyLoading = ref(false)
|
||||
|
||||
// 预设的代理选项
|
||||
const proxyOptions = [
|
||||
{ label: $gettext('Official (proxy.golang.org)'), value: 'https://proxy.golang.org,direct' },
|
||||
{ label: $gettext('China - Qiniu (goproxy.cn)'), value: 'https://goproxy.cn,direct' },
|
||||
{ label: $gettext('China - Alibaba (mirrors.aliyun.com)'), value: 'https://mirrors.aliyun.com/goproxy/,direct' },
|
||||
{ label: $gettext('China - Tencent (mirrors.cloud.tencent.com)'), value: 'https://mirrors.cloud.tencent.com/go/,direct' }
|
||||
]
|
||||
|
||||
// 获取当前代理设置
|
||||
const fetchProxy = async () => {
|
||||
proxyLoading.value = true
|
||||
useRequest(goApi.getProxy(slug))
|
||||
.onSuccess((res) => {
|
||||
proxy.value = res.data
|
||||
})
|
||||
.onComplete(() => {
|
||||
proxyLoading.value = false
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
fetchProxy()
|
||||
})
|
||||
|
||||
const handleSetCli = async () => {
|
||||
useRequest(goApi.setCli(slug)).onSuccess(() => {
|
||||
window.$message.success($gettext('Set successfully'))
|
||||
})
|
||||
}
|
||||
|
||||
const handleSaveProxy = async () => {
|
||||
useRequest(goApi.setProxy(slug, proxy.value)).onSuccess(() => {
|
||||
window.$message.success($gettext('Saved successfully'))
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<common-page show-footer>
|
||||
<n-flex vertical>
|
||||
<n-card>
|
||||
<template #header>
|
||||
Go {{ slug }}
|
||||
</template>
|
||||
<template #header-extra>
|
||||
<n-button type="info" @click="handleSetCli">
|
||||
{{ $gettext('Set as CLI Default Version') }}
|
||||
</n-button>
|
||||
</template>
|
||||
</n-card>
|
||||
|
||||
<n-card :title="$gettext('Proxy Settings')">
|
||||
<n-spin :show="proxyLoading">
|
||||
<n-flex vertical>
|
||||
<n-alert type="info" :show-icon="false">
|
||||
{{ $gettext('GOPROXY is used to configure the Go module proxy. Using a domestic mirror can speed up dependency downloads.') }}
|
||||
</n-alert>
|
||||
<n-form-item :label="$gettext('Proxy Address')">
|
||||
<n-select
|
||||
v-model:value="proxy"
|
||||
:options="proxyOptions"
|
||||
filterable
|
||||
tag
|
||||
:placeholder="$gettext('Select or enter proxy address')"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-flex>
|
||||
<n-button type="primary" @click="handleSaveProxy">
|
||||
{{ $gettext('Save') }}
|
||||
</n-button>
|
||||
</n-flex>
|
||||
</n-flex>
|
||||
</n-spin>
|
||||
</n-card>
|
||||
</n-flex>
|
||||
</common-page>
|
||||
</template>
|
||||
36
web/src/views/environment/JavaView.vue
Normal file
36
web/src/views/environment/JavaView.vue
Normal file
@@ -0,0 +1,36 @@
|
||||
<script setup lang="ts">
|
||||
import { useGettext } from 'vue3-gettext'
|
||||
|
||||
import javaApi from '@/api/panel/environment/java'
|
||||
|
||||
const route = useRoute()
|
||||
const slug = route.params.slug as string
|
||||
|
||||
const { $gettext } = useGettext()
|
||||
|
||||
const handleSetCli = async () => {
|
||||
useRequest(javaApi.setCli(slug)).onSuccess(() => {
|
||||
window.$message.success($gettext('Set successfully'))
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<common-page show-footer>
|
||||
<n-flex vertical>
|
||||
<n-card>
|
||||
<template #header>
|
||||
Java {{ slug }} (Amazon Corretto)
|
||||
</template>
|
||||
<template #header-extra>
|
||||
<n-button type="info" @click="handleSetCli">
|
||||
{{ $gettext('Set as CLI Default Version') }}
|
||||
</n-button>
|
||||
</template>
|
||||
<n-alert type="info" :show-icon="false">
|
||||
{{ $gettext('Amazon Corretto is a no-cost, multiplatform, production-ready distribution of the Open Java Development Kit (OpenJDK).') }}
|
||||
</n-alert>
|
||||
</n-card>
|
||||
</n-flex>
|
||||
</common-page>
|
||||
</template>
|
||||
90
web/src/views/environment/NodejsView.vue
Normal file
90
web/src/views/environment/NodejsView.vue
Normal file
@@ -0,0 +1,90 @@
|
||||
<script setup lang="ts">
|
||||
import { useGettext } from 'vue3-gettext'
|
||||
|
||||
import nodejsApi from '@/api/panel/environment/nodejs'
|
||||
|
||||
const route = useRoute()
|
||||
const slug = route.params.slug as string
|
||||
|
||||
const { $gettext } = useGettext()
|
||||
|
||||
const registry = ref('')
|
||||
const registryLoading = ref(false)
|
||||
|
||||
// 预设的镜像选项
|
||||
const registryOptions = [
|
||||
{ label: $gettext('Official (registry.npmjs.org)'), value: 'https://registry.npmjs.org/' },
|
||||
{ label: $gettext('China - npmmirror (npmmirror.com)'), value: 'https://registry.npmmirror.com/' },
|
||||
{ label: $gettext('China - Tencent (mirrors.cloud.tencent.com)'), value: 'https://mirrors.cloud.tencent.com/npm/' },
|
||||
{ label: $gettext('China - Huawei (repo.huaweicloud.com)'), value: 'https://repo.huaweicloud.com/repository/npm/' }
|
||||
]
|
||||
|
||||
// 获取当前镜像设置
|
||||
const fetchRegistry = async () => {
|
||||
registryLoading.value = true
|
||||
useRequest(nodejsApi.getRegistry(slug))
|
||||
.onSuccess((res) => {
|
||||
registry.value = res.data
|
||||
})
|
||||
.onComplete(() => {
|
||||
registryLoading.value = false
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
fetchRegistry()
|
||||
})
|
||||
|
||||
const handleSetCli = async () => {
|
||||
useRequest(nodejsApi.setCli(slug)).onSuccess(() => {
|
||||
window.$message.success($gettext('Set successfully'))
|
||||
})
|
||||
}
|
||||
|
||||
const handleSaveRegistry = async () => {
|
||||
useRequest(nodejsApi.setRegistry(slug, registry.value)).onSuccess(() => {
|
||||
window.$message.success($gettext('Saved successfully'))
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<common-page show-footer>
|
||||
<n-flex vertical>
|
||||
<n-card>
|
||||
<template #header>
|
||||
Node.js {{ slug }}
|
||||
</template>
|
||||
<template #header-extra>
|
||||
<n-button type="info" @click="handleSetCli">
|
||||
{{ $gettext('Set as CLI Default Version') }}
|
||||
</n-button>
|
||||
</template>
|
||||
</n-card>
|
||||
|
||||
<n-card :title="$gettext('Registry Settings')">
|
||||
<n-spin :show="registryLoading">
|
||||
<n-flex vertical>
|
||||
<n-alert type="info" :show-icon="false">
|
||||
{{ $gettext('npm registry is used to configure the npm package source. Using a domestic mirror can speed up package downloads.') }}
|
||||
</n-alert>
|
||||
<n-form-item :label="$gettext('Registry Address')">
|
||||
<n-select
|
||||
v-model:value="registry"
|
||||
:options="registryOptions"
|
||||
filterable
|
||||
tag
|
||||
:placeholder="$gettext('Select or enter registry address')"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-flex>
|
||||
<n-button type="primary" @click="handleSaveRegistry">
|
||||
{{ $gettext('Save') }}
|
||||
</n-button>
|
||||
</n-flex>
|
||||
</n-flex>
|
||||
</n-spin>
|
||||
</n-card>
|
||||
</n-flex>
|
||||
</common-page>
|
||||
</template>
|
||||
@@ -191,16 +191,22 @@ const handleUninstallModule = async (module: string) => {
|
||||
<n-tabs v-model:value="currentTab" type="line" animated>
|
||||
<n-tab-pane name="status" :tab="$gettext('Running Status')">
|
||||
<n-flex vertical>
|
||||
<n-card> PHP {{ slug }} </n-card>
|
||||
<n-card>
|
||||
<template #header>
|
||||
PHP {{ slug }}
|
||||
</template>
|
||||
<template #header-extra>
|
||||
<n-flex>
|
||||
<n-button type="info" @click="handleSetCli">
|
||||
{{ $gettext('Set as CLI Default Version') }}
|
||||
</n-button>
|
||||
<n-button type="primary" @click="handlePHPInfo">
|
||||
{{ $gettext('View PHPInfo') }}
|
||||
</n-button>
|
||||
</n-flex>
|
||||
</template>
|
||||
</n-card>
|
||||
<service-status :service="`php-fpm-${slug}`" show-reload />
|
||||
<n-flex>
|
||||
<n-button type="info" @click="handleSetCli">
|
||||
{{ $gettext('Set as CLI Default Version') }}
|
||||
</n-button>
|
||||
<n-button type="primary" @click="handlePHPInfo">
|
||||
{{ $gettext('View PHPInfo') }}
|
||||
</n-button>
|
||||
</n-flex>
|
||||
</n-flex>
|
||||
</n-tab-pane>
|
||||
<n-tab-pane name="modules" :tab="$gettext('Module Management')">
|
||||
|
||||
92
web/src/views/environment/PythonView.vue
Normal file
92
web/src/views/environment/PythonView.vue
Normal file
@@ -0,0 +1,92 @@
|
||||
<script setup lang="ts">
|
||||
import { useGettext } from 'vue3-gettext'
|
||||
|
||||
import pythonApi from '@/api/panel/environment/python'
|
||||
|
||||
const route = useRoute()
|
||||
const slug = route.params.slug as string
|
||||
|
||||
const { $gettext } = useGettext()
|
||||
|
||||
const mirror = ref('')
|
||||
const mirrorLoading = ref(false)
|
||||
|
||||
// 预设的镜像选项
|
||||
const mirrorOptions = [
|
||||
{ label: $gettext('Official (pypi.org)'), value: 'https://pypi.org/simple' },
|
||||
{ label: $gettext('China - Tsinghua (tuna.tsinghua.edu.cn)'), value: 'https://pypi.tuna.tsinghua.edu.cn/simple' },
|
||||
{ label: $gettext('China - Alibaba (mirrors.aliyun.com)'), value: 'https://mirrors.aliyun.com/pypi/simple/' },
|
||||
{ label: $gettext('China - Tencent (mirrors.cloud.tencent.com)'), value: 'https://mirrors.cloud.tencent.com/pypi/simple/' },
|
||||
{ label: $gettext('China - Douban (pypi.douban.com)'), value: 'https://pypi.douban.com/simple/' },
|
||||
{ label: $gettext('China - USTC (pypi.mirrors.ustc.edu.cn)'), value: 'https://pypi.mirrors.ustc.edu.cn/simple/' }
|
||||
]
|
||||
|
||||
// 获取当前镜像设置
|
||||
const fetchMirror = async () => {
|
||||
mirrorLoading.value = true
|
||||
useRequest(pythonApi.getMirror(slug))
|
||||
.onSuccess((res) => {
|
||||
mirror.value = res.data
|
||||
})
|
||||
.onComplete(() => {
|
||||
mirrorLoading.value = false
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
fetchMirror()
|
||||
})
|
||||
|
||||
const handleSetCli = async () => {
|
||||
useRequest(pythonApi.setCli(slug)).onSuccess(() => {
|
||||
window.$message.success($gettext('Set successfully'))
|
||||
})
|
||||
}
|
||||
|
||||
const handleSaveMirror = async () => {
|
||||
useRequest(pythonApi.setMirror(slug, mirror.value)).onSuccess(() => {
|
||||
window.$message.success($gettext('Saved successfully'))
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<common-page show-footer>
|
||||
<n-flex vertical>
|
||||
<n-card>
|
||||
<template #header>
|
||||
Python {{ slug }}
|
||||
</template>
|
||||
<template #header-extra>
|
||||
<n-button type="info" @click="handleSetCli">
|
||||
{{ $gettext('Set as CLI Default Version') }}
|
||||
</n-button>
|
||||
</template>
|
||||
</n-card>
|
||||
|
||||
<n-card :title="$gettext('Mirror Settings')">
|
||||
<n-spin :show="mirrorLoading">
|
||||
<n-flex vertical>
|
||||
<n-alert type="info" :show-icon="false">
|
||||
{{ $gettext('pip mirror is used to configure the Python package source. Using a domestic mirror can speed up package downloads.') }}
|
||||
</n-alert>
|
||||
<n-form-item :label="$gettext('Mirror Address')">
|
||||
<n-select
|
||||
v-model:value="mirror"
|
||||
:options="mirrorOptions"
|
||||
filterable
|
||||
tag
|
||||
:placeholder="$gettext('Select or enter mirror address')"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-flex>
|
||||
<n-button type="primary" @click="handleSaveMirror">
|
||||
{{ $gettext('Save') }}
|
||||
</n-button>
|
||||
</n-flex>
|
||||
</n-flex>
|
||||
</n-spin>
|
||||
</n-card>
|
||||
</n-flex>
|
||||
</common-page>
|
||||
</template>
|
||||
@@ -8,6 +8,42 @@ export default {
|
||||
isHidden: true,
|
||||
component: Layout,
|
||||
children: [
|
||||
{
|
||||
name: 'environment-go',
|
||||
path: 'go/:slug',
|
||||
isHidden: true,
|
||||
component: () => import('./GoView.vue'),
|
||||
meta: {
|
||||
title: 'Go',
|
||||
icon: 'mdi:language-go',
|
||||
role: ['admin'],
|
||||
requireAuth: true
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'environment-java',
|
||||
path: 'java/:slug',
|
||||
isHidden: true,
|
||||
component: () => import('./JavaView.vue'),
|
||||
meta: {
|
||||
title: 'Java',
|
||||
icon: 'mdi:language-java',
|
||||
role: ['admin'],
|
||||
requireAuth: true
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'environment-nodejs',
|
||||
path: 'nodejs/:slug',
|
||||
isHidden: true,
|
||||
component: () => import('./NodejsView.vue'),
|
||||
meta: {
|
||||
title: 'Node.js',
|
||||
icon: 'mdi:nodejs',
|
||||
role: ['admin'],
|
||||
requireAuth: true
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'environment-php',
|
||||
path: 'php/:slug',
|
||||
@@ -19,6 +55,18 @@ export default {
|
||||
role: ['admin'],
|
||||
requireAuth: true
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'environment-python',
|
||||
path: 'python/:slug',
|
||||
isHidden: true,
|
||||
component: () => import('./PythonView.vue'),
|
||||
meta: {
|
||||
title: 'Python',
|
||||
icon: 'mdi:language-python',
|
||||
role: ['admin'],
|
||||
requireAuth: true
|
||||
}
|
||||
}
|
||||
]
|
||||
} as RouteType
|
||||
|
||||
Reference in New Issue
Block a user