任务三

This commit is contained in:
Yvan
2026-01-07 19:10:02 +08:00
parent 3c0f3b7165
commit be3b6641a6
50 changed files with 2916 additions and 1167 deletions
+128 -273
View File
@@ -1,13 +1,12 @@
package system
import (
"context"
"kra/internal/biz/system"
"kra/internal/server/middleware"
types "kra/internal/service/types/system"
"github.com/go-kratos/kratos/v2/errors"
"github.com/go-kratos/kratos/v2/transport/http"
khttp "github.com/go-kratos/kratos/v2/transport/http"
)
// ApiService API服务
@@ -20,45 +19,30 @@ func NewApiService(uc *system.ApiUsecase) *ApiService {
return &ApiService{uc: uc}
}
// ApiInfo API信息
type ApiInfo struct {
ID uint `json:"ID"`
Path string `json:"path"`
Description string `json:"description"`
ApiGroup string `json:"apiGroup"`
Method string `json:"method"`
}
// CreateApiRequest 创建API请求
type CreateApiRequest struct {
Path string `json:"path"`
Description string `json:"description"`
ApiGroup string `json:"apiGroup"`
Method string `json:"method"`
}
// CreateApi 创建API
func (s *ApiService) CreateApi(ctx context.Context, req *CreateApiRequest) error {
func (s *ApiService) CreateApi(ctx khttp.Context) error {
var req types.CreateApiRequest
if err := ctx.Bind(&req); err != nil {
return err
}
api := &system.Api{
Path: req.Path,
Description: req.Description,
ApiGroup: req.ApiGroup,
Method: req.Method,
}
return s.uc.CreateApi(ctx, api)
}
// UpdateApiRequest 更新API请求
type UpdateApiRequest struct {
ID uint `json:"ID"`
Path string `json:"path"`
Description string `json:"description"`
ApiGroup string `json:"apiGroup"`
Method string `json:"method"`
if err := s.uc.CreateApi(ctx, api); err != nil {
return errors.BadRequest("CREATE_FAILED", err.Error())
}
return ctx.Result(200, nil)
}
// UpdateApi 更新API
func (s *ApiService) UpdateApi(ctx context.Context, req *UpdateApiRequest) error {
func (s *ApiService) UpdateApi(ctx khttp.Context) error {
var req types.UpdateApiRequest
if err := ctx.Bind(&req); err != nil {
return err
}
api := &system.Api{
ID: req.ID,
Path: req.Path,
@@ -66,55 +50,55 @@ func (s *ApiService) UpdateApi(ctx context.Context, req *UpdateApiRequest) error
ApiGroup: req.ApiGroup,
Method: req.Method,
}
return s.uc.UpdateApi(ctx, api)
if err := s.uc.UpdateApi(ctx, api); err != nil {
return errors.BadRequest("UPDATE_FAILED", err.Error())
}
return ctx.Result(200, nil)
}
// DeleteApi 删除API
func (s *ApiService) DeleteApi(ctx context.Context, id uint) error {
return s.uc.DeleteApi(ctx, id)
}
// DeleteApisByIdsRequest 批量删除API请求
type DeleteApisByIdsRequest struct {
Ids []uint `json:"ids"`
func (s *ApiService) DeleteApi(ctx khttp.Context) error {
var req types.DeleteApiRequest
if err := ctx.Bind(&req); err != nil {
return err
}
if err := s.uc.DeleteApi(ctx, req.ID); err != nil {
return errors.BadRequest("DELETE_FAILED", err.Error())
}
return ctx.Result(200, nil)
}
// DeleteApisByIds 批量删除API
func (s *ApiService) DeleteApisByIds(ctx context.Context, req *DeleteApisByIdsRequest) error {
return s.uc.DeleteApisByIds(ctx, req.Ids)
func (s *ApiService) DeleteApisByIds(ctx khttp.Context) error {
var req types.DeleteApisByIdsRequest
if err := ctx.Bind(&req); err != nil {
return err
}
if err := s.uc.DeleteApisByIds(ctx, req.Ids); err != nil {
return errors.BadRequest("DELETE_FAILED", err.Error())
}
return ctx.Result(200, nil)
}
// GetApiById 根据ID获取API
func (s *ApiService) GetApiById(ctx context.Context, id uint) (*ApiInfo, error) {
api, err := s.uc.GetApiById(ctx, id)
if err != nil {
return nil, err
func (s *ApiService) GetApiById(ctx khttp.Context) error {
var req types.GetApiByIdRequest
if err := ctx.Bind(&req); err != nil {
return err
}
return toApiInfo(api), nil
}
// GetApiListRequest 获取API列表请求
type GetApiListRequest struct {
Page int `json:"page"`
PageSize int `json:"pageSize"`
Path string `json:"path"`
Description string `json:"description"`
Method string `json:"method"`
ApiGroup string `json:"apiGroup"`
OrderKey string `json:"orderKey"`
Desc bool `json:"desc"`
}
// GetApiListResponse 获取API列表响应
type GetApiListResponse struct {
List []*ApiInfo `json:"list"`
Total int64 `json:"total"`
Page int `json:"page"`
PageSize int `json:"pageSize"`
api, err := s.uc.GetApiById(ctx, req.ID)
if err != nil {
return errors.NotFound("NOT_FOUND", err.Error())
}
return ctx.Result(200, &types.GetApiByIdReply{Api: toTypesApiInfo(api)})
}
// GetApiList 获取API列表
func (s *ApiService) GetApiList(ctx context.Context, req *GetApiListRequest) (*GetApiListResponse, error) {
func (s *ApiService) GetApiList(ctx khttp.Context) error {
var req types.GetApiListRequest
if err := ctx.Bind(&req); err != nil {
return err
}
filters := make(map[string]string)
if req.Path != "" {
filters["path"] = req.Path
@@ -128,94 +112,71 @@ func (s *ApiService) GetApiList(ctx context.Context, req *GetApiListRequest) (*G
if req.ApiGroup != "" {
filters["api_group"] = req.ApiGroup
}
apis, total, err := s.uc.GetAPIInfoList(ctx, req.Page, req.PageSize, filters, req.OrderKey, req.Desc)
if err != nil {
return nil, err
return errors.InternalServer("LIST_ERROR", err.Error())
}
list := make([]*ApiInfo, len(apis))
list := make([]types.ApiInfo, len(apis))
for i, api := range apis {
list[i] = toApiInfo(api)
list[i] = toTypesApiInfo(api)
}
return &GetApiListResponse{
List: list,
Total: total,
Page: req.Page,
PageSize: req.PageSize,
}, nil
return ctx.Result(200, &types.GetApiListReply{List: list, Total: total, Page: req.Page, PageSize: req.PageSize})
}
// GetAllApis 获取所有API
func (s *ApiService) GetAllApis(ctx context.Context, authorityID uint) ([]*ApiInfo, error) {
func (s *ApiService) GetAllApis(ctx khttp.Context) error {
authorityID := middleware.GetAuthorityID(ctx)
apis, err := s.uc.GetAllApis(ctx, authorityID)
if err != nil {
return nil, err
return errors.InternalServer("LIST_ERROR", err.Error())
}
list := make([]*ApiInfo, len(apis))
list := make([]types.ApiInfo, len(apis))
for i, api := range apis {
list[i] = toApiInfo(api)
list[i] = toTypesApiInfo(api)
}
return list, nil
return ctx.Result(200, &types.GetAllApisReply{Apis: list})
}
// GetApiGroups 获取API分组
func (s *ApiService) GetApiGroups(ctx context.Context) ([]string, map[string]string, error) {
return s.uc.GetApiGroups(ctx)
}
// SyncApiResponse 同步API响应
type SyncApiResponse struct {
NewApis []*ApiInfo `json:"newApis"`
DeleteApis []*ApiInfo `json:"deleteApis"`
IgnoreApis []*ApiInfo `json:"ignoreApis"`
func (s *ApiService) GetApiGroups(ctx khttp.Context) error {
groups, apiGroupMap, err := s.uc.GetApiGroups(ctx)
if err != nil {
return errors.InternalServer("LIST_ERROR", err.Error())
}
return ctx.Result(200, &types.GetApiGroupsReply{Groups: groups, ApiGroupMap: apiGroupMap})
}
// SyncApi 同步API
func (s *ApiService) SyncApi(ctx context.Context) (*SyncApiResponse, error) {
func (s *ApiService) SyncApi(ctx khttp.Context) error {
newApis, deleteApis, ignoreApis, err := s.uc.SyncApi(ctx)
if err != nil {
return nil, err
return errors.InternalServer("SYNC_ERROR", err.Error())
}
resp := &SyncApiResponse{
NewApis: make([]*ApiInfo, len(newApis)),
DeleteApis: make([]*ApiInfo, len(deleteApis)),
IgnoreApis: make([]*ApiInfo, len(ignoreApis)),
}
for i, api := range newApis {
resp.NewApis[i] = toApiInfo(api)
}
for i, api := range deleteApis {
resp.DeleteApis[i] = toApiInfo(api)
}
for i, api := range ignoreApis {
resp.IgnoreApis[i] = toApiInfo(api)
}
return resp, nil
}
// IgnoreApiRequest 忽略API请求
type IgnoreApiRequest struct {
Path string `json:"path"`
Method string `json:"method"`
Flag bool `json:"flag"`
return ctx.Result(200, &types.SyncApiReply{
NewApis: toTypesApiInfoList(newApis),
DeleteApis: toTypesApiInfoList(deleteApis),
IgnoreApis: toTypesApiInfoList(ignoreApis),
})
}
// IgnoreApi 忽略API
func (s *ApiService) IgnoreApi(ctx context.Context, req *IgnoreApiRequest) error {
return s.uc.IgnoreApi(ctx, req.Path, req.Method, req.Flag)
}
// EnterSyncApiRequest 确认同步API请求
type EnterSyncApiRequest struct {
NewApis []*ApiInfo `json:"newApis"`
DeleteApis []*ApiInfo `json:"deleteApis"`
func (s *ApiService) IgnoreApi(ctx khttp.Context) error {
var req types.IgnoreApiRequest
if err := ctx.Bind(&req); err != nil {
return err
}
if err := s.uc.IgnoreApi(ctx, req.Path, req.Method, req.Flag); err != nil {
return errors.BadRequest("IGNORE_FAILED", err.Error())
}
return ctx.Result(200, nil)
}
// EnterSyncApi 确认同步API
func (s *ApiService) EnterSyncApi(ctx context.Context, req *EnterSyncApiRequest) error {
func (s *ApiService) EnterSyncApi(ctx khttp.Context) error {
var req types.EnterSyncApiRequest
if err := ctx.Bind(&req); err != nil {
return err
}
newApis := make([]*system.Api, len(req.NewApis))
for i, api := range req.NewApis {
newApis[i] = &system.Api{
@@ -233,17 +194,26 @@ func (s *ApiService) EnterSyncApi(ctx context.Context, req *EnterSyncApiRequest)
Method: api.Method,
}
}
return s.uc.EnterSyncApi(ctx, newApis, deleteApis)
if err := s.uc.EnterSyncApi(ctx, newApis, deleteApis); err != nil {
return errors.BadRequest("SYNC_FAILED", err.Error())
}
return ctx.Result(200, nil)
}
// FreshCasbin 刷新Casbin缓存
func (s *ApiService) FreshCasbin() error {
return s.uc.FreshCasbin()
func (s *ApiService) FreshCasbin(ctx khttp.Context) error {
if err := s.uc.FreshCasbin(); err != nil {
return errors.InternalServer("FRESH_FAILED", err.Error())
}
return ctx.Result(200, nil)
}
// 转换函数
func toApiInfo(api *system.Api) *ApiInfo {
return &ApiInfo{
// toTypesApiInfo 转换API信息为types格式
func toTypesApiInfo(api *system.Api) types.ApiInfo {
if api == nil {
return types.ApiInfo{}
}
return types.ApiInfo{
ID: api.ID,
Path: api.Path,
Description: api.Description,
@@ -252,147 +222,32 @@ func toApiInfo(api *system.Api) *ApiInfo {
}
}
// RegisterRoutes 注册路由
func (s *ApiService) RegisterRoutes(srv *http.Server) {
r := srv.Route("/")
r.POST("/api/createApi", s.handleCreateApi)
r.POST("/api/updateApi", s.handleUpdateApi)
r.POST("/api/deleteApi", s.handleDeleteApi)
r.DELETE("/api/deleteApisByIds", s.handleDeleteApisByIds)
r.POST("/api/getApiList", s.handleGetApiList)
r.POST("/api/getApiById", s.handleGetApiById)
r.POST("/api/getAllApis", s.handleGetAllApis)
r.GET("/api/getApiGroups", s.handleGetApiGroups)
r.GET("/api/syncApi", s.handleSyncApi)
r.POST("/api/ignoreApi", s.handleIgnoreApi)
r.POST("/api/enterSyncApi", s.handleEnterSyncApi)
r.GET("/api/freshCasbin", s.handleFreshCasbin)
// toTypesApiInfoList 批量转换API信息
func toTypesApiInfoList(apis []*system.Api) []types.ApiInfo {
list := make([]types.ApiInfo, len(apis))
for i, api := range apis {
list[i] = toTypesApiInfo(api)
}
return list
}
// HTTP Handlers
func (s *ApiService) handleCreateApi(ctx http.Context) error {
var req CreateApiRequest
if err := ctx.Bind(&req); err != nil {
return err
}
if err := s.CreateApi(ctx, &req); err != nil {
return errors.BadRequest("CREATE_FAILED", err.Error())
}
return ctx.Result(200, map[string]any{"code": 0, "msg": "创建成功"})
}
// RegisterRoutes 注册API管理路由
func (s *ApiService) RegisterRoutes(rg *RouterGroup) {
// 公开路由
rg.Public.GET("/api/freshCasbin", s.FreshCasbin)
func (s *ApiService) handleUpdateApi(ctx http.Context) error {
var req UpdateApiRequest
if err := ctx.Bind(&req); err != nil {
return err
}
if err := s.UpdateApi(ctx, &req); err != nil {
return errors.BadRequest("UPDATE_FAILED", err.Error())
}
return ctx.Result(200, map[string]any{"code": 0, "msg": "修改成功"})
}
// 私有路由 + 操作记录(写操作)
rg.PrivateWithRecord.GET("/api/getApiGroups", s.GetApiGroups)
rg.PrivateWithRecord.GET("/api/syncApi", s.SyncApi)
rg.PrivateWithRecord.POST("/api/ignoreApi", s.IgnoreApi)
rg.PrivateWithRecord.POST("/api/enterSyncApi", s.EnterSyncApi)
rg.PrivateWithRecord.POST("/api/createApi", s.CreateApi)
rg.PrivateWithRecord.POST("/api/deleteApi", s.DeleteApi)
rg.PrivateWithRecord.POST("/api/getApiById", s.GetApiById)
rg.PrivateWithRecord.POST("/api/updateApi", s.UpdateApi)
rg.PrivateWithRecord.DELETE("/api/deleteApisByIds", s.DeleteApisByIds)
func (s *ApiService) handleDeleteApi(ctx http.Context) error {
var req struct {
ID uint `json:"ID"`
}
if err := ctx.Bind(&req); err != nil {
return err
}
if err := s.DeleteApi(ctx, req.ID); err != nil {
return errors.BadRequest("DELETE_FAILED", err.Error())
}
return ctx.Result(200, map[string]any{"code": 0, "msg": "删除成功"})
}
func (s *ApiService) handleDeleteApisByIds(ctx http.Context) error {
var req DeleteApisByIdsRequest
if err := ctx.Bind(&req); err != nil {
return err
}
if err := s.DeleteApisByIds(ctx, &req); err != nil {
return errors.BadRequest("DELETE_FAILED", err.Error())
}
return ctx.Result(200, map[string]any{"code": 0, "msg": "删除成功"})
}
func (s *ApiService) handleGetApiList(ctx http.Context) error {
var req GetApiListRequest
if err := ctx.Bind(&req); err != nil {
return err
}
resp, err := s.GetApiList(ctx, &req)
if err != nil {
return errors.InternalServer("LIST_ERROR", err.Error())
}
return ctx.Result(200, map[string]any{"code": 0, "msg": "获取成功", "data": resp})
}
func (s *ApiService) handleGetApiById(ctx http.Context) error {
var req struct {
ID uint `json:"ID"`
}
if err := ctx.Bind(&req); err != nil {
return err
}
resp, err := s.GetApiById(ctx, req.ID)
if err != nil {
return errors.NotFound("NOT_FOUND", err.Error())
}
return ctx.Result(200, map[string]any{"code": 0, "msg": "获取成功", "data": map[string]any{"api": resp}})
}
func (s *ApiService) handleGetAllApis(ctx http.Context) error {
authorityID := middleware.GetAuthorityID(ctx)
resp, err := s.GetAllApis(ctx, authorityID)
if err != nil {
return errors.InternalServer("LIST_ERROR", err.Error())
}
return ctx.Result(200, map[string]any{"code": 0, "msg": "获取成功", "data": map[string]any{"apis": resp}})
}
func (s *ApiService) handleGetApiGroups(ctx http.Context) error {
groups, apiGroupMap, err := s.GetApiGroups(ctx)
if err != nil {
return errors.InternalServer("LIST_ERROR", err.Error())
}
return ctx.Result(200, map[string]any{"code": 0, "msg": "获取成功", "data": map[string]any{"groups": groups, "apiGroupMap": apiGroupMap}})
}
func (s *ApiService) handleSyncApi(ctx http.Context) error {
resp, err := s.SyncApi(ctx)
if err != nil {
return errors.InternalServer("SYNC_ERROR", err.Error())
}
return ctx.Result(200, map[string]any{"code": 0, "data": resp})
}
func (s *ApiService) handleIgnoreApi(ctx http.Context) error {
var req IgnoreApiRequest
if err := ctx.Bind(&req); err != nil {
return err
}
if err := s.IgnoreApi(ctx, &req); err != nil {
return errors.BadRequest("IGNORE_FAILED", err.Error())
}
return ctx.Result(200, map[string]any{"code": 0, "msg": "操作成功"})
}
func (s *ApiService) handleEnterSyncApi(ctx http.Context) error {
var req EnterSyncApiRequest
if err := ctx.Bind(&req); err != nil {
return err
}
if err := s.EnterSyncApi(ctx, &req); err != nil {
return errors.BadRequest("SYNC_FAILED", err.Error())
}
return ctx.Result(200, map[string]any{"code": 0, "msg": "同步成功"})
}
func (s *ApiService) handleFreshCasbin(ctx http.Context) error {
if err := s.FreshCasbin(); err != nil {
return errors.InternalServer("FRESH_FAILED", err.Error())
}
return ctx.Result(200, map[string]any{"code": 0, "msg": "刷新成功"})
// 私有路由(读操作,不记录)
rg.Private.POST("/api/getAllApis", s.GetAllApis)
rg.Private.POST("/api/getApiList", s.GetApiList)
}
+18 -16
View File
@@ -5,6 +5,7 @@ import (
"kra/internal/biz/system"
"kra/internal/server/middleware"
types "kra/internal/service/types/system"
"github.com/go-kratos/kratos/v2/errors"
"github.com/go-kratos/kratos/v2/transport/http"
@@ -26,12 +27,12 @@ func NewAuthorityService(uc *system.AuthorityUsecase, casbin system.CasbinRepo)
// AuthorityInfo 角色信息
type AuthorityFullInfo struct {
AuthorityId uint `json:"authorityId"`
AuthorityName string `json:"authorityName"`
ParentId *uint `json:"parentId,omitempty"`
DefaultRouter string `json:"defaultRouter"`
DataAuthorityId []*AuthorityInfo `json:"dataAuthorityId,omitempty"`
Children []*AuthorityFullInfo `json:"children,omitempty"`
AuthorityId uint `json:"authorityId"`
AuthorityName string `json:"authorityName"`
ParentId *uint `json:"parentId,omitempty"`
DefaultRouter string `json:"defaultRouter"`
DataAuthorityId []*types.AuthorityInfo `json:"dataAuthorityId,omitempty"`
Children []*AuthorityFullInfo `json:"children,omitempty"`
}
// CreateAuthorityRequest 创建角色请求
@@ -172,9 +173,9 @@ func toAuthorityFullInfoList(list []*system.AuthorityFull) []*AuthorityFullInfo
}
// DataAuthorityId
if len(auth.DataAuthorityId) > 0 {
result[i].DataAuthorityId = make([]*AuthorityInfo, len(auth.DataAuthorityId))
result[i].DataAuthorityId = make([]*types.AuthorityInfo, len(auth.DataAuthorityId))
for j, da := range auth.DataAuthorityId {
result[i].DataAuthorityId[j] = &AuthorityInfo{
result[i].DataAuthorityId[j] = &types.AuthorityInfo{
AuthorityId: da.AuthorityId,
AuthorityName: da.AuthorityName,
ParentId: da.ParentId,
@@ -187,15 +188,16 @@ func toAuthorityFullInfoList(list []*system.AuthorityFull) []*AuthorityFullInfo
}
// RegisterRoutes 注册路由
func (s *AuthorityService) RegisterRoutes(srv *http.Server) {
r := srv.Route("/")
func (s *AuthorityService) RegisterRoutes(rg *RouterGroup) {
// 私有路由 + 操作记录(写操作)
rg.PrivateWithRecord.POST("/authority/createAuthority", s.handleCreateAuthority)
rg.PrivateWithRecord.POST("/authority/copyAuthority", s.handleCopyAuthority)
rg.PrivateWithRecord.PUT("/authority/updateAuthority", s.handleUpdateAuthority)
rg.PrivateWithRecord.POST("/authority/deleteAuthority", s.handleDeleteAuthority)
rg.PrivateWithRecord.POST("/authority/setDataAuthority", s.handleSetDataAuthority)
r.POST("/authority/createAuthority", s.handleCreateAuthority)
r.POST("/authority/copyAuthority", s.handleCopyAuthority)
r.PUT("/authority/updateAuthority", s.handleUpdateAuthority)
r.POST("/authority/deleteAuthority", s.handleDeleteAuthority)
r.POST("/authority/getAuthorityList", s.handleGetAuthorityList)
r.POST("/authority/setDataAuthority", s.handleSetDataAuthority)
// 私有路由(读操作,不记录)
rg.Private.POST("/authority/getAuthorityList", s.handleGetAuthorityList)
}
// HTTP Handlers
+5 -5
View File
@@ -38,11 +38,11 @@ type SetAuthorityBtnRequest struct {
}
// RegisterRoutes 注册路由
func (s *AuthorityBtnService) RegisterRoutes(srv *http.Server) {
r := srv.Route("/")
r.POST("/authorityBtn/getAuthorityBtn", s.handleGetAuthorityBtn)
r.POST("/authorityBtn/setAuthorityBtn", s.handleSetAuthorityBtn)
r.POST("/authorityBtn/canRemoveAuthorityBtn", s.handleCanRemoveAuthorityBtn)
func (s *AuthorityBtnService) RegisterRoutes(rg *RouterGroup) {
// 角色按钮权限(不需要操作记录)
rg.Private.POST("/authorityBtn/getAuthorityBtn", s.handleGetAuthorityBtn)
rg.Private.POST("/authorityBtn/setAuthorityBtn", s.handleSetAuthorityBtn)
rg.Private.POST("/authorityBtn/canRemoveAuthorityBtn", s.handleCanRemoveAuthorityBtn)
}
func (s *AuthorityBtnService) handleGetAuthorityBtn(ctx http.Context) error {
+29 -22
View File
@@ -4,24 +4,30 @@ import (
"sync"
"time"
"kra/internal/conf"
"github.com/go-kratos/kratos/v2/transport/http"
"github.com/mojocn/base64Captcha"
)
// CaptchaService 验证码服务
type CaptchaService struct {
config CaptchaConfig
store base64Captcha.Store
blackCache *BlackCache
keyLong int
imgWidth int
imgHeight int
openCaptcha int // 防爆次数,0表示关闭
openCaptchaTimeOut int // 缓存超时时间(秒)
store base64Captcha.Store
blackCache *BlackCache
}
// CaptchaConfig 验证码配置
// CaptchaConfig 验证码配置(保留用于兼容)
type CaptchaConfig struct {
KeyLong int
ImgWidth int
ImgHeight int
OpenCaptcha int // 防爆次数,0表示关闭
OpenCaptchaTimeOut int // 缓存超时时间(秒)
OpenCaptcha int
OpenCaptchaTimeOut int
}
// BlackCache 黑名单缓存
@@ -86,21 +92,22 @@ type CaptchaResponse struct {
}
// NewCaptchaService 创建验证码服务
func NewCaptchaService(config CaptchaConfig, store base64Captcha.Store) *CaptchaService {
if store == nil {
store = base64Captcha.DefaultMemStore
}
func NewCaptchaService(c *conf.Captcha) *CaptchaService {
return &CaptchaService{
config: config,
store: store,
blackCache: NewBlackCache(),
keyLong: int(c.KeyLong),
imgWidth: int(c.ImgWidth),
imgHeight: int(c.ImgHeight),
openCaptcha: int(c.OpenCaptcha),
openCaptchaTimeOut: int(c.OpenCaptchaTimeout),
store: base64Captcha.DefaultMemStore,
blackCache: NewBlackCache(),
}
}
// RegisterRoutes 注册路由
func (s *CaptchaService) RegisterRoutes(srv *http.Server) {
r := srv.Route("/")
r.POST("/base/captcha", s.handleCaptcha)
func (s *CaptchaService) RegisterRoutes(rg *RouterGroup) {
// 验证码(公开路由,无需认证)
rg.Public.POST("/base/captcha", s.handleCaptcha)
}
func (s *CaptchaService) handleCaptcha(ctx http.Context) error {
@@ -108,8 +115,8 @@ func (s *CaptchaService) handleCaptcha(ctx http.Context) error {
clientIP := ctx.Request().RemoteAddr
// 判断验证码是否开启
openCaptcha := s.config.OpenCaptcha
openCaptchaTimeOut := s.config.OpenCaptchaTimeOut
openCaptcha := s.openCaptcha
openCaptchaTimeOut := s.openCaptchaTimeOut
v, ok := s.blackCache.Get(clientIP)
if !ok {
@@ -123,9 +130,9 @@ func (s *CaptchaService) handleCaptcha(ctx http.Context) error {
// 生成验证码
driver := base64Captcha.NewDriverDigit(
s.config.ImgHeight,
s.config.ImgWidth,
s.config.KeyLong,
s.imgHeight,
s.imgWidth,
s.keyLong,
0.7,
80,
)
@@ -144,7 +151,7 @@ func (s *CaptchaService) handleCaptcha(ctx http.Context) error {
"data": CaptchaResponse{
CaptchaId: id,
PicPath: b64s,
CaptchaLength: s.config.KeyLong,
CaptchaLength: s.keyLong,
OpenCaptcha: oc,
},
})
+9 -6
View File
@@ -5,6 +5,7 @@ import (
"strconv"
"kra/internal/biz/system"
"kra/internal/conf"
"kra/internal/server/middleware"
kerrors "github.com/go-kratos/kratos/v2/errors"
@@ -20,12 +21,12 @@ type CasbinService struct {
}
// NewCasbinService 创建Casbin服务
func NewCasbinService(casbinRepo system.CasbinRepo, authUc *system.AuthorityUsecase, apiUc *system.ApiUsecase, useStrictAuth bool) *CasbinService {
func NewCasbinService(casbinRepo system.CasbinRepo, authUc *system.AuthorityUsecase, apiUc *system.ApiUsecase, useStrictAuth conf.UseStrictAuth) *CasbinService {
return &CasbinService{
casbinRepo: casbinRepo,
authUc: authUc,
apiUc: apiUc,
useStrictAuth: useStrictAuth,
useStrictAuth: bool(useStrictAuth),
}
}
@@ -81,10 +82,12 @@ func (s *CasbinService) GetPolicyPathByAuthorityId(authorityId uint) []system.Ca
}
// RegisterRoutes 注册路由
func (s *CasbinService) RegisterRoutes(srv *http.Server) {
r := srv.Route("/")
r.POST("/casbin/UpdateCasbin", s.handleUpdateCasbin)
r.POST("/casbin/getPolicyPathByAuthorityId", s.handleGetPolicyPath)
func (s *CasbinService) RegisterRoutes(rg *RouterGroup) {
// 私有路由 + 操作记录(写操作)
rg.PrivateWithRecord.POST("/casbin/updateCasbin", s.handleUpdateCasbin)
// 私有路由(读操作,不记录)
rg.Private.POST("/casbin/getPolicyPathByAuthorityId", s.handleGetPolicyPath)
}
func (s *CasbinService) handleUpdateCasbin(ctx http.Context) error {
+32 -20
View File
@@ -365,28 +365,30 @@ func toDictionaryDetailInfoList(list []*system.DictionaryDetail) []*DictionaryDe
}
// RegisterRoutes 注册路由
func (s *DictionaryService) RegisterRoutes(srv *http.Server) {
r := srv.Route("/")
func (s *DictionaryService) RegisterRoutes(rg *RouterGroup) {
// 字典接口 - 写操作(带操作记录)
rg.PrivateWithRecord.POST("/sysDictionary/createSysDictionary", s.handleCreateDictionary)
rg.PrivateWithRecord.DELETE("/sysDictionary/deleteSysDictionary", s.handleDeleteDictionary)
rg.PrivateWithRecord.PUT("/sysDictionary/updateSysDictionary", s.handleUpdateDictionary)
rg.PrivateWithRecord.POST("/sysDictionary/importSysDictionary", s.handleImportDictionary)
rg.PrivateWithRecord.GET("/sysDictionary/exportSysDictionary", s.handleExportDictionary)
// 字典接口
r.POST("/sysDictionary/createSysDictionary", s.handleCreateDictionary)
r.DELETE("/sysDictionary/deleteSysDictionary", s.handleDeleteDictionary)
r.PUT("/sysDictionary/updateSysDictionary", s.handleUpdateDictionary)
r.GET("/sysDictionary/findSysDictionary", s.handleGetDictionary)
r.GET("/sysDictionary/getSysDictionaryList", s.handleGetDictionaryList)
r.GET("/sysDictionary/exportSysDictionary", s.handleExportDictionary)
r.POST("/sysDictionary/importSysDictionary", s.handleImportDictionary)
// 字典接口 - 读操作(不记录)
rg.Private.GET("/sysDictionary/findSysDictionary", s.handleGetDictionary)
rg.Private.GET("/sysDictionary/getSysDictionaryList", s.handleGetDictionaryList)
// 字典详情接口
r.POST("/sysDictionaryDetail/createSysDictionaryDetail", s.handleCreateDictionaryDetail)
r.DELETE("/sysDictionaryDetail/deleteSysDictionaryDetail", s.handleDeleteDictionaryDetail)
r.PUT("/sysDictionaryDetail/updateSysDictionaryDetail", s.handleUpdateDictionaryDetail)
r.GET("/sysDictionaryDetail/findSysDictionaryDetail", s.handleGetDictionaryDetail)
r.GET("/sysDictionaryDetail/getSysDictionaryDetailList", s.handleGetDictionaryDetailList)
r.GET("/sysDictionaryDetail/getDictionaryTreeList", s.handleGetDictionaryTreeList)
r.POST("/sysDictionaryDetail/getDictionaryDetailsByParent", s.handleGetDictionaryDetailsByParent)
r.GET("/sysDictionaryDetail/getDictionaryListByType", s.handleGetDictionaryListByType)
r.GET("/sysDictionaryDetail/getDictionaryTreeListByType", s.handleGetDictionaryTreeListByType)
// 字典详情接口 - 写操作(带操作记录)
rg.PrivateWithRecord.POST("/sysDictionaryDetail/createSysDictionaryDetail", s.handleCreateDictionaryDetail)
rg.PrivateWithRecord.DELETE("/sysDictionaryDetail/deleteSysDictionaryDetail", s.handleDeleteDictionaryDetail)
rg.PrivateWithRecord.PUT("/sysDictionaryDetail/updateSysDictionaryDetail", s.handleUpdateDictionaryDetail)
// 字典详情接口 - 读操作(不记录)
rg.Private.GET("/sysDictionaryDetail/findSysDictionaryDetail", s.handleGetDictionaryDetail)
rg.Private.GET("/sysDictionaryDetail/getSysDictionaryDetailList", s.handleGetDictionaryDetailList)
rg.Private.GET("/sysDictionaryDetail/getDictionaryTreeList", s.handleGetDictionaryTreeList)
rg.Private.GET("/sysDictionaryDetail/getDictionaryTreeListByType", s.handleGetDictionaryTreeListByType)
rg.Private.GET("/sysDictionaryDetail/getDictionaryDetailsByParent", s.handleGetDictionaryDetailsByParent)
rg.Private.GET("/sysDictionaryDetail/getDictionaryPath", s.handleGetDictionaryPath)
}
// HTTP Handlers - Dictionary
@@ -568,6 +570,16 @@ func (s *DictionaryService) handleGetDictionaryTreeListByType(ctx http.Context)
return ctx.Result(200, map[string]any{"code": 0, "msg": "获取成功", "data": map[string]any{"list": resp}})
}
func (s *DictionaryService) handleGetDictionaryPath(ctx http.Context) error {
idStr := ctx.Query().Get("id")
id, _ := parseUint(idStr)
resp, err := s.uc.GetDictionaryPath(ctx, id)
if err != nil {
return errors.InternalServer("PATH_ERROR", err.Error())
}
return ctx.Result(200, map[string]any{"code": 0, "msg": "获取成功", "data": map[string]any{"path": toDictionaryDetailInfoList(resp)}})
}
// parseUint 解析uint
func parseUint(s string) (uint, error) {
if s == "" {
+3 -3
View File
@@ -34,7 +34,7 @@ func (s *JwtBlacklistService) JoinBlacklist(ctx http.Context) error {
}
// RegisterRoutes 注册路由
func (s *JwtBlacklistService) RegisterRoutes(srv *http.Server) {
r := srv.Route("/")
r.POST("/jwt/jsonInBlacklist", s.JoinBlacklist)
func (s *JwtBlacklistService) RegisterRoutes(rg *RouterGroup) {
// JWT黑名单(不需要操作记录)
rg.Private.POST("/jwt/jsonInBlacklist", s.JoinBlacklist)
}
+12 -11
View File
@@ -322,18 +322,19 @@ func toBaseMenuInfo(m *system.BaseMenu) *MenuInfo {
}
// RegisterRoutes 注册路由
func (s *MenuService) RegisterRoutes(srv *http.Server) {
r := srv.Route("/")
func (s *MenuService) RegisterRoutes(rg *RouterGroup) {
// 私有路由 + 操作记录(写操作)
rg.PrivateWithRecord.POST("/menu/addBaseMenu", s.handleAddBaseMenu)
rg.PrivateWithRecord.POST("/menu/addMenuAuthority", s.handleAddMenuAuthority)
rg.PrivateWithRecord.POST("/menu/deleteBaseMenu", s.handleDeleteBaseMenu)
rg.PrivateWithRecord.POST("/menu/updateBaseMenu", s.handleUpdateBaseMenu)
r.POST("/menu/getMenu", s.handleGetMenu)
r.POST("/menu/getBaseMenuTree", s.handleGetBaseMenuTree)
r.POST("/menu/getMenuList", s.handleGetMenuList)
r.POST("/menu/addBaseMenu", s.handleAddBaseMenu)
r.POST("/menu/updateBaseMenu", s.handleUpdateBaseMenu)
r.POST("/menu/deleteBaseMenu", s.handleDeleteBaseMenu)
r.POST("/menu/getBaseMenuById", s.handleGetBaseMenuById)
r.POST("/menu/addMenuAuthority", s.handleAddMenuAuthority)
r.POST("/menu/getMenuAuthority", s.handleGetMenuAuthority)
// 私有路由(读操作,不记录)
rg.Private.POST("/menu/getMenu", s.handleGetMenu)
rg.Private.POST("/menu/getMenuList", s.handleGetMenuList)
rg.Private.POST("/menu/getBaseMenuTree", s.handleGetBaseMenuTree)
rg.Private.POST("/menu/getMenuAuthority", s.handleGetMenuAuthority)
rg.Private.POST("/menu/getBaseMenuById", s.handleGetBaseMenuById)
}
// HTTP Handlers
+21 -19
View File
@@ -4,6 +4,7 @@ import (
"fmt"
"kra/internal/biz/system"
types "kra/internal/service/types/system"
"github.com/go-kratos/kratos/v2/errors"
"github.com/go-kratos/kratos/v2/transport/http"
@@ -21,18 +22,18 @@ func NewOperationRecordService(uc *system.OperationRecordUsecase) *OperationReco
// OperationRecordInfo 操作记录信息
type OperationRecordInfo struct {
ID uint `json:"id"`
IP string `json:"ip"`
Method string `json:"method"`
Path string `json:"path"`
Status int `json:"status"`
Latency int64 `json:"latency"`
Agent string `json:"agent"`
ErrorMessage string `json:"error_message"`
Body string `json:"body"`
Resp string `json:"resp"`
UserID uint `json:"user_id"`
User *UserInfo `json:"user,omitempty"`
ID uint `json:"id"`
IP string `json:"ip"`
Method string `json:"method"`
Path string `json:"path"`
Status int `json:"status"`
Latency int64 `json:"latency"`
Agent string `json:"agent"`
ErrorMessage string `json:"error_message"`
Body string `json:"body"`
Resp string `json:"resp"`
UserID uint `json:"user_id"`
User *types.UserInfo `json:"user,omitempty"`
}
// GetOperationRecordListRequest 获取操作记录列表请求
@@ -64,12 +65,12 @@ type DeleteOperationRecordByIdsRequest struct {
}
// RegisterRoutes 注册路由
func (s *OperationRecordService) RegisterRoutes(srv *http.Server) {
r := srv.Route("/")
r.POST("/sysOperationRecord/getSysOperationRecordList", s.handleGetList)
r.DELETE("/sysOperationRecord/deleteSysOperationRecord", s.handleDelete)
r.DELETE("/sysOperationRecord/deleteSysOperationRecordByIds", s.handleDeleteByIds)
r.GET("/sysOperationRecord/findSysOperationRecord", s.handleFind)
func (s *OperationRecordService) RegisterRoutes(rg *RouterGroup) {
// 操作记录(不需要操作记录中间件,避免递归)
rg.Private.DELETE("/sysOperationRecord/deleteSysOperationRecord", s.handleDelete)
rg.Private.DELETE("/sysOperationRecord/deleteSysOperationRecordByIds", s.handleDeleteByIds)
rg.Private.GET("/sysOperationRecord/findSysOperationRecord", s.handleFind)
rg.Private.GET("/sysOperationRecord/getSysOperationRecordList", s.handleGetList)
}
func (s *OperationRecordService) handleGetList(ctx http.Context) error {
@@ -159,7 +160,8 @@ func toOperationRecordInfo(r *system.OperationRecord) *OperationRecordInfo {
UserID: r.UserID,
}
if r.User != nil {
info.User = toUserInfo(r.User)
userInfo := toTypesUserInfo(r.User)
info.User = &userInfo
}
return info
}
+224
View File
@@ -0,0 +1,224 @@
package system
import (
"strconv"
"kra/internal/biz/system"
"github.com/go-kratos/kratos/v2/errors"
"github.com/go-kratos/kratos/v2/transport/http"
)
// ParamsService 系统参数服务
type ParamsService struct {
uc *system.ParamsUsecase
}
// NewParamsService 创建系统参数服务
func NewParamsService(uc *system.ParamsUsecase) *ParamsService {
return &ParamsService{uc: uc}
}
// ParamsInfo 参数信息
type ParamsInfo struct {
ID uint `json:"ID"`
Name string `json:"name"`
Key string `json:"key"`
Value string `json:"value"`
Desc string `json:"desc"`
CreatedAt string `json:"createdAt,omitempty"`
UpdatedAt string `json:"updatedAt,omitempty"`
}
// CreateParamsRequest 创建参数请求
type CreateParamsRequest struct {
Name string `json:"name"`
Key string `json:"key"`
Value string `json:"value"`
Desc string `json:"desc"`
}
// UpdateParamsRequest 更新参数请求
type UpdateParamsRequest struct {
ID uint `json:"ID"`
Name string `json:"name"`
Key string `json:"key"`
Value string `json:"value"`
Desc string `json:"desc"`
}
// GetParamsListRequest 获取参数列表请求
type GetParamsListRequest struct {
Page int `json:"page" form:"page"`
PageSize int `json:"pageSize" form:"pageSize"`
Name string `json:"name" form:"name"`
Key string `json:"key" form:"key"`
}
// RegisterRoutes 注册路由
func (s *ParamsService) RegisterRoutes(rg *RouterGroup) {
// 写操作(带操作记录)
rg.PrivateWithRecord.POST("/sysParams/createSysParams", s.handleCreateParams)
rg.PrivateWithRecord.DELETE("/sysParams/deleteSysParams", s.handleDeleteParams)
rg.PrivateWithRecord.DELETE("/sysParams/deleteSysParamsByIds", s.handleDeleteParamsByIds)
rg.PrivateWithRecord.PUT("/sysParams/updateSysParams", s.handleUpdateParams)
// 读操作(不记录)
rg.Private.GET("/sysParams/findSysParams", s.handleFindParams)
rg.Private.GET("/sysParams/getSysParamsList", s.handleGetParamsList)
rg.Private.GET("/sysParams/getSysParam", s.handleGetParamByKey)
}
// handleCreateParams 创建参数
func (s *ParamsService) handleCreateParams(ctx http.Context) error {
var req CreateParamsRequest
if err := ctx.Bind(&req); err != nil {
return err
}
params := &system.Params{
Name: req.Name,
Key: req.Key,
Value: req.Value,
Desc: req.Desc,
}
if err := s.uc.Create(ctx, params); err != nil {
return errors.BadRequest("CREATE_FAILED", "创建失败:"+err.Error())
}
return ctx.Result(200, map[string]any{"code": 0, "msg": "创建成功"})
}
// handleDeleteParams 删除参数
func (s *ParamsService) handleDeleteParams(ctx http.Context) error {
idStr := ctx.Query().Get("ID")
id, err := strconv.ParseUint(idStr, 10, 64)
if err != nil {
return errors.BadRequest("INVALID_ID", "无效的ID")
}
if err := s.uc.Delete(ctx, uint(id)); err != nil {
return errors.BadRequest("DELETE_FAILED", "删除失败:"+err.Error())
}
return ctx.Result(200, map[string]any{"code": 0, "msg": "删除成功"})
}
// handleDeleteParamsByIds 批量删除参数
func (s *ParamsService) handleDeleteParamsByIds(ctx http.Context) error {
idsStr := ctx.Query()["IDs[]"]
if len(idsStr) == 0 {
return errors.BadRequest("INVALID_IDS", "无效的IDs")
}
ids := make([]uint, 0, len(idsStr))
for _, idStr := range idsStr {
id, err := strconv.ParseUint(idStr, 10, 64)
if err != nil {
continue
}
ids = append(ids, uint(id))
}
if err := s.uc.DeleteByIds(ctx, ids); err != nil {
return errors.BadRequest("DELETE_FAILED", "批量删除失败:"+err.Error())
}
return ctx.Result(200, map[string]any{"code": 0, "msg": "批量删除成功"})
}
// handleUpdateParams 更新参数
func (s *ParamsService) handleUpdateParams(ctx http.Context) error {
var req UpdateParamsRequest
if err := ctx.Bind(&req); err != nil {
return err
}
params := &system.Params{
ID: req.ID,
Name: req.Name,
Key: req.Key,
Value: req.Value,
Desc: req.Desc,
}
if err := s.uc.Update(ctx, params); err != nil {
return errors.BadRequest("UPDATE_FAILED", "更新失败:"+err.Error())
}
return ctx.Result(200, map[string]any{"code": 0, "msg": "更新成功"})
}
// handleFindParams 根据ID查询参数
func (s *ParamsService) handleFindParams(ctx http.Context) error {
idStr := ctx.Query().Get("ID")
id, err := strconv.ParseUint(idStr, 10, 64)
if err != nil {
return errors.BadRequest("INVALID_ID", "无效的ID")
}
params, err := s.uc.GetByID(ctx, uint(id))
if err != nil {
return errors.NotFound("NOT_FOUND", "查询失败:"+err.Error())
}
return ctx.Result(200, map[string]any{"code": 0, "msg": "查询成功", "data": toParamsInfo(params)})
}
// handleGetParamsList 分页获取参数列表
func (s *ParamsService) handleGetParamsList(ctx http.Context) error {
var req GetParamsListRequest
if err := ctx.BindQuery(&req); err != nil {
return err
}
if req.Page <= 0 {
req.Page = 1
}
if req.PageSize <= 0 {
req.PageSize = 10
}
filters := make(map[string]interface{})
if req.Name != "" {
filters["name"] = req.Name
}
if req.Key != "" {
filters["key"] = req.Key
}
list, total, err := s.uc.GetList(ctx, req.Page, req.PageSize, filters)
if err != nil {
return errors.InternalServer("LIST_ERROR", "获取失败:"+err.Error())
}
result := make([]ParamsInfo, len(list))
for i, p := range list {
result[i] = toParamsInfo(p)
}
return ctx.Result(200, map[string]any{
"code": 0,
"msg": "获取成功",
"data": map[string]any{
"list": result,
"total": total,
"page": req.Page,
"pageSize": req.PageSize,
},
})
}
// handleGetParamByKey 根据key获取参数
func (s *ParamsService) handleGetParamByKey(ctx http.Context) error {
key := ctx.Query().Get("key")
if key == "" {
return errors.BadRequest("INVALID_KEY", "无效的key")
}
params, err := s.uc.GetByKey(ctx, key)
if err != nil {
return errors.NotFound("NOT_FOUND", "获取失败:"+err.Error())
}
return ctx.Result(200, map[string]any{"code": 0, "msg": "获取成功", "data": toParamsInfo(params)})
}
// toParamsInfo 转换为ParamsInfo
func toParamsInfo(p *system.Params) ParamsInfo {
info := ParamsInfo{
ID: p.ID,
Name: p.Name,
Key: p.Key,
Value: p.Value,
Desc: p.Desc,
}
if !p.CreatedAt.IsZero() {
info.CreatedAt = p.CreatedAt.Format("2006-01-02 15:04:05")
}
if !p.UpdatedAt.IsZero() {
info.UpdatedAt = p.UpdatedAt.Format("2006-01-02 15:04:05")
}
return info
}
+40
View File
@@ -0,0 +1,40 @@
package system
import (
"kra/pkg/server"
"github.com/go-kratos/kratos/v2/errors"
"github.com/go-kratos/kratos/v2/transport/http"
)
// SystemConfigService 系统配置服务
type SystemConfigService struct {
diskMountPoints []string
}
// NewSystemConfigService 创建系统配置服务
func NewSystemConfigService() *SystemConfigService {
// 默认磁盘挂载点,可以从配置中读取
return &SystemConfigService{
diskMountPoints: []string{"/"},
}
}
// RegisterRoutes 注册路由
func (s *SystemConfigService) RegisterRoutes(rg *RouterGroup) {
// 读操作(不记录)
rg.Private.POST("/system/getServerInfo", s.handleGetServerInfo)
}
// handleGetServerInfo 获取服务器信息
func (s *SystemConfigService) handleGetServerInfo(ctx http.Context) error {
serverInfo, err := server.GetServerInfo(s.diskMountPoints)
if err != nil {
return errors.InternalServer("GET_SERVER_INFO_FAILED", "获取失败:"+err.Error())
}
return ctx.Result(200, map[string]any{
"code": 0,
"msg": "获取成功",
"data": map[string]any{"server": serverInfo},
})
}
+211 -466
View File
@@ -1,18 +1,24 @@
package system
import (
"context"
"encoding/json"
"fmt"
"kra/internal/biz/system"
"kra/internal/server/middleware"
types "kra/internal/service/types/system"
"kra/pkg/jwt"
"github.com/go-kratos/kratos/v2/errors"
"github.com/go-kratos/kratos/v2/transport/http"
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
@@ -24,93 +30,43 @@ func NewUserService(uc *system.UserUsecase, jwtPkg *jwt.JWT) *UserService {
return &UserService{uc: uc, jwtPkg: jwtPkg}
}
// LoginRequest 登录请求
type LoginRequest struct {
Username string `json:"username"`
Password string `json:"password"`
Captcha string `json:"captcha"`
CaptchaId string `json:"captchaId"`
}
// LoginResponse 登录响应
type LoginResponse struct {
User *UserInfo `json:"user"`
Token string `json:"token"`
ExpiresAt int64 `json:"expiresAt"`
}
// UserInfo 用户信息
type UserInfo struct {
ID uint `json:"id"`
UUID string `json:"uuid"`
Username string `json:"username"`
NickName string `json:"nickName"`
SideMode string `json:"sideMode"`
HeaderImg string `json:"headerImg"`
BaseColor string `json:"baseColor"`
AuthorityId uint `json:"authorityId"`
Phone string `json:"phone"`
Email string `json:"email"`
Enable int `json:"enable"`
OriginSetting json.RawMessage `json:"originSetting,omitempty"`
Authority *AuthorityInfo `json:"authority,omitempty"`
Authorities []*AuthorityInfo `json:"authorities,omitempty"`
}
// AuthorityInfo 角色信息
type AuthorityInfo struct {
AuthorityId uint `json:"authorityId"`
AuthorityName string `json:"authorityName"`
ParentId *uint `json:"parentId,omitempty"`
DefaultRouter string `json:"defaultRouter"`
}
// Login 用户登录
func (s *UserService) Login(ctx context.Context, req *LoginRequest) (*LoginResponse, error) {
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 nil, errors.Unauthorized("LOGIN_FAILED", err.Error())
return errors.Unauthorized("LOGIN_FAILED", err.Error())
}
if user.Enable != 1 {
return nil, errors.Forbidden("USER_DISABLED", "用户被禁止登录")
return errors.Forbidden("USER_DISABLED", "用户被禁止登录")
}
// 生成 JWT token
claims := s.jwtPkg.CreateClaims(jwt.BaseClaims{
UUID: user.UUID.String(),
ID: uint(user.ID),
ID: user.ID,
Username: user.Username,
NickName: user.NickName,
AuthorityID: user.AuthorityId,
})
token, err := s.jwtPkg.CreateToken(claims.BaseClaims)
if err != nil {
return nil, errors.InternalServer("TOKEN_ERROR", "生成token失败")
return errors.InternalServer("TOKEN_ERROR", "生成token失败")
}
return &LoginResponse{
User: toUserInfo(user),
return ctx.Result(200, &types.LoginReply{
User: toTypesUserInfo(user),
Token: token,
ExpiresAt: claims.ExpiresAt.UnixMilli(),
}, nil
}
// RegisterRequest 注册请求
type RegisterRequest struct {
Username string `json:"username"`
Password string `json:"password"`
NickName string `json:"nickName"`
HeaderImg string `json:"headerImg"`
AuthorityId uint `json:"authorityId"`
AuthorityIds []uint `json:"authorityIds"`
Phone string `json:"phone"`
Email string `json:"email"`
Enable int `json:"enable"`
})
}
// Register 用户注册
func (s *UserService) Register(ctx context.Context, req *RegisterRequest) (*UserInfo, error) {
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,
@@ -121,66 +77,60 @@ func (s *UserService) Register(ctx context.Context, req *RegisterRequest) (*User
Email: req.Email,
Enable: req.Enable,
}
created, err := s.uc.Register(ctx, user)
if err != nil {
return nil, errors.BadRequest("REGISTER_FAILED", err.Error())
return errors.BadRequest("REGISTER_FAILED", err.Error())
}
return toUserInfo(created), nil
}
// ChangePasswordRequest 修改密码请求
type ChangePasswordRequest struct {
Password string `json:"password"`
NewPassword string `json:"newPassword"`
return ctx.Result(200, &types.UserInfoReply{User: toTypesUserInfo(created)})
}
// ChangePassword 修改密码
func (s *UserService) ChangePassword(ctx context.Context, userID uint, req *ChangePasswordRequest) error {
return s.uc.ChangePassword(ctx, userID, req.Password, req.NewPassword)
}
// ResetPasswordRequest 重置密码请求
type ResetPasswordRequest struct {
ID uint `json:"id"`
Password string `json:"password"`
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 context.Context, req *ResetPasswordRequest) error {
return s.uc.ResetPassword(ctx, req.ID, req.Password)
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 context.Context, uuid string) (*UserInfo, error) {
user, err := s.uc.GetUserInfo(ctx, uuid)
if err != nil {
return nil, errors.NotFound("USER_NOT_FOUND", err.Error())
func (s *UserService) GetUserInfo(ctx khttp.Context) error {
claims, ok := middleware.GetClaims(ctx)
if !ok {
return errors.Unauthorized("UNAUTHORIZED", "请先登录")
}
return toUserInfo(user), nil
}
// GetUserListRequest 获取用户列表请求
type GetUserListRequest struct {
Page int `json:"page"`
PageSize int `json:"pageSize"`
Username string `json:"username"`
NickName string `json:"nickName"`
Phone string `json:"phone"`
Email string `json:"email"`
}
// GetUserListResponse 获取用户列表响应
type GetUserListResponse struct {
List []*UserInfo `json:"list"`
Total int64 `json:"total"`
Page int `json:"page"`
PageSize int `json:"pageSize"`
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 context.Context, req *GetUserListRequest) (*GetUserListResponse, error) {
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
@@ -194,45 +144,23 @@ func (s *UserService) GetUserList(ctx context.Context, req *GetUserListRequest)
if req.Email != "" {
filters["email"] = req.Email
}
users, total, err := s.uc.GetUserList(ctx, req.Page, req.PageSize, filters)
if err != nil {
return nil, errors.InternalServer("LIST_ERROR", err.Error())
return errors.InternalServer("LIST_ERROR", err.Error())
}
list := make([]*UserInfo, len(users))
list := make([]types.UserInfo, len(users))
for i, u := range users {
list[i] = toUserInfo(u)
list[i] = toTypesUserInfo(u)
}
return &GetUserListResponse{
List: list,
Total: total,
Page: req.Page,
PageSize: req.PageSize,
}, nil
}
// SetUserInfoRequest 设置用户信息请求(管理员用)
type SetUserInfoRequest struct {
ID uint `json:"id"`
NickName string `json:"nickName"`
HeaderImg string `json:"headerImg"`
Phone string `json:"phone"`
Email string `json:"email"`
Enable int `json:"enable"`
AuthorityIds []uint `json:"authorityIds"`
return ctx.Result(200, &types.GetUserListReply{List: list, Total: total, Page: req.Page, PageSize: req.PageSize})
}
// SetUserInfo 设置用户信息
func (s *UserService) SetUserInfo(ctx context.Context, adminAuthorityID uint, req *SetUserInfoRequest) error {
// 如果提供了AuthorityIds,先设置用户角色(与GVA保持一致)
if len(req.AuthorityIds) > 0 {
if err := s.uc.SetUserAuthorities(ctx, adminAuthorityID, req.ID, req.AuthorityIds); err != nil {
return err
}
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,
@@ -241,360 +169,177 @@ func (s *UserService) SetUserInfo(ctx context.Context, adminAuthorityID uint, re
Email: req.Email,
Enable: req.Enable,
}
return s.uc.SetUserInfo(ctx, user)
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)
}
// SetSelfInfoRequest 设置自己信息请求(用户用)
type SetSelfInfoRequest struct {
NickName string `json:"nickName"`
HeaderImg string `json:"headerImg"`
Phone string `json:"phone"`
Email string `json:"email"`
SideMode string `json:"sideMode"`
BaseColor string `json:"baseColor"`
}
// SetSelfInfo 设置自己的信息
func (s *UserService) SetSelfInfo(ctx context.Context, userID uint, req *SetSelfInfoRequest) error {
// 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,
SideMode: req.SideMode,
BaseColor: req.BaseColor,
}
return s.uc.SetSelfInfo(ctx, user)
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 context.Context, userID uint, setting json.RawMessage) error {
return s.uc.SetSelfSetting(ctx, userID, setting)
// 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 context.Context, id uint) error {
return s.uc.DeleteUser(ctx, id)
}
// SetUserAuthorityRequest 设置用户角色请求
type SetUserAuthorityRequest struct {
AuthorityId uint `json:"authorityId"`
}
// SetUserAuthorityResponse 设置用户角色响应
type SetUserAuthorityResponse struct {
Token string `json:"token"`
ExpiresAt int64 `json:"expiresAt"`
}
// SetUserAuthority 设置用户角色(切换角色)- 返回新token
func (s *UserService) SetUserAuthority(ctx context.Context, userID uint, uuid string, username string, nickName string, req *SetUserAuthorityRequest) (*SetUserAuthorityResponse, error) {
if err := s.uc.SetUserAuthority(ctx, userID, req.AuthorityId); err != nil {
return nil, err
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)
}
// 生成新的JWT token(与GVA保持一致)
claims := s.jwtPkg.CreateClaims(jwt.BaseClaims{
UUID: uuid,
ID: userID,
Username: username,
NickName: nickName,
AuthorityID: req.AuthorityId,
})
// 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 nil, errors.InternalServer("TOKEN_ERROR", "生成token失败")
return errors.InternalServer("TOKEN_ERROR", "生成token失败")
}
return &SetUserAuthorityResponse{
Token: token,
ExpiresAt: claims.ExpiresAt.UnixMilli(),
}, nil
}
// SetUserAuthoritiesRequest 设置用户多角色请求
type SetUserAuthoritiesRequest struct {
ID uint `json:"id"`
AuthorityIds []uint `json:"authorityIds"`
return ctx.Result(200, &types.SetUserAuthorityReply{Token: token, ExpiresAt: claims.ExpiresAt.UnixMilli()})
}
// SetUserAuthorities 设置用户多角色
func (s *UserService) SetUserAuthorities(ctx context.Context, adminAuthorityID uint, req *SetUserAuthoritiesRequest) error {
return s.uc.SetUserAuthorities(ctx, adminAuthorityID, req.ID, req.AuthorityIds)
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)
}
// 转换函数
func toUserInfo(u *system.User) *UserInfo {
info := &UserInfo{
ID: u.ID,
UUID: u.UUID.String(),
Username: u.Username,
NickName: u.NickName,
SideMode: u.SideMode,
HeaderImg: u.HeaderImg,
BaseColor: u.BaseColor,
AuthorityId: u.AuthorityId,
Phone: u.Phone,
Email: u.Email,
Enable: u.Enable,
OriginSetting: u.OriginSetting,
// toTypesUserInfo 转换用户信息为types格式
func toTypesUserInfo(user *system.User) types.UserInfo {
if user == nil {
return types.UserInfo{}
}
if u.Authority != nil {
info.Authority = &AuthorityInfo{
AuthorityId: u.Authority.AuthorityId,
AuthorityName: u.Authority.AuthorityName,
ParentId: u.Authority.ParentId,
DefaultRouter: u.Authority.DefaultRouter,
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)
}
}
if len(u.Authorities) > 0 {
info.Authorities = make([]*AuthorityInfo, len(u.Authorities))
for i, a := range u.Authorities {
info.Authorities[i] = &AuthorityInfo{
AuthorityId: a.AuthorityId,
AuthorityName: a.AuthorityName,
ParentId: a.ParentId,
DefaultRouter: a.DefaultRouter,
}
}
}
return info
}
// RegisterRoutes 注册路由
func (s *UserService) RegisterRoutes(srv *http.Server) {
r := srv.Route("/")
// 公开接口
r.POST("/base/login", s.handleLogin)
// 需要认证的接口
r.POST("/user/register", s.handleRegister)
r.POST("/user/changePassword", s.handleChangePassword)
r.POST("/user/resetPassword", s.handleResetPassword)
r.GET("/user/getUserInfo", s.handleGetUserInfo)
r.POST("/user/getUserList", s.handleGetUserList)
r.PUT("/user/setUserInfo", s.handleSetUserInfo)
r.PUT("/user/setSelfInfo", s.handleSetSelfInfo)
r.PUT("/user/setSelfSetting", s.handleSetSelfSetting)
r.DELETE("/user/deleteUser", s.handleDeleteUser)
r.POST("/user/setUserAuthority", s.handleSetUserAuthority)
r.POST("/user/setUserAuthorities", s.handleSetUserAuthorities)
// 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,
}
}
// HTTP Handlers
func (s *UserService) handleLogin(ctx http.Context) error {
var req LoginRequest
if err := ctx.Bind(&req); err != nil {
return err
}
resp, err := s.Login(ctx, &req)
if err != nil {
return err
}
return ctx.Result(200, map[string]any{
"code": 0,
"msg": "登录成功",
"data": resp,
})
}
// RegisterRoutes 注册用户路由
func (s *UserService) RegisterRoutes(rg *RouterGroup) {
// 公开路由(无需认证)
rg.Public.POST("/base/login", s.Login)
func (s *UserService) handleRegister(ctx http.Context) error {
var req RegisterRequest
if err := ctx.Bind(&req); err != nil {
return err
}
resp, err := s.Register(ctx, &req)
if err != nil {
return err
}
return ctx.Result(200, map[string]any{
"code": 0,
"msg": "注册成功",
"data": resp,
})
}
// 私有路由 + 操作记录(写操作)
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)
func (s *UserService) handleChangePassword(ctx http.Context) error {
var req ChangePasswordRequest
if err := ctx.Bind(&req); err != nil {
return err
}
userID := middleware.GetUserID(ctx)
if userID == 0 {
return errors.Unauthorized("UNAUTHORIZED", "请先登录")
}
if err := s.ChangePassword(ctx, userID, &req); err != nil {
return err
}
return ctx.Result(200, map[string]any{
"code": 0,
"msg": "修改成功",
})
}
func (s *UserService) handleResetPassword(ctx http.Context) error {
var req ResetPasswordRequest
if err := ctx.Bind(&req); err != nil {
return err
}
if err := s.ResetPassword(ctx, &req); err != nil {
return err
}
return ctx.Result(200, map[string]any{
"code": 0,
"msg": "重置成功",
})
}
func (s *UserService) handleGetUserInfo(ctx http.Context) error {
claims, ok := middleware.GetClaims(ctx)
if !ok {
return errors.Unauthorized("UNAUTHORIZED", "请先登录")
}
resp, err := s.GetUserInfo(ctx, claims.UUID)
if err != nil {
return err
}
return ctx.Result(200, map[string]any{
"code": 0,
"msg": "获取成功",
"data": map[string]any{"userInfo": resp},
})
}
func (s *UserService) handleGetUserList(ctx http.Context) error {
var req GetUserListRequest
if err := ctx.Bind(&req); err != nil {
return err
}
resp, err := s.GetUserList(ctx, &req)
if err != nil {
return err
}
return ctx.Result(200, map[string]any{
"code": 0,
"msg": "获取成功",
"data": resp,
})
}
func (s *UserService) handleSetUserInfo(ctx http.Context) error {
var req SetUserInfoRequest
if err := ctx.Bind(&req); err != nil {
return err
}
adminAuthorityID := middleware.GetAuthorityID(ctx)
if adminAuthorityID == 0 {
return errors.Unauthorized("UNAUTHORIZED", "请先登录")
}
if err := s.SetUserInfo(ctx, adminAuthorityID, &req); err != nil {
return err
}
return ctx.Result(200, map[string]any{
"code": 0,
"msg": "设置成功",
})
}
func (s *UserService) handleSetSelfInfo(ctx http.Context) error {
var req SetSelfInfoRequest
if err := ctx.Bind(&req); err != nil {
return err
}
userID := middleware.GetUserID(ctx)
if userID == 0 {
return errors.Unauthorized("UNAUTHORIZED", "请先登录")
}
if err := s.SetSelfInfo(ctx, userID, &req); err != nil {
return err
}
return ctx.Result(200, map[string]any{
"code": 0,
"msg": "设置成功",
})
}
func (s *UserService) handleSetSelfSetting(ctx http.Context) error {
var req json.RawMessage
if err := ctx.Bind(&req); err != nil {
return err
}
userID := middleware.GetUserID(ctx)
if userID == 0 {
return errors.Unauthorized("UNAUTHORIZED", "请先登录")
}
if err := s.SetSelfSetting(ctx, userID, req); err != nil {
return err
}
return ctx.Result(200, map[string]any{
"code": 0,
"msg": "设置成功",
})
}
func (s *UserService) handleDeleteUser(ctx http.Context) error {
var req struct {
ID uint `json:"id"`
}
if err := ctx.Bind(&req); err != nil {
return err
}
// 不能删除自己
userID := middleware.GetUserID(ctx)
if userID == req.ID {
return errors.BadRequest("DELETE_SELF", "删除失败, 无法删除自己")
}
if err := s.DeleteUser(ctx, req.ID); err != nil {
return err
}
return ctx.Result(200, map[string]any{
"code": 0,
"msg": "删除成功",
})
}
func (s *UserService) handleSetUserAuthority(ctx http.Context) error {
var req SetUserAuthorityRequest
if err := ctx.Bind(&req); err != nil {
return err
}
claims, ok := middleware.GetClaims(ctx)
if !ok {
return errors.Unauthorized("UNAUTHORIZED", "请先登录")
}
resp, err := s.SetUserAuthority(ctx, claims.BaseClaims.ID, claims.UUID, claims.Username, claims.NickName, &req)
if err != nil {
return err
}
// 设置响应头(与GVA保持一致)
ctx.Response().Header().Set("new-token", resp.Token)
ctx.Response().Header().Set("new-expires-at", fmt.Sprintf("%d", resp.ExpiresAt/1000))
return ctx.Result(200, map[string]any{
"code": 0,
"msg": "修改成功",
})
}
func (s *UserService) handleSetUserAuthorities(ctx http.Context) error {
var req SetUserAuthoritiesRequest
if err := ctx.Bind(&req); err != nil {
return err
}
adminAuthorityID := middleware.GetAuthorityID(ctx)
if adminAuthorityID == 0 {
return errors.Unauthorized("UNAUTHORIZED", "请先登录")
}
if err := s.SetUserAuthorities(ctx, adminAuthorityID, &req); err != nil {
return err
}
return ctx.Result(200, map[string]any{
"code": 0,
"msg": "修改成功",
})
// 私有路由(读操作,不记录)
rg.Private.POST("/user/getUserList", s.GetUserList)
rg.Private.GET("/user/getUserInfo", s.GetUserInfo)
}