mirror of
https://github.com/acepanel/panel.git
synced 2026-02-04 09:13:49 +08:00
feat: php支持74和80
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
package php
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
|
||||
"github.com/TheTNB/panel/pkg/apploader"
|
||||
@@ -8,76 +10,25 @@ import (
|
||||
)
|
||||
|
||||
func init() {
|
||||
apploader.Register(&types.App{
|
||||
Slug: "php80",
|
||||
Route: func(r chi.Router) {
|
||||
service := NewService(80)
|
||||
r.Get("/load", service.Load)
|
||||
r.Get("/config", service.GetConfig)
|
||||
r.Post("/config", service.UpdateConfig)
|
||||
r.Get("/fpmConfig", service.GetFPMConfig)
|
||||
r.Post("/fpmConfig", service.UpdateFPMConfig)
|
||||
r.Get("/errorLog", service.ErrorLog)
|
||||
r.Get("/slowLog", service.SlowLog)
|
||||
r.Post("/clearErrorLog", service.ClearErrorLog)
|
||||
r.Post("/clearSlowLog", service.ClearSlowLog)
|
||||
r.Get("/extensions", service.ExtensionList)
|
||||
r.Post("/extensions", service.InstallExtension)
|
||||
r.Delete("/extensions", service.UninstallExtension)
|
||||
},
|
||||
})
|
||||
apploader.Register(&types.App{
|
||||
Slug: "php81",
|
||||
Route: func(r chi.Router) {
|
||||
service := NewService(81)
|
||||
r.Get("/load", service.Load)
|
||||
r.Get("/config", service.GetConfig)
|
||||
r.Post("/config", service.UpdateConfig)
|
||||
r.Get("/fpmConfig", service.GetFPMConfig)
|
||||
r.Post("/fpmConfig", service.UpdateFPMConfig)
|
||||
r.Get("/errorLog", service.ErrorLog)
|
||||
r.Get("/slowLog", service.SlowLog)
|
||||
r.Post("/clearErrorLog", service.ClearErrorLog)
|
||||
r.Post("/clearSlowLog", service.ClearSlowLog)
|
||||
r.Get("/extensions", service.ExtensionList)
|
||||
r.Post("/extensions", service.InstallExtension)
|
||||
r.Delete("/extensions", service.UninstallExtension)
|
||||
},
|
||||
})
|
||||
apploader.Register(&types.App{
|
||||
Slug: "php82",
|
||||
Route: func(r chi.Router) {
|
||||
service := NewService(82)
|
||||
r.Get("/load", service.Load)
|
||||
r.Get("/config", service.GetConfig)
|
||||
r.Post("/config", service.UpdateConfig)
|
||||
r.Get("/fpmConfig", service.GetFPMConfig)
|
||||
r.Post("/fpmConfig", service.UpdateFPMConfig)
|
||||
r.Get("/errorLog", service.ErrorLog)
|
||||
r.Get("/slowLog", service.SlowLog)
|
||||
r.Post("/clearErrorLog", service.ClearErrorLog)
|
||||
r.Post("/clearSlowLog", service.ClearSlowLog)
|
||||
r.Get("/extensions", service.ExtensionList)
|
||||
r.Post("/extensions", service.InstallExtension)
|
||||
r.Delete("/extensions", service.UninstallExtension)
|
||||
},
|
||||
})
|
||||
apploader.Register(&types.App{
|
||||
Slug: "php83",
|
||||
Route: func(r chi.Router) {
|
||||
service := NewService(83)
|
||||
r.Get("/load", service.Load)
|
||||
r.Get("/config", service.GetConfig)
|
||||
r.Post("/config", service.UpdateConfig)
|
||||
r.Get("/fpmConfig", service.GetFPMConfig)
|
||||
r.Post("/fpmConfig", service.UpdateFPMConfig)
|
||||
r.Get("/errorLog", service.ErrorLog)
|
||||
r.Get("/slowLog", service.SlowLog)
|
||||
r.Post("/clearErrorLog", service.ClearErrorLog)
|
||||
r.Post("/clearSlowLog", service.ClearSlowLog)
|
||||
r.Get("/extensions", service.ExtensionList)
|
||||
r.Post("/extensions", service.InstallExtension)
|
||||
r.Delete("/extensions", service.UninstallExtension)
|
||||
},
|
||||
})
|
||||
php := []uint{74, 80, 81, 82, 83}
|
||||
for _, version := range php {
|
||||
apploader.Register(&types.App{
|
||||
Slug: fmt.Sprintf("php%d", version),
|
||||
Route: func(r chi.Router) {
|
||||
service := NewService(version)
|
||||
r.Get("/load", service.Load)
|
||||
r.Get("/config", service.GetConfig)
|
||||
r.Post("/config", service.UpdateConfig)
|
||||
r.Get("/fpmConfig", service.GetFPMConfig)
|
||||
r.Post("/fpmConfig", service.UpdateFPMConfig)
|
||||
r.Get("/errorLog", service.ErrorLog)
|
||||
r.Get("/slowLog", service.SlowLog)
|
||||
r.Post("/clearErrorLog", service.ClearErrorLog)
|
||||
r.Post("/clearSlowLog", service.ClearSlowLog)
|
||||
r.Get("/extensions", service.ExtensionList)
|
||||
r.Post("/extensions", service.InstallExtension)
|
||||
r.Delete("/extensions", service.UninstallExtension)
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -138,17 +138,6 @@ func (s *Service) ClearSlowLog(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
func (s *Service) ExtensionList(w http.ResponseWriter, r *http.Request) {
|
||||
extensions := s.getExtensions()
|
||||
|
||||
// ionCube 只支持 PHP 8.3 以下版本
|
||||
if cast.ToUint(s.version) < 83 {
|
||||
extensions = append(extensions, Extension{
|
||||
Name: "ionCube",
|
||||
Slug: "ionCube Loader",
|
||||
Description: "ionCube 是一个专业级的 PHP 加密解密工具。",
|
||||
Installed: false,
|
||||
})
|
||||
}
|
||||
|
||||
raw, err := shell.Execf("%s/server/php/%d/bin/php -m", app.Root, s.version)
|
||||
if err != nil {
|
||||
service.Error(w, http.StatusInternalServerError, "%v", err)
|
||||
@@ -182,10 +171,10 @@ func (s *Service) InstallExtension(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
cmd := fmt.Sprintf(`curl -fsLm 10 --retry 3 "https://dl.cdn.haozi.net/panel/php_exts/%s.sh" | bash -s -- "install" "%d" >> /tmp/%s.log 2>&1`, url.QueryEscape(req.Slug), s.version, req.Slug)
|
||||
cmd := fmt.Sprintf(`curl -fsLm 10 --retry 3 'https://dl.cdn.haozi.net/panel/php_exts/%s.sh' | bash -s -- 'install' '%d' >> '/tmp/%s.log' 2>&1`, url.PathEscape(req.Slug), s.version, req.Slug)
|
||||
officials := []string{"fileinfo", "exif", "imap", "pdo_pgsql", "zip", "bz2", "readline", "snmp", "ldap", "enchant", "pspell", "calendar", "gmp", "sysvmsg", "sysvsem", "sysvshm", "xsl", "intl", "gettext"}
|
||||
if slices.Contains(officials, req.Slug) {
|
||||
cmd = fmt.Sprintf(`curl -fsLm 10 --retry 3 "https://dl.cdn.haozi.net/panel/php_exts/official.sh" | bash -s -- "install" "%d" "%s" >> /tmp/%s.log 2>&1`, s.version, req.Slug, req.Slug)
|
||||
cmd = fmt.Sprintf(`curl -fsLm 10 --retry 3 'https://dl.cdn.haozi.net/panel/php_exts/official.sh' | bash -s -- 'install' '%d' '%s' >> '/tmp/%s.log' 2>&1`, s.version, req.Slug, req.Slug)
|
||||
}
|
||||
|
||||
task := new(biz.Task)
|
||||
@@ -213,10 +202,10 @@ func (s *Service) UninstallExtension(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
cmd := fmt.Sprintf(`curl -fsLm 10 --retry 3 "https://dl.cdn.haozi.net/panel/php_exts/%s.sh" | bash -s -- "uninstall" "%d" >> /tmp/%s.log 2>&1`, url.QueryEscape(req.Slug), s.version, req.Slug)
|
||||
cmd := fmt.Sprintf(`curl -fsLm 10 --retry 3 'https://dl.cdn.haozi.net/panel/php_exts/%s.sh' | bash -s -- 'uninstall' '%d' >> '/tmp/%s.log' 2>&1`, url.PathEscape(req.Slug), s.version, req.Slug)
|
||||
officials := []string{"fileinfo", "exif", "imap", "pdo_pgsql", "zip", "bz2", "readline", "snmp", "ldap", "enchant", "pspell", "calendar", "gmp", "sysvmsg", "sysvsem", "sysvshm", "xsl", "intl", "gettext"}
|
||||
if slices.Contains(officials, req.Slug) {
|
||||
cmd = fmt.Sprintf(`curl -fsLm 10 --retry 3 "https://dl.cdn.haozi.net/panel/php_exts/official.sh" | bash -s -- "uninstall" "%d" "%s" >> /tmp/%s.log 2>&1`, s.version, req.Slug, req.Slug)
|
||||
cmd = fmt.Sprintf(`curl -fsLm 10 --retry 3 'https://dl.cdn.haozi.net/panel/php_exts/official.sh' | bash -s -- 'uninstall' '%d' '%s' >> '/tmp/%s.log' 2>&1`, s.version, req.Slug, req.Slug)
|
||||
}
|
||||
|
||||
task := new(biz.Task)
|
||||
@@ -237,137 +226,136 @@ func (s *Service) getExtensions() []Extension {
|
||||
{
|
||||
Name: "fileinfo",
|
||||
Slug: "fileinfo",
|
||||
Description: "Fileinfo 是一个用于识别文件类型的库。",
|
||||
Description: "Fileinfo 是一个用于识别文件类型的库",
|
||||
},
|
||||
{
|
||||
Name: "OPcache",
|
||||
Slug: "Zend OPcache",
|
||||
Description: "OPcache 通过将 PHP 脚本预编译的字节码存储到共享内存中来提升 PHP 的性能,存储预编译字节码可以省去每次加载和解析 PHP 脚本的开销。",
|
||||
Description: "OPcache 通过将 PHP 脚本预编译的字节码存储到共享内存中来提升 PHP 的性能,存储预编译字节码可以省去每次加载和解析 PHP 脚本的开销",
|
||||
},
|
||||
{
|
||||
Name: "PhpRedis",
|
||||
Slug: "redis",
|
||||
Description: "PhpRedis 是一个用 C 语言编写的 PHP 模块,用来连接并操作 Redis 数据库上的数据。",
|
||||
Description: "PhpRedis 是一个用 C 语言编写的 PHP 模块,用来连接并操作 Redis 数据库上的数据",
|
||||
},
|
||||
{
|
||||
Name: "ImageMagick",
|
||||
Slug: "imagick",
|
||||
Description: "ImageMagick 是一个免费的创建、编辑、合成图片的软件。",
|
||||
Description: "ImageMagick 是一个免费的创建、编辑、合成图片的软件",
|
||||
},
|
||||
{
|
||||
Name: "exif",
|
||||
Slug: "exif",
|
||||
Description: "通过 exif 扩展,您可以操作图像元数据。",
|
||||
Description: "通过 exif 扩展,您可以操作图像元数据",
|
||||
},
|
||||
{
|
||||
Name: "pdo_pgsql",
|
||||
Slug: "pdo_pgsql",
|
||||
Description: "(需先安装PostgreSQL)pdo_pgsql 是一个驱动程序,它实现了 PHP 数据对象(PDO)接口以启用从 PHP 到 PostgreSQL 数据库的访问。",
|
||||
Description: "pdo_pgsql 是一个驱动程序,它实现了 PHP 数据对象(PDO)接口以启用从 PHP 到 PostgreSQL 数据库的访问(需先安装PostgreSQL)",
|
||||
},
|
||||
{
|
||||
Name: "imap",
|
||||
Slug: "imap",
|
||||
Description: "IMAP 扩展允许 PHP 读取、搜索、删除、下载和管理邮件。",
|
||||
Description: "IMAP 扩展允许 PHP 读取、搜索、删除、下载和管理邮件",
|
||||
},
|
||||
{
|
||||
Name: "zip",
|
||||
Slug: "zip",
|
||||
Description: "Zip 是一个用于处理 ZIP 文件的库。",
|
||||
Description: "Zip 是一个用于处理 ZIP 文件的库",
|
||||
},
|
||||
{
|
||||
Name: "bz2",
|
||||
Slug: "bz2",
|
||||
Description: "Bzip2 是一个用于压缩和解压缩文件的库。",
|
||||
Description: "Bzip2 是一个用于压缩和解压缩文件的库",
|
||||
},
|
||||
{
|
||||
Name: "readline",
|
||||
Slug: "readline",
|
||||
Description: "Readline 是一个库,它提供了一种用于处理文本的接口。",
|
||||
Description: "Readline 是一个库,它提供了一种用于处理文本的接口",
|
||||
},
|
||||
{
|
||||
Name: "snmp",
|
||||
Slug: "snmp",
|
||||
Description: "SNMP 是一种用于网络管理的协议。",
|
||||
Description: "SNMP 是一种用于网络管理的协议",
|
||||
},
|
||||
{
|
||||
Name: "ldap",
|
||||
Slug: "ldap",
|
||||
Description: "LDAP 是一种用于访问目录服务的协议。",
|
||||
Description: "LDAP 是一种用于访问目录服务的协议",
|
||||
},
|
||||
{
|
||||
Name: "enchant",
|
||||
Slug: "enchant",
|
||||
Description: "Enchant 是一个拼写检查库。",
|
||||
Description: "Enchant 是一个拼写检查库",
|
||||
},
|
||||
{
|
||||
Name: "pspell",
|
||||
Slug: "pspell",
|
||||
Description: "Pspell 是一个拼写检查库。",
|
||||
Description: "Pspell 是一个拼写检查库",
|
||||
},
|
||||
{
|
||||
Name: "calendar",
|
||||
Slug: "calendar",
|
||||
Description: "Calendar 是一个用于处理日期的库。",
|
||||
Description: "Calendar 是一个用于处理日期的库",
|
||||
},
|
||||
{
|
||||
Name: "gmp",
|
||||
Slug: "gmp",
|
||||
Description: "GMP 是一个用于处理大整数的库。",
|
||||
Description: "GMP 是一个用于处理大整数的库",
|
||||
},
|
||||
{
|
||||
Name: "sysvmsg",
|
||||
Slug: "sysvmsg",
|
||||
Description: "Sysvmsg 是一个用于处理 System V 消息队列的库。",
|
||||
Description: "Sysvmsg 是一个用于处理 System V 消息队列的库",
|
||||
},
|
||||
{
|
||||
Name: "sysvsem",
|
||||
Slug: "sysvsem",
|
||||
Description: "Sysvsem 是一个用于处理 System V 信号量的库。",
|
||||
Description: "Sysvsem 是一个用于处理 System V 信号量的库",
|
||||
},
|
||||
{
|
||||
Name: "sysvshm",
|
||||
Slug: "sysvshm",
|
||||
Description: "Sysvshm 是一个用于处理 System V 共享内存的库。",
|
||||
Description: "Sysvshm 是一个用于处理 System V 共享内存的库",
|
||||
},
|
||||
{
|
||||
Name: "xsl",
|
||||
Slug: "xsl",
|
||||
Description: "XSL 是一个用于处理 XML 文档的库。",
|
||||
Description: "XSL 是一个用于处理 XML 文档的库",
|
||||
},
|
||||
{
|
||||
Name: "intl",
|
||||
Slug: "intl",
|
||||
Description: "Intl 是一个用于处理国际化和本地化的库。",
|
||||
Description: "Intl 是一个用于处理国际化和本地化的库",
|
||||
},
|
||||
{
|
||||
Name: "gettext",
|
||||
Slug: "gettext",
|
||||
Description: "Gettext 是一个用于处理多语言的库。",
|
||||
Description: "Gettext 是一个用于处理多语言的库",
|
||||
},
|
||||
{
|
||||
Name: "igbinary",
|
||||
Slug: "igbinary",
|
||||
Description: "Igbinary 是一个用于序列化和反序列化数据的库。",
|
||||
Description: "Igbinary 是一个用于序列化和反序列化数据的库",
|
||||
},
|
||||
{
|
||||
Name: "ionCube",
|
||||
Slug: "ionCube Loader",
|
||||
Description: "ionCube 是一个专业级的 PHP 加密解密工具(需在 OPcache 之后安装)",
|
||||
},
|
||||
{
|
||||
Name: "Swoole",
|
||||
Slug: "swoole",
|
||||
Description: "Swoole 是一个用于构建高性能的异步并发服务器的 PHP 扩展。",
|
||||
},
|
||||
{
|
||||
Name: "Swow",
|
||||
Slug: "Swow",
|
||||
Description: "Swow 是一个用于构建高性能的异步并发服务器的 PHP 扩展。",
|
||||
Description: "Swoole 是一个用于构建高性能的异步并发服务器的 PHP 扩展",
|
||||
},
|
||||
}
|
||||
|
||||
// ionCube 只支持 PHP 8.3 以下版本
|
||||
if cast.ToUint(s.version) < 83 {
|
||||
// Swow 不支持 PHP 8.0 以下版本
|
||||
if cast.ToUint(s.version) >= 80 {
|
||||
extensions = append(extensions, Extension{
|
||||
Name: "ionCube",
|
||||
Slug: "ionCube Loader",
|
||||
Description: "ionCube 是一个专业级的 PHP 加密解密工具。",
|
||||
Installed: false,
|
||||
Name: "Swow",
|
||||
Slug: "Swow",
|
||||
Description: "Swow 是一个用于构建高性能的异步并发服务器的 PHP 扩展。",
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -76,7 +76,7 @@ func (r *containerImageRepo) Pull(req *request.ContainerImagePull) error {
|
||||
|
||||
if req.Auth {
|
||||
sb.WriteString(fmt.Sprintf("docker login -u %s -p %s", req.Username, req.Password))
|
||||
if _, err := shell.ExecfWithTimeout(1*time.Minute, sb.String()); err != nil { // nolint: govet
|
||||
if _, err := shell.Exec(sb.String()); err != nil {
|
||||
return fmt.Errorf("login failed: %w", err)
|
||||
}
|
||||
sb.Reset()
|
||||
@@ -84,7 +84,7 @@ func (r *containerImageRepo) Pull(req *request.ContainerImagePull) error {
|
||||
|
||||
sb.WriteString(fmt.Sprintf("docker pull %s", req.Name))
|
||||
|
||||
if _, err := shell.Execf(sb.String()); err != nil { // nolint: govet
|
||||
if _, err := shell.Exec(sb.String()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
@@ -115,7 +115,7 @@ func (r *containerNetworkRepo) Create(req *request.ContainerNetworkCreate) (stri
|
||||
sb.WriteString(fmt.Sprintf(" --opt %s=%s", option.Key, option.Value))
|
||||
}
|
||||
|
||||
return shell.ExecfWithTimeout(120*time.Second, sb.String()) // nolint: govet
|
||||
return shell.Exec(sb.String())
|
||||
}
|
||||
|
||||
// Remove 删除网络
|
||||
|
||||
@@ -89,7 +89,7 @@ func (r *containerVolumeRepo) Create(req *request.ContainerVolumeCreate) (string
|
||||
sb.WriteString(fmt.Sprintf(" --opt %s=%s", option.Key, option.Value))
|
||||
}
|
||||
|
||||
return shell.ExecfWithTimeout(120*time.Second, sb.String()) // nolint: govet
|
||||
return shell.Exec(sb.String())
|
||||
}
|
||||
|
||||
// Remove 删除存储卷
|
||||
|
||||
@@ -2,7 +2,9 @@ package queuejob
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"log/slog"
|
||||
|
||||
"github.com/TheTNB/panel/internal/app"
|
||||
"github.com/TheTNB/panel/internal/biz"
|
||||
"github.com/TheTNB/panel/pkg/shell"
|
||||
)
|
||||
@@ -36,7 +38,7 @@ func (r *ProcessTask) Handle(args ...any) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err = shell.Execf(task.Shell); err != nil { // nolint: govet
|
||||
if _, err = shell.Exec(task.Shell); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -48,5 +50,6 @@ func (r *ProcessTask) Handle(args ...any) error {
|
||||
}
|
||||
|
||||
func (r *ProcessTask) ErrHandle(err error) {
|
||||
app.Logger.Warn("background task failed", slog.Any("task_id", r.taskID), slog.Any("err", err))
|
||||
_ = r.taskRepo.UpdateStatus(r.taskID, biz.TaskStatusFailed)
|
||||
}
|
||||
|
||||
@@ -162,8 +162,26 @@ func (s *FileService) Upload(w http.ResponseWriter, r *http.Request) {
|
||||
Success(w, nil)
|
||||
}
|
||||
|
||||
func (s *FileService) Exist(w http.ResponseWriter, r *http.Request) {
|
||||
binder := chix.NewBind(r)
|
||||
defer binder.Release()
|
||||
|
||||
var paths []string
|
||||
if err := binder.Body(&paths); err != nil {
|
||||
Error(w, http.StatusInternalServerError, "%v", err)
|
||||
return
|
||||
}
|
||||
|
||||
var results []bool
|
||||
for item := range slices.Values(paths) {
|
||||
results = append(results, io.Exists(item))
|
||||
}
|
||||
|
||||
Success(w, results)
|
||||
}
|
||||
|
||||
func (s *FileService) Move(w http.ResponseWriter, r *http.Request) {
|
||||
req, err := Bind[request.FileMove](r)
|
||||
req, err := Bind[request.FileControl](r)
|
||||
if err != nil {
|
||||
Error(w, http.StatusInternalServerError, "%v", err)
|
||||
return
|
||||
@@ -183,7 +201,7 @@ func (s *FileService) Move(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
func (s *FileService) Copy(w http.ResponseWriter, r *http.Request) {
|
||||
req, err := Bind[request.FileCopy](r)
|
||||
req, err := Bind[request.FileControl](r)
|
||||
if err != nil {
|
||||
Error(w, http.StatusInternalServerError, "%v", err)
|
||||
return
|
||||
|
||||
@@ -266,7 +266,7 @@ func (r *Firewall) Forward(rule Forward, operation Operation) error {
|
||||
}
|
||||
ruleBuilder.WriteString(" --permanent")
|
||||
|
||||
_, err := shell.Execf(ruleBuilder.String()) // nolint: govet
|
||||
_, err := shell.Exec(ruleBuilder.String())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -16,7 +16,23 @@ import (
|
||||
"github.com/creack/pty"
|
||||
)
|
||||
|
||||
// Execf 执行 shell 命令
|
||||
// Exec 执行 shell 命令
|
||||
func Exec(shell string) (string, error) {
|
||||
_ = os.Setenv("LC_ALL", "C")
|
||||
cmd := exec.Command("bash", "-c", shell)
|
||||
|
||||
var stdout, stderr bytes.Buffer
|
||||
cmd.Stdout = &stdout
|
||||
cmd.Stderr = &stderr
|
||||
|
||||
if err := cmd.Run(); err != nil {
|
||||
return strings.TrimSpace(stdout.String()), fmt.Errorf("run %s failed, err: %s", shell, strings.TrimSpace(stderr.String()))
|
||||
}
|
||||
|
||||
return strings.TrimSpace(stdout.String()), nil
|
||||
}
|
||||
|
||||
// Execf 安全执行 shell 命令
|
||||
func Execf(shell string, args ...any) (string, error) {
|
||||
if !preCheckArg(args) {
|
||||
return "", errors.New("command contains illegal characters")
|
||||
|
||||
398
web/src/views/apps/php/PhpView.vue
Normal file
398
web/src/views/apps/php/PhpView.vue
Normal file
@@ -0,0 +1,398 @@
|
||||
<script setup lang="ts">
|
||||
import Editor from '@guolao/vue-monaco-editor'
|
||||
import { NButton, NDataTable, NPopconfirm } from 'naive-ui'
|
||||
|
||||
import php from '@/api/apps/php'
|
||||
import systemctl from '@/api/panel/systemctl'
|
||||
import { renderIcon } from '@/utils'
|
||||
|
||||
const props = defineProps({
|
||||
version: Number
|
||||
})
|
||||
|
||||
const { version } = toRefs(props)
|
||||
|
||||
const currentTab = ref('status')
|
||||
const status = ref(false)
|
||||
const isEnabled = ref(false)
|
||||
const config = ref('')
|
||||
const fpmConfig = ref('')
|
||||
const errorLog = ref('')
|
||||
const slowLog = ref('')
|
||||
|
||||
const statusType = computed(() => {
|
||||
return status.value ? 'success' : 'error'
|
||||
})
|
||||
const statusStr = computed(() => {
|
||||
return status.value ? '正常运行中' : '已停止运行'
|
||||
})
|
||||
|
||||
const extensionColumns: any = [
|
||||
{
|
||||
title: '拓展名',
|
||||
key: 'name',
|
||||
minWidth: 250,
|
||||
resizable: true,
|
||||
ellipsis: { tooltip: true }
|
||||
},
|
||||
{
|
||||
title: '描述',
|
||||
key: 'description',
|
||||
resizable: true,
|
||||
minWidth: 250,
|
||||
ellipsis: { tooltip: true }
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
key: 'actions',
|
||||
width: 240,
|
||||
align: 'center',
|
||||
hideInExcel: true,
|
||||
render(row: any) {
|
||||
return [
|
||||
!row.installed
|
||||
? h(
|
||||
NButton,
|
||||
{
|
||||
size: 'small',
|
||||
type: 'primary',
|
||||
secondary: true,
|
||||
onClick: () => handleInstallExtension(row.slug)
|
||||
},
|
||||
{
|
||||
default: () => '安装',
|
||||
icon: renderIcon('material-symbols:download-rounded', { size: 14 })
|
||||
}
|
||||
)
|
||||
: null,
|
||||
row.installed
|
||||
? h(
|
||||
NPopconfirm,
|
||||
{
|
||||
onPositiveClick: () => handleUninstallExtension(row.slug)
|
||||
},
|
||||
{
|
||||
default: () => {
|
||||
return '确定卸载' + row.name + '吗?'
|
||||
},
|
||||
trigger: () => {
|
||||
return h(
|
||||
NButton,
|
||||
{
|
||||
size: 'small',
|
||||
type: 'error'
|
||||
},
|
||||
{
|
||||
default: () => '删除',
|
||||
icon: renderIcon('material-symbols:delete-outline', { size: 14 })
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
)
|
||||
: null
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
const loadColumns: any = [
|
||||
{
|
||||
title: '属性',
|
||||
key: 'name',
|
||||
minWidth: 200,
|
||||
resizable: true,
|
||||
ellipsis: { tooltip: true }
|
||||
},
|
||||
{
|
||||
title: '当前值',
|
||||
key: 'value',
|
||||
minWidth: 200,
|
||||
ellipsis: { tooltip: true }
|
||||
}
|
||||
]
|
||||
|
||||
const extensions = ref<any[]>([])
|
||||
const load = ref<any[]>([])
|
||||
|
||||
const getLoad = async () => {
|
||||
const { data } = await php.load(version.value)
|
||||
return data
|
||||
}
|
||||
|
||||
const getExtensions = async () => {
|
||||
const { data } = await php.extensions(version.value)
|
||||
return data
|
||||
}
|
||||
|
||||
const getStatus = async () => {
|
||||
await systemctl.status(`php-fpm-${version.value}`).then((res: any) => {
|
||||
status.value = res.data
|
||||
})
|
||||
}
|
||||
|
||||
const getIsEnabled = async () => {
|
||||
await systemctl.isEnabled(`php-fpm-${version.value}`).then((res: any) => {
|
||||
isEnabled.value = res.data
|
||||
})
|
||||
}
|
||||
|
||||
const getErrorLog = async () => {
|
||||
php.errorLog(version.value).then((res: any) => {
|
||||
errorLog.value = res.data
|
||||
})
|
||||
}
|
||||
|
||||
const getSlowLog = async () => {
|
||||
php.slowLog(version.value).then((res: any) => {
|
||||
slowLog.value = res.data
|
||||
})
|
||||
}
|
||||
|
||||
const getConfig = async () => {
|
||||
php.config(version.value).then((res: any) => {
|
||||
config.value = res.data
|
||||
})
|
||||
}
|
||||
|
||||
const getFPMConfig = async () => {
|
||||
php.fpmConfig(version.value).then((res: any) => {
|
||||
fpmConfig.value = res.data
|
||||
})
|
||||
}
|
||||
|
||||
const handleSaveConfig = async () => {
|
||||
await php.saveConfig(version.value, config.value)
|
||||
window.$message.success('保存成功')
|
||||
}
|
||||
|
||||
const handleSaveFPMConfig = async () => {
|
||||
await php.saveFPMConfig(version.value, fpmConfig.value)
|
||||
window.$message.success('保存成功')
|
||||
await getFPMConfig()
|
||||
}
|
||||
|
||||
const handleClearErrorLog = async () => {
|
||||
await php.clearErrorLog(version.value)
|
||||
window.$message.success('清空成功')
|
||||
}
|
||||
|
||||
const handleClearSlowLog = async () => {
|
||||
await php.clearSlowLog(version.value)
|
||||
window.$message.success('清空成功')
|
||||
}
|
||||
|
||||
const handleIsEnabled = async () => {
|
||||
if (isEnabled.value) {
|
||||
await systemctl.enable(`php-fpm-${version.value}`)
|
||||
window.$message.success('开启自启动成功')
|
||||
} else {
|
||||
await systemctl.disable(`php-fpm-${version.value}`)
|
||||
window.$message.success('禁用自启动成功')
|
||||
}
|
||||
await getIsEnabled()
|
||||
}
|
||||
|
||||
const handleStart = async () => {
|
||||
await systemctl.start(`php-fpm-${version.value}`)
|
||||
window.$message.success('启动成功')
|
||||
await getStatus()
|
||||
}
|
||||
|
||||
const handleStop = async () => {
|
||||
await systemctl.stop(`php-fpm-${version.value}`)
|
||||
window.$message.success('停止成功')
|
||||
await getStatus()
|
||||
}
|
||||
|
||||
const handleRestart = async () => {
|
||||
await systemctl.restart(`php-fpm-${version.value}`)
|
||||
window.$message.success('重启成功')
|
||||
await getStatus()
|
||||
}
|
||||
|
||||
const handleReload = async () => {
|
||||
await systemctl.reload(`php-fpm-${version.value}`)
|
||||
window.$message.success('重载成功')
|
||||
await getStatus()
|
||||
}
|
||||
|
||||
const handleInstallExtension = async (slug: string) => {
|
||||
await php.installExtension(version.value, slug).then(() => {
|
||||
window.$message.success('任务已提交,请稍后查看任务进度')
|
||||
})
|
||||
}
|
||||
|
||||
const handleUninstallExtension = async (name: string) => {
|
||||
await php.uninstallExtension(version.value, name).then(() => {
|
||||
window.$message.success('任务已提交,请稍后查看任务进度')
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
getStatus()
|
||||
getIsEnabled()
|
||||
getExtensions().then((res) => {
|
||||
extensions.value = res
|
||||
})
|
||||
getLoad().then((res) => {
|
||||
load.value = res
|
||||
})
|
||||
getErrorLog()
|
||||
getSlowLog()
|
||||
getConfig()
|
||||
getFPMConfig()
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<common-page show-footer>
|
||||
<template #action>
|
||||
<n-button
|
||||
v-if="currentTab == 'config'"
|
||||
class="ml-16"
|
||||
type="primary"
|
||||
@click="handleSaveConfig"
|
||||
>
|
||||
<TheIcon :size="18" icon="material-symbols:save-outline" />
|
||||
保存
|
||||
</n-button>
|
||||
<n-button
|
||||
v-if="currentTab == 'fpm-config'"
|
||||
class="ml-16"
|
||||
type="primary"
|
||||
@click="handleSaveFPMConfig"
|
||||
>
|
||||
<TheIcon :size="18" icon="material-symbols:save-outline" />
|
||||
保存
|
||||
</n-button>
|
||||
<n-button
|
||||
v-if="currentTab == 'error-log'"
|
||||
class="ml-16"
|
||||
type="primary"
|
||||
@click="handleClearErrorLog"
|
||||
>
|
||||
<TheIcon :size="18" icon="material-symbols:delete-outline" />
|
||||
清空错误日志
|
||||
</n-button>
|
||||
<n-button
|
||||
v-if="currentTab == 'slow-log'"
|
||||
class="ml-16"
|
||||
type="primary"
|
||||
@click="handleClearSlowLog"
|
||||
>
|
||||
<TheIcon :size="18" icon="material-symbols:delete-outline" />
|
||||
清空慢日志
|
||||
</n-button>
|
||||
</template>
|
||||
<n-tabs v-model:value="currentTab" type="line" animated>
|
||||
<n-tab-pane name="status" tab="运行状态">
|
||||
<n-space vertical>
|
||||
<n-card title="运行状态" rounded-10>
|
||||
<template #header-extra>
|
||||
<n-switch v-model:value="isEnabled" @update:value="handleIsEnabled">
|
||||
<template #checked> 自启动开 </template>
|
||||
<template #unchecked> 自启动关 </template>
|
||||
</n-switch>
|
||||
</template>
|
||||
<n-space vertical>
|
||||
<n-alert :type="statusType">
|
||||
{{ statusStr }}
|
||||
</n-alert>
|
||||
<n-space>
|
||||
<n-button type="success" @click="handleStart">
|
||||
<TheIcon :size="24" icon="material-symbols:play-arrow-outline-rounded" />
|
||||
启动
|
||||
</n-button>
|
||||
<n-popconfirm @positive-click="handleStop">
|
||||
<template #trigger>
|
||||
<n-button type="error">
|
||||
<TheIcon :size="24" icon="material-symbols:stop-outline-rounded" />
|
||||
停止
|
||||
</n-button>
|
||||
</template>
|
||||
停止 PHP {{ version }} 会导致使用 PHP {{ version }} 的网站无法访问,确定要停止吗?
|
||||
</n-popconfirm>
|
||||
<n-button type="warning" @click="handleRestart">
|
||||
<TheIcon :size="18" icon="material-symbols:replay-rounded" />
|
||||
重启
|
||||
</n-button>
|
||||
<n-button type="primary" @click="handleReload">
|
||||
<TheIcon :size="20" icon="material-symbols:refresh-rounded" />
|
||||
重载
|
||||
</n-button>
|
||||
</n-space>
|
||||
</n-space>
|
||||
</n-card>
|
||||
</n-space>
|
||||
</n-tab-pane>
|
||||
<n-tab-pane name="extensions" tab="拓展管理">
|
||||
<n-card title="拓展列表" :segmented="true" rounded-10>
|
||||
<n-data-table
|
||||
striped
|
||||
remote
|
||||
:scroll-x="1000"
|
||||
:loading="false"
|
||||
:columns="extensionColumns"
|
||||
:data="extensions"
|
||||
:row-key="(row: any) => row.slug"
|
||||
/>
|
||||
</n-card>
|
||||
</n-tab-pane>
|
||||
<n-tab-pane name="config" tab="主配置">
|
||||
<n-space vertical>
|
||||
<n-alert type="warning">
|
||||
此处修改的是 PHP {{ version }} 主配置文件,如果您不了解各参数的含义,请不要随意修改!
|
||||
</n-alert>
|
||||
<Editor
|
||||
v-model:value="config"
|
||||
language="ini"
|
||||
theme="vs-dark"
|
||||
height="60vh"
|
||||
mt-8
|
||||
:options="{
|
||||
automaticLayout: true,
|
||||
formatOnType: true,
|
||||
formatOnPaste: true
|
||||
}"
|
||||
/>
|
||||
</n-space>
|
||||
</n-tab-pane>
|
||||
<n-tab-pane name="fpm-config" tab="FPM 配置">
|
||||
<n-space vertical>
|
||||
<n-alert type="warning">
|
||||
此处修改的是 PHP {{ version }} FPM 配置文件,如果您不了解各参数的含义,请不要随意修改!
|
||||
</n-alert>
|
||||
<Editor
|
||||
v-model:value="fpmConfig"
|
||||
language="ini"
|
||||
theme="vs-dark"
|
||||
height="60vh"
|
||||
mt-8
|
||||
:options="{
|
||||
automaticLayout: true,
|
||||
formatOnType: true,
|
||||
formatOnPaste: true
|
||||
}"
|
||||
/>
|
||||
</n-space>
|
||||
</n-tab-pane>
|
||||
<n-tab-pane name="load" tab="负载状态">
|
||||
<n-data-table
|
||||
striped
|
||||
remote
|
||||
:scroll-x="400"
|
||||
:loading="false"
|
||||
:columns="loadColumns"
|
||||
:data="load"
|
||||
/>
|
||||
</n-tab-pane>
|
||||
<n-tab-pane name="error-log" tab="错误日志">
|
||||
<realtime-log :path="errorLog" />
|
||||
</n-tab-pane>
|
||||
<n-tab-pane name="slow-log" tab="慢日志">
|
||||
<realtime-log :path="slowLog" />
|
||||
</n-tab-pane>
|
||||
</n-tabs>
|
||||
</common-page>
|
||||
</template>
|
||||
11
web/src/views/apps/php74/IndexView.vue
Normal file
11
web/src/views/apps/php74/IndexView.vue
Normal file
@@ -0,0 +1,11 @@
|
||||
<script setup lang="ts">
|
||||
import PhpView from '@/views/apps/php/PhpView.vue'
|
||||
|
||||
defineOptions({
|
||||
name: 'apps-php74-index'
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<php-view :version="74" />
|
||||
</template>
|
||||
23
web/src/views/apps/php74/route.ts
Normal file
23
web/src/views/apps/php74/route.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import type { RouteType } from '~/types/router'
|
||||
|
||||
const Layout = () => import('@/layout/IndexView.vue')
|
||||
|
||||
export default {
|
||||
name: 'php74',
|
||||
path: '/apps/php74',
|
||||
component: Layout,
|
||||
isHidden: true,
|
||||
children: [
|
||||
{
|
||||
name: 'apps-php74-index',
|
||||
path: '',
|
||||
component: () => import('./IndexView.vue'),
|
||||
meta: {
|
||||
title: 'PHP 7.4',
|
||||
icon: 'logos:php',
|
||||
role: ['admin'],
|
||||
requireAuth: true
|
||||
}
|
||||
}
|
||||
]
|
||||
} as RouteType
|
||||
11
web/src/views/apps/php80/IndexView.vue
Normal file
11
web/src/views/apps/php80/IndexView.vue
Normal file
@@ -0,0 +1,11 @@
|
||||
<script setup lang="ts">
|
||||
import PhpView from '@/views/apps/php/PhpView.vue'
|
||||
|
||||
defineOptions({
|
||||
name: 'apps-php80-index'
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<php-view :version="80" />
|
||||
</template>
|
||||
23
web/src/views/apps/php80/route.ts
Normal file
23
web/src/views/apps/php80/route.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import type { RouteType } from '~/types/router'
|
||||
|
||||
const Layout = () => import('@/layout/IndexView.vue')
|
||||
|
||||
export default {
|
||||
name: 'php80',
|
||||
path: '/apps/php80',
|
||||
component: Layout,
|
||||
isHidden: true,
|
||||
children: [
|
||||
{
|
||||
name: 'apps-php80-index',
|
||||
path: '',
|
||||
component: () => import('./IndexView.vue'),
|
||||
meta: {
|
||||
title: 'PHP 8.0',
|
||||
icon: 'logos:php',
|
||||
role: ['admin'],
|
||||
requireAuth: true
|
||||
}
|
||||
}
|
||||
]
|
||||
} as RouteType
|
||||
@@ -1,397 +1,11 @@
|
||||
<script setup lang="ts">
|
||||
import PhpView from '@/views/apps/php/PhpView.vue'
|
||||
|
||||
defineOptions({
|
||||
name: 'apps-php81-index'
|
||||
})
|
||||
|
||||
import Editor from '@guolao/vue-monaco-editor'
|
||||
import { NButton, NDataTable, NPopconfirm } from 'naive-ui'
|
||||
|
||||
import php from '@/api/apps/php'
|
||||
import systemctl from '@/api/panel/systemctl'
|
||||
import { renderIcon } from '@/utils'
|
||||
|
||||
const currentTab = ref('status')
|
||||
const version = Number(81)
|
||||
const status = ref(false)
|
||||
const isEnabled = ref(false)
|
||||
const config = ref('')
|
||||
const fpmConfig = ref('')
|
||||
const errorLog = ref('')
|
||||
const slowLog = ref('')
|
||||
|
||||
const statusType = computed(() => {
|
||||
return status.value ? 'success' : 'error'
|
||||
})
|
||||
const statusStr = computed(() => {
|
||||
return status.value ? '正常运行中' : '已停止运行'
|
||||
})
|
||||
|
||||
const extensionColumns: any = [
|
||||
{
|
||||
title: '拓展名',
|
||||
key: 'name',
|
||||
minWidth: 250,
|
||||
resizable: true,
|
||||
ellipsis: { tooltip: true }
|
||||
},
|
||||
{
|
||||
title: '描述',
|
||||
key: 'description',
|
||||
resizable: true,
|
||||
minWidth: 250,
|
||||
ellipsis: { tooltip: true }
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
key: 'actions',
|
||||
width: 240,
|
||||
align: 'center',
|
||||
hideInExcel: true,
|
||||
render(row: any) {
|
||||
return [
|
||||
!row.installed
|
||||
? h(
|
||||
NButton,
|
||||
{
|
||||
size: 'small',
|
||||
type: 'primary',
|
||||
secondary: true,
|
||||
onClick: () => handleInstallExtension(row.slug)
|
||||
},
|
||||
{
|
||||
default: () => '安装',
|
||||
icon: renderIcon('material-symbols:download-rounded', { size: 14 })
|
||||
}
|
||||
)
|
||||
: null,
|
||||
row.installed
|
||||
? h(
|
||||
NPopconfirm,
|
||||
{
|
||||
onPositiveClick: () => handleUninstallExtension(row.slug)
|
||||
},
|
||||
{
|
||||
default: () => {
|
||||
return '确定卸载' + row.name + '吗?'
|
||||
},
|
||||
trigger: () => {
|
||||
return h(
|
||||
NButton,
|
||||
{
|
||||
size: 'small',
|
||||
type: 'error'
|
||||
},
|
||||
{
|
||||
default: () => '删除',
|
||||
icon: renderIcon('material-symbols:delete-outline', { size: 14 })
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
)
|
||||
: null
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
const loadColumns: any = [
|
||||
{
|
||||
title: '属性',
|
||||
key: 'name',
|
||||
minWidth: 200,
|
||||
resizable: true,
|
||||
ellipsis: { tooltip: true }
|
||||
},
|
||||
{
|
||||
title: '当前值',
|
||||
key: 'value',
|
||||
minWidth: 200,
|
||||
ellipsis: { tooltip: true }
|
||||
}
|
||||
]
|
||||
|
||||
const extensions = ref<any[]>([])
|
||||
const load = ref<any[]>([])
|
||||
|
||||
const getLoad = async () => {
|
||||
const { data } = await php.load(version)
|
||||
return data
|
||||
}
|
||||
|
||||
const getExtensions = async () => {
|
||||
const { data } = await php.extensions(version)
|
||||
return data
|
||||
}
|
||||
|
||||
const getStatus = async () => {
|
||||
await systemctl.status(`php-fpm-${version}`).then((res: any) => {
|
||||
status.value = res.data
|
||||
})
|
||||
}
|
||||
|
||||
const getIsEnabled = async () => {
|
||||
await systemctl.isEnabled(`php-fpm-${version}`).then((res: any) => {
|
||||
isEnabled.value = res.data
|
||||
})
|
||||
}
|
||||
|
||||
const getErrorLog = async () => {
|
||||
php.errorLog(version).then((res: any) => {
|
||||
errorLog.value = res.data
|
||||
})
|
||||
}
|
||||
|
||||
const getSlowLog = async () => {
|
||||
php.slowLog(version).then((res: any) => {
|
||||
slowLog.value = res.data
|
||||
})
|
||||
}
|
||||
|
||||
const getConfig = async () => {
|
||||
php.config(version).then((res: any) => {
|
||||
config.value = res.data
|
||||
})
|
||||
}
|
||||
|
||||
const getFPMConfig = async () => {
|
||||
php.fpmConfig(version).then((res: any) => {
|
||||
fpmConfig.value = res.data
|
||||
})
|
||||
}
|
||||
|
||||
const handleSaveConfig = async () => {
|
||||
await php.saveConfig(version, config.value)
|
||||
window.$message.success('保存成功')
|
||||
}
|
||||
|
||||
const handleSaveFPMConfig = async () => {
|
||||
await php.saveFPMConfig(version, fpmConfig.value)
|
||||
window.$message.success('保存成功')
|
||||
await getFPMConfig()
|
||||
}
|
||||
|
||||
const handleClearErrorLog = async () => {
|
||||
await php.clearErrorLog(version)
|
||||
window.$message.success('清空成功')
|
||||
}
|
||||
|
||||
const handleClearSlowLog = async () => {
|
||||
await php.clearSlowLog(version)
|
||||
window.$message.success('清空成功')
|
||||
}
|
||||
|
||||
const handleIsEnabled = async () => {
|
||||
if (isEnabled.value) {
|
||||
await systemctl.enable(`php-fpm-${version}`)
|
||||
window.$message.success('开启自启动成功')
|
||||
} else {
|
||||
await systemctl.disable(`php-fpm-${version}`)
|
||||
window.$message.success('禁用自启动成功')
|
||||
}
|
||||
await getIsEnabled()
|
||||
}
|
||||
|
||||
const handleStart = async () => {
|
||||
await systemctl.start(`php-fpm-${version}`)
|
||||
window.$message.success('启动成功')
|
||||
await getStatus()
|
||||
}
|
||||
|
||||
const handleStop = async () => {
|
||||
await systemctl.stop(`php-fpm-${version}`)
|
||||
window.$message.success('停止成功')
|
||||
await getStatus()
|
||||
}
|
||||
|
||||
const handleRestart = async () => {
|
||||
await systemctl.restart(`php-fpm-${version}`)
|
||||
window.$message.success('重启成功')
|
||||
await getStatus()
|
||||
}
|
||||
|
||||
const handleReload = async () => {
|
||||
await systemctl.reload(`php-fpm-${version}`)
|
||||
window.$message.success('重载成功')
|
||||
await getStatus()
|
||||
}
|
||||
|
||||
const handleInstallExtension = async (slug: string) => {
|
||||
await php.installExtension(version, slug).then(() => {
|
||||
window.$message.success('任务已提交,请稍后查看任务进度')
|
||||
})
|
||||
}
|
||||
|
||||
const handleUninstallExtension = async (name: string) => {
|
||||
await php.uninstallExtension(version, name).then(() => {
|
||||
window.$message.success('任务已提交,请稍后查看任务进度')
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
getStatus()
|
||||
getIsEnabled()
|
||||
getExtensions().then((res) => {
|
||||
extensions.value = res
|
||||
})
|
||||
getLoad().then((res) => {
|
||||
load.value = res
|
||||
})
|
||||
getErrorLog()
|
||||
getSlowLog()
|
||||
getConfig()
|
||||
getFPMConfig()
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<common-page show-footer>
|
||||
<template #action>
|
||||
<n-button
|
||||
v-if="currentTab == 'config'"
|
||||
class="ml-16"
|
||||
type="primary"
|
||||
@click="handleSaveConfig"
|
||||
>
|
||||
<TheIcon :size="18" icon="material-symbols:save-outline" />
|
||||
保存
|
||||
</n-button>
|
||||
<n-button
|
||||
v-if="currentTab == 'fpm-config'"
|
||||
class="ml-16"
|
||||
type="primary"
|
||||
@click="handleSaveFPMConfig"
|
||||
>
|
||||
<TheIcon :size="18" icon="material-symbols:save-outline" />
|
||||
保存
|
||||
</n-button>
|
||||
<n-button
|
||||
v-if="currentTab == 'error-log'"
|
||||
class="ml-16"
|
||||
type="primary"
|
||||
@click="handleClearErrorLog"
|
||||
>
|
||||
<TheIcon :size="18" icon="material-symbols:delete-outline" />
|
||||
清空错误日志
|
||||
</n-button>
|
||||
<n-button
|
||||
v-if="currentTab == 'slow-log'"
|
||||
class="ml-16"
|
||||
type="primary"
|
||||
@click="handleClearSlowLog"
|
||||
>
|
||||
<TheIcon :size="18" icon="material-symbols:delete-outline" />
|
||||
清空慢日志
|
||||
</n-button>
|
||||
</template>
|
||||
<n-tabs v-model:value="currentTab" type="line" animated>
|
||||
<n-tab-pane name="status" tab="运行状态">
|
||||
<n-space vertical>
|
||||
<n-card title="运行状态" rounded-10>
|
||||
<template #header-extra>
|
||||
<n-switch v-model:value="isEnabled" @update:value="handleIsEnabled">
|
||||
<template #checked> 自启动开 </template>
|
||||
<template #unchecked> 自启动关 </template>
|
||||
</n-switch>
|
||||
</template>
|
||||
<n-space vertical>
|
||||
<n-alert :type="statusType">
|
||||
{{ statusStr }}
|
||||
</n-alert>
|
||||
<n-space>
|
||||
<n-button type="success" @click="handleStart">
|
||||
<TheIcon :size="24" icon="material-symbols:play-arrow-outline-rounded" />
|
||||
启动
|
||||
</n-button>
|
||||
<n-popconfirm @positive-click="handleStop">
|
||||
<template #trigger>
|
||||
<n-button type="error">
|
||||
<TheIcon :size="24" icon="material-symbols:stop-outline-rounded" />
|
||||
停止
|
||||
</n-button>
|
||||
</template>
|
||||
停止 PHP {{ version }} 会导致使用 PHP {{ version }} 的网站无法访问,确定要停止吗?
|
||||
</n-popconfirm>
|
||||
<n-button type="warning" @click="handleRestart">
|
||||
<TheIcon :size="18" icon="material-symbols:replay-rounded" />
|
||||
重启
|
||||
</n-button>
|
||||
<n-button type="primary" @click="handleReload">
|
||||
<TheIcon :size="20" icon="material-symbols:refresh-rounded" />
|
||||
重载
|
||||
</n-button>
|
||||
</n-space>
|
||||
</n-space>
|
||||
</n-card>
|
||||
</n-space>
|
||||
</n-tab-pane>
|
||||
<n-tab-pane name="extensions" tab="拓展管理">
|
||||
<n-card title="拓展列表" :segmented="true" rounded-10>
|
||||
<n-data-table
|
||||
striped
|
||||
remote
|
||||
:scroll-x="1000"
|
||||
:loading="false"
|
||||
:columns="extensionColumns"
|
||||
:data="extensions"
|
||||
:row-key="(row: any) => row.slug"
|
||||
/>
|
||||
</n-card>
|
||||
</n-tab-pane>
|
||||
<n-tab-pane name="config" tab="主配置">
|
||||
<n-space vertical>
|
||||
<n-alert type="warning">
|
||||
此处修改的是 PHP {{ version }} 主配置文件,如果您不了解各参数的含义,请不要随意修改!
|
||||
</n-alert>
|
||||
<Editor
|
||||
v-model:value="config"
|
||||
language="ini"
|
||||
theme="vs-dark"
|
||||
height="60vh"
|
||||
mt-8
|
||||
:options="{
|
||||
automaticLayout: true,
|
||||
formatOnType: true,
|
||||
formatOnPaste: true
|
||||
}"
|
||||
/>
|
||||
</n-space>
|
||||
</n-tab-pane>
|
||||
<n-tab-pane name="fpm-config" tab="FPM 配置">
|
||||
<n-space vertical>
|
||||
<n-alert type="warning">
|
||||
此处修改的是 PHP {{ version }} FPM 配置文件,如果您不了解各参数的含义,请不要随意修改!
|
||||
</n-alert>
|
||||
<Editor
|
||||
v-model:value="fpmConfig"
|
||||
language="ini"
|
||||
theme="vs-dark"
|
||||
height="60vh"
|
||||
mt-8
|
||||
:options="{
|
||||
automaticLayout: true,
|
||||
formatOnType: true,
|
||||
formatOnPaste: true
|
||||
}"
|
||||
/>
|
||||
</n-space>
|
||||
</n-tab-pane>
|
||||
<n-tab-pane name="load" tab="负载状态">
|
||||
<n-data-table
|
||||
striped
|
||||
remote
|
||||
:scroll-x="400"
|
||||
:loading="false"
|
||||
:columns="loadColumns"
|
||||
:data="load"
|
||||
/>
|
||||
</n-tab-pane>
|
||||
<n-tab-pane name="error-log" tab="错误日志">
|
||||
<realtime-log :path="errorLog" />
|
||||
</n-tab-pane>
|
||||
<n-tab-pane name="slow-log" tab="慢日志">
|
||||
<realtime-log :path="slowLog" />
|
||||
</n-tab-pane>
|
||||
</n-tabs>
|
||||
</common-page>
|
||||
<php-view :version="81" />
|
||||
</template>
|
||||
|
||||
@@ -1,397 +1,11 @@
|
||||
<script setup lang="ts">
|
||||
import PhpView from '@/views/apps/php/PhpView.vue'
|
||||
|
||||
defineOptions({
|
||||
name: 'apps-php82-index'
|
||||
})
|
||||
|
||||
import Editor from '@guolao/vue-monaco-editor'
|
||||
import { NButton, NDataTable, NPopconfirm } from 'naive-ui'
|
||||
|
||||
import php from '@/api/apps/php'
|
||||
import systemctl from '@/api/panel/systemctl'
|
||||
import { renderIcon } from '@/utils'
|
||||
|
||||
const currentTab = ref('status')
|
||||
const version = Number(82)
|
||||
const status = ref(false)
|
||||
const isEnabled = ref(false)
|
||||
const config = ref('')
|
||||
const fpmConfig = ref('')
|
||||
const errorLog = ref('')
|
||||
const slowLog = ref('')
|
||||
|
||||
const statusType = computed(() => {
|
||||
return status.value ? 'success' : 'error'
|
||||
})
|
||||
const statusStr = computed(() => {
|
||||
return status.value ? '正常运行中' : '已停止运行'
|
||||
})
|
||||
|
||||
const extensionColumns: any = [
|
||||
{
|
||||
title: '拓展名',
|
||||
key: 'name',
|
||||
minWidth: 250,
|
||||
resizable: true,
|
||||
ellipsis: { tooltip: true }
|
||||
},
|
||||
{
|
||||
title: '描述',
|
||||
key: 'description',
|
||||
resizable: true,
|
||||
minWidth: 250,
|
||||
ellipsis: { tooltip: true }
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
key: 'actions',
|
||||
width: 240,
|
||||
align: 'center',
|
||||
hideInExcel: true,
|
||||
render(row: any) {
|
||||
return [
|
||||
!row.installed
|
||||
? h(
|
||||
NButton,
|
||||
{
|
||||
size: 'small',
|
||||
type: 'primary',
|
||||
secondary: true,
|
||||
onClick: () => handleInstallExtension(row.slug)
|
||||
},
|
||||
{
|
||||
default: () => '安装',
|
||||
icon: renderIcon('material-symbols:download-rounded', { size: 14 })
|
||||
}
|
||||
)
|
||||
: null,
|
||||
row.installed
|
||||
? h(
|
||||
NPopconfirm,
|
||||
{
|
||||
onPositiveClick: () => handleUninstallExtension(row.slug)
|
||||
},
|
||||
{
|
||||
default: () => {
|
||||
return '确定卸载' + row.name + '吗?'
|
||||
},
|
||||
trigger: () => {
|
||||
return h(
|
||||
NButton,
|
||||
{
|
||||
size: 'small',
|
||||
type: 'error'
|
||||
},
|
||||
{
|
||||
default: () => '删除',
|
||||
icon: renderIcon('material-symbols:delete-outline', { size: 14 })
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
)
|
||||
: null
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
const loadColumns: any = [
|
||||
{
|
||||
title: '属性',
|
||||
key: 'name',
|
||||
minWidth: 200,
|
||||
resizable: true,
|
||||
ellipsis: { tooltip: true }
|
||||
},
|
||||
{
|
||||
title: '当前值',
|
||||
key: 'value',
|
||||
minWidth: 200,
|
||||
ellipsis: { tooltip: true }
|
||||
}
|
||||
]
|
||||
|
||||
const extensions = ref<any[]>([])
|
||||
const load = ref<any[]>([])
|
||||
|
||||
const getLoad = async () => {
|
||||
const { data } = await php.load(version)
|
||||
return data
|
||||
}
|
||||
|
||||
const getExtensions = async () => {
|
||||
const { data } = await php.extensions(version)
|
||||
return data
|
||||
}
|
||||
|
||||
const getStatus = async () => {
|
||||
await systemctl.status(`php-fpm-${version}`).then((res: any) => {
|
||||
status.value = res.data
|
||||
})
|
||||
}
|
||||
|
||||
const getIsEnabled = async () => {
|
||||
await systemctl.isEnabled(`php-fpm-${version}`).then((res: any) => {
|
||||
isEnabled.value = res.data
|
||||
})
|
||||
}
|
||||
|
||||
const getErrorLog = async () => {
|
||||
php.errorLog(version).then((res: any) => {
|
||||
errorLog.value = res.data
|
||||
})
|
||||
}
|
||||
|
||||
const getSlowLog = async () => {
|
||||
php.slowLog(version).then((res: any) => {
|
||||
slowLog.value = res.data
|
||||
})
|
||||
}
|
||||
|
||||
const getConfig = async () => {
|
||||
php.config(version).then((res: any) => {
|
||||
config.value = res.data
|
||||
})
|
||||
}
|
||||
|
||||
const getFPMConfig = async () => {
|
||||
php.fpmConfig(version).then((res: any) => {
|
||||
fpmConfig.value = res.data
|
||||
})
|
||||
}
|
||||
|
||||
const handleSaveConfig = async () => {
|
||||
await php.saveConfig(version, config.value)
|
||||
window.$message.success('保存成功')
|
||||
}
|
||||
|
||||
const handleSaveFPMConfig = async () => {
|
||||
await php.saveFPMConfig(version, fpmConfig.value)
|
||||
window.$message.success('保存成功')
|
||||
await getFPMConfig()
|
||||
}
|
||||
|
||||
const handleClearErrorLog = async () => {
|
||||
await php.clearErrorLog(version)
|
||||
window.$message.success('清空成功')
|
||||
}
|
||||
|
||||
const handleClearSlowLog = async () => {
|
||||
await php.clearSlowLog(version)
|
||||
window.$message.success('清空成功')
|
||||
}
|
||||
|
||||
const handleIsEnabled = async () => {
|
||||
if (isEnabled.value) {
|
||||
await systemctl.enable(`php-fpm-${version}`)
|
||||
window.$message.success('开启自启动成功')
|
||||
} else {
|
||||
await systemctl.disable(`php-fpm-${version}`)
|
||||
window.$message.success('禁用自启动成功')
|
||||
}
|
||||
await getIsEnabled()
|
||||
}
|
||||
|
||||
const handleStart = async () => {
|
||||
await systemctl.start(`php-fpm-${version}`)
|
||||
window.$message.success('启动成功')
|
||||
await getStatus()
|
||||
}
|
||||
|
||||
const handleStop = async () => {
|
||||
await systemctl.stop(`php-fpm-${version}`)
|
||||
window.$message.success('停止成功')
|
||||
await getStatus()
|
||||
}
|
||||
|
||||
const handleRestart = async () => {
|
||||
await systemctl.restart(`php-fpm-${version}`)
|
||||
window.$message.success('重启成功')
|
||||
await getStatus()
|
||||
}
|
||||
|
||||
const handleReload = async () => {
|
||||
await systemctl.reload(`php-fpm-${version}`)
|
||||
window.$message.success('重载成功')
|
||||
await getStatus()
|
||||
}
|
||||
|
||||
const handleInstallExtension = async (slug: string) => {
|
||||
await php.installExtension(version, slug).then(() => {
|
||||
window.$message.success('任务已提交,请稍后查看任务进度')
|
||||
})
|
||||
}
|
||||
|
||||
const handleUninstallExtension = async (name: string) => {
|
||||
await php.uninstallExtension(version, name).then(() => {
|
||||
window.$message.success('任务已提交,请稍后查看任务进度')
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
getStatus()
|
||||
getIsEnabled()
|
||||
getExtensions().then((res) => {
|
||||
extensions.value = res
|
||||
})
|
||||
getLoad().then((res) => {
|
||||
load.value = res
|
||||
})
|
||||
getErrorLog()
|
||||
getSlowLog()
|
||||
getConfig()
|
||||
getFPMConfig()
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<common-page show-footer>
|
||||
<template #action>
|
||||
<n-button
|
||||
v-if="currentTab == 'config'"
|
||||
class="ml-16"
|
||||
type="primary"
|
||||
@click="handleSaveConfig"
|
||||
>
|
||||
<TheIcon :size="18" icon="material-symbols:save-outline" />
|
||||
保存
|
||||
</n-button>
|
||||
<n-button
|
||||
v-if="currentTab == 'fpm-config'"
|
||||
class="ml-16"
|
||||
type="primary"
|
||||
@click="handleSaveFPMConfig"
|
||||
>
|
||||
<TheIcon :size="18" icon="material-symbols:save-outline" />
|
||||
保存
|
||||
</n-button>
|
||||
<n-button
|
||||
v-if="currentTab == 'error-log'"
|
||||
class="ml-16"
|
||||
type="primary"
|
||||
@click="handleClearErrorLog"
|
||||
>
|
||||
<TheIcon :size="18" icon="material-symbols:delete-outline" />
|
||||
清空错误日志
|
||||
</n-button>
|
||||
<n-button
|
||||
v-if="currentTab == 'slow-log'"
|
||||
class="ml-16"
|
||||
type="primary"
|
||||
@click="handleClearSlowLog"
|
||||
>
|
||||
<TheIcon :size="18" icon="material-symbols:delete-outline" />
|
||||
清空慢日志
|
||||
</n-button>
|
||||
</template>
|
||||
<n-tabs v-model:value="currentTab" type="line" animated>
|
||||
<n-tab-pane name="status" tab="运行状态">
|
||||
<n-space vertical>
|
||||
<n-card title="运行状态" rounded-10>
|
||||
<template #header-extra>
|
||||
<n-switch v-model:value="isEnabled" @update:value="handleIsEnabled">
|
||||
<template #checked> 自启动开 </template>
|
||||
<template #unchecked> 自启动关 </template>
|
||||
</n-switch>
|
||||
</template>
|
||||
<n-space vertical>
|
||||
<n-alert :type="statusType">
|
||||
{{ statusStr }}
|
||||
</n-alert>
|
||||
<n-space>
|
||||
<n-button type="success" @click="handleStart">
|
||||
<TheIcon :size="24" icon="material-symbols:play-arrow-outline-rounded" />
|
||||
启动
|
||||
</n-button>
|
||||
<n-popconfirm @positive-click="handleStop">
|
||||
<template #trigger>
|
||||
<n-button type="error">
|
||||
<TheIcon :size="24" icon="material-symbols:stop-outline-rounded" />
|
||||
停止
|
||||
</n-button>
|
||||
</template>
|
||||
停止 PHP {{ version }} 会导致使用 PHP {{ version }} 的网站无法访问,确定要停止吗?
|
||||
</n-popconfirm>
|
||||
<n-button type="warning" @click="handleRestart">
|
||||
<TheIcon :size="18" icon="material-symbols:replay-rounded" />
|
||||
重启
|
||||
</n-button>
|
||||
<n-button type="primary" @click="handleReload">
|
||||
<TheIcon :size="20" icon="material-symbols:refresh-rounded" />
|
||||
重载
|
||||
</n-button>
|
||||
</n-space>
|
||||
</n-space>
|
||||
</n-card>
|
||||
</n-space>
|
||||
</n-tab-pane>
|
||||
<n-tab-pane name="extensions" tab="拓展管理">
|
||||
<n-card title="拓展列表" :segmented="true" rounded-10>
|
||||
<n-data-table
|
||||
striped
|
||||
remote
|
||||
:scroll-x="1000"
|
||||
:loading="false"
|
||||
:columns="extensionColumns"
|
||||
:data="extensions"
|
||||
:row-key="(row: any) => row.slug"
|
||||
/>
|
||||
</n-card>
|
||||
</n-tab-pane>
|
||||
<n-tab-pane name="config" tab="主配置">
|
||||
<n-space vertical>
|
||||
<n-alert type="warning">
|
||||
此处修改的是 PHP {{ version }} 主配置文件,如果您不了解各参数的含义,请不要随意修改!
|
||||
</n-alert>
|
||||
<Editor
|
||||
v-model:value="config"
|
||||
language="ini"
|
||||
theme="vs-dark"
|
||||
height="60vh"
|
||||
mt-8
|
||||
:options="{
|
||||
automaticLayout: true,
|
||||
formatOnType: true,
|
||||
formatOnPaste: true
|
||||
}"
|
||||
/>
|
||||
</n-space>
|
||||
</n-tab-pane>
|
||||
<n-tab-pane name="fpm-config" tab="FPM 配置">
|
||||
<n-space vertical>
|
||||
<n-alert type="warning">
|
||||
此处修改的是 PHP {{ version }} FPM 配置文件,如果您不了解各参数的含义,请不要随意修改!
|
||||
</n-alert>
|
||||
<Editor
|
||||
v-model:value="fpmConfig"
|
||||
language="ini"
|
||||
theme="vs-dark"
|
||||
height="60vh"
|
||||
mt-8
|
||||
:options="{
|
||||
automaticLayout: true,
|
||||
formatOnType: true,
|
||||
formatOnPaste: true
|
||||
}"
|
||||
/>
|
||||
</n-space>
|
||||
</n-tab-pane>
|
||||
<n-tab-pane name="load" tab="负载状态">
|
||||
<n-data-table
|
||||
striped
|
||||
remote
|
||||
:scroll-x="400"
|
||||
:loading="false"
|
||||
:columns="loadColumns"
|
||||
:data="load"
|
||||
/>
|
||||
</n-tab-pane>
|
||||
<n-tab-pane name="error-log" tab="错误日志">
|
||||
<realtime-log :path="errorLog" />
|
||||
</n-tab-pane>
|
||||
<n-tab-pane name="slow-log" tab="慢日志">
|
||||
<realtime-log :path="slowLog" />
|
||||
</n-tab-pane>
|
||||
</n-tabs>
|
||||
</common-page>
|
||||
<php-view :version="82" />
|
||||
</template>
|
||||
|
||||
@@ -1,397 +1,11 @@
|
||||
<script setup lang="ts">
|
||||
import PhpView from '@/views/apps/php/PhpView.vue'
|
||||
|
||||
defineOptions({
|
||||
name: 'apps-php83-index'
|
||||
})
|
||||
|
||||
import Editor from '@guolao/vue-monaco-editor'
|
||||
import { NButton, NDataTable, NPopconfirm } from 'naive-ui'
|
||||
|
||||
import php from '@/api/apps/php'
|
||||
import systemctl from '@/api/panel/systemctl'
|
||||
import { renderIcon } from '@/utils'
|
||||
|
||||
const currentTab = ref('status')
|
||||
const version = Number(83)
|
||||
const status = ref(false)
|
||||
const isEnabled = ref(false)
|
||||
const config = ref('')
|
||||
const fpmConfig = ref('')
|
||||
const errorLog = ref('')
|
||||
const slowLog = ref('')
|
||||
|
||||
const statusType = computed(() => {
|
||||
return status.value ? 'success' : 'error'
|
||||
})
|
||||
const statusStr = computed(() => {
|
||||
return status.value ? '正常运行中' : '已停止运行'
|
||||
})
|
||||
|
||||
const extensionColumns: any = [
|
||||
{
|
||||
title: '拓展名',
|
||||
key: 'name',
|
||||
minWidth: 250,
|
||||
resizable: true,
|
||||
ellipsis: { tooltip: true }
|
||||
},
|
||||
{
|
||||
title: '描述',
|
||||
key: 'description',
|
||||
resizable: true,
|
||||
minWidth: 250,
|
||||
ellipsis: { tooltip: true }
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
key: 'actions',
|
||||
width: 240,
|
||||
align: 'center',
|
||||
hideInExcel: true,
|
||||
render(row: any) {
|
||||
return [
|
||||
!row.installed
|
||||
? h(
|
||||
NButton,
|
||||
{
|
||||
size: 'small',
|
||||
type: 'primary',
|
||||
secondary: true,
|
||||
onClick: () => handleInstallExtension(row.slug)
|
||||
},
|
||||
{
|
||||
default: () => '安装',
|
||||
icon: renderIcon('material-symbols:download-rounded', { size: 14 })
|
||||
}
|
||||
)
|
||||
: null,
|
||||
row.installed
|
||||
? h(
|
||||
NPopconfirm,
|
||||
{
|
||||
onPositiveClick: () => handleUninstallExtension(row.slug)
|
||||
},
|
||||
{
|
||||
default: () => {
|
||||
return '确定卸载' + row.name + '吗?'
|
||||
},
|
||||
trigger: () => {
|
||||
return h(
|
||||
NButton,
|
||||
{
|
||||
size: 'small',
|
||||
type: 'error'
|
||||
},
|
||||
{
|
||||
default: () => '删除',
|
||||
icon: renderIcon('material-symbols:delete-outline', { size: 14 })
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
)
|
||||
: null
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
const loadColumns: any = [
|
||||
{
|
||||
title: '属性',
|
||||
key: 'name',
|
||||
minWidth: 200,
|
||||
resizable: true,
|
||||
ellipsis: { tooltip: true }
|
||||
},
|
||||
{
|
||||
title: '当前值',
|
||||
key: 'value',
|
||||
minWidth: 200,
|
||||
ellipsis: { tooltip: true }
|
||||
}
|
||||
]
|
||||
|
||||
const extensions = ref<any[]>([])
|
||||
const load = ref<any[]>([])
|
||||
|
||||
const getLoad = async () => {
|
||||
const { data } = await php.load(version)
|
||||
return data
|
||||
}
|
||||
|
||||
const getExtensions = async () => {
|
||||
const { data } = await php.extensions(version)
|
||||
return data
|
||||
}
|
||||
|
||||
const getStatus = async () => {
|
||||
await systemctl.status(`php-fpm-${version}`).then((res: any) => {
|
||||
status.value = res.data
|
||||
})
|
||||
}
|
||||
|
||||
const getIsEnabled = async () => {
|
||||
await systemctl.isEnabled(`php-fpm-${version}`).then((res: any) => {
|
||||
isEnabled.value = res.data
|
||||
})
|
||||
}
|
||||
|
||||
const getErrorLog = async () => {
|
||||
php.errorLog(version).then((res: any) => {
|
||||
errorLog.value = res.data
|
||||
})
|
||||
}
|
||||
|
||||
const getSlowLog = async () => {
|
||||
php.slowLog(version).then((res: any) => {
|
||||
slowLog.value = res.data
|
||||
})
|
||||
}
|
||||
|
||||
const getConfig = async () => {
|
||||
php.config(version).then((res: any) => {
|
||||
config.value = res.data
|
||||
})
|
||||
}
|
||||
|
||||
const getFPMConfig = async () => {
|
||||
php.fpmConfig(version).then((res: any) => {
|
||||
fpmConfig.value = res.data
|
||||
})
|
||||
}
|
||||
|
||||
const handleSaveConfig = async () => {
|
||||
await php.saveConfig(version, config.value)
|
||||
window.$message.success('保存成功')
|
||||
}
|
||||
|
||||
const handleSaveFPMConfig = async () => {
|
||||
await php.saveFPMConfig(version, fpmConfig.value)
|
||||
window.$message.success('保存成功')
|
||||
await getFPMConfig()
|
||||
}
|
||||
|
||||
const handleClearErrorLog = async () => {
|
||||
await php.clearErrorLog(version)
|
||||
window.$message.success('清空成功')
|
||||
}
|
||||
|
||||
const handleClearSlowLog = async () => {
|
||||
await php.clearSlowLog(version)
|
||||
window.$message.success('清空成功')
|
||||
}
|
||||
|
||||
const handleIsEnabled = async () => {
|
||||
if (isEnabled.value) {
|
||||
await systemctl.enable(`php-fpm-${version}`)
|
||||
window.$message.success('开启自启动成功')
|
||||
} else {
|
||||
await systemctl.disable(`php-fpm-${version}`)
|
||||
window.$message.success('禁用自启动成功')
|
||||
}
|
||||
await getIsEnabled()
|
||||
}
|
||||
|
||||
const handleStart = async () => {
|
||||
await systemctl.start(`php-fpm-${version}`)
|
||||
window.$message.success('启动成功')
|
||||
await getStatus()
|
||||
}
|
||||
|
||||
const handleStop = async () => {
|
||||
await systemctl.stop(`php-fpm-${version}`)
|
||||
window.$message.success('停止成功')
|
||||
await getStatus()
|
||||
}
|
||||
|
||||
const handleRestart = async () => {
|
||||
await systemctl.restart(`php-fpm-${version}`)
|
||||
window.$message.success('重启成功')
|
||||
await getStatus()
|
||||
}
|
||||
|
||||
const handleReload = async () => {
|
||||
await systemctl.reload(`php-fpm-${version}`)
|
||||
window.$message.success('重载成功')
|
||||
await getStatus()
|
||||
}
|
||||
|
||||
const handleInstallExtension = async (slug: string) => {
|
||||
await php.installExtension(version, slug).then(() => {
|
||||
window.$message.success('任务已提交,请稍后查看任务进度')
|
||||
})
|
||||
}
|
||||
|
||||
const handleUninstallExtension = async (name: string) => {
|
||||
await php.uninstallExtension(version, name).then(() => {
|
||||
window.$message.success('任务已提交,请稍后查看任务进度')
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
getStatus()
|
||||
getIsEnabled()
|
||||
getExtensions().then((res) => {
|
||||
extensions.value = res
|
||||
})
|
||||
getLoad().then((res) => {
|
||||
load.value = res
|
||||
})
|
||||
getErrorLog()
|
||||
getSlowLog()
|
||||
getConfig()
|
||||
getFPMConfig()
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<common-page show-footer>
|
||||
<template #action>
|
||||
<n-button
|
||||
v-if="currentTab == 'config'"
|
||||
class="ml-16"
|
||||
type="primary"
|
||||
@click="handleSaveConfig"
|
||||
>
|
||||
<TheIcon :size="18" icon="material-symbols:save-outline" />
|
||||
保存
|
||||
</n-button>
|
||||
<n-button
|
||||
v-if="currentTab == 'fpm-config'"
|
||||
class="ml-16"
|
||||
type="primary"
|
||||
@click="handleSaveFPMConfig"
|
||||
>
|
||||
<TheIcon :size="18" icon="material-symbols:save-outline" />
|
||||
保存
|
||||
</n-button>
|
||||
<n-button
|
||||
v-if="currentTab == 'error-log'"
|
||||
class="ml-16"
|
||||
type="primary"
|
||||
@click="handleClearErrorLog"
|
||||
>
|
||||
<TheIcon :size="18" icon="material-symbols:delete-outline" />
|
||||
清空错误日志
|
||||
</n-button>
|
||||
<n-button
|
||||
v-if="currentTab == 'slow-log'"
|
||||
class="ml-16"
|
||||
type="primary"
|
||||
@click="handleClearSlowLog"
|
||||
>
|
||||
<TheIcon :size="18" icon="material-symbols:delete-outline" />
|
||||
清空慢日志
|
||||
</n-button>
|
||||
</template>
|
||||
<n-tabs v-model:value="currentTab" type="line" animated>
|
||||
<n-tab-pane name="status" tab="运行状态">
|
||||
<n-space vertical>
|
||||
<n-card title="运行状态" rounded-10>
|
||||
<template #header-extra>
|
||||
<n-switch v-model:value="isEnabled" @update:value="handleIsEnabled">
|
||||
<template #checked> 自启动开 </template>
|
||||
<template #unchecked> 自启动关 </template>
|
||||
</n-switch>
|
||||
</template>
|
||||
<n-space vertical>
|
||||
<n-alert :type="statusType">
|
||||
{{ statusStr }}
|
||||
</n-alert>
|
||||
<n-space>
|
||||
<n-button type="success" @click="handleStart">
|
||||
<TheIcon :size="24" icon="material-symbols:play-arrow-outline-rounded" />
|
||||
启动
|
||||
</n-button>
|
||||
<n-popconfirm @positive-click="handleStop">
|
||||
<template #trigger>
|
||||
<n-button type="error">
|
||||
<TheIcon :size="24" icon="material-symbols:stop-outline-rounded" />
|
||||
停止
|
||||
</n-button>
|
||||
</template>
|
||||
停止 PHP {{ version }} 会导致使用 PHP {{ version }} 的网站无法访问,确定要停止吗?
|
||||
</n-popconfirm>
|
||||
<n-button type="warning" @click="handleRestart">
|
||||
<TheIcon :size="18" icon="material-symbols:replay-rounded" />
|
||||
重启
|
||||
</n-button>
|
||||
<n-button type="primary" @click="handleReload">
|
||||
<TheIcon :size="20" icon="material-symbols:refresh-rounded" />
|
||||
重载
|
||||
</n-button>
|
||||
</n-space>
|
||||
</n-space>
|
||||
</n-card>
|
||||
</n-space>
|
||||
</n-tab-pane>
|
||||
<n-tab-pane name="extensions" tab="拓展管理">
|
||||
<n-card title="拓展列表" :segmented="true" rounded-10>
|
||||
<n-data-table
|
||||
striped
|
||||
remote
|
||||
:scroll-x="1000"
|
||||
:loading="false"
|
||||
:columns="extensionColumns"
|
||||
:data="extensions"
|
||||
:row-key="(row: any) => row.slug"
|
||||
/>
|
||||
</n-card>
|
||||
</n-tab-pane>
|
||||
<n-tab-pane name="config" tab="主配置">
|
||||
<n-space vertical>
|
||||
<n-alert type="warning">
|
||||
此处修改的是 PHP {{ version }} 主配置文件,如果您不了解各参数的含义,请不要随意修改!
|
||||
</n-alert>
|
||||
<Editor
|
||||
v-model:value="config"
|
||||
language="ini"
|
||||
theme="vs-dark"
|
||||
height="60vh"
|
||||
mt-8
|
||||
:options="{
|
||||
automaticLayout: true,
|
||||
formatOnType: true,
|
||||
formatOnPaste: true
|
||||
}"
|
||||
/>
|
||||
</n-space>
|
||||
</n-tab-pane>
|
||||
<n-tab-pane name="fpm-config" tab="FPM 配置">
|
||||
<n-space vertical>
|
||||
<n-alert type="warning">
|
||||
此处修改的是 PHP {{ version }} FPM 配置文件,如果您不了解各参数的含义,请不要随意修改!
|
||||
</n-alert>
|
||||
<Editor
|
||||
v-model:value="fpmConfig"
|
||||
language="ini"
|
||||
theme="vs-dark"
|
||||
height="60vh"
|
||||
mt-8
|
||||
:options="{
|
||||
automaticLayout: true,
|
||||
formatOnType: true,
|
||||
formatOnPaste: true
|
||||
}"
|
||||
/>
|
||||
</n-space>
|
||||
</n-tab-pane>
|
||||
<n-tab-pane name="load" tab="负载状态">
|
||||
<n-data-table
|
||||
striped
|
||||
remote
|
||||
:scroll-x="400"
|
||||
:loading="false"
|
||||
:columns="loadColumns"
|
||||
:data="load"
|
||||
/>
|
||||
</n-tab-pane>
|
||||
<n-tab-pane name="error-log" tab="错误日志">
|
||||
<realtime-log :path="errorLog" />
|
||||
</n-tab-pane>
|
||||
<n-tab-pane name="slow-log" tab="慢日志">
|
||||
<realtime-log :path="slowLog" />
|
||||
</n-tab-pane>
|
||||
</n-tabs>
|
||||
</common-page>
|
||||
<php-view :version="83" />
|
||||
</template>
|
||||
|
||||
Reference in New Issue
Block a user