feat: add post buy count
This commit is contained in:
@@ -38,3 +38,22 @@ func (ctl *medias) Show(ctx fiber.Ctx, id int64) error {
|
||||
|
||||
return ctx.Redirect().To(url)
|
||||
}
|
||||
|
||||
// Delete
|
||||
// @Router /v1/admin/medias/:id [delete]
|
||||
// @Bind id path
|
||||
func (ctl *medias) Delete(ctx fiber.Ctx, id int64) error {
|
||||
media, err := models.Medias.GetByID(ctx.Context(), id)
|
||||
if err != nil {
|
||||
return ctx.SendString("Media not found")
|
||||
}
|
||||
|
||||
if err := ctl.oss.Delete(ctx.Context(), media.Path); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := models.Medias.Delete(ctx.Context(), id); err != nil {
|
||||
return err
|
||||
}
|
||||
return ctx.SendStatus(fiber.StatusNoContent)
|
||||
}
|
||||
|
||||
@@ -23,7 +23,32 @@ type posts struct{}
|
||||
// @Bind query query
|
||||
func (ctl *posts) List(ctx fiber.Ctx, pagination *requests.Pagination, query *ListQuery) (*requests.Pager, error) {
|
||||
cond := models.Posts.BuildConditionWithKey(query.Keyword)
|
||||
return models.Posts.List(ctx.Context(), pagination, cond)
|
||||
pager, err := models.Posts.List(ctx.Context(), pagination, cond)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
postIds := lo.Map(pager.Items.([]model.Posts), func(item model.Posts, _ int) int64 {
|
||||
return item.ID
|
||||
})
|
||||
if len(postIds) > 0 {
|
||||
postCntMap, err := models.Posts.BoughtStatistics(ctx.Context(), postIds)
|
||||
if err != nil {
|
||||
return pager, err
|
||||
}
|
||||
|
||||
items := lo.Map(pager.Items.([]model.Posts), func(item model.Posts, _ int) PostItem {
|
||||
cnt := int64(0)
|
||||
if v, ok := postCntMap[item.ID]; ok {
|
||||
cnt = v
|
||||
}
|
||||
|
||||
return PostItem{Posts: &item, BoughtCount: cnt}
|
||||
})
|
||||
|
||||
pager.Items = items
|
||||
}
|
||||
return pager, err
|
||||
}
|
||||
|
||||
type PostForm struct {
|
||||
@@ -142,7 +167,8 @@ func (ctl *posts) Delete(ctx fiber.Ctx, id int64) error {
|
||||
|
||||
type PostItem struct {
|
||||
*model.Posts
|
||||
Medias []*model.Medias `json:"medias"`
|
||||
Medias []*model.Medias `json:"medias"`
|
||||
BoughtCount int64 `json:"bought_count"`
|
||||
}
|
||||
|
||||
// Show posts by id
|
||||
@@ -165,3 +191,22 @@ func (ctl *posts) Show(ctx fiber.Ctx, id int64) (*PostItem, error) {
|
||||
Medias: medias,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// SendTo
|
||||
// @Router /v1/admin/posts/:id/send-to/:userId [post]
|
||||
// @Bind id path
|
||||
// @Bind userId path
|
||||
func (ctl *posts) SendTo(ctx fiber.Ctx, id, userId int64) error {
|
||||
if _, err := models.Posts.GetByID(ctx.Context(), id); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := models.Users.GetByID(ctx.Context(), userId); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := models.Posts.SendTo(ctx.Context(), id, userId); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -50,6 +50,11 @@ func (r *Routes) Register(router fiber.Router) {
|
||||
PathParam[int64]("id"),
|
||||
))
|
||||
|
||||
router.Delete("/v1/admin/medias/:id", Func1(
|
||||
r.medias.Delete,
|
||||
PathParam[int64]("id"),
|
||||
))
|
||||
|
||||
// 注册路由组: orders
|
||||
router.Get("/v1/admin/orders", DataFunc2(
|
||||
r.orders.List,
|
||||
@@ -85,6 +90,12 @@ func (r *Routes) Register(router fiber.Router) {
|
||||
PathParam[int64]("id"),
|
||||
))
|
||||
|
||||
router.Post("/v1/admin/posts/:id/send-to/:userId", Func2(
|
||||
r.posts.SendTo,
|
||||
PathParam[int64]("id"),
|
||||
PathParam[int64]("userId"),
|
||||
))
|
||||
|
||||
// 注册路由组: uploads
|
||||
router.Get("/v1/admin/uploads/pre-uploaded-check/:md5.:ext", DataFunc3(
|
||||
r.uploads.PreUploadCheck,
|
||||
|
||||
@@ -14,6 +14,7 @@ import (
|
||||
"github.com/gofiber/fiber/v3"
|
||||
"github.com/gofiber/fiber/v3/log"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/samber/lo"
|
||||
)
|
||||
|
||||
type ListQuery struct {
|
||||
@@ -25,6 +26,11 @@ type posts struct {
|
||||
wepay *wepay.Client
|
||||
}
|
||||
|
||||
type PostItem struct {
|
||||
model.Posts
|
||||
BoughtCount int64 `json:"bought_count"`
|
||||
}
|
||||
|
||||
// List posts
|
||||
// @Router /api/posts [get]
|
||||
// @Bind pagination query
|
||||
@@ -32,11 +38,34 @@ type posts struct {
|
||||
// @Bind user local
|
||||
func (ctl *posts) List(ctx fiber.Ctx, pagination *requests.Pagination, query *ListQuery, user *model.Users) (*requests.Pager, error) {
|
||||
cond := models.Posts.BuildConditionWithKey(query.Keyword)
|
||||
return models.Posts.List(ctx.Context(), pagination, cond, func(item model.Posts) model.Posts {
|
||||
pager, err := models.Posts.List(ctx.Context(), pagination, cond, func(item model.Posts) model.Posts {
|
||||
item.Assets = fields.ToJson([]fields.MediaAsset{})
|
||||
item.Content = ""
|
||||
return item
|
||||
})
|
||||
|
||||
postIds := lo.Map(pager.Items.([]model.Posts), func(item model.Posts, _ int) int64 {
|
||||
return item.ID
|
||||
})
|
||||
if len(postIds) > 0 {
|
||||
postCntMap, err := models.Posts.BoughtStatistics(ctx.Context(), postIds)
|
||||
if err != nil {
|
||||
return pager, err
|
||||
}
|
||||
|
||||
items := lo.Map(pager.Items.([]model.Posts), func(item model.Posts, _ int) PostItem {
|
||||
cnt := int64(0)
|
||||
if v, ok := postCntMap[item.ID]; ok {
|
||||
cnt = v
|
||||
}
|
||||
|
||||
return PostItem{Posts: item, BoughtCount: cnt}
|
||||
})
|
||||
|
||||
pager.Items = items
|
||||
}
|
||||
|
||||
return pager, err
|
||||
}
|
||||
|
||||
// Show
|
||||
|
||||
@@ -198,3 +198,20 @@ func (m *mediasModel) GetByID(ctx context.Context, id int64) (*model.Medias, err
|
||||
|
||||
return &media, nil
|
||||
}
|
||||
|
||||
// Delete
|
||||
func (m *mediasModel) Delete(ctx context.Context, id int64) error {
|
||||
tbl := table.Medias
|
||||
stmt := tbl.
|
||||
DELETE().
|
||||
WHERE(tbl.ID.EQ(Int64(id)))
|
||||
m.log.Infof("sql: %s", stmt.DebugSql())
|
||||
|
||||
if _, err := stmt.ExecContext(ctx, db); err != nil {
|
||||
m.log.Errorf("error deleting media item: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
m.log.Infof("media item deleted successfully")
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -233,3 +233,56 @@ func (m *postsModel) DeleteByID(ctx context.Context, id int64) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// SendTo
|
||||
func (m *postsModel) SendTo(ctx context.Context, userId, postId int64) error {
|
||||
// add record to user_posts
|
||||
tbl := table.UserPosts
|
||||
stmt := tbl.INSERT(tbl.MutableColumns).MODEL(model.UserPosts{
|
||||
UserID: userId,
|
||||
PostID: postId,
|
||||
})
|
||||
m.log.Infof("sql: %s", stmt.DebugSql())
|
||||
if _, err := stmt.ExecContext(ctx, db); err != nil {
|
||||
m.log.Errorf("error sending post to user: %v", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// PostBoughtStatistics 获取指定文件 ID 的购买次数
|
||||
func (m *postsModel) BoughtStatistics(ctx context.Context, postIds []int64) (map[int64]int64, error) {
|
||||
tbl := table.UserPosts
|
||||
|
||||
// select count(user_id), post_id from user_posts up where post_id in (1, 2,3,4,5,6,7,8,9,10) group by post_id
|
||||
stmt := tbl.
|
||||
SELECT(
|
||||
COUNT(tbl.UserID).AS("cnt"),
|
||||
tbl.PostID.AS("post_id"),
|
||||
).
|
||||
WHERE(
|
||||
tbl.PostID.IN(lo.Map(postIds, func(id int64, _ int) Expression { return Int64(id) })...),
|
||||
).
|
||||
GROUP_BY(
|
||||
tbl.PostID,
|
||||
)
|
||||
m.log.Infof("sql: %s", stmt.DebugSql())
|
||||
|
||||
var result []struct {
|
||||
Cnt int64
|
||||
PostId int64
|
||||
}
|
||||
|
||||
if err := stmt.QueryContext(ctx, db, &result); err != nil {
|
||||
m.log.Errorf("error getting post bought statistics: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// convert to map
|
||||
resultMap := make(map[int64]int64)
|
||||
for _, item := range result {
|
||||
resultMap[item.PostId] = item.Cnt
|
||||
}
|
||||
|
||||
return resultMap, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user