feat(user): 添加用户分页列表接口及通用查询封装
This commit is contained in:
1 parent
50dc1b0f09
commit
1bca4808e9
11 files changed
+165
-10
No files matched your search
@@ -1,9 +1,13 @@
|
||||
package api
|
||||
|
||||
import "EnGin/internal/api/auth_api"
|
||||
import (
|
||||
"EnGin/internal/api/auth_api"
|
||||
"EnGin/internal/api/user_api"
|
||||
)
|
||||
|
||||
type Api struct {
|
||||
AuthApi auth_api.AuthApi
|
||||
UserApi user_api.UserApi
|
||||
}
|
||||
|
||||
// App 统一导出全局 API 实例
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
package user_api
|
||||
|
||||
type UserApi struct {
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package user_api
|
||||
|
||||
import (
|
||||
"EnGin/internal/global"
|
||||
"EnGin/internal/middleware"
|
||||
"EnGin/internal/service/user_ser"
|
||||
"EnGin/internal/utils/res"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
type UserListRequest struct {
|
||||
Page int `form:"page"`
|
||||
Limit int `form:"limit"`
|
||||
UsernameKey string `form:"username_key"` // 可选模糊搜索
|
||||
}
|
||||
|
||||
type UserListResponse struct {
|
||||
Username string `json:"username"`
|
||||
Email string `json:"email"`
|
||||
IP string `json:"ip"`
|
||||
CreateAt time.Time `json:"create_at"`
|
||||
}
|
||||
|
||||
func (UserApi) UserListView(c *gin.Context) {
|
||||
cr := middleware.GetBind[UserListRequest](c)
|
||||
|
||||
list, count, err := user_ser.GetUserListWithPage(
|
||||
c.Request.Context(),
|
||||
cr.UsernameKey,
|
||||
cr.Page,
|
||||
cr.Limit,
|
||||
)
|
||||
if err != nil {
|
||||
global.Log.Error("查询用户列表失败", zap.Error(err))
|
||||
res.InternalError("获取用户列表失败", c)
|
||||
return
|
||||
}
|
||||
|
||||
var users = make([]UserListResponse, 0, count)
|
||||
for _, u := range list {
|
||||
users = append(users, UserListResponse{
|
||||
Username: u.Username,
|
||||
Email: u.Email,
|
||||
IP: u.IP,
|
||||
CreateAt: u.CreatedAt,
|
||||
})
|
||||
}
|
||||
|
||||
res.OkWithList(users, count, c)
|
||||
}
|
||||
@@ -11,7 +11,7 @@ type Config struct {
|
||||
Server ServerConfig `mapstructure:"server" yaml:"server"`
|
||||
Database DatabaseConfig `mapstructure:"database" yaml:"database"`
|
||||
Logger LoggerConfig `mapstructure:"logger" yaml:"logger"`
|
||||
Jwt JwtConfig `mapstructure:"logger" yaml:"jwt"`
|
||||
Jwt JwtConfig `mapstructure:"jwt" yaml:"jwt"`
|
||||
Redis RedisConfig `mapstructure:"redis" yaml:"redis"`
|
||||
}
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ func Auth(c *gin.Context) {
|
||||
func AuthAdmin(c *gin.Context) {
|
||||
accessToken := c.GetHeader("access_token")
|
||||
if accessToken == "" {
|
||||
res.Unauthorized("未携带 access_token", c)
|
||||
res.Unauthorized("认证失败", c)
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
@@ -47,7 +47,7 @@ func AuthAdmin(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
// 💡 预加载用户的关联角色列表 (WithRoles)
|
||||
// 预加载用户的关联角色列表 (WithRoles)
|
||||
ctx := c.Request.Context()
|
||||
u, err := db.Client.User.Query().
|
||||
Where(user.ID(int(claims.UserID))).
|
||||
@@ -60,7 +60,7 @@ func AuthAdmin(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
// 💡 遍历用户的角色列表,检查是否有 "admin" 角色代码
|
||||
// 遍历用户的角色列表,检查是否有 "admin" 角色代码
|
||||
isAdmin := false
|
||||
for _, role := range u.Edges.Roles {
|
||||
if role.Code == "admin" {
|
||||
|
||||
@@ -9,4 +9,5 @@ func RegisterRoutes(r *gin.Engine) {
|
||||
// 分组并调用子路由
|
||||
g := r.Group("api/v1")
|
||||
AuthRouter(g)
|
||||
UserRouter(g)
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package router
|
||||
|
||||
import (
|
||||
"EnGin/internal/api"
|
||||
"EnGin/internal/api/user_api"
|
||||
"EnGin/internal/middleware"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func UserRouter(g *gin.RouterGroup) {
|
||||
app := api.App.UserApi
|
||||
g.GET("users",
|
||||
middleware.BindQueryMiddleware[user_api.UserListRequest],
|
||||
middleware.AuthAdmin,
|
||||
app.UserListView)
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package common
|
||||
|
||||
import "context"
|
||||
|
||||
// EntQuery 定义满足 Ent 所有查询构建器的泛型接口
|
||||
// Q 为具体的查询器类型(如 *ent.UserQuery),T 为返回的实体类型(如 *ent.User)
|
||||
type EntQuery[Q any, T any] interface {
|
||||
Limit(int) Q
|
||||
Offset(int) Q
|
||||
Count(ctx context.Context) (int, error)
|
||||
All(ctx context.Context) ([]T, error)
|
||||
}
|
||||
|
||||
// QueryOptions 通用列表查询配置项
|
||||
type QueryOptions[Q any] struct {
|
||||
Page int
|
||||
Limit int
|
||||
Query func(Q) Q // Query 闭包:在这里传入具体的过滤条件(Where)、排序(Order)和预加载(With)
|
||||
}
|
||||
|
||||
func QueryList[Q EntQuery[Q, T], T any](ctx context.Context, query Q, opts QueryOptions[Q]) (list []T, count int, err error) {
|
||||
if opts.Query != nil {
|
||||
query = opts.Query(query)
|
||||
}
|
||||
|
||||
count, err = query.Count(ctx)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
page := opts.Page
|
||||
if page <= 0 {
|
||||
page = 1
|
||||
}
|
||||
|
||||
limit := opts.Limit
|
||||
if limit <= 0 {
|
||||
limit = 10 // 默认每页 10 条
|
||||
}
|
||||
offset := (page - 1) * limit
|
||||
|
||||
list, err = query.Limit(limit).Offset(offset).All(ctx)
|
||||
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
return list, count, nil
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package user_ser
|
||||
|
||||
import (
|
||||
"EnGin/internal/db"
|
||||
"EnGin/internal/ent"
|
||||
"EnGin/internal/ent/user"
|
||||
"EnGin/internal/service/common"
|
||||
"context"
|
||||
|
||||
"entgo.io/ent/dialect/sql"
|
||||
)
|
||||
|
||||
func GetUserListWithPage(ctx context.Context, usernameKey string, page, limit int) ([]*ent.User, int, error) {
|
||||
return common.QueryList(ctx, db.Client.User.Query(), common.QueryOptions[*ent.UserQuery]{
|
||||
Page: page,
|
||||
Limit: limit,
|
||||
Query: func(q *ent.UserQuery) *ent.UserQuery {
|
||||
// 模糊匹配(编译期安全,杜绝拼写错误)
|
||||
if usernameKey != "" {
|
||||
q = q.Where(user.UsernameContains(usernameKey))
|
||||
}
|
||||
|
||||
// 预加载关联角色,并按照创建时间倒序
|
||||
return q.WithRoles().Order(user.ByCreatedAt(sql.OrderDesc()))
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -61,7 +61,7 @@ func OkWithMsg(msg string, c *gin.Context) {
|
||||
Ok(gin.H{}, Success, msg, c)
|
||||
}
|
||||
|
||||
func OkWithList(list any, count int64, c *gin.Context) {
|
||||
func OkWithList(list any, count int, c *gin.Context) {
|
||||
Ok(map[string]any{
|
||||
"list": list,
|
||||
"count": count,
|
||||
|
||||
Reference in new issue
Block a user