Compare commits

...

3 Commits

Author SHA1 Message Date
619834a673 feat: update post list
Some checks failed
build quyun / Build (push) Failing after 1m39s
2025-12-20 21:49:34 +08:00
be8a57c649 fix: query 2025-12-20 21:41:41 +08:00
3313c3aa7d feat: 重构用户列表查询,支持通过手机号和用户名搜索 2025-12-20 21:27:48 +08:00
15 changed files with 123 additions and 148 deletions

View File

@@ -1,14 +1,13 @@
package admin
import (
"quyun/v2/app/http/dto"
"quyun/v2/app/requests"
"quyun/v2/app/services"
"quyun/v2/database"
"quyun/v2/database/models"
"quyun/v2/providers/ali"
"github.com/gofiber/fiber/v3"
"go.ipao.vip/gen"
)
// @provider
@@ -21,19 +20,12 @@ type medias struct {
// @Summary 媒体列表
// @Tags Admin Medias
// @Produce json
// @Param pagination query requests.Pagination false "分页参数"
// @Param query query ListQuery false "筛选条件"
// @Success 200 {object} requests.Pager{items=models.Medium} "成功"
// @Router /admin/v1/medias [get]
// @Bind pagination query
// @Bind query query
func (ctl *medias) List(ctx fiber.Ctx, pagination *requests.Pagination, query *ListQuery) (*requests.Pager, error) {
conds := []gen.Condition{}
if query.Keyword != nil {
conds = append(conds, models.MediumQuery.Name.Like(database.WrapLike(*query.Keyword)))
}
return services.Media.List(ctx, pagination, conds...)
func (ctl *medias) List(ctx fiber.Ctx, query *dto.ListQuery) (*requests.Pager, error) {
return services.Media.List(ctx, query)
}
// Show media

View File

@@ -1,7 +1,7 @@
package admin
import (
"quyun/v2/app/http/admin/dto"
"quyun/v2/app/http/dto"
"quyun/v2/app/requests"
"quyun/v2/app/services"
"quyun/v2/database/models"

View File

@@ -1,22 +1,17 @@
package admin
import (
"quyun/v2/app/http/dto"
"quyun/v2/app/requests"
"quyun/v2/app/services"
"quyun/v2/database"
"quyun/v2/database/models"
"quyun/v2/pkg/fields"
"github.com/gofiber/fiber/v3"
"github.com/samber/lo"
"go.ipao.vip/gen"
"go.ipao.vip/gen/types"
)
type ListQuery struct {
Keyword *string `query:"keyword"`
}
// @provider
type posts struct{}
@@ -25,18 +20,12 @@ type posts struct{}
// @Summary 作品列表
// @Tags Admin Posts
// @Produce json
// @Param pagination query requests.Pagination false "分页参数"
// @Param query query ListQuery false "筛选条件"
// @Param query query dto.PostListQuery false "筛选条件"
// @Success 200 {object} requests.Pager{items=PostItem} "成功"
// @Router /admin/v1/posts [get]
// @Bind pagination query
// @Bind query query
func (ctl *posts) List(ctx fiber.Ctx, pagination *requests.Pagination, query *ListQuery) (*requests.Pager, error) {
conds := []gen.Condition{}
if query.Keyword != nil && *query.Keyword != "" {
conds = append(conds, models.PostQuery.Title.Like(database.WrapLike(*query.Keyword)))
}
pager, err := services.Posts.List(ctx, pagination, conds...)
func (ctl *posts) List(ctx fiber.Ctx, query *dto.PostListQuery) (*requests.Pager, error) {
pager, err := services.Posts.List(ctx, query)
if err != nil {
return nil, err
}

View File

@@ -6,7 +6,7 @@ package admin
import (
"go.ipao.vip/gen/field"
"quyun/v2/app/http/admin/dto"
"quyun/v2/app/http/dto"
"quyun/v2/app/middlewares"
"quyun/v2/app/requests"
"quyun/v2/database/models"
@@ -66,10 +66,9 @@ func (r *Routes) Register(router fiber.Router) {
},
))
r.log.Debugf("Registering route: Get /admin/v1/medias -> medias.List")
router.Get("/admin/v1/medias"[len(r.Path()):], DataFunc2(
router.Get("/admin/v1/medias"[len(r.Path()):], DataFunc1(
r.medias.List,
Query[requests.Pagination]("pagination"),
Query[ListQuery]("query"),
Query[dto.ListQuery]("query"),
))
r.log.Debugf("Registering route: Get /admin/v1/medias/:id -> medias.Show")
router.Get("/admin/v1/medias/:id"[len(r.Path()):], Func1(
@@ -103,10 +102,9 @@ func (r *Routes) Register(router fiber.Router) {
},
))
r.log.Debugf("Registering route: Get /admin/v1/posts -> posts.List")
router.Get("/admin/v1/posts"[len(r.Path()):], DataFunc2(
router.Get("/admin/v1/posts"[len(r.Path()):], DataFunc1(
r.posts.List,
Query[requests.Pagination]("pagination"),
Query[ListQuery]("query"),
Query[dto.PostListQuery]("query"),
))
r.log.Debugf("Registering route: Get /admin/v1/posts/:id -> posts.Show")
router.Get("/admin/v1/posts/:id"[len(r.Path()):], DataFunc1(
@@ -162,10 +160,9 @@ func (r *Routes) Register(router fiber.Router) {
))
// Register routes for controller: users
r.log.Debugf("Registering route: Get /admin/v1/users -> users.List")
router.Get("/admin/v1/users"[len(r.Path()):], DataFunc2(
router.Get("/admin/v1/users"[len(r.Path()):], DataFunc1(
r.users.List,
Query[requests.Pagination]("pagination"),
Query[UserListQuery]("query"),
Query[dto.UserListQuery]("query"),
))
r.log.Debugf("Registering route: Get /admin/v1/users/:id -> users.Show")
router.Get("/admin/v1/users/:id"[len(r.Path()):], DataFunc1(

View File

@@ -1,19 +1,14 @@
package admin
import (
"quyun/v2/app/http/dto"
"quyun/v2/app/requests"
"quyun/v2/app/services"
"quyun/v2/database"
"quyun/v2/database/models"
"github.com/gofiber/fiber/v3"
"go.ipao.vip/gen"
)
type UserListQuery struct {
Keyword *string `query:"keyword"`
}
// @provider
type users struct{}
@@ -22,20 +17,12 @@ type users struct{}
// @Summary 用户列表
// @Tags Admin Users
// @Produce json
// @Param pagination query requests.Pagination false "分页参数"
// @Param query query UserListQuery false "筛选条件"
// @Success 200 {object} requests.Pager{items=models.User} "成功"
// @Router /admin/v1/users [get]
// @Bind pagination query
// @Bind query query
func (ctl *users) List(ctx fiber.Ctx, pagination *requests.Pagination, query *UserListQuery) (*requests.Pager, error) {
conds := []gen.Condition{}
if query.Keyword != nil && *query.Keyword != "" {
conds = append(conds,
models.UserQuery.Phone.Like(database.WrapLike(*query.Keyword)),
)
}
return services.Users.List(ctx, pagination, conds...)
func (ctl *users) List(ctx fiber.Ctx, query *dto.UserListQuery) (*requests.Pager, error) {
return services.Users.List(ctx, query)
}
// Show user

View File

@@ -0,0 +1,8 @@
package dto
import "quyun/v2/app/requests"
type ListQuery struct {
*requests.Pagination
Keyword *string `query:"keyword"`
}

View File

@@ -0,0 +1,12 @@
package dto
import (
"quyun/v2/app/requests"
"quyun/v2/pkg/fields"
)
type PostListQuery struct {
*requests.Pagination
Keyword *string `query:"keyword"`
Status fields.PostStatus `query:"status"`
}

View File

@@ -0,0 +1,8 @@
package dto
import "quyun/v2/app/requests"
type UserListQuery struct {
*requests.Pagination
Keyword *string `query:"keyword"`
}

View File

@@ -5,10 +5,10 @@ import (
"strconv"
"time"
"quyun/v2/app/http/dto"
"quyun/v2/app/jobs"
"quyun/v2/app/requests"
"quyun/v2/app/services"
"quyun/v2/database"
"quyun/v2/database/models"
"quyun/v2/pkg/fields"
"quyun/v2/providers/ali"
@@ -20,7 +20,6 @@ import (
"github.com/pkg/errors"
"github.com/samber/lo"
log "github.com/sirupsen/logrus"
"go.ipao.vip/gen"
)
type ListQuery struct {
@@ -39,30 +38,15 @@ type posts struct {
// @Summary 作品列表
// @Tags Posts
// @Produce json
// @Param pagination query requests.Pagination false "分页参数"
// @Param query query ListQuery false "筛选条件"
// @Param query query dto.PostListQuery false "筛选条件"
// @Success 200 {object} requests.Pager{items=PostItem} "成功"
// @Router /v1/posts [get]
// @Bind pagination query
// @Bind query query
// @Bind user local
func (ctl *posts) List(
ctx fiber.Ctx,
pagination *requests.Pagination,
query *ListQuery,
user *models.User,
) (*requests.Pager, error) {
tbl, _ := models.PostQuery.QueryContext(ctx)
conds := []gen.Condition{
tbl.Status.Eq(fields.PostStatusPublished),
}
if query.Keyword != nil && *query.Keyword != "" {
conds = append(conds,
tbl.Title.Like(database.WrapLike(*query.Keyword)),
)
}
func (ctl *posts) List(ctx fiber.Ctx, query *dto.PostListQuery, user *models.User) (*requests.Pager, error) {
query.Status = fields.PostStatusPublished
pager, err := services.Posts.List(ctx, pagination, conds...)
pager, err := services.Posts.List(ctx, query)
if err != nil {
log.WithError(err).Errorf("post list err: %v", err)
return nil, err
@@ -248,31 +232,19 @@ func (ctl *posts) Play(ctx fiber.Ctx, post *models.Post, user *models.User) (*Pl
// @Summary 我的已购作品
// @Tags Posts
// @Produce json
// @Param pagination query requests.Pagination false "分页参数"
// @Param query query ListQuery false "筛选条件"
// @Success 200 {object} requests.Pager{items=PostItem} "成功"
// @Router /v1/posts/mine [get]
// @Bind pagination query
// @Bind query query
// @Bind user local
func (ctl *posts) Mine(
ctx fiber.Ctx,
pagination *requests.Pagination,
query *ListQuery,
query *dto.PostListQuery,
user *models.User,
) (*requests.Pager, error) {
log.Infof("Fetching posts for user with pagination: %+v and keyword: %v", pagination, query.Keyword)
log.Infof("Fetching posts for user with keyword: %v", query.Keyword)
conds := []gen.Condition{
models.PostQuery.Status.Eq(fields.PostStatusPublished),
}
if query.Keyword != nil && *query.Keyword != "" {
conds = append(conds,
models.PostQuery.Title.Like(database.WrapLike(*query.Keyword)),
)
}
pager, err := services.Users.PostList(ctx, user.ID, pagination, conds...)
pager, err := services.Users.PostList(ctx, user.ID, query)
if err != nil {
log.WithError(err).Errorf("post list err: %v", err)
return nil, err

View File

@@ -6,8 +6,8 @@ package http
import (
"go.ipao.vip/gen/field"
"quyun/v2/app/http/dto"
"quyun/v2/app/middlewares"
"quyun/v2/app/requests"
"quyun/v2/database/models"
"github.com/gofiber/fiber/v3"
@@ -58,10 +58,9 @@ func (r *Routes) Register(router fiber.Router) {
))
// Register routes for controller: posts
r.log.Debugf("Registering route: Get /v1/posts -> posts.List")
router.Get("/v1/posts"[len(r.Path()):], DataFunc3(
router.Get("/v1/posts"[len(r.Path()):], DataFunc2(
r.posts.List,
Query[requests.Pagination]("pagination"),
Query[ListQuery]("query"),
Query[dto.PostListQuery]("query"),
Local[*models.User]("user"),
))
r.log.Debugf("Registering route: Get /v1/posts/:id/play -> posts.Play")
@@ -83,10 +82,9 @@ func (r *Routes) Register(router fiber.Router) {
Local[*models.User]("user"),
))
r.log.Debugf("Registering route: Get /v1/posts/mine -> posts.Mine")
router.Get("/v1/posts/mine"[len(r.Path()):], DataFunc3(
router.Get("/v1/posts/mine"[len(r.Path()):], DataFunc2(
r.posts.Mine,
Query[requests.Pagination]("pagination"),
Query[ListQuery]("query"),
Query[dto.PostListQuery]("query"),
Local[*models.User]("user"),
))
r.log.Debugf("Registering route: Post /v1/posts/:id/buy -> posts.Buy")

View File

@@ -3,7 +3,9 @@ package services
import (
"context"
"quyun/v2/app/http/dto"
"quyun/v2/app/requests"
"quyun/v2/database"
"quyun/v2/database/models"
"quyun/v2/pkg/fields"
@@ -14,19 +16,18 @@ import (
// @provider
type media struct{}
func (m *media) List(
ctx context.Context,
pagination *requests.Pagination,
conds ...gen.Condition,
) (*requests.Pager, error) {
pagination.Format()
func (m *media) List(ctx context.Context, filter *dto.ListQuery) (*requests.Pager, error) {
filter.Format()
tbl, query := models.MediumQuery.QueryContext(ctx)
items, cnt, err := query.
Where(conds...).
Order(tbl.ID.Desc()).
FindByPage(int(pagination.Offset()), int(pagination.Limit))
query = query.Order(tbl.ID.Desc())
if filter.Keyword != nil && *filter.Keyword != "" {
query = query.Where(tbl.Name.Like(database.WrapLike(*filter.Keyword)))
}
items, cnt, err := query.FindByPage(int(filter.Offset()), int(filter.Limit))
if err != nil {
return nil, errors.Wrap(err, "failed to list media items")
}
@@ -34,7 +35,7 @@ func (m *media) List(
return &requests.Pager{
Items: items,
Total: cnt,
Pagination: *pagination,
Pagination: *filter.Pagination,
}, nil
}

View File

@@ -4,7 +4,7 @@ import (
"context"
"time"
"quyun/v2/app/http/admin/dto"
"quyun/v2/app/http/dto"
"quyun/v2/app/requests"
"quyun/v2/database"
"quyun/v2/database/models"

View File

@@ -4,6 +4,7 @@ import (
"context"
"time"
"quyun/v2/app/http/dto"
"quyun/v2/app/requests"
"quyun/v2/database"
"quyun/v2/database/models"
@@ -28,17 +29,20 @@ func (m *posts) IncrViewCount(ctx context.Context, postID int64) error {
}
// List
func (m *posts) List(
ctx context.Context,
pagination *requests.Pagination,
conds ...gen.Condition,
) (*requests.Pager, error) {
pagination.Format()
func (m *posts) List(ctx context.Context, filter *dto.PostListQuery) (*requests.Pager, error) {
filter.Pagination.Format()
// conds := []gen.Condition{}
tbl, query := models.PostQuery.QueryContext(ctx)
items, cnt, err := query.Where(conds...).
Order(tbl.ID.Desc()).
FindByPage(int(pagination.Offset()), int(pagination.Limit))
query = query.Order(tbl.ID.Desc())
if filter.Keyword != nil && *filter.Keyword != "" {
keyword := database.WrapLike(*filter.Keyword)
query = query.Where(tbl.Title.Like(keyword))
}
items, cnt, err := query.FindByPage(int(filter.Offset()), int(filter.Limit))
if err != nil {
return nil, errors.Wrap(err, "list post failed")
}
@@ -46,7 +50,7 @@ func (m *posts) List(
return &requests.Pager{
Items: items,
Total: cnt,
Pagination: *pagination,
Pagination: *filter.Pagination,
}, nil
}

View File

@@ -5,11 +5,14 @@ import (
"crypto/rand"
"fmt"
"math/big"
"strconv"
"strings"
"sync"
"time"
"quyun/v2/app/http/dto"
"quyun/v2/app/requests"
"quyun/v2/database"
"quyun/v2/database/models"
"github.com/pkg/errors"
@@ -38,16 +41,24 @@ func (m *users) Prepare() error {
// List returns a paginated list of users
func (m *users) List(
ctx context.Context,
pagination *requests.Pagination,
conds ...gen.Condition,
filter *dto.UserListQuery,
) (*requests.Pager, error) {
pagination.Format()
filter.Pagination.Format()
tbl, query := models.UserQuery.QueryContext(ctx)
items, cnt, err := query.
Where(conds...).
Order(tbl.ID.Desc()).
FindByPage(int(pagination.Offset()), int(pagination.Limit))
query = query.Order(tbl.ID.Desc())
if filter.Keyword != nil && *filter.Keyword != "" {
query = query.
Where(tbl.Phone.Like(database.WrapLike(*filter.Keyword))).
Or(tbl.Username.Like(database.WrapLike(*filter.Keyword)))
if id, err := strconv.ParseInt(strings.TrimSpace(*filter.Keyword), 10, 64); err == nil && id > 0 {
query = query.Or(tbl.ID.Eq(id))
}
}
items, cnt, err := query.FindByPage(int(filter.Pagination.Offset()), int(filter.Pagination.Limit))
if err != nil {
return nil, errors.Wrap(err, "query users error")
}
@@ -55,35 +66,20 @@ func (m *users) List(
return &requests.Pager{
Items: items,
Total: cnt,
Pagination: *pagination,
Pagination: *filter.Pagination,
}, nil
}
// PostList returns a paginated list of posts for a user
func (m *users) PostList(
ctx context.Context,
userId int64,
pagination *requests.Pagination,
conds ...gen.Condition,
) (*requests.Pager, error) {
pagination.Format()
// stmt := SELECT(tbl.AllColumns).
// FROM(tbl.
// RIGHT_JOIN(
// tblUserPosts,
// tblUserPosts.PostID.EQ(tbl.ID),
// ),
// ).
// WHERE(CondTrue(cond...)).
// ORDER_BY(tblUserPosts.ID.DESC()).
// LIMIT(pagination.Limit).
// OFFSET(pagination.Offset)
// m.log().Infof("sql: %s", stmt.DebugSql())
func (m *users) PostList(ctx context.Context, userId int64, filter *dto.PostListQuery) (*requests.Pager, error) {
filter.Format()
tbl, query := models.UserPostQuery.QueryContext(ctx)
query = query.Order(tbl.CreatedAt.Desc())
pagePosts, cnt, err := query.Select(tbl.PostID).
Where(tbl.UserID.Eq(userId)).
FindByPage(int(pagination.Offset()), int(pagination.Limit))
FindByPage(int(filter.Offset()), int(filter.Limit))
if err != nil {
return nil, err
}
@@ -94,10 +90,21 @@ func (m *users) PostList(
if err != nil {
return nil, err
}
itemMap := lo.KeyBy(items, func(item *models.Post) int64 { return item.ID })
tmpItems := []*models.Post{}
for _, id := range postIds {
if i, ok := itemMap[id]; ok {
tmpItems = append(tmpItems, i)
}
}
return &requests.Pager{
Items: items,
Items: tmpItems,
Total: cnt,
Pagination: *pagination,
Pagination: *filter.Pagination,
}, nil
}