From 44336c2ea2158b228c466913015fe9de9ed66f56 Mon Sep 17 00:00:00 2001 From: zhengkunwang <31820853+zhengkunwang223@users.noreply.github.com> Date: Thu, 5 Sep 2024 16:27:47 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20PHP=20=E8=BF=90=E8=A1=8C=E7=8E=AF?= =?UTF-8?q?=E5=A2=83=E5=A2=9E=E5=8A=A0=E6=93=8D=E4=BD=9C=20(#6377)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- agent/app/api/v2/runtime.go | 23 +- agent/app/dto/request/runtime.go | 2 +- agent/app/dto/response/runtime.go | 1 + agent/app/service/runtime.go | 27 +- agent/app/service/runtime_utils.go | 137 ++++++-- .../cmd/server/nginx_conf/php_extensions.json | 292 +++++++++++++++--- agent/router/ro_runtime.go | 1 + frontend/src/api/interface/runtime.ts | 2 +- frontend/src/api/modules/runtime.ts | 4 + frontend/src/components/log-dialog/index.vue | 4 +- frontend/src/components/log-file/index.vue | 1 + frontend/src/components/task-log/index.vue | 24 +- frontend/src/lang/modules/en.ts | 1 + frontend/src/lang/modules/tw.ts | 1 + frontend/src/lang/modules/zh.ts | 2 + .../website/runtime/php/create/index.vue | 18 +- .../php/extension-management/index.vue | 40 ++- .../src/views/website/runtime/php/index.vue | 64 +++- 18 files changed, 524 insertions(+), 120 deletions(-) diff --git a/agent/app/api/v2/runtime.go b/agent/app/api/v2/runtime.go index edade0b54..344b3774c 100644 --- a/agent/app/api/v2/runtime.go +++ b/agent/app/api/v2/runtime.go @@ -260,7 +260,7 @@ func (b *BaseApi) GetRuntimeExtension(c *gin.Context) { // @Summary Install php extension // @Description 安装 PHP 扩展 // @Accept json -// @Param request body request.PHPExtensionsCreate true "request" +// @Param request body request.PHPExtensionInstallReq true "request" // @Success 200 // @Security ApiKeyAuth // @Router /runtimes/php/extensions/install [post] @@ -276,3 +276,24 @@ func (b *BaseApi) InstallPHPExtension(c *gin.Context) { } helper.SuccessWithOutData(c) } + +// @Tags Runtime +// @Summary UnInstall php extension +// @Description 卸载 PHP 扩展 +// @Accept json +// @Param request body request.PHPExtensionInstallReq true "request" +// @Success 200 +// @Security ApiKeyAuth +// @Router /runtimes/php/extensions/uninstall [post] +func (b *BaseApi) UnInstallPHPExtension(c *gin.Context) { + var req request.PHPExtensionInstallReq + if err := helper.CheckBindAndValidate(&req, c); err != nil { + return + } + err := runtimeService.UnInstallPHPExtension(req) + if err != nil { + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) + return + } + helper.SuccessWithOutData(c) +} diff --git a/agent/app/dto/request/runtime.go b/agent/app/dto/request/runtime.go index 23cb1dfb0..3300a44e6 100644 --- a/agent/app/dto/request/runtime.go +++ b/agent/app/dto/request/runtime.go @@ -74,5 +74,5 @@ type NodeModuleReq struct { type PHPExtensionInstallReq struct { ID uint `json:"ID" validate:"required"` Name string `json:"name" validate:"required"` - TaskID string `json:"taskID" validate:"required"` + TaskID string `json:"taskID"` } diff --git a/agent/app/dto/response/runtime.go b/agent/app/dto/response/runtime.go index c5085b555..da7c40492 100644 --- a/agent/app/dto/response/runtime.go +++ b/agent/app/dto/response/runtime.go @@ -64,6 +64,7 @@ type SupportExtension struct { Installed bool `json:"installed"` Check string `json:"check"` Versions []string `json:"versions"` + File string `json:"file"` } type PHPExtensionRes struct { diff --git a/agent/app/service/runtime.go b/agent/app/service/runtime.go index e1b08d150..fbf12386c 100644 --- a/agent/app/service/runtime.go +++ b/agent/app/service/runtime.go @@ -50,6 +50,7 @@ type IRuntimeService interface { GetPHPExtensions(runtimeID uint) (response.PHPExtensionRes, error) InstallPHPExtension(req request.PHPExtensionInstallReq) error + UnInstallPHPExtension(req request.PHPExtensionInstallReq) error } func NewRuntimeService() IRuntimeService { @@ -380,6 +381,7 @@ func (r *RuntimeService) Update(req request.RuntimeUpdate) error { return runtimeRepo.Save(runtime) } oldImage := runtime.Image + oldEnv := runtime.Env switch runtime.Type { case constant.RuntimePHP: exist, _ := runtimeRepo.GetFirst(runtimeRepo.WithImage(req.Name), runtimeRepo.WithNotId(req.ID)) @@ -418,17 +420,10 @@ func (r *RuntimeService) Update(req request.RuntimeUpdate) error { } } - if containerName, ok := req.Params["CONTAINER_NAME"]; ok { - envs, err := gotenv.Unmarshal(runtime.Env) - if err != nil { + if containerName, ok := req.Params["CONTAINER_NAME"]; ok && containerName != getRuntimeEnv(runtime.Env, "CONTAINER_NAME") { + if err := checkContainerName(containerName.(string)); err != nil { return err } - oldContainerName := envs["CONTAINER_NAME"] - if containerName != oldContainerName { - if err := checkContainerName(containerName.(string)); err != nil { - return err - } - } } projectDir := path.Join(constant.RuntimeDir, runtime.Type, runtime.Name) @@ -466,7 +461,7 @@ func (r *RuntimeService) Update(req request.RuntimeUpdate) error { if err != nil { return err } - go buildRuntime(runtime, imageID, req.Rebuild) + go buildRuntime(runtime, imageID, oldEnv, req.Rebuild) case constant.RuntimeNode, constant.RuntimeJava, constant.RuntimeGo: runtime.Version = req.Version runtime.CodeDir = req.CodeDir @@ -687,7 +682,6 @@ func (r *RuntimeService) InstallPHPExtension(req request.PHPExtensionInstallReq) if err != nil { return err } - installTask, err := task.NewTaskWithOps(req.Name, task.TaskInstall, task.TaskScopeRuntime, req.TaskID, runtime.ID) if err != nil { return err @@ -739,3 +733,14 @@ func (r *RuntimeService) InstallPHPExtension(req request.PHPExtensionInstallReq) }() return nil } + +func (r *RuntimeService) UnInstallPHPExtension(req request.PHPExtensionInstallReq) error { + runtime, err := runtimeRepo.GetFirst(commonRepo.WithByID(req.ID)) + if err != nil { + return err + } + if err := unInstallPHPExtension(runtime, []string{req.Name}); err != nil { + return err + } + return runtimeRepo.Save(runtime) +} diff --git a/agent/app/service/runtime_utils.go b/agent/app/service/runtime_utils.go index 854dd8f45..81c2e2317 100644 --- a/agent/app/service/runtime_utils.go +++ b/agent/app/service/runtime_utils.go @@ -6,10 +6,13 @@ import ( "fmt" "github.com/1Panel-dev/1Panel/agent/app/dto" "github.com/1Panel-dev/1Panel/agent/app/dto/request" + "github.com/1Panel-dev/1Panel/agent/app/dto/response" "github.com/1Panel-dev/1Panel/agent/app/model" "github.com/1Panel-dev/1Panel/agent/buserr" + "github.com/1Panel-dev/1Panel/agent/cmd/server/nginx_conf" "github.com/1Panel-dev/1Panel/agent/constant" "github.com/1Panel-dev/1Panel/agent/global" + cmd2 "github.com/1Panel-dev/1Panel/agent/utils/cmd" "github.com/1Panel-dev/1Panel/agent/utils/compose" "github.com/1Panel-dev/1Panel/agent/utils/docker" "github.com/1Panel-dev/1Panel/agent/utils/files" @@ -24,6 +27,7 @@ import ( "path" "path/filepath" "strings" + "time" ) func handleNodeAndJava(create request.RuntimeCreate, runtime *model.Runtime, fileOp files.FileOp, appVersionDir string) (err error) { @@ -86,7 +90,7 @@ func handlePHP(create request.RuntimeCreate, runtime *model.Runtime, fileOp file runtime.Params = string(forms) runtime.Status = constant.RuntimeBuildIng - go buildRuntime(runtime, "", false) + go buildRuntime(runtime, "", "", false) return } @@ -127,9 +131,9 @@ func reCreateRuntime(runtime *model.Runtime) { } func runComposeCmdWithLog(operate string, composePath string, logPath string) error { - cmd := exec.Command("docker compose", "-f", composePath, operate) + cmd := exec.Command("docker", "compose", "-f", composePath, operate) if operate == "up" { - cmd = exec.Command("docker compose", "-f", composePath, operate, "-d") + cmd = exec.Command("docker", "compose", "-f", composePath, operate, "-d") } logFile, err := os.OpenFile(logPath, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0666) if err != nil { @@ -191,7 +195,33 @@ func SyncRuntimeContainerStatus(runtime *model.Runtime) error { return runtimeRepo.Save(runtime) } -func buildRuntime(runtime *model.Runtime, oldImageID string, rebuild bool) { +func getRuntimeEnv(envStr, key string) string { + env, err := gotenv.Unmarshal(envStr) + if err != nil { + return "" + } + if v, ok := env[key]; ok { + return v + } + return "" +} + +func getFileEnv(filePath, key string) (string, error) { + envContent, err := files.NewFileOp().GetContent(filePath) + if err != nil { + return "", err + } + env, err := gotenv.Unmarshal(string(envContent)) + if err != nil { + return "", err + } + if v, ok := env[key]; ok { + return v, nil + } + return "", nil +} + +func buildRuntime(runtime *model.Runtime, oldImageID string, oldEnv string, rebuild bool) { runtimePath := runtime.GetPath() composePath := runtime.GetComposePath() logPath := path.Join(runtimePath, "build.log") @@ -206,10 +236,9 @@ func buildRuntime(runtime *model.Runtime, oldImageID string, rebuild bool) { }() cmd := exec.Command("docker", "compose", "-f", composePath, "build") - multiWriterStdout := io.MultiWriter(os.Stdout, logFile) - cmd.Stdout = multiWriterStdout + cmd.Stdout = logFile var stderrBuf bytes.Buffer - multiWriterStderr := io.MultiWriter(&stderrBuf, logFile, os.Stderr) + multiWriterStderr := io.MultiWriter(&stderrBuf, logFile) cmd.Stderr = multiWriterStderr err = cmd.Run() @@ -239,34 +268,44 @@ func buildRuntime(runtime *model.Runtime, oldImageID string, rebuild bool) { } } if rebuild && runtime.ID > 0 { - websites, _ := websiteRepo.GetBy(websiteRepo.WithRuntimeID(runtime.ID)) - if len(websites) > 0 { - installService := NewIAppInstalledService() - installMap := make(map[uint]string) - for _, website := range websites { - if website.AppInstallID > 0 { - installMap[website.AppInstallID] = website.PrimaryDomain + extensionsStr := getRuntimeEnv(runtime.Env, "PHP_EXTENSIONS") + extensionsArray := strings.Split(extensionsStr, ",") + oldExtensionStr := getRuntimeEnv(oldEnv, "PHP_EXTENSIONS") + oldExtensionArray := strings.Split(oldExtensionStr, ",") + var delExtensions []string + for _, oldExt := range oldExtensionArray { + exist := false + for _, ext := range extensionsArray { + if oldExt == ext { + exist = true + break } } - for installID, domain := range installMap { - go func(installID uint, domain string) { - global.LOG.Infof("rebuild php runtime [%s] domain [%s]", runtime.Name, domain) - if err := installService.Operate(request.AppInstalledOperate{ - InstallId: installID, - Operate: constant.Rebuild, - }); err != nil { - global.LOG.Errorf("rebuild php runtime [%s] domain [%s] error %v", runtime.Name, domain, err) - } - }(installID, domain) + if !exist { + delExtensions = append(delExtensions, oldExt) } } + + if err = unInstallPHPExtension(runtime, delExtensions); err != nil { + global.LOG.Errorf("unInstallPHPExtension error %v", err) + } } - runtime.Status = constant.RuntimeStarting - _ = runtimeRepo.Save(runtime) + if out, err := compose.Up(composePath); err != nil { runtime.Status = constant.RuntimeStartErr runtime.Message = out } else { + extensions := getRuntimeEnv(runtime.Env, "PHP_EXTENSIONS") + if extensions != "" { + installCmd := fmt.Sprintf("docker exec -i %s %s %s", runtime.ContainerName, "install-ext", extensions) + err = cmd2.ExecWithLogFile(installCmd, 60*time.Minute, logPath) + if err != nil { + runtime.Status = constant.RuntimeError + runtime.Message = buserr.New(constant.ErrImageBuildErr).Error() + ":" + err.Error() + _ = runtimeRepo.Save(runtime) + return + } + } runtime.Status = constant.RuntimeRunning } } @@ -446,3 +485,49 @@ func checkContainerName(name string) error { } return nil } + +func unInstallPHPExtension(runtime *model.Runtime, delExtensions []string) error { + dir := runtime.GetPath() + fileOP := files.NewFileOp() + var phpExtensions []response.SupportExtension + if err := json.Unmarshal(nginx_conf.PHPExtensionsJson, &phpExtensions); err != nil { + return err + } + delMap := make(map[string]struct{}) + for _, ext := range phpExtensions { + for _, del := range delExtensions { + if ext.Check == del { + delMap[ext.Check] = struct{}{} + _ = fileOP.DeleteFile(path.Join(dir, "extensions", ext.File)) + _ = fileOP.DeleteFile(path.Join(dir, "conf", "conf.d", "docker-php-ext-"+ext.Check+".ini")) + break + } + } + } + extensions := getRuntimeEnv(runtime.Env, "PHP_EXTENSIONS") + var ( + oldExts []string + newExts []string + ) + oldExts = strings.Split(extensions, ",") + for _, ext := range oldExts { + if _, ok := delMap[ext]; !ok { + newExts = append(newExts, ext) + } + } + newExtensions := strings.Join(newExts, ",") + envs, err := gotenv.Unmarshal(runtime.Env) + if err != nil { + return err + } + envs["PHP_EXTENSIONS"] = newExtensions + if err = gotenv.Write(envs, runtime.GetEnvPath()); err != nil { + return err + } + envContent, err := gotenv.Marshal(envs) + if err != nil { + return err + } + runtime.Env = envContent + return nil +} diff --git a/agent/cmd/server/nginx_conf/php_extensions.json b/agent/cmd/server/nginx_conf/php_extensions.json index 57d063015..6ff17df78 100644 --- a/agent/cmd/server/nginx_conf/php_extensions.json +++ b/agent/cmd/server/nginx_conf/php_extensions.json @@ -1,135 +1,331 @@ [ - { - "name": "ZendGuardLoader", - "description": "用于解密ZendGuard加密脚本!", - "check": "ZendGuardLoader", - "versions": ["53", "54", "55", "56"], - "installed": false - }, { "name": "ionCube", - "description": "用于解密ionCube Encoder加密脚本!", - "check": "ionCube", + "check": "ioncube_loader", + "file": "ioncube_loader.so", "versions": ["56", "70", "71", "72", "73", "74", "81", "82"], "installed": false }, - { - "name": "fileinfo", - "description": "", - "check": "fileinfo", - "versions": ["56", "70", "71", "72", "73", "74", "80", "81", "82", "83"], - "installed": false - }, { "name": "opcache", - "description": "用于加速PHP脚本!", "check": "opcache", + "file": "opcache.so", "versions": ["56", "70", "71", "72", "73", "74", "80", "81", "82", "83"], "installed": false }, - { - "name": "xcache", - "description": "支持脚本缓存和变量缓存!", - "check": "xcache", - "versions": ["56"], - "installed": false - }, { "name": "memcache", - "description": "强大的内容缓存器", "check": "memcache", + "file": "memcache.so", "versions": ["56", "70", "71", "72", "73", "74", "80"], "installed": false }, { "name": "memcached", - "description": "比memcache支持更多高级功能", "check": "memcached", + "file": "memcached.so", "versions": ["56", "70", "71", "72", "73", "74", "80", "81", "82", "83"], "installed": false }, { "name": "redis", - "description": "基于内存亦可持久化的Key-Value数据库", "check": "redis", + "file": "redis.so", "versions": [ "56", "70", "71", "72", "73", "74", "80", "81", "82", "83"], "installed": false }, { "name": "mcrypt", - "description": "mcrypt加密/解密", "check": "mcrypt", + "file": "mcrypt.so", "versions": ["70", "71", "72", "73", "74", "80", "81", "82", "83"], "installed": false }, { "name": "apcu", - "description": "脚本缓存器", "check": "apcu", + "file": "apcu.so", "versions": ["56", "70", "71", "72", "73", "74", "80", "81", "82", "83"], "installed": false }, { - "name": "imagemagick", - "description": "Imagick高性能图形库", + "name": "imagick", "check": "imagick", - "versions": ["56", "70", "71", "72", "73", "74", "80", "81", "82", "83"], + "file": "imagick.so", + "versions": ["56", "70", "71", "72", "73", "74", "80", "81", "82"], "installed": false }, { "name": "xdebug", - "description": "开源的PHP程序调试器", "check": "xdebug", + "file": "xdebug.so", "versions": ["56", "70", "71", "72", "73", "74", "80", "81", "82", "83"], "installed": false }, { "name": "imap", - "description": "邮件服务器必备", "check": "imap", + "file": "imap.so", "versions": ["56", "70", "71", "72", "73", "74", "80", "81", "82", "83"], "installed": false }, { "name": "exif", - "description": "用于读取图片EXIF信息", "check": "exif", + "file": "exif.so", "versions": [ "56", "70", "71", "72", "73", "74", "80", "81", "82", "83"], "installed": false }, { "name": "intl", - "description": "提供国际化支持", "check": "intl", + "file": "intl.so", "versions": ["56", "70", "71", "72", "73", "74", "80", "81", "82", "83"], "installed": false }, { "name": "xsl", - "description": "xsl解析扩展", "check": "xsl", + "file": "xsl.so", "versions": ["56", "70", "71", "72", "73", "74", "80", "81", "82"], "installed": false }, - { - "name": "mbstring", - "description": "mbstring扩展", - "check": "mbstring", - "versions": ["83"], - "installed": false - }, { "name": "Swoole", - "description": "异步、协程高性能网络通信引擎", "check": "swoole", - "versions": ["70", "71", "72"], + "file": "swoole.so", + "versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83"], "installed": false }, { "name": "zstd", - "description": "使用 Zstandard 库进行压缩和解压缩的 PHP 扩展", "check": "zstd", - "versions": ["70", "71", "72"], + "file": "zstd.so", + "versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83"], + "installed": false + }, + { + "name": "xlswriter", + "check": "xlswriter", + "file": "xlswriter.so", + "versions": ["70", "71", "72", "73", "74", "80", "81", "82", "83"], + "installed": false + }, + { + "name": "oci8", + "check": "oci8", + "file": "oci8.so", + "versions": ["70", "71", "72", "73", "74", "80", "81", "82", "83"], + "installed": false + }, + { + "name": "pdo_oci", + "check": "pdo_oci", + "file": "pdo_oci.so", + "versions": ["70", "71", "72", "73", "74", "80", "81", "82", "83"], + "installed": false + }, + { + "name": "pdo_sqlsrv", + "check": "pdo_sqlsrv", + "file": "pdo_sqlsrv.so", + "versions": ["70", "71", "72", "73", "74", "80", "81", "82", "83"], + "installed": false + }, + { + "name": "sqlsrv", + "check": "sqlsrv", + "file": "sqlsrv.so", + "versions": ["70", "71", "72", "73", "74","80", "81", "82", "83"], + "installed": false + }, + { + "name": "yaf", + "check": "yaf", + "file": "yaf.so", + "versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83"], + "installed": false + }, + { + "name": "mongodb", + "check": "mongodb", + "file": "mongodb.so", + "versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83"], + "installed": false + }, + { + "name": "yac", + "check": "yac", + "file": "yac.so", + "versions": ["70", "71", "72", "73", "74", "80", "81", "82", "83"], + "installed": false + }, + { + "name": "pgsql", + "check": "pgsql", + "file": "pgsql.so", + "versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83"], + "installed": false + }, + { + "name": "ssh2", + "check": "ssh2", + "file": "ssh2.so", + "versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83"], + "installed": false + }, + { + "name": "grpc", + "check": "grpc", + "file": "grpc.so", + "versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83"], + "installed": false + }, + { + "name": "xhprof", + "check": "xhprof", + "file": "xhprof.so", + "versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83"], + "installed": false + }, + { + "name": "protobuf", + "check": "protobuf", + "file": "protobuf.so", + "versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83"], + "installed": false + }, + { + "name": "pdo_pgsql", + "check": "pdo_pgsql", + "file": "pdo_pgsql.so", + "versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83"], + "installed": false + }, + { + "name": "snmp", + "check": "snmp", + "file": "snmp.so", + "versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83"], + "installed": false + }, + { + "name": "ldap", + "check": "ldap", + "file": "ldap.so", + "versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83"], + "installed": false + }, + { + "name": "recode", + "check": "recode", + "file": "recode.so", + "versions": ["56","70", "71", "72", "73"], + "installed": false + }, + { + "name": "enchant", + "check": "enchant", + "file": "enchant.so", + "versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83"], + "installed": false + }, + { + "name": "pspell", + "check": "pspell", + "file": "pspell.so", + "versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83"], + "installed": false + }, + { + "name": "bz2", + "check": "bz2", + "file": "bz2.so", + "versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83"], + "installed": false + }, + { + "name": "sysvshm", + "check": "sysvshm", + "file": "sysvshm.so", + "versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83"], + "installed": false + }, + { + "name": "calendar", + "check": "calendar", + "file": "calendar.so", + "versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83"], + "installed": false + }, + { + "name": "gmp", + "check": "gmp", + "file": "gmp.so", + "versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83"], + "installed": false + }, + { + "name": "wddx", + "check": "wddx", + "file": "wddx.so", + "versions": ["56","70", "71", "72", "73", "74"], + "installed": false + }, + { + "name": "sysvmsg", + "check": "sysvmsg", + "file": "sysvmsg.so", + "versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83"], + "installed": false + }, + { + "name": "igbinary", + "check": "igbinary", + "file": "igbinary.so", + "versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83"], + "installed": false + }, + { + "name": "zmq", + "check": "zmq", + "file": "zmq.so", + "versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83"], + "installed": false + }, + { + "name": "smbclient", + "check": "smbclient", + "file": "smbclient.so", + "versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83"], + "installed": false + }, + { + "name": "event", + "check": "event", + "file": "event.so", + "versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83"], + "installed": false + }, + { + "name": "mailparse", + "check": "mailparse", + "file": "mailparse.so", + "versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83"], + "installed": false + }, + { + "name": "yaml", + "check": "yaml", + "file": "yaml.so", + "versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83"], + "installed": false + }, + { + "name": "sg11", + "check": "SourceGuardian", + "file": "sourceguardian.so", + "versions": ["56","70", "71", "72", "73", "74", "80", "81", "82", "83"], "installed": false } ] diff --git a/agent/router/ro_runtime.go b/agent/router/ro_runtime.go index 2b822d047..420b404a1 100644 --- a/agent/router/ro_runtime.go +++ b/agent/router/ro_runtime.go @@ -33,6 +33,7 @@ func (r *RuntimeRouter) InitRouter(Router *gin.RouterGroup) { groupRouter.GET("/php/:id/extensions", baseApi.GetRuntimeExtension) groupRouter.POST("/php/extensions/install", baseApi.InstallPHPExtension) + groupRouter.POST("/php/extensions/uninstall", baseApi.UnInstallPHPExtension) } } diff --git a/frontend/src/api/interface/runtime.ts b/frontend/src/api/interface/runtime.ts index 1a20ea0db..a0a0e2b3f 100644 --- a/frontend/src/api/interface/runtime.ts +++ b/frontend/src/api/interface/runtime.ts @@ -139,6 +139,6 @@ export namespace Runtime { export interface PHPExtensionInstall { name: string; id: number; - taskID: string; + taskID?: string; } } diff --git a/frontend/src/api/modules/runtime.ts b/frontend/src/api/modules/runtime.ts index 39e8c4d3a..3b7cb3cf8 100644 --- a/frontend/src/api/modules/runtime.ts +++ b/frontend/src/api/modules/runtime.ts @@ -75,3 +75,7 @@ export const GetPHPExtensions = (id: number) => { export const InstallPHPExtension = (req: Runtime.PHPExtensionInstall) => { return http.post(`/runtimes/php/extensions/install`, req); }; + +export const UnInstallPHPExtension = (req: Runtime.PHPExtensionInstall) => { + return http.post(`/runtimes/php/extensions/uninstall`, req); +}; diff --git a/frontend/src/components/log-dialog/index.vue b/frontend/src/components/log-dialog/index.vue index ba01b1ce1..ee07b8686 100644 --- a/frontend/src/components/log-dialog/index.vue +++ b/frontend/src/components/log-dialog/index.vue @@ -16,7 +16,7 @@
- +
@@ -39,6 +39,7 @@ interface LogProps { style: string; name: string; tail: boolean; + heightDiff: number; } const open = ref(false); @@ -62,6 +63,7 @@ const loadTooltip = () => { const acceptParams = (props: LogProps) => { config.value = props; + console.log('config', config.value); open.value = true; if (!mobile.value) { diff --git a/frontend/src/components/log-file/index.vue b/frontend/src/components/log-file/index.vue index 6ada55232..1095a5f9e 100644 --- a/frontend/src/components/log-file/index.vue +++ b/frontend/src/components/log-file/index.vue @@ -266,6 +266,7 @@ onUnmounted(() => { }); onMounted(() => { + console.log(props.heightDiff); initCodemirror(); init(); }); diff --git a/frontend/src/components/task-log/index.vue b/frontend/src/components/task-log/index.vue index 724e86ec3..5df108a2d 100644 --- a/frontend/src/components/task-log/index.vue +++ b/frontend/src/components/task-log/index.vue @@ -9,7 +9,13 @@ :width="width" >
- +
@@ -115,6 +121,7 @@ const getContent = (pre: boolean) => { } end.value = res.data.end; nextTick(() => { + console.log('scrollerElement', scrollerElement.value); if (pre) { if (scrollerElement.value.scrollHeight > 2000) { scrollerElement.value.scrollTop = 2000; @@ -122,6 +129,8 @@ const getContent = (pre: boolean) => { } else { scrollerElement.value.scrollTop = scrollerElement.value.scrollHeight; } + console.log('scrollHeight', scrollerElement.value.scrollHeight); + console.log('scrollTop', scrollerElement.value.scrollTop); }); if (readReq.latest) { @@ -179,6 +188,7 @@ const initCodemirror = () => { nextTick(() => { if (editorRef.value) { scrollerElement.value = editorRef.value.$el as HTMLElement; + console.log('scrollerElement', scrollerElement.value); scrollerElement.value.addEventListener('scroll', function () { if (isScrolledToBottom(scrollerElement.value)) { readReq.page = maxPage.value; @@ -194,8 +204,7 @@ const initCodemirror = () => { } }); let hljsDom = scrollerElement.value.querySelector('.hljs') as HTMLElement; - hljsDom.style['min-height'] = '100px'; - hljsDom.style['max-height'] = '400px'; + hljsDom.style['min-height'] = '400px'; } }); }; @@ -227,8 +236,11 @@ defineExpose({ openWithResourceID, openWithTaskID }); height: calc(var(--dialog-max-height) - var(--dialog-header-height) - var(--dialog-padding) * 2); overflow: hidden; } - .log-file { - height: 100%; - } +} + +.editor-main { + width: 100%; + overflow: auto; + height: 420px; } diff --git a/frontend/src/lang/modules/en.ts b/frontend/src/lang/modules/en.ts index ed8b5095b..41f19795a 100644 --- a/frontend/src/lang/modules/en.ts +++ b/frontend/src/lang/modules/en.ts @@ -153,6 +153,7 @@ const message = { resetSuccess: 'Reset successful', creatingInfo: 'Creating, no need for this operation', installSuccess: 'Install successful', + uninstallSuccess: 'Uninstall successful', }, login: { username: 'Username', diff --git a/frontend/src/lang/modules/tw.ts b/frontend/src/lang/modules/tw.ts index 5633e676f..03b6f43dd 100644 --- a/frontend/src/lang/modules/tw.ts +++ b/frontend/src/lang/modules/tw.ts @@ -153,6 +153,7 @@ const message = { resetSuccess: '重置成功', creatingInfo: '正在創建,無需此操作', installSuccess: '安裝成功', + uninstallSuccess: '卸載成功', }, login: { username: '用戶名', diff --git a/frontend/src/lang/modules/zh.ts b/frontend/src/lang/modules/zh.ts index b71c530f5..8197e8cd2 100644 --- a/frontend/src/lang/modules/zh.ts +++ b/frontend/src/lang/modules/zh.ts @@ -153,6 +153,7 @@ const message = { resetSuccess: '重置成功', creatingInfo: '正在创建,无需此操作', installSuccess: '安装成功', + uninstallSuccess: '卸载成功', }, login: { username: '用户名', @@ -2265,6 +2266,7 @@ const message = { installExtension: '是否确认安装扩展 {0}', loadedExtension: '已加载扩展', popularExtension: '常用扩展', + uninstallExtension: '是否确认卸载扩展 {0}', }, process: { pid: '进程ID', diff --git a/frontend/src/views/website/runtime/php/create/index.vue b/frontend/src/views/website/runtime/php/create/index.vue index d41481a73..2e7204e51 100644 --- a/frontend/src/views/website/runtime/php/create/index.vue +++ b/frontend/src/views/website/runtime/php/create/index.vue @@ -156,20 +156,6 @@ > - -
- - - {{ $t('runtime.rebuild') }} - - - - - {{ $t('runtime.rebuildHelper') }} -
-
-
-
@@ -410,7 +396,9 @@ const getRuntime = async (id: number) => { forms[fileds[index].key] = fileds[index]; } formFields.value = forms; - runtime.params['PHP_EXTENSIONS'] = runtime.params['PHP_EXTENSIONS'].split(','); + if (data.params['PHP_EXTENSIONS'] != '') { + runtime.params['PHP_EXTENSIONS'] = runtime.params['PHP_EXTENSIONS'].split(','); + } initParam.value = true; } catch (error) {} }; diff --git a/frontend/src/views/website/runtime/php/extension-management/index.vue b/frontend/src/views/website/runtime/php/extension-management/index.vue index 7b7dfc66a..5b11f0dbd 100644 --- a/frontend/src/views/website/runtime/php/extension-management/index.vue +++ b/frontend/src/views/website/runtime/php/extension-management/index.vue @@ -9,16 +9,15 @@ {{ $t('runtime.popularExtension') }}
- - - + + - +