From bce7fdd54759eec9b00b91a3e46047aef49c9c59 Mon Sep 17 00:00:00 2001 From: naiba Date: Mon, 16 Jun 2025 23:46:36 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=89=B9=E9=87=8F=E8=BD=AC=E7=A7=BB?= =?UTF-8?q?=E6=9C=8D=E5=8A=A1=E5=99=A8=E7=BB=99=E5=85=B6=E4=BB=96=E7=94=A8?= =?UTF-8?q?=E6=88=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cmd/dashboard/controller/controller.go | 1 + cmd/dashboard/controller/server.go | 58 +++++++++++++++++++++++ model/service_api.go | 5 ++ service/singleton/frontend-templates.yaml | 4 +- 4 files changed, 66 insertions(+), 2 deletions(-) diff --git a/cmd/dashboard/controller/controller.go b/cmd/dashboard/controller/controller.go index f61474f..29ab671 100644 --- a/cmd/dashboard/controller/controller.go +++ b/cmd/dashboard/controller/controller.go @@ -113,6 +113,7 @@ func routers(r *gin.Engine, frontendDist fs.FS) { auth.GET("/server/config/:id", commonHandler(getServerConfig)) auth.POST("/server/config", commonHandler(setServerConfig)) auth.POST("/batch-delete/server", commonHandler(batchDeleteServer)) + auth.POST("/batch-move/server", commonHandler(batchMoveServer)) auth.POST("/force-update/server", commonHandler(forceUpdateServer)) auth.GET("/notification", listHandler(listNotification)) diff --git a/cmd/dashboard/controller/server.go b/cmd/dashboard/controller/server.go index dc6839c..8256255 100644 --- a/cmd/dashboard/controller/server.go +++ b/cmd/dashboard/controller/server.go @@ -309,3 +309,61 @@ func setServerConfig(c *gin.Context) (*model.ServerTaskResponse, error) { wg.Wait() return &resp, nil } + +// Batch move servers to other user +// @Summary Batch move servers to other user +// @Security BearerAuth +// @Schemes +// @Description Batch move servers to other user +// @Tags auth required +// @Accept json +// @Param request body model.BatchMoveServerForm true "BatchMoveServerForm" +// @Produce json +// @Success 200 {object} model.CommonResponse[any] +// @Router /batch-move/server [post] +func batchMoveServer(c *gin.Context) (any, error) { + var moveForm model.BatchMoveServerForm + if err := c.ShouldBindJSON(&moveForm); err != nil { + return nil, err + } + + if !singleton.ServerShared.CheckPermission(c, slices.Values(moveForm.Ids)) { + return nil, singleton.Localizer.ErrorT("permission denied") + } + + if moveForm.ToUser == 0 { + return nil, singleton.Localizer.ErrorT("user id is required") + } + + singleton.UserLock.RLock() + defer singleton.UserLock.RUnlock() + if _, ok := singleton.UserInfoMap[moveForm.ToUser]; !ok { + return nil, singleton.Localizer.ErrorT("user id %d does not exist", moveForm.ToUser) + } + + err := singleton.DB.Transaction(func(tx *gorm.DB) error { + if err := tx.Model(&model.Server{}).Where("id in (?)", moveForm.ToUser).Update("user_id", moveForm.ToUser).Error; err != nil { + return err + } + return nil + }) + + if err != nil { + return nil, newGormError("%v", err) + } + + idsMap := make(map[uint64]bool) + for _, id := range moveForm.Ids { + idsMap[id] = true + } + + singleton.ServerShared.Range(func(_ uint64, s *model.Server) bool { + if s == nil || !idsMap[s.ID] { + return true + } + s.UserID = moveForm.ToUser + return true + }) + + return nil, nil +} diff --git a/model/service_api.go b/model/service_api.go index df67af3..ad877f2 100644 --- a/model/service_api.go +++ b/model/service_api.go @@ -53,3 +53,8 @@ type ServiceResponse struct { Services map[uint64]ServiceResponseItem `json:"services,omitempty"` CycleTransferStats map[uint64]CycleTransferStats `json:"cycle_transfer_stats,omitempty"` } + +type BatchMoveServerForm struct { + Ids []uint64 `json:"ids,omitempty" validate:"required"` + ToUser uint64 `json:"to_user,omitempty" validate:"required"` +} diff --git a/service/singleton/frontend-templates.yaml b/service/singleton/frontend-templates.yaml index 673d016..8ea5648 100644 --- a/service/singleton/frontend-templates.yaml +++ b/service/singleton/frontend-templates.yaml @@ -2,14 +2,14 @@ name: "OfficialAdmin" repository: "https://github.com/nezhahq/admin-frontend" author: "nezhahq" - version: "v1.12.0" + version: "v1.13.0" is_admin: true is_official: true - path: "user-dist" name: "Official" repository: "https://github.com/hamster1963/nezha-dash-v1" author: "hamster1963" - version: "v1.30.2" + version: "v1.30.4" is_official: true - path: "nezha-ascii-dist" name: "Nezha-ASCII"