This commit is contained in:
@@ -22,14 +22,14 @@ type TokenResponse struct {
|
||||
|
||||
// Login
|
||||
//
|
||||
// @Summary 管理员登录
|
||||
// @Tags Admin Auth
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param body body AuthBody true "请求体"
|
||||
// @Success 200 {object} TokenResponse "成功"
|
||||
// @Router /admin/auth [post]
|
||||
// @Bind body body
|
||||
// @Summary 管理员登录
|
||||
// @Tags Admin Auth
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param body body AuthBody true "请求体"
|
||||
// @Success 200 {object} TokenResponse "成功"
|
||||
// @Router /admin/auth [post]
|
||||
// @Bind body body
|
||||
func (ctl *auth) Login(ctx fiber.Ctx, body *AuthBody) (*TokenResponse, error) {
|
||||
if body.Username == "pl.yang" && body.Password == "Xixi@0202" {
|
||||
claim := ctl.jwt.CreateClaims(jwt.BaseClaims{
|
||||
|
||||
@@ -17,28 +17,28 @@ type medias struct {
|
||||
|
||||
// List medias
|
||||
//
|
||||
// @Summary 媒体列表
|
||||
// @Tags Admin Medias
|
||||
// @Produce json
|
||||
// @Param pagination query requests.Pagination false "分页参数"
|
||||
// @Param query query ListQuery false "筛选条件"
|
||||
// @Success 200 {object} requests.Pager{items=models.Media} "成功"
|
||||
// @Router /admin/medias [get]
|
||||
// @Bind pagination query
|
||||
// @Bind query query
|
||||
// @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/medias [get]
|
||||
// @Bind pagination query
|
||||
// @Bind query query
|
||||
func (ctl *medias) List(ctx fiber.Ctx, pagination *requests.Pagination, query *ListQuery) (*requests.Pager, error) {
|
||||
return services.Media.List(ctx, pagination, models.MediaQuery.Name.Like(database.WrapLike(*query.Keyword)))
|
||||
return services.Media.List(ctx, pagination, models.MediumQuery.Name.Like(database.WrapLike(*query.Keyword)))
|
||||
}
|
||||
|
||||
// Show media
|
||||
//
|
||||
// @Summary 媒体预览(跳转到签名 URL)
|
||||
// @Tags Admin Medias
|
||||
// @Param id path int64 true "媒体 ID"
|
||||
// @Success 302 {string} string "跳转"
|
||||
// @Router /admin/medias/:id [get]
|
||||
// @Bind media path key(id) model(id)
|
||||
func (ctl *medias) Show(ctx fiber.Ctx, media *models.Media) error {
|
||||
// @Summary 媒体预览(跳转到签名 URL)
|
||||
// @Tags Admin Medias
|
||||
// @Param id path int64 true "媒体 ID"
|
||||
// @Success 302 {string} string "跳转"
|
||||
// @Router /admin/medias/:id [get]
|
||||
// @Bind media path key(id) model(id)
|
||||
func (ctl *medias) Show(ctx fiber.Ctx, media *models.Medium) error {
|
||||
url, err := ctl.oss.GetSignedUrl(ctx, media.Path)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -49,14 +49,14 @@ func (ctl *medias) Show(ctx fiber.Ctx, media *models.Media) error {
|
||||
|
||||
// Delete
|
||||
//
|
||||
// @Summary 删除媒体
|
||||
// @Tags Admin Medias
|
||||
// @Produce json
|
||||
// @Param id path int64 true "媒体 ID"
|
||||
// @Success 204 {object} any "成功"
|
||||
// @Router /admin/medias/:id [delete]
|
||||
// @Bind media path key(id) model(id)
|
||||
func (ctl *medias) Delete(ctx fiber.Ctx, media *models.Media) error {
|
||||
// @Summary 删除媒体
|
||||
// @Tags Admin Medias
|
||||
// @Produce json
|
||||
// @Param id path int64 true "媒体 ID"
|
||||
// @Success 204 {object} any "成功"
|
||||
// @Router /admin/medias/:id [delete]
|
||||
// @Bind media path key(id) model(id)
|
||||
func (ctl *medias) Delete(ctx fiber.Ctx, media *models.Medium) error {
|
||||
if err := ctl.oss.Delete(ctx, media.Path); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -19,15 +19,15 @@ type orders struct{}
|
||||
|
||||
// List
|
||||
//
|
||||
// @Summary 订单列表
|
||||
// @Tags Admin Orders
|
||||
// @Produce json
|
||||
// @Param pagination query requests.Pagination false "分页参数"
|
||||
// @Param query query OrderListQuery false "筛选条件"
|
||||
// @Success 200 {object} requests.Pager{items=services.OrderListItem} "成功"
|
||||
// @Router /admin/orders [get]
|
||||
// @Bind pagination query
|
||||
// @Bind query query
|
||||
// @Summary 订单列表
|
||||
// @Tags Admin Orders
|
||||
// @Produce json
|
||||
// @Param pagination query requests.Pagination false "分页参数"
|
||||
// @Param query query OrderListQuery false "筛选条件"
|
||||
// @Success 200 {object} requests.Pager{items=services.OrderListItem} "成功"
|
||||
// @Router /admin/orders [get]
|
||||
// @Bind pagination query
|
||||
// @Bind query query
|
||||
func (ctl *orders) List(
|
||||
ctx fiber.Ctx,
|
||||
pagination *requests.Pagination,
|
||||
@@ -47,13 +47,13 @@ func (ctl *orders) List(
|
||||
|
||||
// Refund
|
||||
//
|
||||
// @Summary 订单退款
|
||||
// @Tags Admin Orders
|
||||
// @Produce json
|
||||
// @Param id path int64 true "订单 ID"
|
||||
// @Success 200 {object} any "成功"
|
||||
// @Router /admin/orders/:id/refund [post]
|
||||
// @Bind order path key(id) model(id)
|
||||
// @Summary 订单退款
|
||||
// @Tags Admin Orders
|
||||
// @Produce json
|
||||
// @Param id path int64 true "订单 ID"
|
||||
// @Success 200 {object} any "成功"
|
||||
// @Router /admin/orders/:id/refund [post]
|
||||
// @Bind order path key(id) model(id)
|
||||
func (ctl *orders) Refund(ctx fiber.Ctx, order *models.Order) error {
|
||||
return services.Orders.Refund(ctx, order)
|
||||
}
|
||||
|
||||
@@ -21,15 +21,15 @@ type posts struct{}
|
||||
|
||||
// List posts
|
||||
//
|
||||
// @Summary 作品列表
|
||||
// @Tags Admin Posts
|
||||
// @Produce json
|
||||
// @Param pagination query requests.Pagination false "分页参数"
|
||||
// @Param query query ListQuery false "筛选条件"
|
||||
// @Success 200 {object} requests.Pager{items=PostItem} "成功"
|
||||
// @Router /admin/posts [get]
|
||||
// @Bind pagination query
|
||||
// @Bind query query
|
||||
// @Summary 作品列表
|
||||
// @Tags Admin Posts
|
||||
// @Produce json
|
||||
// @Param pagination query requests.Pagination false "分页参数"
|
||||
// @Param query query ListQuery false "筛选条件"
|
||||
// @Success 200 {object} requests.Pager{items=PostItem} "成功"
|
||||
// @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),
|
||||
@@ -75,14 +75,14 @@ type PostForm struct {
|
||||
|
||||
// Create
|
||||
//
|
||||
// @Summary 创建作品
|
||||
// @Tags Admin Posts
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param form body PostForm true "请求体"
|
||||
// @Success 200 {object} any "成功"
|
||||
// @Router /admin/posts [post]
|
||||
// @Bind form body
|
||||
// @Summary 创建作品
|
||||
// @Tags Admin Posts
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param form body PostForm true "请求体"
|
||||
// @Success 200 {object} any "成功"
|
||||
// @Router /admin/posts [post]
|
||||
// @Bind form body
|
||||
func (ctl *posts) Create(ctx fiber.Ctx, form *PostForm) error {
|
||||
post := models.Post{
|
||||
Title: form.Title,
|
||||
@@ -101,7 +101,7 @@ func (ctl *posts) Create(ctx fiber.Ctx, form *PostForm) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
assets := lo.Map(medias, func(media *models.Media, _ int) fields.MediaAsset {
|
||||
assets := lo.Map(medias, func(media *models.Medium, _ int) fields.MediaAsset {
|
||||
return fields.MediaAsset{
|
||||
Type: media.MimeType,
|
||||
Media: media.ID,
|
||||
@@ -119,16 +119,16 @@ func (ctl *posts) Create(ctx fiber.Ctx, form *PostForm) error {
|
||||
|
||||
// Update posts
|
||||
//
|
||||
// @Summary 更新作品
|
||||
// @Tags Admin Posts
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path int64 true "作品 ID"
|
||||
// @Param form body PostForm true "请求体"
|
||||
// @Success 200 {object} any "成功"
|
||||
// @Router /admin/posts/:id [put]
|
||||
// @Bind post path key(id) model(id)
|
||||
// @Bind form body
|
||||
// @Summary 更新作品
|
||||
// @Tags Admin Posts
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path int64 true "作品 ID"
|
||||
// @Param form body PostForm true "请求体"
|
||||
// @Success 200 {object} any "成功"
|
||||
// @Router /admin/posts/:id [put]
|
||||
// @Bind post path key(id) model(id)
|
||||
// @Bind form body
|
||||
func (ctl *posts) Update(ctx fiber.Ctx, post *models.Post, form *PostForm) error {
|
||||
post.Title = form.Title
|
||||
post.HeadImages = types.NewJSONType(form.HeadImages)
|
||||
@@ -144,7 +144,7 @@ func (ctl *posts) Update(ctx fiber.Ctx, post *models.Post, form *PostForm) error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
assets := lo.Map(medias, func(media *models.Media, _ int) fields.MediaAsset {
|
||||
assets := lo.Map(medias, func(media *models.Medium, _ int) fields.MediaAsset {
|
||||
return fields.MediaAsset{
|
||||
Type: media.MimeType,
|
||||
Media: media.ID,
|
||||
@@ -162,13 +162,13 @@ func (ctl *posts) Update(ctx fiber.Ctx, post *models.Post, form *PostForm) error
|
||||
|
||||
// Delete posts
|
||||
//
|
||||
// @Summary 删除作品
|
||||
// @Tags Admin Posts
|
||||
// @Produce json
|
||||
// @Param id path int64 true "作品 ID"
|
||||
// @Success 204 {object} any "成功"
|
||||
// @Router /admin/posts/:id [delete]
|
||||
// @Bind post path key(id) model(id)
|
||||
// @Summary 删除作品
|
||||
// @Tags Admin Posts
|
||||
// @Produce json
|
||||
// @Param id path int64 true "作品 ID"
|
||||
// @Success 204 {object} any "成功"
|
||||
// @Router /admin/posts/:id [delete]
|
||||
// @Bind post path key(id) model(id)
|
||||
func (ctl *posts) Delete(ctx fiber.Ctx, post *models.Post) error {
|
||||
if _, err := post.ForceDelete(ctx); err != nil {
|
||||
return err
|
||||
@@ -178,19 +178,19 @@ func (ctl *posts) Delete(ctx fiber.Ctx, post *models.Post) error {
|
||||
|
||||
type PostItem struct {
|
||||
*models.Post
|
||||
Medias []*models.Media `json:"medias"`
|
||||
BoughtCount int64 `json:"bought_count"`
|
||||
Medias []*models.Medium `json:"medias"`
|
||||
BoughtCount int64 `json:"bought_count"`
|
||||
}
|
||||
|
||||
// Show posts by id
|
||||
//
|
||||
// @Summary 作品详情
|
||||
// @Tags Admin Posts
|
||||
// @Produce json
|
||||
// @Param id path int64 true "作品 ID"
|
||||
// @Success 200 {object} PostItem "成功"
|
||||
// @Router /admin/posts/:id [get]
|
||||
// @Bind post path key(id) model(id)
|
||||
// @Summary 作品详情
|
||||
// @Tags Admin Posts
|
||||
// @Produce json
|
||||
// @Param id path int64 true "作品 ID"
|
||||
// @Success 200 {object} PostItem "成功"
|
||||
// @Router /admin/posts/:id [get]
|
||||
// @Bind post path key(id) model(id)
|
||||
func (ctl *posts) Show(ctx fiber.Ctx, post *models.Post) (*PostItem, error) {
|
||||
medias, err := services.Media.GetByIds(ctx, lo.Map(post.Assets.Data(), func(asset fields.MediaAsset, _ int) int64 {
|
||||
return asset.Media
|
||||
@@ -206,15 +206,15 @@ func (ctl *posts) Show(ctx fiber.Ctx, post *models.Post) (*PostItem, error) {
|
||||
|
||||
// SendTo
|
||||
//
|
||||
// @Summary 赠送作品给用户
|
||||
// @Tags Admin Posts
|
||||
// @Produce json
|
||||
// @Param id path int64 true "作品 ID"
|
||||
// @Param userId path int64 true "用户 ID"
|
||||
// @Success 200 {object} any "成功"
|
||||
// @Router /admin/posts/:id/send-to/:userId [post]
|
||||
// @Bind post path key(id) model(id)
|
||||
// @Bind user path key(userId) model(id)
|
||||
// @Summary 赠送作品给用户
|
||||
// @Tags Admin Posts
|
||||
// @Produce json
|
||||
// @Param id path int64 true "作品 ID"
|
||||
// @Param userId path int64 true "用户 ID"
|
||||
// @Success 200 {object} any "成功"
|
||||
// @Router /admin/posts/:id/send-to/:userId [post]
|
||||
// @Bind post path key(id) model(id)
|
||||
// @Bind user path key(userId) model(id)
|
||||
func (ctl *posts) SendTo(ctx fiber.Ctx, post *models.Post, user *models.User) error {
|
||||
if err := services.Posts.SendTo(ctx, post.ID, user.ID); err != nil {
|
||||
return err
|
||||
|
||||
@@ -5,11 +5,12 @@
|
||||
package admin
|
||||
|
||||
import (
|
||||
"go.ipao.vip/gen/field"
|
||||
"quyun/v2/app/middlewares"
|
||||
"quyun/v2/app/requests"
|
||||
"quyun/v2/database/models"
|
||||
|
||||
"go.ipao.vip/gen/field"
|
||||
|
||||
"github.com/gofiber/fiber/v3"
|
||||
log "github.com/sirupsen/logrus"
|
||||
_ "go.ipao.vip/atom"
|
||||
@@ -20,7 +21,7 @@ import (
|
||||
// Routes implements the HttpRoute contract and provides route registration
|
||||
// for all controllers in the admin module.
|
||||
//
|
||||
// @provider contracts.HttpRoute atom.GroupRoutes
|
||||
// @provider contracts.HttpRoute atom.GroupRoutes
|
||||
type Routes struct {
|
||||
log *log.Entry `inject:"false"`
|
||||
middlewares *middlewares.Middlewares
|
||||
@@ -59,9 +60,9 @@ func (r *Routes) Register(router fiber.Router) {
|
||||
r.log.Debugf("Registering route: Delete /admin/medias/:id -> medias.Delete")
|
||||
router.Delete("/admin/medias/:id"[len(r.Path()):], Func1(
|
||||
r.medias.Delete,
|
||||
func(ctx fiber.Ctx) (*models.Media, error) {
|
||||
func(ctx fiber.Ctx) (*models.Medium, error) {
|
||||
v := fiber.Params[int](ctx, "id")
|
||||
return models.MediaQuery.WithContext(ctx).Where(field.NewUnsafeFieldRaw("id = ?", v)).First()
|
||||
return models.MediumQuery.WithContext(ctx).Where(field.NewUnsafeFieldRaw("id = ?", v)).First()
|
||||
},
|
||||
))
|
||||
r.log.Debugf("Registering route: Get /admin/medias -> medias.List")
|
||||
@@ -73,9 +74,9 @@ func (r *Routes) Register(router fiber.Router) {
|
||||
r.log.Debugf("Registering route: Get /admin/medias/:id -> medias.Show")
|
||||
router.Get("/admin/medias/:id"[len(r.Path()):], Func1(
|
||||
r.medias.Show,
|
||||
func(ctx fiber.Ctx) (*models.Media, error) {
|
||||
func(ctx fiber.Ctx) (*models.Medium, error) {
|
||||
v := fiber.Params[int](ctx, "id")
|
||||
return models.MediaQuery.WithContext(ctx).Where(field.NewUnsafeFieldRaw("id = ?", v)).First()
|
||||
return models.MediumQuery.WithContext(ctx).Where(field.NewUnsafeFieldRaw("id = ?", v)).First()
|
||||
},
|
||||
))
|
||||
// Register routes for controller: orders
|
||||
|
||||
@@ -22,11 +22,11 @@ type StatisticsResponse struct {
|
||||
|
||||
// dashboard statistics
|
||||
//
|
||||
// @Summary 仪表盘统计
|
||||
// @Tags Admin Statistics
|
||||
// @Produce json
|
||||
// @Success 200 {object} StatisticsResponse "成功"
|
||||
// @Router /admin/statistics [get]
|
||||
// @Summary 仪表盘统计
|
||||
// @Tags Admin Statistics
|
||||
// @Produce json
|
||||
// @Success 200 {object} StatisticsResponse "成功"
|
||||
// @Router /admin/statistics [get]
|
||||
func (s *statistics) statistics(ctx fiber.Ctx) (*StatisticsResponse, error) {
|
||||
statistics := &StatisticsResponse{}
|
||||
|
||||
|
||||
@@ -34,17 +34,17 @@ type PreCheckResp struct {
|
||||
|
||||
// PreUploadCheck
|
||||
//
|
||||
// @Summary 预上传检查
|
||||
// @Tags Admin Uploads
|
||||
// @Produce json
|
||||
// @Param md5 path string true "文件 MD5"
|
||||
// @Param ext path string true "文件扩展名(不含点)"
|
||||
// @Param mime query string true "文件 MIME 类型"
|
||||
// @Success 200 {object} PreCheckResp "成功"
|
||||
// @Router /admin/uploads/pre-uploaded-check/:md5.:ext [get]
|
||||
// @Bind md5 path
|
||||
// @Bind ext path
|
||||
// @Bind mime query
|
||||
// @Summary 预上传检查
|
||||
// @Tags Admin Uploads
|
||||
// @Produce json
|
||||
// @Param md5 path string true "文件 MD5"
|
||||
// @Param ext path string true "文件扩展名(不含点)"
|
||||
// @Param mime query string true "文件 MIME 类型"
|
||||
// @Success 200 {object} PreCheckResp "成功"
|
||||
// @Router /admin/uploads/pre-uploaded-check/:md5.:ext [get]
|
||||
// @Bind md5 path
|
||||
// @Bind ext path
|
||||
// @Bind mime query
|
||||
func (up *uploads) PreUploadCheck(ctx fiber.Ctx, md5, ext, mime string) (*PreCheckResp, error) {
|
||||
_, err := services.Media.GetByHash(ctx, md5)
|
||||
if err != nil && errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
@@ -68,21 +68,21 @@ type PostUploadedForm struct {
|
||||
|
||||
// PostUploadedAction
|
||||
//
|
||||
// @Summary 上传完成回调处理
|
||||
// @Tags Admin Uploads
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param body body PostUploadedForm true "请求体"
|
||||
// @Success 200 {object} any "成功"
|
||||
// @Router /admin/uploads/post-uploaded-action [post]
|
||||
// @Bind body body
|
||||
// @Summary 上传完成回调处理
|
||||
// @Tags Admin Uploads
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param body body PostUploadedForm true "请求体"
|
||||
// @Success 200 {object} any "成功"
|
||||
// @Router /admin/uploads/post-uploaded-action [post]
|
||||
// @Bind body body
|
||||
func (up *uploads) PostUploadedAction(ctx fiber.Ctx, body *PostUploadedForm) error {
|
||||
m, err := services.Media.GetByHash(ctx, body.Md5)
|
||||
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return err
|
||||
}
|
||||
|
||||
m = &models.Media{
|
||||
m = &models.Medium{
|
||||
Name: body.OriginalName,
|
||||
MimeType: body.MimeType,
|
||||
Size: body.Size,
|
||||
|
||||
@@ -19,15 +19,15 @@ type users struct{}
|
||||
|
||||
// List users
|
||||
//
|
||||
// @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/users [get]
|
||||
// @Bind pagination query
|
||||
// @Bind query query
|
||||
// @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/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{
|
||||
models.UserQuery.Username.Like(database.WrapLike(*query.Keyword)),
|
||||
@@ -37,28 +37,28 @@ func (ctl *users) List(ctx fiber.Ctx, pagination *requests.Pagination, query *Us
|
||||
|
||||
// Show user
|
||||
//
|
||||
// @Summary 用户详情
|
||||
// @Tags Admin Users
|
||||
// @Produce json
|
||||
// @Param id path int64 true "用户 ID"
|
||||
// @Success 200 {object} models.User "成功"
|
||||
// @Router /admin/users/:id [get]
|
||||
// @Bind user path key(id) model(id)
|
||||
// @Summary 用户详情
|
||||
// @Tags Admin Users
|
||||
// @Produce json
|
||||
// @Param id path int64 true "用户 ID"
|
||||
// @Success 200 {object} models.User "成功"
|
||||
// @Router /admin/users/:id [get]
|
||||
// @Bind user path key(id) model(id)
|
||||
func (ctl *users) Show(ctx fiber.Ctx, user *models.User) (*models.User, error) {
|
||||
return user, nil
|
||||
}
|
||||
|
||||
// Articles show user bought articles
|
||||
//
|
||||
// @Summary 用户已购作品
|
||||
// @Tags Admin Users
|
||||
// @Produce json
|
||||
// @Param id path int64 true "用户 ID"
|
||||
// @Param pagination query requests.Pagination false "分页参数"
|
||||
// @Success 200 {object} requests.Pager{items=models.Post} "成功"
|
||||
// @Router /admin/users/:id/articles [get]
|
||||
// @Bind user path key(id) model(id)
|
||||
// @Bind pagination query
|
||||
// @Summary 用户已购作品
|
||||
// @Tags Admin Users
|
||||
// @Produce json
|
||||
// @Param id path int64 true "用户 ID"
|
||||
// @Param pagination query requests.Pagination false "分页参数"
|
||||
// @Success 200 {object} requests.Pager{items=models.Post} "成功"
|
||||
// @Router /admin/users/:id/articles [get]
|
||||
// @Bind user path key(id) model(id)
|
||||
// @Bind pagination query
|
||||
func (ctl *users) Articles(ctx fiber.Ctx, user *models.User, pagination *requests.Pagination) (*requests.Pager, error) {
|
||||
return services.Posts.Bought(ctx, user.ID, pagination)
|
||||
}
|
||||
@@ -69,16 +69,16 @@ type UserBalance struct {
|
||||
|
||||
// Balance
|
||||
//
|
||||
// @Summary 调整用户余额
|
||||
// @Tags Admin Users
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path int64 true "用户 ID"
|
||||
// @Param balance body UserBalance true "请求体"
|
||||
// @Success 200 {object} any "成功"
|
||||
// @Router /admin/users/:id/balance [post]
|
||||
// @Bind user path key(id) model(id)
|
||||
// @Bind balance body
|
||||
// @Summary 调整用户余额
|
||||
// @Tags Admin Users
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path int64 true "用户 ID"
|
||||
// @Param balance body UserBalance true "请求体"
|
||||
// @Success 200 {object} any "成功"
|
||||
// @Router /admin/users/:id/balance [post]
|
||||
// @Bind user path key(id) model(id)
|
||||
// @Bind balance body
|
||||
func (ctl *users) Balance(ctx fiber.Ctx, user *models.User, balance *UserBalance) error {
|
||||
return services.Users.AddBalance(ctx, user.ID, balance.Balance)
|
||||
}
|
||||
|
||||
34
backend_v1/app/http/auth.go
Normal file
34
backend_v1/app/http/auth.go
Normal file
@@ -0,0 +1,34 @@
|
||||
package http
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
"errors"
|
||||
|
||||
"quyun/v2/app/services"
|
||||
|
||||
"github.com/gofiber/fiber/v3"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// @provider
|
||||
type auth struct{}
|
||||
|
||||
// Phone
|
||||
//
|
||||
// @Summary 手机验证
|
||||
// @Tags Auth
|
||||
// @Produce json
|
||||
// @Success 200 {object} requests.Pager{items=PostItem} "成功"
|
||||
// @Router /v1/auth/:phone [post]
|
||||
// @Bind phone path
|
||||
func (ctl *posts) Phone(ctx fiber.Ctx, phone string) error {
|
||||
_, err := services.Users.FindByPhone(ctx, phone)
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return errors.New("手机号未注册,请联系管理员开通")
|
||||
}
|
||||
return err
|
||||
}
|
||||
// TODO: send sms
|
||||
return nil
|
||||
}
|
||||
@@ -36,16 +36,16 @@ type posts struct {
|
||||
|
||||
// List posts
|
||||
//
|
||||
// @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 [get]
|
||||
// @Bind pagination query
|
||||
// @Bind query query
|
||||
// @Bind user local
|
||||
// @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 [get]
|
||||
// @Bind pagination query
|
||||
// @Bind query query
|
||||
// @Bind user local
|
||||
func (ctl *posts) List(
|
||||
ctx fiber.Ctx,
|
||||
pagination *requests.Pagination,
|
||||
@@ -81,7 +81,7 @@ func (ctl *posts) List(
|
||||
log.Errorf("GetMediaByIds err: %v", err)
|
||||
return PostItem{}, false
|
||||
}
|
||||
mediaUrls := lo.FilterMap(medias, func(item *models.Media, _ int) (string, bool) {
|
||||
mediaUrls := lo.FilterMap(medias, func(item *models.Medium, _ int) (string, bool) {
|
||||
url, err := ctl.oss.GetSignedUrl(ctx, item.Path)
|
||||
if err != nil {
|
||||
log.WithError(err).Errorf("head image GetSignedUrl err: %v", err)
|
||||
@@ -131,14 +131,14 @@ type PostItem struct {
|
||||
|
||||
// Show
|
||||
//
|
||||
// @Summary 作品详情
|
||||
// @Tags Posts
|
||||
// @Produce json
|
||||
// @Param id path int64 true "作品 ID"
|
||||
// @Success 200 {object} PostItem "成功"
|
||||
// @Router /v1/posts/:id/show [get]
|
||||
// @Bind post path key(id) model(id)
|
||||
// @Bind user local
|
||||
// @Summary 作品详情
|
||||
// @Tags Posts
|
||||
// @Produce json
|
||||
// @Param id path int64 true "作品 ID"
|
||||
// @Success 200 {object} PostItem "成功"
|
||||
// @Router /v1/posts/:id/show [get]
|
||||
// @Bind post path key(id) model(id)
|
||||
// @Bind user local
|
||||
func (ctl *posts) Show(ctx fiber.Ctx, post *models.Post, user *models.User) (*PostItem, error) {
|
||||
log.Infof("Fetching post with ID: %d", post.ID)
|
||||
|
||||
@@ -155,7 +155,7 @@ func (ctl *posts) Show(ctx fiber.Ctx, post *models.Post, user *models.User) (*Po
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
mediaUrls := lo.FilterMap(medias, func(item *models.Media, _ int) (string, bool) {
|
||||
mediaUrls := lo.FilterMap(medias, func(item *models.Medium, _ int) (string, bool) {
|
||||
url, err := ctl.oss.GetSignedUrl(ctx, item.Path)
|
||||
if err != nil {
|
||||
return "", false
|
||||
@@ -186,14 +186,14 @@ type PlayUrl struct {
|
||||
|
||||
// Play
|
||||
//
|
||||
// @Summary 获取播放地址
|
||||
// @Tags Posts
|
||||
// @Produce json
|
||||
// @Param id path int64 true "作品 ID"
|
||||
// @Success 200 {object} PlayUrl "成功"
|
||||
// @Router /v1/posts/:id/play [get]
|
||||
// @Bind post path key(id) model(id)
|
||||
// @Bind user local
|
||||
// @Summary 获取播放地址
|
||||
// @Tags Posts
|
||||
// @Produce json
|
||||
// @Param id path int64 true "作品 ID"
|
||||
// @Success 200 {object} PlayUrl "成功"
|
||||
// @Router /v1/posts/:id/play [get]
|
||||
// @Bind post path key(id) model(id)
|
||||
// @Bind user local
|
||||
func (ctl *posts) Play(ctx fiber.Ctx, post *models.Post, user *models.User) (*PlayUrl, error) {
|
||||
log := log.WithField("PlayPostID", strconv.FormatInt(post.ID, 10))
|
||||
// return &PlayUrl{
|
||||
@@ -237,16 +237,16 @@ func (ctl *posts) Play(ctx fiber.Ctx, post *models.Post, user *models.User) (*Pl
|
||||
|
||||
// Mine posts
|
||||
//
|
||||
// @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
|
||||
// @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,
|
||||
@@ -278,7 +278,7 @@ func (ctl *posts) Mine(
|
||||
log.Errorf("GetMediaByIds err: %v", err)
|
||||
return PostItem{}, false
|
||||
}
|
||||
mediaUrls := lo.FilterMap(medias, func(item *models.Media, _ int) (string, bool) {
|
||||
mediaUrls := lo.FilterMap(medias, func(item *models.Medium, _ int) (string, bool) {
|
||||
url, err := ctl.oss.GetSignedUrl(ctx, item.Path)
|
||||
if err != nil {
|
||||
log.WithError(err).Errorf("head image GetSignedUrl err: %v", err)
|
||||
@@ -309,14 +309,14 @@ func (ctl *posts) Mine(
|
||||
|
||||
// Buy
|
||||
//
|
||||
// @Summary 购买作品
|
||||
// @Tags Posts
|
||||
// @Produce json
|
||||
// @Param id path int64 true "作品 ID"
|
||||
// @Success 200 {object} wechat.JSAPIPayParams "成功(余额支付返回 AppId=balance)"
|
||||
// @Router /v1/posts/:id/buy [post]
|
||||
// @Bind post path key(id) model(id)
|
||||
// @Bind user local
|
||||
// @Summary 购买作品
|
||||
// @Tags Posts
|
||||
// @Produce json
|
||||
// @Param id path int64 true "作品 ID"
|
||||
// @Success 200 {object} wechat.JSAPIPayParams "成功(余额支付返回 AppId=balance)"
|
||||
// @Router /v1/posts/:id/buy [post]
|
||||
// @Bind post path key(id) model(id)
|
||||
// @Bind user local
|
||||
func (ctl *posts) Buy(ctx fiber.Ctx, post *models.Post, user *models.User) (*wechat.JSAPIPayParams, error) {
|
||||
bought, err := services.Users.HasBought(ctx, user.ID, post.ID)
|
||||
if err != nil {
|
||||
|
||||
@@ -5,11 +5,12 @@
|
||||
package http
|
||||
|
||||
import (
|
||||
"go.ipao.vip/gen/field"
|
||||
"quyun/v2/app/middlewares"
|
||||
"quyun/v2/app/requests"
|
||||
"quyun/v2/database/models"
|
||||
|
||||
"go.ipao.vip/gen/field"
|
||||
|
||||
"github.com/gofiber/fiber/v3"
|
||||
log "github.com/sirupsen/logrus"
|
||||
_ "go.ipao.vip/atom"
|
||||
@@ -20,7 +21,7 @@ import (
|
||||
// Routes implements the HttpRoute contract and provides route registration
|
||||
// for all controllers in the http module.
|
||||
//
|
||||
// @provider contracts.HttpRoute atom.GroupRoutes
|
||||
// @provider contracts.HttpRoute atom.GroupRoutes
|
||||
type Routes struct {
|
||||
log *log.Entry `inject:"false"`
|
||||
middlewares *middlewares.Middlewares
|
||||
|
||||
@@ -23,12 +23,12 @@ type UserInfo struct {
|
||||
|
||||
// Profile 获取当前登录用户的基础信息。
|
||||
//
|
||||
// @Summary 获取个人信息
|
||||
// @Tags Users
|
||||
// @Produce json
|
||||
// @Success 200 {object} UserInfo "成功"
|
||||
// @Router /v1/users/profile [get]
|
||||
// @Bind user local
|
||||
// @Summary 获取个人信息
|
||||
// @Tags Users
|
||||
// @Produce json
|
||||
// @Success 200 {object} UserInfo "成功"
|
||||
// @Router /v1/users/profile [get]
|
||||
// @Bind user local
|
||||
func (ctl *users) Profile(ctx fiber.Ctx, user *models.User) (*UserInfo, error) {
|
||||
return &UserInfo{
|
||||
ID: user.ID,
|
||||
@@ -45,15 +45,15 @@ type ProfileForm struct {
|
||||
|
||||
// Update 修改当前登录用户的用户名。
|
||||
//
|
||||
// @Summary 修改用户名
|
||||
// @Tags Users
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param form body ProfileForm true "请求体"
|
||||
// @Success 200 {object} any "成功"
|
||||
// @Router /v1/users/username [put]
|
||||
// @Bind user local
|
||||
// @Bind form body
|
||||
// @Summary 修改用户名
|
||||
// @Tags Users
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param form body ProfileForm true "请求体"
|
||||
// @Success 200 {object} any "成功"
|
||||
// @Router /v1/users/username [put]
|
||||
// @Bind user local
|
||||
// @Bind form body
|
||||
func (ctl *users) Update(ctx fiber.Ctx, user *models.User, form *ProfileForm) error {
|
||||
username := strings.TrimSpace(form.Username)
|
||||
if len([]rune(username)) > 12 {
|
||||
|
||||
@@ -32,27 +32,27 @@ type ResponseItem struct{}
|
||||
|
||||
// Foo 演示端点:展示 Fiber 参数绑定与 Swagger 注释写法。
|
||||
//
|
||||
// @Summary 演示接口
|
||||
// @Tags Demo
|
||||
// @Accept multipart/form-data
|
||||
// @Produce json
|
||||
// @Summary 演示接口
|
||||
// @Tags Demo
|
||||
// @Accept multipart/form-data
|
||||
// @Produce json
|
||||
//
|
||||
// @Param id path int true "ID"
|
||||
// @Param pager query requests.Pagination false "分页参数"
|
||||
// @Param query query FooQuery false "查询参数"
|
||||
// @Param Content-Type header string false "内容类型"
|
||||
// @Param folder formData string false "上传到指定文件夹"
|
||||
// @Param file formData file true "上传文件"
|
||||
// @Success 200 {object} requests.Pager{items=ResponseItem} "成功"
|
||||
// @Param id path int true "ID"
|
||||
// @Param pager query requests.Pagination false "分页参数"
|
||||
// @Param query query FooQuery false "查询参数"
|
||||
// @Param Content-Type header string false "内容类型"
|
||||
// @Param folder formData string false "上传到指定文件夹"
|
||||
// @Param file formData file true "上传文件"
|
||||
// @Success 200 {object} requests.Pager{items=ResponseItem} "成功"
|
||||
//
|
||||
// @Router /v1/medias/:id [post]
|
||||
// @Bind query query
|
||||
// @Bind pager query
|
||||
// @Bind header header
|
||||
// @Bind id path
|
||||
// @Bind req body
|
||||
// @Bind file file
|
||||
// @Bind claim local
|
||||
// @Router /v1/medias/:id [post]
|
||||
// @Bind query query
|
||||
// @Bind pager query
|
||||
// @Bind header header
|
||||
// @Bind id path
|
||||
// @Bind req body
|
||||
// @Bind file file
|
||||
// @Bind claim local
|
||||
func (d *demo) Foo(
|
||||
ctx fiber.Ctx,
|
||||
id int,
|
||||
|
||||
@@ -20,7 +20,7 @@ import (
|
||||
// Routes implements the HttpRoute contract and provides route registration
|
||||
// for all controllers in the v1 module.
|
||||
//
|
||||
// @provider contracts.HttpRoute atom.GroupRoutes
|
||||
// @provider contracts.HttpRoute atom.GroupRoutes
|
||||
type Routes struct {
|
||||
log *log.Entry `inject:"false"`
|
||||
middlewares *middlewares.Middlewares
|
||||
|
||||
Reference in New Issue
Block a user