From 3ff09c8b7ac6e3fb20b37d118eadbc92c95288d2 Mon Sep 17 00:00:00 2001 From: ssongliu <73214554+ssongliu@users.noreply.github.com> Date: Tue, 17 Oct 2023 17:54:30 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=A6=82=E8=A7=88=E7=95=8C=E9=9D=A2?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=9C=8D=E5=8A=A1=E9=87=8D=E5=90=AF=E4=BB=A5?= =?UTF-8?q?=E5=8F=8A=E9=9D=A2=E6=9D=BF=E9=87=8D=E5=90=AF=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=20(#2579)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Refs #328 --- backend/app/api/v1/dashboard.go | 22 +++++++++++++ backend/app/service/dashboard.go | 22 +++++++++++++ backend/router/ro_dashboard.go | 1 + cmd/server/docs/docs.go | 31 ++++++++++++++++++ cmd/server/docs/swagger.json | 31 ++++++++++++++++++ cmd/server/docs/swagger.yaml | 19 +++++++++++ frontend/src/api/modules/dashboard.ts | 4 +++ .../src/components/router-button/index.vue | 1 + frontend/src/lang/modules/en.ts | 5 +++ frontend/src/lang/modules/tw.ts | 4 +++ frontend/src/lang/modules/zh.ts | 4 +++ frontend/src/styles/common.scss | 6 ++++ frontend/src/views/home/index.vue | 32 +++++++++++++++++-- 13 files changed, 180 insertions(+), 2 deletions(-) diff --git a/backend/app/api/v1/dashboard.go b/backend/app/api/v1/dashboard.go index bd6501e53..61fa05047 100644 --- a/backend/app/api/v1/dashboard.go +++ b/backend/app/api/v1/dashboard.go @@ -56,6 +56,28 @@ func (b *BaseApi) LoadDashboardCurrentInfo(c *gin.Context) { helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, errors.New("error netOption in path")) return } + data := dashboardService.LoadCurrentInfo(ioOption, netOption) helper.SuccessWithData(c, data) } + +// @Tags Dashboard +// @Summary System restart +// @Description 重启服务器/面板 +// @Accept json +// @Param operation path string true "request" +// @Success 200 +// @Security ApiKeyAuth +// @Router /dashboard/system/restart/:operation [post] +func (b *BaseApi) SystemRestart(c *gin.Context) { + operation, ok := c.Params.Get("operation") + if !ok { + helper.ErrorWithDetail(c, constant.CodeErrBadRequest, constant.ErrTypeInvalidParams, errors.New("error operation in path")) + return + } + if err := dashboardService.Restart(operation); err != nil { + helper.ErrorWithDetail(c, constant.CodeErrInternalServer, constant.ErrTypeInternalServer, err) + return + } + helper.SuccessWithData(c, nil) +} diff --git a/backend/app/service/dashboard.go b/backend/app/service/dashboard.go index d0062f7bb..0a37ecfda 100644 --- a/backend/app/service/dashboard.go +++ b/backend/app/service/dashboard.go @@ -2,10 +2,12 @@ package service import ( "encoding/json" + "fmt" "strings" "time" "github.com/1Panel-dev/1Panel/backend/app/dto" + "github.com/1Panel-dev/1Panel/backend/global" "github.com/1Panel-dev/1Panel/backend/utils/cmd" "github.com/shirou/gopsutil/v3/cpu" "github.com/shirou/gopsutil/v3/disk" @@ -20,11 +22,31 @@ type DashboardService struct{} type IDashboardService interface { LoadBaseInfo(ioOption string, netOption string) (*dto.DashboardBase, error) LoadCurrentInfo(ioOption string, netOption string) *dto.DashboardCurrent + + Restart(operation string) error } func NewIDashboardService() IDashboardService { return &DashboardService{} } + +func (u *DashboardService) Restart(operation string) error { + if operation != "1panel" && operation != "system" { + return fmt.Errorf("handle restart operation %s failed, err: nonsupport such operation", operation) + } + itemCmd := fmt.Sprintf("%s 1pctl restart", cmd.SudoHandleCmd()) + if operation == "system" { + itemCmd = fmt.Sprintf("%s reboot", cmd.SudoHandleCmd()) + } + go func() { + stdout, err := cmd.Exec(itemCmd) + if err != nil { + global.LOG.Errorf("handle %s failed, err: %v", itemCmd, stdout) + } + }() + return nil +} + func (u *DashboardService) LoadBaseInfo(ioOption string, netOption string) (*dto.DashboardBase, error) { var baseInfo dto.DashboardBase hostInfo, err := host.Info() diff --git a/backend/router/ro_dashboard.go b/backend/router/ro_dashboard.go index 9dd927905..314139b82 100644 --- a/backend/router/ro_dashboard.go +++ b/backend/router/ro_dashboard.go @@ -18,5 +18,6 @@ func (s *CronjobRouter) InitDashboardRouter(Router *gin.RouterGroup) { { cmdRouter.GET("/base/:ioOption/:netOption", baseApi.LoadDashboardBaseInfo) cmdRouter.GET("/current/:ioOption/:netOption", baseApi.LoadDashboardCurrentInfo) + cmdRouter.POST("/system/restart/:operation", baseApi.SystemRestart) } } diff --git a/cmd/server/docs/docs.go b/cmd/server/docs/docs.go index ceeb7b505..16cf66352 100644 --- a/cmd/server/docs/docs.go +++ b/cmd/server/docs/docs.go @@ -3718,6 +3718,37 @@ const docTemplate = `{ } } }, + "/dashboard/system/restart/:operation": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "重启服务器/面板", + "consumes": [ + "application/json" + ], + "tags": [ + "Dashboard" + ], + "summary": "System restart", + "parameters": [ + { + "type": "string", + "description": "request", + "name": "operation", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, "/databases": { "post": { "security": [ diff --git a/cmd/server/docs/swagger.json b/cmd/server/docs/swagger.json index 074511a39..129f84d67 100644 --- a/cmd/server/docs/swagger.json +++ b/cmd/server/docs/swagger.json @@ -3711,6 +3711,37 @@ } } }, + "/dashboard/system/restart/:operation": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "重启服务器/面板", + "consumes": [ + "application/json" + ], + "tags": [ + "Dashboard" + ], + "summary": "System restart", + "parameters": [ + { + "type": "string", + "description": "request", + "name": "operation", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, "/databases": { "post": { "security": [ diff --git a/cmd/server/docs/swagger.yaml b/cmd/server/docs/swagger.yaml index 4d64f43d3..d9e1427ad 100644 --- a/cmd/server/docs/swagger.yaml +++ b/cmd/server/docs/swagger.yaml @@ -6536,6 +6536,25 @@ paths: summary: Load dashboard current info tags: - Dashboard + /dashboard/system/restart/:operation: + post: + consumes: + - application/json + description: 重启服务器/面板 + parameters: + - description: request + in: path + name: operation + required: true + type: string + responses: + "200": + description: OK + security: + - ApiKeyAuth: [] + summary: System restart + tags: + - Dashboard /databases: post: consumes: diff --git a/frontend/src/api/modules/dashboard.ts b/frontend/src/api/modules/dashboard.ts index 962141b28..07624b0ff 100644 --- a/frontend/src/api/modules/dashboard.ts +++ b/frontend/src/api/modules/dashboard.ts @@ -8,3 +8,7 @@ export const loadBaseInfo = (ioOption: string, netOption: string) => { export const loadCurrentInfo = (ioOption: string, netOption: string) => { return http.get(`/dashboard/current/${ioOption}/${netOption}`); }; + +export const systemRestart = (operation: string) => { + return http.post(`/dashboard/system/restart/${operation}`); +}; diff --git a/frontend/src/components/router-button/index.vue b/frontend/src/components/router-button/index.vue index 77d832257..8ab7cc803 100644 --- a/frontend/src/components/router-button/index.vue +++ b/frontend/src/components/router-button/index.vue @@ -13,6 +13,7 @@ + diff --git a/frontend/src/lang/modules/en.ts b/frontend/src/lang/modules/en.ts index f524c72c5..f97e5843b 100644 --- a/frontend/src/lang/modules/en.ts +++ b/frontend/src/lang/modules/en.ts @@ -277,6 +277,11 @@ const message = { supervisor: 'Supervisor', }, home: { + restart_1panel: 'Restart Panel', + restart_system: 'Restart Server', + restartHelper: + 'Do you want to perform the operation [{0}] on this machine? This action will temporarily disable the service. Do you want to continue?', + operationSuccess: 'Operation successful! Restarting, please wait...', overview: 'Overview', entranceHelper: 'Enabling a secure entrance can help improve system security. If necessary, go to the Control Panel settings, select Security, and enable the secure entrance.', diff --git a/frontend/src/lang/modules/tw.ts b/frontend/src/lang/modules/tw.ts index 229b97f83..4cb2ced6c 100644 --- a/frontend/src/lang/modules/tw.ts +++ b/frontend/src/lang/modules/tw.ts @@ -275,6 +275,10 @@ const message = { supervisor: '進程守護', }, home: { + restart_1panel: '重啟面板', + restart_system: '重啟伺服器', + restartHelper: '您是否要對這台機器執行 [{0}] 操作?此操作將導致服務暫時無法使用。您要繼續嗎?', + operationSuccess: '操作成功!正在重啟,請稍候...', overview: '概覽', entranceHelper: '設置安全入口有利於提高系統的安全性,如有需要,前往 面板設置-安全 中,啟用安全入口', appInstalled: '已安裝應用', diff --git a/frontend/src/lang/modules/zh.ts b/frontend/src/lang/modules/zh.ts index e1c40949d..c8e45eae2 100644 --- a/frontend/src/lang/modules/zh.ts +++ b/frontend/src/lang/modules/zh.ts @@ -275,6 +275,10 @@ const message = { supervisor: '进程守护', }, home: { + restart_1panel: '重启面板', + restart_system: '重启服务器', + restartHelper: '是否对该机器进行 [{0}] 操作,该操作将导致服务暂时不可用,是否继续?', + operationSuccess: '操作成功!正在重启,请稍候...', overview: '概览', entranceHelper: '设置安全入口有利于提高系统的安全性,如有需要,前往 面板设置-安全 中,启用安全入口', appInstalled: '已安装应用', diff --git a/frontend/src/styles/common.scss b/frontend/src/styles/common.scss index a56d120f9..76c2e7234 100644 --- a/frontend/src/styles/common.scss +++ b/frontend/src/styles/common.scss @@ -376,4 +376,10 @@ html { .limit-height-popover { max-height: 300px; overflow: auto; +} + +.router-button { + margin-top: 12px; + float: right; + margin-right: 50px; } \ No newline at end of file diff --git a/frontend/src/views/home/index.vue b/frontend/src/views/home/index.vue index c80dac475..a5674b236 100644 --- a/frontend/src/views/home/index.vue +++ b/frontend/src/views/home/index.vue @@ -7,7 +7,19 @@ path: '/', }, ]" - /> + > + + { isSafety.value = res.data.securityEntrance; }; +const restart = async (type: string) => { + ElMessageBox.confirm( + i18n.global.t('home.restartHelper', [i18n.global.t('home.restart_' + type)]), + i18n.global.t('commons.msg.operate'), + { + confirmButtonText: i18n.global.t('commons.button.confirm'), + cancelButtonText: i18n.global.t('commons.button.cancel'), + type: 'info', + }, + ).then(async () => { + MsgSuccess(i18n.global.t('home.operationSuccess')); + await systemRestart(type); + }); +}; + const onFocus = () => { isActive.value = true; };