package adminuser import ( "errors" "fmt" "github.com/gin-gonic/gin" "gorm.io/gorm" "hyapp-admin-server/internal/config" "hyapp-admin-server/internal/model" "hyapp-admin-server/internal/modules/shared" "hyapp-admin-server/internal/repository" "hyapp-admin-server/internal/response" ) type Handler struct { service *AdminUserService audit shared.OperationLogger } func New(store *repository.Store, cfg config.Config, audit shared.OperationLogger) *Handler { return &Handler{service: NewService(store, cfg), audit: audit} } func (h *Handler) ListUsers(c *gin.Context) { options := shared.ListOptions(c) users, total, err := h.service.ListUsers(shared.ActorFromContext(c), options) if err != nil { response.ServerError(c, "获取用户失败") return } response.OK(c, response.Page{Items: shared.UserDTOs(users), Page: options.Page, PageSize: options.PageSize, Total: total}) } func (h *Handler) CreateUser(c *gin.Context) { var req userRequest if err := c.ShouldBindJSON(&req); err != nil { response.BadRequest(c, "用户参数不正确") return } user, password, err := h.service.CreateUser(CreateUserInput{ Username: req.Username, Name: req.Name, Team: req.Team, TeamID: req.TeamID, Status: req.Status, Password: req.Password, MFAEnabled: req.MFAEnabled, RoleIDs: req.RoleIDs, }) if err != nil { response.BadRequest(c, err.Error()) return } shared.OperationLog(c, h.audit, "create-user", "admin_users", "success", user.Username) response.Created(c, gin.H{"user": shared.UserDTO(*user), "initialPassword": password.Password}) } func (h *Handler) GetUser(c *gin.Context) { id, ok := shared.ParseID(c, "id") if !ok { return } user, err := h.service.GetUser(id) if errors.Is(err, gorm.ErrRecordNotFound) { response.NotFound(c, "用户不存在") return } if err != nil { response.ServerError(c, "获取用户失败") return } response.OK(c, shared.UserDTO(*user)) } func (h *Handler) ListUserMoneyScopes(c *gin.Context) { id, ok := shared.ParseID(c, "id") if !ok { return } scopes, err := h.service.ListUserMoneyScopes(id) if err != nil { response.ServerError(c, "获取财务范围失败") return } response.OK(c, gin.H{"items": moneyScopeDTOs(scopes), "total": len(scopes)}) } func (h *Handler) ReplaceUserMoneyScopes(c *gin.Context) { id, ok := shared.ParseID(c, "id") if !ok { return } var req moneyScopeRequest if err := c.ShouldBindJSON(&req); err != nil { response.BadRequest(c, "财务范围参数不正确") return } input := make([]MoneyScopeInput, 0, len(req.Scopes)) for _, item := range req.Scopes { input = append(input, MoneyScopeInput{AppCode: item.AppCode, RegionID: item.RegionID}) } scopes, err := h.service.ReplaceUserMoneyScopes(id, input) if err != nil { response.BadRequest(c, err.Error()) return } shared.OperationLog(c, h.audit, "replace-user-money-scopes", "admin_user_money_scopes", "success", fmt.Sprintf("user_id=%d scopes=%d", id, len(scopes))) response.OK(c, gin.H{"items": moneyScopeDTOs(scopes), "total": len(scopes)}) } func (h *Handler) UpdateUser(c *gin.Context) { id, ok := shared.ParseID(c, "id") if !ok { return } var req updateUserRequest if err := c.ShouldBindJSON(&req); err != nil { response.BadRequest(c, "用户参数不正确") return } user, err := h.service.UpdateUser(id, UpdateUserInput{ Name: req.Name, Team: req.Team, TeamID: req.TeamID, Status: req.Status, MFAEnabled: req.MFAEnabled, RoleIDs: req.RoleIDs, }) if err != nil { response.BadRequest(c, err.Error()) return } shared.OperationLog(c, h.audit, "update-user", "admin_users", "success", user.Username) response.OK(c, shared.UserDTO(*user)) } func (h *Handler) UpdateUserStatus(c *gin.Context) { id, ok := shared.ParseID(c, "id") if !ok { return } var req statusRequest if err := c.ShouldBindJSON(&req); err != nil { response.BadRequest(c, "状态参数不正确") return } user, err := h.service.UpdateUserStatus(id, UserStatusInput{Status: req.Status}) if err != nil { response.BadRequest(c, err.Error()) return } shared.OperationLog(c, h.audit, "update-user-status", "admin_users", "success", fmt.Sprintf("%s -> %s", user.Username, req.Status)) response.OK(c, shared.UserDTO(*user)) } func (h *Handler) ResetUserPassword(c *gin.Context) { id, ok := shared.ParseID(c, "id") if !ok { return } var req resetPasswordRequest _ = c.ShouldBindJSON(&req) password, err := h.service.ResetUserPassword(id, req.Password) if err != nil { response.BadRequest(c, err.Error()) return } shared.OperationLog(c, h.audit, "reset-user-password", "admin_users", "success", fmt.Sprintf("user_id=%d", id)) response.OK(c, gin.H{"reset": true, "initialPassword": password.Password}) } func (h *Handler) BatchUpdateUserStatus(c *gin.Context) { var req batchStatusRequest if err := c.ShouldBindJSON(&req); err != nil { response.BadRequest(c, "批量状态参数不正确") return } if err := h.service.BatchUpdateUserStatus(BatchUserStatusInput{IDs: req.IDs, Status: req.Status}); err != nil { response.BadRequest(c, err.Error()) return } shared.OperationLog(c, h.audit, "batch-update-user-status", "admin_users", "success", fmt.Sprintf("%d users -> %s", len(req.IDs), req.Status)) response.OK(c, gin.H{"updated": len(req.IDs)}) } func (h *Handler) ExportUsers(c *gin.Context) { export, err := h.service.ExportUsers(shared.ActorFromContext(c), shared.ListOptions(c)) if err != nil { response.ServerError(c, "导出用户失败") return } shared.OperationLog(c, h.audit, "export-users", "admin_users", "success", fmt.Sprintf("%d users", export.Count)) c.Header("Content-Disposition", "attachment; filename="+export.FileName) c.Header("Content-Type", "text/csv; charset=utf-8") c.Writer.WriteHeader(200) _, _ = c.Writer.Write(export.Content) } func moneyScopeDTOs(scopes []model.UserMoneyScope) []gin.H { out := make([]gin.H, 0, len(scopes)) for _, scope := range scopes { out = append(out, gin.H{ "appCode": scope.AppCode, "regionId": scope.RegionID, "userId": scope.UserID, }) } return out }