package admin import ( "quyun/v2/app/requests" "quyun/v2/app/services" "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{} // List posts // // @Router /admin/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{ models.PostQuery.Title.Like(*query.Keyword), } pager, err := services.Posts.List(ctx, pagination, conds...) if err != nil { return nil, err } postIds := lo.Map(pager.Items.([]models.Post), func(item models.Post, _ int) int64 { return item.ID }) if len(postIds) > 0 { postCntMap, err := services.Posts.BoughtStatistics(ctx, postIds) if err != nil { return pager, err } items := lo.Map(pager.Items.([]models.Post), func(item models.Post, _ int) PostItem { cnt := int64(0) if v, ok := postCntMap[item.ID]; ok { cnt = v } return PostItem{Post: &item, BoughtCount: cnt} }) pager.Items = items } return pager, err } type PostForm struct { Title string `json:"title"` HeadImages []int64 `json:"head_images"` Price int64 `json:"price"` Discount int16 `json:"discount"` Introduction string `json:"introduction"` Medias []int64 `json:"medias"` Status fields.PostStatus `json:"status"` Content string `json:"content"` } // Create // // @Router /admin/posts [post] // @Bind form body func (ctl *posts) Create(ctx fiber.Ctx, form *PostForm) error { post := models.Post{ Title: form.Title, HeadImages: types.NewJSONType(form.HeadImages), Price: form.Price, Discount: form.Discount, Description: form.Introduction, Status: form.Status, Content: form.Content, Tags: types.NewJSONType([]string{}), Assets: types.NewJSONType([]fields.MediaAsset{}), } if form.Medias != nil { medias, err := services.Medias.GetByIds(ctx, form.Medias) if err != nil { return err } assets := lo.Map(medias, func(media *models.Media, _ int) fields.MediaAsset { return fields.MediaAsset{ Type: media.MimeType, Media: media.ID, Metas: lo.ToPtr(media.Metas.Data()), } }) post.Assets = types.NewJSONType(assets) } if err := post.Create(ctx); err != nil { return err } return nil } // Update posts // // @Router /admin/posts/:id [put] // @Bind id path // @Bind form body func (ctl *posts) Update(ctx fiber.Ctx, id int64, form *PostForm) error { post, err := services.Posts.FindByID(ctx, id) if err != nil { return err } post.Title = form.Title post.HeadImages = types.NewJSONType(form.HeadImages) post.Price = form.Price post.Discount = form.Discount post.Description = form.Introduction post.Status = form.Status post.Content = form.Content post.Tags = types.NewJSONType([]string{}) if form.Medias != nil { medias, err := services.Medias.GetByIds(ctx, form.Medias) if err != nil { return err } assets := lo.Map(medias, func(media *models.Media, _ int) fields.MediaAsset { return fields.MediaAsset{ Type: media.MimeType, Media: media.ID, Metas: lo.ToPtr(media.Metas.Data()), } }) post.Assets = types.NewJSONType(assets) } if _, err := post.Update(ctx); err != nil { return err } return nil } // Delete posts // // @Router /admin/posts/:id [delete] // @Bind id path func (ctl *posts) Delete(ctx fiber.Ctx, id int64) error { post, err := services.Posts.FindByID(ctx, id) if err != nil { return err } if post == nil { return fiber.ErrNotFound } if _, err := post.ForceDelete(ctx); err != nil { return err } return nil } type PostItem struct { *models.Post Medias []*models.Media `json:"medias"` BoughtCount int64 `json:"bought_count"` } // Show posts by id // // @Router /admin/posts/:id [get] // @Bind id path func (ctl *posts) Show(ctx fiber.Ctx, id int64) (*PostItem, error) { post, err := services.Posts.FindByID(ctx, id) if err != nil { return nil, err } medias, err := services.Medias.GetByIds(ctx, lo.Map(post.Assets.Data(), func(asset fields.MediaAsset, _ int) int64 { return asset.Media })) if err != nil { return nil, err } return &PostItem{ Post: post, Medias: medias, }, nil } // SendTo // // @Router /admin/posts/:id/send-to/:userId [post] // @Bind id path // @Bind userId path func (ctl *posts) SendTo(ctx fiber.Ctx, id, userId int64) error { post, err := services.Posts.FindByID(ctx, id) if err != nil { return err } user, err := services.Users.FindByID(ctx, userId) if err != nil { return err } if err := services.Posts.SendTo(ctx, post.ID, user.ID); err != nil { return err } return nil }