package system import ( "encoding/json" "kra/internal/biz/system" "kra/internal/server/middleware" types "kra/internal/service/types/system" "kra/pkg/jwt" "github.com/go-kratos/kratos/v2/errors" khttp "github.com/go-kratos/kratos/v2/transport/http" ) // RouterGroup 路由组接口 type RouterGroup struct { Public *khttp.Router // 公开路由(无需认证) Private *khttp.Router // 私有路由(需要JWT认证) PrivateWithRecord *khttp.Router // 私有路由 + 操作记录 } // UserService 用户服务 type UserService struct { uc *system.UserUsecase jwtPkg *jwt.JWT } // NewUserService 创建用户服务 func NewUserService(uc *system.UserUsecase, jwtPkg *jwt.JWT) *UserService { return &UserService{uc: uc, jwtPkg: jwtPkg} } // Login 用户登录 func (s *UserService) Login(ctx khttp.Context) error { var req types.LoginRequest if err := ctx.Bind(&req); err != nil { return err } user, err := s.uc.Login(ctx, req.Username, req.Password) if err != nil { return errors.Unauthorized("LOGIN_FAILED", err.Error()) } if user.Enable != 1 { return errors.Forbidden("USER_DISABLED", "用户被禁止登录") } claims := s.jwtPkg.CreateClaims(jwt.BaseClaims{ UUID: user.UUID.String(), ID: user.ID, Username: user.Username, NickName: user.NickName, AuthorityID: user.AuthorityId, }) token, err := s.jwtPkg.CreateToken(claims.BaseClaims) if err != nil { return errors.InternalServer("TOKEN_ERROR", "生成token失败") } return ctx.Result(200, &types.LoginReply{ User: toTypesUserInfo(user), Token: token, ExpiresAt: claims.ExpiresAt.UnixMilli(), }) } // Register 用户注册 func (s *UserService) Register(ctx khttp.Context) error { var req types.RegisterRequest if err := ctx.Bind(&req); err != nil { return err } user := &system.User{ Username: req.Username, Password: req.Password, NickName: req.NickName, HeaderImg: req.HeaderImg, AuthorityId: req.AuthorityId, Phone: req.Phone, Email: req.Email, Enable: req.Enable, } created, err := s.uc.Register(ctx, user) if err != nil { return errors.BadRequest("REGISTER_FAILED", err.Error()) } return ctx.Result(200, &types.UserInfoReply{User: toTypesUserInfo(created)}) } // ChangePassword 修改密码 func (s *UserService) ChangePassword(ctx khttp.Context) error { var req types.ChangePasswordRequest if err := ctx.Bind(&req); err != nil { return err } userID := middleware.GetUserID(ctx) if userID == 0 { return errors.Unauthorized("UNAUTHORIZED", "请先登录") } if err := s.uc.ChangePassword(ctx, userID, req.Password, req.NewPassword); err != nil { return errors.BadRequest("CHANGE_PASSWORD_FAILED", err.Error()) } return ctx.Result(200, nil) } // ResetPassword 重置密码 func (s *UserService) ResetPassword(ctx khttp.Context) error { var req types.ResetPasswordRequest if err := ctx.Bind(&req); err != nil { return err } if err := s.uc.ResetPassword(ctx, req.ID, req.Password); err != nil { return errors.BadRequest("RESET_PASSWORD_FAILED", err.Error()) } return ctx.Result(200, nil) } // GetUserInfo 获取用户信息 func (s *UserService) GetUserInfo(ctx khttp.Context) error { claims, ok := middleware.GetClaims(ctx) if !ok { return errors.Unauthorized("UNAUTHORIZED", "请先登录") } user, err := s.uc.GetUserInfo(ctx, claims.UUID) if err != nil { return errors.NotFound("USER_NOT_FOUND", err.Error()) } return ctx.Result(200, &types.GetUserInfoReply{UserInfo: toTypesUserInfo(user)}) } // GetUserList 获取用户列表 func (s *UserService) GetUserList(ctx khttp.Context) error { var req types.GetUserListRequest if err := ctx.Bind(&req); err != nil { return err } filters := make(map[string]string) if req.Username != "" { filters["username"] = req.Username } if req.NickName != "" { filters["nick_name"] = req.NickName } if req.Phone != "" { filters["phone"] = req.Phone } if req.Email != "" { filters["email"] = req.Email } users, total, err := s.uc.GetUserList(ctx, req.Page, req.PageSize, filters) if err != nil { return errors.InternalServer("LIST_ERROR", err.Error()) } list := make([]types.UserInfo, len(users)) for i, u := range users { list[i] = toTypesUserInfo(u) } return ctx.Result(200, &types.GetUserListReply{List: list, Total: total, Page: req.Page, PageSize: req.PageSize}) } // SetUserInfo 设置用户信息 func (s *UserService) SetUserInfo(ctx khttp.Context) error { var req types.SetUserInfoRequest if err := ctx.Bind(&req); err != nil { return err } user := &system.User{ ID: req.ID, NickName: req.NickName, HeaderImg: req.HeaderImg, Phone: req.Phone, Email: req.Email, Enable: req.Enable, } if err := s.uc.SetUserInfo(ctx, user); err != nil { return errors.BadRequest("SET_USER_INFO_FAILED", err.Error()) } if len(req.AuthorityIds) > 0 { adminAuthorityID := middleware.GetAuthorityID(ctx) if err := s.uc.SetUserAuthorities(ctx, adminAuthorityID, req.ID, req.AuthorityIds); err != nil { return errors.BadRequest("SET_USER_AUTHORITIES_FAILED", err.Error()) } } return ctx.Result(200, nil) } // SetSelfInfo 设置自己信息 func (s *UserService) SetSelfInfo(ctx khttp.Context) error { var req types.SetSelfInfoRequest if err := ctx.Bind(&req); err != nil { return err } userID := middleware.GetUserID(ctx) if userID == 0 { return errors.Unauthorized("UNAUTHORIZED", "请先登录") } user := &system.User{ ID: userID, NickName: req.NickName, HeaderImg: req.HeaderImg, Phone: req.Phone, Email: req.Email, } if err := s.uc.SetSelfInfo(ctx, user); err != nil { return errors.BadRequest("SET_SELF_INFO_FAILED", err.Error()) } return ctx.Result(200, nil) } // SetSelfSetting 设置自己配置 func (s *UserService) SetSelfSetting(ctx khttp.Context) error { var req types.SetSelfSettingRequest if err := ctx.Bind(&req); err != nil { return err } userID := middleware.GetUserID(ctx) if userID == 0 { return errors.Unauthorized("UNAUTHORIZED", "请先登录") } setting := json.RawMessage(req.Setting) if err := s.uc.SetSelfSetting(ctx, userID, setting); err != nil { return errors.BadRequest("SET_SELF_SETTING_FAILED", err.Error()) } return ctx.Result(200, nil) } // DeleteUser 删除用户 func (s *UserService) DeleteUser(ctx khttp.Context) error { var req types.DeleteUserRequest if err := ctx.Bind(&req); err != nil { return err } currentUserID := middleware.GetUserID(ctx) if currentUserID == req.ID { return errors.BadRequest("DELETE_FAILED", "无法删除自己") } if err := s.uc.DeleteUser(ctx, req.ID); err != nil { return errors.BadRequest("DELETE_FAILED", err.Error()) } return ctx.Result(200, nil) } // SetUserAuthority 设置用户角色 func (s *UserService) SetUserAuthority(ctx khttp.Context) error { var req types.SetUserAuthorityRequest if err := ctx.Bind(&req); err != nil { return err } userID := middleware.GetUserID(ctx) if userID == 0 { return errors.Unauthorized("UNAUTHORIZED", "请先登录") } if err := s.uc.SetUserAuthority(ctx, userID, req.AuthorityId); err != nil { return errors.BadRequest("SET_AUTHORITY_FAILED", err.Error()) } // 重新生成token claims, ok := middleware.GetClaims(ctx) if !ok { return errors.Unauthorized("UNAUTHORIZED", "请先登录") } claims.AuthorityID = req.AuthorityId token, err := s.jwtPkg.CreateToken(claims.BaseClaims) if err != nil { return errors.InternalServer("TOKEN_ERROR", "生成token失败") } return ctx.Result(200, &types.SetUserAuthorityReply{Token: token, ExpiresAt: claims.ExpiresAt.UnixMilli()}) } // SetUserAuthorities 设置用户多角色 func (s *UserService) SetUserAuthorities(ctx khttp.Context) error { var req types.SetUserAuthoritiesRequest if err := ctx.Bind(&req); err != nil { return err } adminAuthorityID := middleware.GetAuthorityID(ctx) if err := s.uc.SetUserAuthorities(ctx, adminAuthorityID, req.ID, req.AuthorityIds); err != nil { return errors.BadRequest("SET_AUTHORITIES_FAILED", err.Error()) } return ctx.Result(200, nil) } // toTypesUserInfo 转换用户信息为types格式 func toTypesUserInfo(user *system.User) types.UserInfo { if user == nil { return types.UserInfo{} } info := types.UserInfo{ ID: user.ID, UUID: user.UUID.String(), Username: user.Username, NickName: user.NickName, SideMode: user.SideMode, HeaderImg: user.HeaderImg, BaseColor: user.BaseColor, AuthorityId: user.AuthorityId, Phone: user.Phone, Email: user.Email, Enable: user.Enable, } if user.OriginSetting != nil { info.OriginSetting = string(user.OriginSetting) } if user.Authority != nil { auth := toTypesAuthorityInfo(user.Authority) info.Authority = &auth } if len(user.Authorities) > 0 { info.Authorities = make([]types.AuthorityInfo, len(user.Authorities)) for i, a := range user.Authorities { info.Authorities[i] = toTypesAuthorityInfo(a) } } return info } // toTypesAuthorityInfo 转换角色信息为types格式 func toTypesAuthorityInfo(auth *system.Authority) types.AuthorityInfo { if auth == nil { return types.AuthorityInfo{} } return types.AuthorityInfo{ AuthorityId: auth.AuthorityId, AuthorityName: auth.AuthorityName, ParentId: auth.ParentId, DefaultRouter: auth.DefaultRouter, } } // RegisterRoutes 注册用户路由 func (s *UserService) RegisterRoutes(rg *RouterGroup) { // 公开路由(无需认证) rg.Public.POST("/base/login", s.Login) // 私有路由 + 操作记录(写操作) rg.PrivateWithRecord.POST("/user/admin_register", s.Register) rg.PrivateWithRecord.POST("/user/changePassword", s.ChangePassword) rg.PrivateWithRecord.POST("/user/setUserAuthority", s.SetUserAuthority) rg.PrivateWithRecord.DELETE("/user/deleteUser", s.DeleteUser) rg.PrivateWithRecord.PUT("/user/setUserInfo", s.SetUserInfo) rg.PrivateWithRecord.PUT("/user/setSelfInfo", s.SetSelfInfo) rg.PrivateWithRecord.POST("/user/setUserAuthorities", s.SetUserAuthorities) rg.PrivateWithRecord.POST("/user/resetPassword", s.ResetPassword) rg.PrivateWithRecord.PUT("/user/setSelfSetting", s.SetSelfSetting) // 私有路由(读操作,不记录) rg.Private.POST("/user/getUserList", s.GetUserList) rg.Private.GET("/user/getUserInfo", s.GetUserInfo) }