diff --git a/backend_v1/app/http/admin/auth.go b/backend_v1/app/http/admin/auth.go index 0988573..9d1c6e8 100644 --- a/backend_v1/app/http/admin/auth.go +++ b/backend_v1/app/http/admin/auth.go @@ -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{ diff --git a/backend_v1/app/http/admin/medias.go b/backend_v1/app/http/admin/medias.go index 0bf432e..898b02f 100644 --- a/backend_v1/app/http/admin/medias.go +++ b/backend_v1/app/http/admin/medias.go @@ -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 } diff --git a/backend_v1/app/http/admin/orders.go b/backend_v1/app/http/admin/orders.go index 269d491..69f8757 100644 --- a/backend_v1/app/http/admin/orders.go +++ b/backend_v1/app/http/admin/orders.go @@ -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) } diff --git a/backend_v1/app/http/admin/posts.go b/backend_v1/app/http/admin/posts.go index 95231ae..f0c2e2f 100644 --- a/backend_v1/app/http/admin/posts.go +++ b/backend_v1/app/http/admin/posts.go @@ -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 diff --git a/backend_v1/app/http/admin/routes.gen.go b/backend_v1/app/http/admin/routes.gen.go index 22f52cc..f09dbf4 100644 --- a/backend_v1/app/http/admin/routes.gen.go +++ b/backend_v1/app/http/admin/routes.gen.go @@ -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 diff --git a/backend_v1/app/http/admin/statistics.go b/backend_v1/app/http/admin/statistics.go index d1b5931..9f0f42d 100644 --- a/backend_v1/app/http/admin/statistics.go +++ b/backend_v1/app/http/admin/statistics.go @@ -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{} diff --git a/backend_v1/app/http/admin/uploads.go b/backend_v1/app/http/admin/uploads.go index f7cfd82..95ae08c 100644 --- a/backend_v1/app/http/admin/uploads.go +++ b/backend_v1/app/http/admin/uploads.go @@ -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, diff --git a/backend_v1/app/http/admin/users.go b/backend_v1/app/http/admin/users.go index 375b73d..623e95b 100644 --- a/backend_v1/app/http/admin/users.go +++ b/backend_v1/app/http/admin/users.go @@ -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) } diff --git a/backend_v1/app/http/auth.go b/backend_v1/app/http/auth.go new file mode 100644 index 0000000..953f93f --- /dev/null +++ b/backend_v1/app/http/auth.go @@ -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 +} diff --git a/backend_v1/app/http/posts.go b/backend_v1/app/http/posts.go index c1808a1..a4151fc 100644 --- a/backend_v1/app/http/posts.go +++ b/backend_v1/app/http/posts.go @@ -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 { diff --git a/backend_v1/app/http/routes.gen.go b/backend_v1/app/http/routes.gen.go index d434369..107868c 100644 --- a/backend_v1/app/http/routes.gen.go +++ b/backend_v1/app/http/routes.gen.go @@ -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 diff --git a/backend_v1/app/http/users.go b/backend_v1/app/http/users.go index 9c4c44c..6052b9c 100644 --- a/backend_v1/app/http/users.go +++ b/backend_v1/app/http/users.go @@ -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 { diff --git a/backend_v1/app/http/v1/demo.go b/backend_v1/app/http/v1/demo.go index edcec46..64e5224 100644 --- a/backend_v1/app/http/v1/demo.go +++ b/backend_v1/app/http/v1/demo.go @@ -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, diff --git a/backend_v1/app/http/v1/routes.gen.go b/backend_v1/app/http/v1/routes.gen.go index 0b47171..903180b 100644 --- a/backend_v1/app/http/v1/routes.gen.go +++ b/backend_v1/app/http/v1/routes.gen.go @@ -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 diff --git a/backend_v1/app/jobs/publish_draft_posts.go b/backend_v1/app/jobs/publish_draft_posts.go index f036cc9..9a51e22 100644 --- a/backend_v1/app/jobs/publish_draft_posts.go +++ b/backend_v1/app/jobs/publish_draft_posts.go @@ -70,7 +70,7 @@ func (w *PublishDraftPostsWorker) Work(ctx context.Context, job *Job[PublishDraf return JobCancel(err) } - assets := lo.FilterMap(relationMedias, func(media *models.Media, _ int) (fields.MediaAsset, bool) { + assets := lo.FilterMap(relationMedias, func(media *models.Medium, _ int) (fields.MediaAsset, bool) { return fields.MediaAsset{ Type: media.MimeType, Media: media.ID, @@ -95,7 +95,7 @@ func (w *PublishDraftPostsWorker) Work(ctx context.Context, job *Job[PublishDraf Likes: 0, Tags: types.NewJSONType([]string{}), Assets: types.NewJSONType(assets), - HeadImages: types.NewJSONType(lo.FilterMap(relationMedias, func(media *models.Media, _ int) (int64, bool) { + HeadImages: types.NewJSONType(lo.FilterMap(relationMedias, func(media *models.Medium, _ int) (int64, bool) { return media.ID, media.MimeType == "image/jpeg" })), } diff --git a/backend_v1/app/jobs/video_extract_head_image.go b/backend_v1/app/jobs/video_extract_head_image.go index 6e39bfb..744a51c 100644 --- a/backend_v1/app/jobs/video_extract_head_image.go +++ b/backend_v1/app/jobs/video_extract_head_image.go @@ -90,7 +90,7 @@ func (w *VideoExtractHeadImageWorker) Work(ctx context.Context, job *Job[VideoEx name := "[展示图]" + media.Name + ".jpg" // create a new media record for the image - imageMedia := &models.Media{ + imageMedia := &models.Medium{ Name: name, MimeType: "image/jpeg", Size: fileSize, diff --git a/backend_v1/app/jobs/video_store_short.go b/backend_v1/app/jobs/video_store_short.go index 566e108..da783dd 100644 --- a/backend_v1/app/jobs/video_store_short.go +++ b/backend_v1/app/jobs/video_store_short.go @@ -92,7 +92,7 @@ func (w *VideoStoreShortWorker) Work(ctx context.Context, job *Job[VideoStoreSho log.Infof("got file size %s %d", job.Args.FilePath, fileSize) // save to db and relate to master - mediaModel := &models.Media{ + mediaModel := &models.Medium{ Name: "[试听] " + media.Name, MimeType: media.MimeType, Size: fileSize, diff --git a/backend_v1/app/middlewares/mid_auth.go b/backend_v1/app/middlewares/mid_auth_frontend.go similarity index 94% rename from backend_v1/app/middlewares/mid_auth.go rename to backend_v1/app/middlewares/mid_auth_frontend.go index dffc2aa..d481e03 100644 --- a/backend_v1/app/middlewares/mid_auth.go +++ b/backend_v1/app/middlewares/mid_auth_frontend.go @@ -16,7 +16,7 @@ func (f *Middlewares) AuthFrontend(ctx fiber.Ctx) error { return ctx.Next() } - if f.app.IsDevMode() && true { + if f.app.IsDevMode() && false { user, err := services.Users.FindByID(ctx.Context(), 1001) if err != nil { return ctx.Send([]byte("User not found")) @@ -33,7 +33,7 @@ func (f *Middlewares) AuthFrontend(ctx fiber.Ctx) error { query := u.Query() query.Set("redirect", fullUrl) u.RawQuery = query.Encode() - u.Path = "/v1/auth/wechat" // TODO: use phone validation + u.Path = "/v1/auth/phone" fullUrl = u.String() // check cookie exists diff --git a/backend_v1/app/services/media.go b/backend_v1/app/services/media.go index 842fc69..a21f637 100644 --- a/backend_v1/app/services/media.go +++ b/backend_v1/app/services/media.go @@ -21,7 +21,7 @@ func (m *media) List( ) (*requests.Pager, error) { pagination.Format() - tbl, query := models.MediaQuery.QueryContext(ctx) + tbl, query := models.MediumQuery.QueryContext(ctx) items, cnt, err := query. Where(conds...). @@ -39,12 +39,12 @@ func (m *media) List( } // GetByIds -func (m *media) GetByIds(ctx context.Context, ids []int64) ([]*models.Media, error) { +func (m *media) GetByIds(ctx context.Context, ids []int64) ([]*models.Medium, error) { if len(ids) == 0 { - return []*models.Media{}, nil + return []*models.Medium{}, nil } - tbl, query := models.MediaQuery.QueryContext(ctx) + tbl, query := models.MediumQuery.QueryContext(ctx) items, err := query. Where(tbl.ID.In(ids...)). @@ -57,8 +57,8 @@ func (m *media) GetByIds(ctx context.Context, ids []int64) ([]*models.Media, err } // GetByHash -func (m *media) GetByHash(ctx context.Context, hash string) (*models.Media, error) { - tbl, query := models.MediaQuery.QueryContext(ctx) +func (m *media) GetByHash(ctx context.Context, hash string) (*models.Medium, error) { + tbl, query := models.MediumQuery.QueryContext(ctx) item, err := query. Where(tbl.Hash.Eq(hash)). First() @@ -70,7 +70,7 @@ func (m *media) GetByHash(ctx context.Context, hash string) (*models.Media, erro // UpdateMetas func (m *media) UpdateMetas(ctx context.Context, id int64, metas fields.MediaMetas) error { - tbl, query := models.MediaQuery.QueryContext(ctx) + tbl, query := models.MediumQuery.QueryContext(ctx) _, err := query. Where(tbl.ID.Eq(id)). Update(tbl.Metas, metas) @@ -82,14 +82,14 @@ func (m *media) UpdateMetas(ctx context.Context, id int64, metas fields.MediaMet // GetRelationMedias -func (m *media) GetRelations(ctx context.Context, hash string) ([]*models.Media, error) { - tbl, query := models.MediaQuery.QueryContext(ctx) +func (m *media) GetRelations(ctx context.Context, hash string) ([]*models.Medium, error) { + tbl, query := models.MediumQuery.QueryContext(ctx) return query.Where(tbl.Metas.KeyEq("parent_hash", hash)).Find() } // FindByID -func (m *media) FindByID(ctx context.Context, id int64) (*models.Media, error) { - tbl, query := models.MediaQuery.QueryContext(ctx) +func (m *media) FindByID(ctx context.Context, id int64) (*models.Medium, error) { + tbl, query := models.MediumQuery.QueryContext(ctx) item, err := query.Where(tbl.ID.Eq(id)).First() if err != nil { return nil, errors.Wrapf(err, "failed to find media by id: %d", id) @@ -99,7 +99,7 @@ func (m *media) FindByID(ctx context.Context, id int64) (*models.Media, error) { // Count func (m *media) Count(ctx context.Context, conds ...gen.Condition) (int64, error) { - _, query := models.MediaQuery.QueryContext(ctx) + _, query := models.MediumQuery.QueryContext(ctx) if len(conds) > 0 { query = query.Where(conds...) } diff --git a/backend_v1/app/services/posts.go b/backend_v1/app/services/posts.go index e816bcb..56d0124 100644 --- a/backend_v1/app/services/posts.go +++ b/backend_v1/app/services/posts.go @@ -142,11 +142,11 @@ func (m *posts) GetPostsMapByIDs(ctx context.Context, ids []int64) (map[int64]*m } // GetMediaByIds -func (m *posts) GetMediasByIds(ctx context.Context, ids []int64) ([]*models.Media, error) { +func (m *posts) GetMediasByIds(ctx context.Context, ids []int64) ([]*models.Medium, error) { if len(ids) == 0 { return nil, nil } - tbl, query := models.MediaQuery.QueryContext(ctx) + tbl, query := models.MediumQuery.QueryContext(ctx) return query.Where(tbl.ID.In(ids...)).Find() } diff --git a/backend_v1/app/services/users.go b/backend_v1/app/services/users.go index e8fa652..a7bf8ce 100644 --- a/backend_v1/app/services/users.go +++ b/backend_v1/app/services/users.go @@ -60,7 +60,6 @@ func (m *users) PostList( pagePosts, cnt, err := query.Select(tbl.PostID). Where(tbl.UserID.Eq(userId)). FindByPage(int(pagination.Offset()), int(pagination.Limit)) - if err != nil { return nil, err } @@ -211,3 +210,9 @@ func (m *users) Count(ctx context.Context, conds ...gen.Condition) (int64, error } return query.Count() } + +// FindByPhone +func (m *users) FindByPhone(ctx context.Context, phone string) (*models.User, error) { + tbl, query := models.UserQuery.QueryContext(ctx) + return query.Where(tbl.Phone.Eq(phone)).First() +} diff --git a/backend_v1/database/.transform.yaml b/backend_v1/database/.transform.yaml index 9819e04..53e6fe5 100644 --- a/backend_v1/database/.transform.yaml +++ b/backend_v1/database/.transform.yaml @@ -26,6 +26,6 @@ field_type: status: fields.OrderStatus meta: types.JSONType[fields.OrderMeta] - medias: + media: metas: types.JSONType[fields.MediaMetas] field_relate: diff --git a/backend_v1/database/migrations/20251220033752_alter_user.sql b/backend_v1/database/migrations/20251220033752_alter_user.sql new file mode 100644 index 0000000..76a0ee4 --- /dev/null +++ b/backend_v1/database/migrations/20251220033752_alter_user.sql @@ -0,0 +1,13 @@ +-- +goose Up +-- +goose StatementBegin +-- add phone field to users table +ALTER TABLE public.users + ADD phone varchar(15) DEFAULT '' NOT NULL; + +-- +goose StatementEnd +-- +goose Down +-- +goose StatementBegin +ALTER TABLE public.users + DROP COLUMN phone; + +-- +goose StatementEnd diff --git a/backend_v1/database/models/medias.gen.go b/backend_v1/database/models/media.gen.go similarity index 70% rename from backend_v1/database/models/medias.gen.go rename to backend_v1/database/models/media.gen.go index cd8f7e8..f0be001 100644 --- a/backend_v1/database/models/medias.gen.go +++ b/backend_v1/database/models/media.gen.go @@ -14,10 +14,10 @@ import ( "go.ipao.vip/gen/types" ) -const TableNameMedia = "medias" +const TableNameMedium = "media" -// Media mapped from table -type Media struct { +// Medium mapped from table +type Medium struct { ID int64 `gorm:"column:id;type:bigint;primaryKey;autoIncrement:true" json:"id"` CreatedAt time.Time `gorm:"column:created_at;type:timestamp without time zone;not null;default:now()" json:"created_at"` Name string `gorm:"column:name;type:character varying(255);not null" json:"name"` @@ -30,29 +30,29 @@ type Media struct { // Quick operations without importing query package // Update applies changed fields to the database using the default DB. -func (m *Media) Update(ctx context.Context) (gen.ResultInfo, error) { - return Q.Media.WithContext(ctx).Updates(m) +func (m *Medium) Update(ctx context.Context) (gen.ResultInfo, error) { + return Q.Medium.WithContext(ctx).Updates(m) } // Save upserts the model using the default DB. -func (m *Media) Save(ctx context.Context) error { return Q.Media.WithContext(ctx).Save(m) } +func (m *Medium) Save(ctx context.Context) error { return Q.Medium.WithContext(ctx).Save(m) } // Create inserts the model using the default DB. -func (m *Media) Create(ctx context.Context) error { return Q.Media.WithContext(ctx).Create(m) } +func (m *Medium) Create(ctx context.Context) error { return Q.Medium.WithContext(ctx).Create(m) } // Delete removes the row represented by the model using the default DB. -func (m *Media) Delete(ctx context.Context) (gen.ResultInfo, error) { - return Q.Media.WithContext(ctx).Delete(m) +func (m *Medium) Delete(ctx context.Context) (gen.ResultInfo, error) { + return Q.Medium.WithContext(ctx).Delete(m) } // ForceDelete permanently deletes the row (ignores soft delete) using the default DB. -func (m *Media) ForceDelete(ctx context.Context) (gen.ResultInfo, error) { - return Q.Media.WithContext(ctx).Unscoped().Delete(m) +func (m *Medium) ForceDelete(ctx context.Context) (gen.ResultInfo, error) { + return Q.Medium.WithContext(ctx).Unscoped().Delete(m) } // Reload reloads the model from database by its primary key and overwrites current fields. -func (m *Media) Reload(ctx context.Context) error { - fresh, err := Q.Media.WithContext(ctx).GetByID(m.ID) +func (m *Medium) Reload(ctx context.Context) error { + fresh, err := Q.Medium.WithContext(ctx).GetByID(m.ID) if err != nil { return err } diff --git a/backend_v1/database/models/medias.query.gen.go b/backend_v1/database/models/media.query.gen.go similarity index 53% rename from backend_v1/database/models/medias.query.gen.go rename to backend_v1/database/models/media.query.gen.go index 572324b..e1e2d0d 100644 --- a/backend_v1/database/models/medias.query.gen.go +++ b/backend_v1/database/models/media.query.gen.go @@ -17,30 +17,30 @@ import ( "gorm.io/plugin/dbresolver" ) -func newMedia(db *gorm.DB, opts ...gen.DOOption) mediaQuery { - _mediaQuery := mediaQuery{} +func newMedium(db *gorm.DB, opts ...gen.DOOption) mediumQuery { + _mediumQuery := mediumQuery{} - _mediaQuery.mediaQueryDo.UseDB(db, opts...) - _mediaQuery.mediaQueryDo.UseModel(&Media{}) + _mediumQuery.mediumQueryDo.UseDB(db, opts...) + _mediumQuery.mediumQueryDo.UseModel(&Medium{}) - tableName := _mediaQuery.mediaQueryDo.TableName() - _mediaQuery.ALL = field.NewAsterisk(tableName) - _mediaQuery.ID = field.NewInt64(tableName, "id") - _mediaQuery.CreatedAt = field.NewTime(tableName, "created_at") - _mediaQuery.Name = field.NewString(tableName, "name") - _mediaQuery.MimeType = field.NewString(tableName, "mime_type") - _mediaQuery.Size = field.NewInt64(tableName, "size") - _mediaQuery.Path = field.NewString(tableName, "path") - _mediaQuery.Metas = field.NewJSONB(tableName, "metas") - _mediaQuery.Hash = field.NewString(tableName, "hash") + tableName := _mediumQuery.mediumQueryDo.TableName() + _mediumQuery.ALL = field.NewAsterisk(tableName) + _mediumQuery.ID = field.NewInt64(tableName, "id") + _mediumQuery.CreatedAt = field.NewTime(tableName, "created_at") + _mediumQuery.Name = field.NewString(tableName, "name") + _mediumQuery.MimeType = field.NewString(tableName, "mime_type") + _mediumQuery.Size = field.NewInt64(tableName, "size") + _mediumQuery.Path = field.NewString(tableName, "path") + _mediumQuery.Metas = field.NewJSONB(tableName, "metas") + _mediumQuery.Hash = field.NewString(tableName, "hash") - _mediaQuery.fillFieldMap() + _mediumQuery.fillFieldMap() - return _mediaQuery + return _mediumQuery } -type mediaQuery struct { - mediaQueryDo mediaQueryDo +type mediumQuery struct { + mediumQueryDo mediumQueryDo ALL field.Asterisk ID field.Int64 @@ -55,17 +55,17 @@ type mediaQuery struct { fieldMap map[string]field.Expr } -func (m mediaQuery) Table(newTableName string) *mediaQuery { - m.mediaQueryDo.UseTable(newTableName) +func (m mediumQuery) Table(newTableName string) *mediumQuery { + m.mediumQueryDo.UseTable(newTableName) return m.updateTableName(newTableName) } -func (m mediaQuery) As(alias string) *mediaQuery { - m.mediaQueryDo.DO = *(m.mediaQueryDo.As(alias).(*gen.DO)) +func (m mediumQuery) As(alias string) *mediumQuery { + m.mediumQueryDo.DO = *(m.mediumQueryDo.As(alias).(*gen.DO)) return m.updateTableName(alias) } -func (m *mediaQuery) updateTableName(table string) *mediaQuery { +func (m *mediumQuery) updateTableName(table string) *mediumQuery { m.ALL = field.NewAsterisk(table) m.ID = field.NewInt64(table, "id") m.CreatedAt = field.NewTime(table, "created_at") @@ -81,21 +81,21 @@ func (m *mediaQuery) updateTableName(table string) *mediaQuery { return m } -func (m *mediaQuery) QueryContext(ctx context.Context) (*mediaQuery, *mediaQueryDo) { - return m, m.mediaQueryDo.WithContext(ctx) +func (m *mediumQuery) QueryContext(ctx context.Context) (*mediumQuery, *mediumQueryDo) { + return m, m.mediumQueryDo.WithContext(ctx) } -func (m *mediaQuery) WithContext(ctx context.Context) *mediaQueryDo { - return m.mediaQueryDo.WithContext(ctx) +func (m *mediumQuery) WithContext(ctx context.Context) *mediumQueryDo { + return m.mediumQueryDo.WithContext(ctx) } -func (m mediaQuery) TableName() string { return m.mediaQueryDo.TableName() } +func (m mediumQuery) TableName() string { return m.mediumQueryDo.TableName() } -func (m mediaQuery) Alias() string { return m.mediaQueryDo.Alias() } +func (m mediumQuery) Alias() string { return m.mediumQueryDo.Alias() } -func (m mediaQuery) Columns(cols ...field.Expr) gen.Columns { return m.mediaQueryDo.Columns(cols...) } +func (m mediumQuery) Columns(cols ...field.Expr) gen.Columns { return m.mediumQueryDo.Columns(cols...) } -func (m *mediaQuery) GetFieldByName(fieldName string) (field.OrderExpr, bool) { +func (m *mediumQuery) GetFieldByName(fieldName string) (field.OrderExpr, bool) { _f, ok := m.fieldMap[fieldName] if !ok || _f == nil { return nil, false @@ -104,7 +104,7 @@ func (m *mediaQuery) GetFieldByName(fieldName string) (field.OrderExpr, bool) { return _oe, ok } -func (m *mediaQuery) fillFieldMap() { +func (m *mediumQuery) fillFieldMap() { m.fieldMap = make(map[string]field.Expr, 8) m.fieldMap["id"] = m.ID m.fieldMap["created_at"] = m.CreatedAt @@ -116,161 +116,161 @@ func (m *mediaQuery) fillFieldMap() { m.fieldMap["hash"] = m.Hash } -func (m mediaQuery) clone(db *gorm.DB) mediaQuery { - m.mediaQueryDo.ReplaceConnPool(db.Statement.ConnPool) +func (m mediumQuery) clone(db *gorm.DB) mediumQuery { + m.mediumQueryDo.ReplaceConnPool(db.Statement.ConnPool) return m } -func (m mediaQuery) replaceDB(db *gorm.DB) mediaQuery { - m.mediaQueryDo.ReplaceDB(db) +func (m mediumQuery) replaceDB(db *gorm.DB) mediumQuery { + m.mediumQueryDo.ReplaceDB(db) return m } -type mediaQueryDo struct{ gen.DO } +type mediumQueryDo struct{ gen.DO } -func (m mediaQueryDo) Debug() *mediaQueryDo { +func (m mediumQueryDo) Debug() *mediumQueryDo { return m.withDO(m.DO.Debug()) } -func (m mediaQueryDo) WithContext(ctx context.Context) *mediaQueryDo { +func (m mediumQueryDo) WithContext(ctx context.Context) *mediumQueryDo { return m.withDO(m.DO.WithContext(ctx)) } -func (m mediaQueryDo) ReadDB() *mediaQueryDo { +func (m mediumQueryDo) ReadDB() *mediumQueryDo { return m.Clauses(dbresolver.Read) } -func (m mediaQueryDo) WriteDB() *mediaQueryDo { +func (m mediumQueryDo) WriteDB() *mediumQueryDo { return m.Clauses(dbresolver.Write) } -func (m mediaQueryDo) Session(config *gorm.Session) *mediaQueryDo { +func (m mediumQueryDo) Session(config *gorm.Session) *mediumQueryDo { return m.withDO(m.DO.Session(config)) } -func (m mediaQueryDo) Clauses(conds ...clause.Expression) *mediaQueryDo { +func (m mediumQueryDo) Clauses(conds ...clause.Expression) *mediumQueryDo { return m.withDO(m.DO.Clauses(conds...)) } -func (m mediaQueryDo) Returning(value interface{}, columns ...string) *mediaQueryDo { +func (m mediumQueryDo) Returning(value interface{}, columns ...string) *mediumQueryDo { return m.withDO(m.DO.Returning(value, columns...)) } -func (m mediaQueryDo) Not(conds ...gen.Condition) *mediaQueryDo { +func (m mediumQueryDo) Not(conds ...gen.Condition) *mediumQueryDo { return m.withDO(m.DO.Not(conds...)) } -func (m mediaQueryDo) Or(conds ...gen.Condition) *mediaQueryDo { +func (m mediumQueryDo) Or(conds ...gen.Condition) *mediumQueryDo { return m.withDO(m.DO.Or(conds...)) } -func (m mediaQueryDo) Select(conds ...field.Expr) *mediaQueryDo { +func (m mediumQueryDo) Select(conds ...field.Expr) *mediumQueryDo { return m.withDO(m.DO.Select(conds...)) } -func (m mediaQueryDo) Where(conds ...gen.Condition) *mediaQueryDo { +func (m mediumQueryDo) Where(conds ...gen.Condition) *mediumQueryDo { return m.withDO(m.DO.Where(conds...)) } -func (m mediaQueryDo) Order(conds ...field.Expr) *mediaQueryDo { +func (m mediumQueryDo) Order(conds ...field.Expr) *mediumQueryDo { return m.withDO(m.DO.Order(conds...)) } -func (m mediaQueryDo) Distinct(cols ...field.Expr) *mediaQueryDo { +func (m mediumQueryDo) Distinct(cols ...field.Expr) *mediumQueryDo { return m.withDO(m.DO.Distinct(cols...)) } -func (m mediaQueryDo) Omit(cols ...field.Expr) *mediaQueryDo { +func (m mediumQueryDo) Omit(cols ...field.Expr) *mediumQueryDo { return m.withDO(m.DO.Omit(cols...)) } -func (m mediaQueryDo) Join(table schema.Tabler, on ...field.Expr) *mediaQueryDo { +func (m mediumQueryDo) Join(table schema.Tabler, on ...field.Expr) *mediumQueryDo { return m.withDO(m.DO.Join(table, on...)) } -func (m mediaQueryDo) LeftJoin(table schema.Tabler, on ...field.Expr) *mediaQueryDo { +func (m mediumQueryDo) LeftJoin(table schema.Tabler, on ...field.Expr) *mediumQueryDo { return m.withDO(m.DO.LeftJoin(table, on...)) } -func (m mediaQueryDo) RightJoin(table schema.Tabler, on ...field.Expr) *mediaQueryDo { +func (m mediumQueryDo) RightJoin(table schema.Tabler, on ...field.Expr) *mediumQueryDo { return m.withDO(m.DO.RightJoin(table, on...)) } -func (m mediaQueryDo) Group(cols ...field.Expr) *mediaQueryDo { +func (m mediumQueryDo) Group(cols ...field.Expr) *mediumQueryDo { return m.withDO(m.DO.Group(cols...)) } -func (m mediaQueryDo) Having(conds ...gen.Condition) *mediaQueryDo { +func (m mediumQueryDo) Having(conds ...gen.Condition) *mediumQueryDo { return m.withDO(m.DO.Having(conds...)) } -func (m mediaQueryDo) Limit(limit int) *mediaQueryDo { +func (m mediumQueryDo) Limit(limit int) *mediumQueryDo { return m.withDO(m.DO.Limit(limit)) } -func (m mediaQueryDo) Offset(offset int) *mediaQueryDo { +func (m mediumQueryDo) Offset(offset int) *mediumQueryDo { return m.withDO(m.DO.Offset(offset)) } -func (m mediaQueryDo) Scopes(funcs ...func(gen.Dao) gen.Dao) *mediaQueryDo { +func (m mediumQueryDo) Scopes(funcs ...func(gen.Dao) gen.Dao) *mediumQueryDo { return m.withDO(m.DO.Scopes(funcs...)) } -func (m mediaQueryDo) Unscoped() *mediaQueryDo { +func (m mediumQueryDo) Unscoped() *mediumQueryDo { return m.withDO(m.DO.Unscoped()) } -func (m mediaQueryDo) Create(values ...*Media) error { +func (m mediumQueryDo) Create(values ...*Medium) error { if len(values) == 0 { return nil } return m.DO.Create(values) } -func (m mediaQueryDo) CreateInBatches(values []*Media, batchSize int) error { +func (m mediumQueryDo) CreateInBatches(values []*Medium, batchSize int) error { return m.DO.CreateInBatches(values, batchSize) } // Save : !!! underlying implementation is different with GORM // The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values) -func (m mediaQueryDo) Save(values ...*Media) error { +func (m mediumQueryDo) Save(values ...*Medium) error { if len(values) == 0 { return nil } return m.DO.Save(values) } -func (m mediaQueryDo) First() (*Media, error) { +func (m mediumQueryDo) First() (*Medium, error) { if result, err := m.DO.First(); err != nil { return nil, err } else { - return result.(*Media), nil + return result.(*Medium), nil } } -func (m mediaQueryDo) Take() (*Media, error) { +func (m mediumQueryDo) Take() (*Medium, error) { if result, err := m.DO.Take(); err != nil { return nil, err } else { - return result.(*Media), nil + return result.(*Medium), nil } } -func (m mediaQueryDo) Last() (*Media, error) { +func (m mediumQueryDo) Last() (*Medium, error) { if result, err := m.DO.Last(); err != nil { return nil, err } else { - return result.(*Media), nil + return result.(*Medium), nil } } -func (m mediaQueryDo) Find() ([]*Media, error) { +func (m mediumQueryDo) Find() ([]*Medium, error) { result, err := m.DO.Find() - return result.([]*Media), err + return result.([]*Medium), err } -func (m mediaQueryDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*Media, err error) { - buf := make([]*Media, 0, batchSize) +func (m mediumQueryDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*Medium, err error) { + buf := make([]*Medium, 0, batchSize) err = m.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error { defer func() { results = append(results, buf...) }() return fc(tx, batch) @@ -278,49 +278,49 @@ func (m mediaQueryDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) return results, err } -func (m mediaQueryDo) FindInBatches(result *[]*Media, batchSize int, fc func(tx gen.Dao, batch int) error) error { +func (m mediumQueryDo) FindInBatches(result *[]*Medium, batchSize int, fc func(tx gen.Dao, batch int) error) error { return m.DO.FindInBatches(result, batchSize, fc) } -func (m mediaQueryDo) Attrs(attrs ...field.AssignExpr) *mediaQueryDo { +func (m mediumQueryDo) Attrs(attrs ...field.AssignExpr) *mediumQueryDo { return m.withDO(m.DO.Attrs(attrs...)) } -func (m mediaQueryDo) Assign(attrs ...field.AssignExpr) *mediaQueryDo { +func (m mediumQueryDo) Assign(attrs ...field.AssignExpr) *mediumQueryDo { return m.withDO(m.DO.Assign(attrs...)) } -func (m mediaQueryDo) Joins(fields ...field.RelationField) *mediaQueryDo { +func (m mediumQueryDo) Joins(fields ...field.RelationField) *mediumQueryDo { for _, _f := range fields { m = *m.withDO(m.DO.Joins(_f)) } return &m } -func (m mediaQueryDo) Preload(fields ...field.RelationField) *mediaQueryDo { +func (m mediumQueryDo) Preload(fields ...field.RelationField) *mediumQueryDo { for _, _f := range fields { m = *m.withDO(m.DO.Preload(_f)) } return &m } -func (m mediaQueryDo) FirstOrInit() (*Media, error) { +func (m mediumQueryDo) FirstOrInit() (*Medium, error) { if result, err := m.DO.FirstOrInit(); err != nil { return nil, err } else { - return result.(*Media), nil + return result.(*Medium), nil } } -func (m mediaQueryDo) FirstOrCreate() (*Media, error) { +func (m mediumQueryDo) FirstOrCreate() (*Medium, error) { if result, err := m.DO.FirstOrCreate(); err != nil { return nil, err } else { - return result.(*Media), nil + return result.(*Medium), nil } } -func (m mediaQueryDo) FindByPage(offset int, limit int) (result []*Media, count int64, err error) { +func (m mediumQueryDo) FindByPage(offset int, limit int) (result []*Medium, count int64, err error) { result, err = m.Offset(offset).Limit(limit).Find() if err != nil { return @@ -335,7 +335,7 @@ func (m mediaQueryDo) FindByPage(offset int, limit int) (result []*Media, count return } -func (m mediaQueryDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) { +func (m mediumQueryDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) { count, err = m.Count() if err != nil { return @@ -345,35 +345,35 @@ func (m mediaQueryDo) ScanByPage(result interface{}, offset int, limit int) (cou return } -func (m mediaQueryDo) Scan(result interface{}) (err error) { +func (m mediumQueryDo) Scan(result interface{}) (err error) { return m.DO.Scan(result) } -func (m mediaQueryDo) Delete(models ...*Media) (result gen.ResultInfo, err error) { +func (m mediumQueryDo) Delete(models ...*Medium) (result gen.ResultInfo, err error) { return m.DO.Delete(models) } // ForceDelete performs a permanent delete (ignores soft-delete) for current scope. -func (m mediaQueryDo) ForceDelete() (gen.ResultInfo, error) { +func (m mediumQueryDo) ForceDelete() (gen.ResultInfo, error) { return m.Unscoped().Delete() } // Inc increases the given column by step for current scope. -func (m mediaQueryDo) Inc(column field.Expr, step int64) (gen.ResultInfo, error) { +func (m mediumQueryDo) Inc(column field.Expr, step int64) (gen.ResultInfo, error) { // column = column + step e := field.NewUnsafeFieldRaw("?+?", column.RawExpr(), step) return m.DO.UpdateColumn(column, e) } // Dec decreases the given column by step for current scope. -func (m mediaQueryDo) Dec(column field.Expr, step int64) (gen.ResultInfo, error) { +func (m mediumQueryDo) Dec(column field.Expr, step int64) (gen.ResultInfo, error) { // column = column - step e := field.NewUnsafeFieldRaw("?-?", column.RawExpr(), step) return m.DO.UpdateColumn(column, e) } // Sum returns SUM(column) for current scope. -func (m mediaQueryDo) Sum(column field.Expr) (float64, error) { +func (m mediumQueryDo) Sum(column field.Expr) (float64, error) { var _v float64 agg := field.NewUnsafeFieldRaw("SUM(?)", column.RawExpr()) if err := m.Select(agg).Scan(&_v); err != nil { @@ -383,7 +383,7 @@ func (m mediaQueryDo) Sum(column field.Expr) (float64, error) { } // Avg returns AVG(column) for current scope. -func (m mediaQueryDo) Avg(column field.Expr) (float64, error) { +func (m mediumQueryDo) Avg(column field.Expr) (float64, error) { var _v float64 agg := field.NewUnsafeFieldRaw("AVG(?)", column.RawExpr()) if err := m.Select(agg).Scan(&_v); err != nil { @@ -393,7 +393,7 @@ func (m mediaQueryDo) Avg(column field.Expr) (float64, error) { } // Min returns MIN(column) for current scope. -func (m mediaQueryDo) Min(column field.Expr) (float64, error) { +func (m mediumQueryDo) Min(column field.Expr) (float64, error) { var _v float64 agg := field.NewUnsafeFieldRaw("MIN(?)", column.RawExpr()) if err := m.Select(agg).Scan(&_v); err != nil { @@ -403,7 +403,7 @@ func (m mediaQueryDo) Min(column field.Expr) (float64, error) { } // Max returns MAX(column) for current scope. -func (m mediaQueryDo) Max(column field.Expr) (float64, error) { +func (m mediumQueryDo) Max(column field.Expr) (float64, error) { var _v float64 agg := field.NewUnsafeFieldRaw("MAX(?)", column.RawExpr()) if err := m.Select(agg).Scan(&_v); err != nil { @@ -413,7 +413,7 @@ func (m mediaQueryDo) Max(column field.Expr) (float64, error) { } // PluckMap returns a map[key]value for selected key/value expressions within current scope. -func (m mediaQueryDo) PluckMap(key, val field.Expr) (map[interface{}]interface{}, error) { +func (m mediumQueryDo) PluckMap(key, val field.Expr) (map[interface{}]interface{}, error) { do := m.Select(key, val) rows, err := do.DO.Rows() if err != nil { @@ -433,7 +433,7 @@ func (m mediaQueryDo) PluckMap(key, val field.Expr) (map[interface{}]interface{} } // Exists returns true if any record matches the given conditions. -func (m mediaQueryDo) Exists(conds ...gen.Condition) (bool, error) { +func (m mediumQueryDo) Exists(conds ...gen.Condition) (bool, error) { cnt, err := m.Where(conds...).Count() if err != nil { return false, err @@ -442,7 +442,7 @@ func (m mediaQueryDo) Exists(conds ...gen.Condition) (bool, error) { } // PluckIDs returns all primary key values under current scope. -func (m mediaQueryDo) PluckIDs() ([]int64, error) { +func (m mediumQueryDo) PluckIDs() ([]int64, error) { ids := make([]int64, 0, 16) pk := field.NewInt64(m.TableName(), "id") if err := m.DO.Pluck(pk, &ids); err != nil { @@ -452,28 +452,28 @@ func (m mediaQueryDo) PluckIDs() ([]int64, error) { } // GetByID finds a single record by primary key. -func (m mediaQueryDo) GetByID(id int64) (*Media, error) { +func (m mediumQueryDo) GetByID(id int64) (*Medium, error) { pk := field.NewInt64(m.TableName(), "id") return m.Where(pk.Eq(id)).First() } // GetByIDs finds records by primary key list. -func (m mediaQueryDo) GetByIDs(ids ...int64) ([]*Media, error) { +func (m mediumQueryDo) GetByIDs(ids ...int64) ([]*Medium, error) { if len(ids) == 0 { - return []*Media{}, nil + return []*Medium{}, nil } pk := field.NewInt64(m.TableName(), "id") return m.Where(pk.In(ids...)).Find() } // DeleteByID deletes records by primary key. -func (m mediaQueryDo) DeleteByID(id int64) (gen.ResultInfo, error) { +func (m mediumQueryDo) DeleteByID(id int64) (gen.ResultInfo, error) { pk := field.NewInt64(m.TableName(), "id") return m.Where(pk.Eq(id)).Delete() } // DeleteByIDs deletes records by a list of primary keys. -func (m mediaQueryDo) DeleteByIDs(ids ...int64) (gen.ResultInfo, error) { +func (m mediumQueryDo) DeleteByIDs(ids ...int64) (gen.ResultInfo, error) { if len(ids) == 0 { return gen.ResultInfo{RowsAffected: 0, Error: nil}, nil } @@ -481,7 +481,7 @@ func (m mediaQueryDo) DeleteByIDs(ids ...int64) (gen.ResultInfo, error) { return m.Where(pk.In(ids...)).Delete() } -func (m *mediaQueryDo) withDO(do gen.Dao) *mediaQueryDo { +func (m *mediumQueryDo) withDO(do gen.Dao) *mediumQueryDo { m.DO = *do.(*gen.DO) return m } diff --git a/backend_v1/database/models/query.gen.go b/backend_v1/database/models/query.gen.go index 5e2852a..9e4edd1 100644 --- a/backend_v1/database/models/query.gen.go +++ b/backend_v1/database/models/query.gen.go @@ -17,7 +17,7 @@ import ( var ( Q = new(Query) - MediaQuery *mediaQuery + MediumQuery *mediumQuery OrderQuery *orderQuery PostQuery *postQuery UserQuery *userQuery @@ -26,7 +26,7 @@ var ( func SetDefault(db *gorm.DB, opts ...gen.DOOption) { *Q = *Use(db, opts...) - MediaQuery = &Q.Media + MediumQuery = &Q.Medium OrderQuery = &Q.Order PostQuery = &Q.Post UserQuery = &Q.User @@ -36,7 +36,7 @@ func SetDefault(db *gorm.DB, opts ...gen.DOOption) { func Use(db *gorm.DB, opts ...gen.DOOption) *Query { return &Query{ db: db, - Media: newMedia(db, opts...), + Medium: newMedium(db, opts...), Order: newOrder(db, opts...), Post: newPost(db, opts...), User: newUser(db, opts...), @@ -47,7 +47,7 @@ func Use(db *gorm.DB, opts ...gen.DOOption) *Query { type Query struct { db *gorm.DB - Media mediaQuery + Medium mediumQuery Order orderQuery Post postQuery User userQuery @@ -59,7 +59,7 @@ func (q *Query) Available() bool { return q.db != nil } func (q *Query) clone(db *gorm.DB) *Query { return &Query{ db: db, - Media: q.Media.clone(db), + Medium: q.Medium.clone(db), Order: q.Order.clone(db), Post: q.Post.clone(db), User: q.User.clone(db), @@ -78,7 +78,7 @@ func (q *Query) WriteDB() *Query { func (q *Query) ReplaceDB(db *gorm.DB) *Query { return &Query{ db: db, - Media: q.Media.replaceDB(db), + Medium: q.Medium.replaceDB(db), Order: q.Order.replaceDB(db), Post: q.Post.replaceDB(db), User: q.User.replaceDB(db), @@ -87,7 +87,7 @@ func (q *Query) ReplaceDB(db *gorm.DB) *Query { } type queryCtx struct { - Media *mediaQueryDo + Medium *mediumQueryDo Order *orderQueryDo Post *postQueryDo User *userQueryDo @@ -96,7 +96,7 @@ type queryCtx struct { func (q *Query) WithContext(ctx context.Context) *queryCtx { return &queryCtx{ - Media: q.Media.WithContext(ctx), + Medium: q.Medium.WithContext(ctx), Order: q.Order.WithContext(ctx), Post: q.Post.WithContext(ctx), User: q.User.WithContext(ctx), diff --git a/backend_v1/database/models/users.gen.go b/backend_v1/database/models/users.gen.go index c1d1f8b..ecada23 100644 --- a/backend_v1/database/models/users.gen.go +++ b/backend_v1/database/models/users.gen.go @@ -30,6 +30,7 @@ type User struct { Metas types.JSONType[fields.UserMetas] `gorm:"column:metas;type:jsonb;not null;default:{}" json:"metas"` AuthToken types.JSONType[fields.UserAuthToken] `gorm:"column:auth_token;type:jsonb;not null;default:{}" json:"auth_token"` Balance int64 `gorm:"column:balance;type:bigint;not null" json:"balance"` + Phone string `gorm:"column:phone;type:character varying(15);not null" json:"phone"` } // Quick operations without importing query package diff --git a/backend_v1/database/models/users.query.gen.go b/backend_v1/database/models/users.query.gen.go index 3dc20af..ed861fe 100644 --- a/backend_v1/database/models/users.query.gen.go +++ b/backend_v1/database/models/users.query.gen.go @@ -36,6 +36,7 @@ func newUser(db *gorm.DB, opts ...gen.DOOption) userQuery { _userQuery.Metas = field.NewJSONB(tableName, "metas") _userQuery.AuthToken = field.NewJSONB(tableName, "auth_token") _userQuery.Balance = field.NewInt64(tableName, "balance") + _userQuery.Phone = field.NewString(tableName, "phone") _userQuery.fillFieldMap() @@ -57,6 +58,7 @@ type userQuery struct { Metas field.JSONB AuthToken field.JSONB Balance field.Int64 + Phone field.String fieldMap map[string]field.Expr } @@ -84,6 +86,7 @@ func (u *userQuery) updateTableName(table string) *userQuery { u.Metas = field.NewJSONB(table, "metas") u.AuthToken = field.NewJSONB(table, "auth_token") u.Balance = field.NewInt64(table, "balance") + u.Phone = field.NewString(table, "phone") u.fillFieldMap() @@ -114,7 +117,7 @@ func (u *userQuery) GetFieldByName(fieldName string) (field.OrderExpr, bool) { } func (u *userQuery) fillFieldMap() { - u.fieldMap = make(map[string]field.Expr, 11) + u.fieldMap = make(map[string]field.Expr, 12) u.fieldMap["id"] = u.ID u.fieldMap["created_at"] = u.CreatedAt u.fieldMap["updated_at"] = u.UpdatedAt @@ -126,6 +129,7 @@ func (u *userQuery) fillFieldMap() { u.fieldMap["metas"] = u.Metas u.fieldMap["auth_token"] = u.AuthToken u.fieldMap["balance"] = u.Balance + u.fieldMap["phone"] = u.Phone } func (u userQuery) clone(db *gorm.DB) userQuery { diff --git a/backend_v1/docs/docs.go b/backend_v1/docs/docs.go index 8176d62..b6a0be2 100644 --- a/backend_v1/docs/docs.go +++ b/backend_v1/docs/docs.go @@ -95,7 +95,7 @@ const docTemplate = `{ "type": "object", "properties": { "items": { - "$ref": "#/definitions/models.Media" + "$ref": "#/definitions/models.Medium" } } } @@ -698,239 +698,37 @@ const docTemplate = `{ } } }, - "/posts": { - "get": { - "produces": [ - "application/json" - ], - "tags": [ - "Posts" - ], - "summary": "作品列表", - "parameters": [ - { - "type": "integer", - "name": "limit", - "in": "query" - }, - { - "type": "integer", - "name": "page", - "in": "query" - }, - { - "type": "string", - "name": "keyword", - "in": "query" - } - ], - "responses": { - "200": { - "description": "成功", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/requests.Pager" - }, - { - "type": "object", - "properties": { - "items": { - "$ref": "#/definitions/http.PostItem" - } - } - } - ] - } - } - } - } - }, - "/posts/mine": { - "get": { - "produces": [ - "application/json" - ], - "tags": [ - "Posts" - ], - "summary": "我的已购作品", - "parameters": [ - { - "type": "integer", - "name": "limit", - "in": "query" - }, - { - "type": "integer", - "name": "page", - "in": "query" - }, - { - "type": "string", - "name": "keyword", - "in": "query" - } - ], - "responses": { - "200": { - "description": "成功", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/requests.Pager" - }, - { - "type": "object", - "properties": { - "items": { - "$ref": "#/definitions/http.PostItem" - } - } - } - ] - } - } - } - } - }, - "/posts/{id}/buy": { + "/v1/auth/{phone}": { "post": { "produces": [ "application/json" ], "tags": [ - "Posts" - ], - "summary": "购买作品", - "parameters": [ - { - "type": "integer", - "format": "int64", - "description": "作品 ID", - "name": "id", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "成功(余额支付返回 AppId=balance)", - "schema": { - "$ref": "#/definitions/wechat.JSAPIPayParams" - } - } - } - } - }, - "/posts/{id}/play": { - "get": { - "produces": [ - "application/json" - ], - "tags": [ - "Posts" - ], - "summary": "获取播放地址", - "parameters": [ - { - "type": "integer", - "format": "int64", - "description": "作品 ID", - "name": "id", - "in": "path", - "required": true - } + "Auth" ], + "summary": "手机验证", "responses": { "200": { "description": "成功", "schema": { - "$ref": "#/definitions/http.PlayUrl" + "allOf": [ + { + "$ref": "#/definitions/requests.Pager" + }, + { + "type": "object", + "properties": { + "items": { + "$ref": "#/definitions/http.PostItem" + } + } + } + ] } } } } }, - "/posts/{id}/show": { - "get": { - "produces": [ - "application/json" - ], - "tags": [ - "Posts" - ], - "summary": "作品详情", - "parameters": [ - { - "type": "integer", - "format": "int64", - "description": "作品 ID", - "name": "id", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "成功", - "schema": { - "$ref": "#/definitions/http.PostItem" - } - } - } - } - }, - "/users/profile": { - "get": { - "produces": [ - "application/json" - ], - "tags": [ - "Users" - ], - "summary": "获取个人信息", - "responses": { - "200": { - "description": "成功", - "schema": { - "$ref": "#/definitions/http.UserInfo" - } - } - } - } - }, - "/users/username": { - "put": { - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Users" - ], - "summary": "修改用户名", - "parameters": [ - { - "description": "请求体", - "name": "form", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/http.ProfileForm" - } - } - ], - "responses": { - "200": { - "description": "成功", - "schema": {} - } - } - } - }, "/v1/medias/{id}": { "post": { "consumes": [ @@ -1008,6 +806,239 @@ const docTemplate = `{ } } } + }, + "/v1/posts": { + "get": { + "produces": [ + "application/json" + ], + "tags": [ + "Posts" + ], + "summary": "作品列表", + "parameters": [ + { + "type": "integer", + "name": "limit", + "in": "query" + }, + { + "type": "integer", + "name": "page", + "in": "query" + }, + { + "type": "string", + "name": "keyword", + "in": "query" + } + ], + "responses": { + "200": { + "description": "成功", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/requests.Pager" + }, + { + "type": "object", + "properties": { + "items": { + "$ref": "#/definitions/http.PostItem" + } + } + } + ] + } + } + } + } + }, + "/v1/posts/mine": { + "get": { + "produces": [ + "application/json" + ], + "tags": [ + "Posts" + ], + "summary": "我的已购作品", + "parameters": [ + { + "type": "integer", + "name": "limit", + "in": "query" + }, + { + "type": "integer", + "name": "page", + "in": "query" + }, + { + "type": "string", + "name": "keyword", + "in": "query" + } + ], + "responses": { + "200": { + "description": "成功", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/requests.Pager" + }, + { + "type": "object", + "properties": { + "items": { + "$ref": "#/definitions/http.PostItem" + } + } + } + ] + } + } + } + } + }, + "/v1/posts/{id}/buy": { + "post": { + "produces": [ + "application/json" + ], + "tags": [ + "Posts" + ], + "summary": "购买作品", + "parameters": [ + { + "type": "integer", + "format": "int64", + "description": "作品 ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "成功(余额支付返回 AppId=balance)", + "schema": { + "$ref": "#/definitions/wechat.JSAPIPayParams" + } + } + } + } + }, + "/v1/posts/{id}/play": { + "get": { + "produces": [ + "application/json" + ], + "tags": [ + "Posts" + ], + "summary": "获取播放地址", + "parameters": [ + { + "type": "integer", + "format": "int64", + "description": "作品 ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "成功", + "schema": { + "$ref": "#/definitions/http.PlayUrl" + } + } + } + } + }, + "/v1/posts/{id}/show": { + "get": { + "produces": [ + "application/json" + ], + "tags": [ + "Posts" + ], + "summary": "作品详情", + "parameters": [ + { + "type": "integer", + "format": "int64", + "description": "作品 ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "成功", + "schema": { + "$ref": "#/definitions/http.PostItem" + } + } + } + } + }, + "/v1/users/profile": { + "get": { + "produces": [ + "application/json" + ], + "tags": [ + "Users" + ], + "summary": "获取个人信息", + "responses": { + "200": { + "description": "成功", + "schema": { + "$ref": "#/definitions/http.UserInfo" + } + } + } + } + }, + "/v1/users/username": { + "put": { + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Users" + ], + "summary": "修改用户名", + "parameters": [ + { + "description": "请求体", + "name": "form", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/http.ProfileForm" + } + } + ], + "responses": { + "200": { + "description": "成功", + "schema": {} + } + } + } } }, "definitions": { @@ -1097,7 +1128,7 @@ const docTemplate = `{ "medias": { "type": "array", "items": { - "$ref": "#/definitions/models.Media" + "$ref": "#/definitions/models.Medium" } }, "price": { @@ -1335,7 +1366,7 @@ const docTemplate = `{ } } }, - "models.Media": { + "models.Medium": { "type": "object", "properties": { "created_at": { @@ -1348,7 +1379,10 @@ const docTemplate = `{ "type": "integer" }, "metas": { - "$ref": "#/definitions/types.JSONType-fields_MediaMetas" + "type": "array", + "items": { + "type": "integer" + } }, "mime_type": { "type": "string" @@ -1441,6 +1475,9 @@ const docTemplate = `{ "open_id": { "type": "string" }, + "phone": { + "type": "string" + }, "status": { "$ref": "#/definitions/fields.UserStatus" }, @@ -1552,9 +1589,6 @@ const docTemplate = `{ "types.JSONType-array_string": { "type": "object" }, - "types.JSONType-fields_MediaMetas": { - "type": "object" - }, "types.JSONType-fields_OrderMeta": { "type": "object" }, diff --git a/backend_v1/docs/swagger.json b/backend_v1/docs/swagger.json index c1127dd..986147c 100644 --- a/backend_v1/docs/swagger.json +++ b/backend_v1/docs/swagger.json @@ -89,7 +89,7 @@ "type": "object", "properties": { "items": { - "$ref": "#/definitions/models.Media" + "$ref": "#/definitions/models.Medium" } } } @@ -692,239 +692,37 @@ } } }, - "/posts": { - "get": { - "produces": [ - "application/json" - ], - "tags": [ - "Posts" - ], - "summary": "作品列表", - "parameters": [ - { - "type": "integer", - "name": "limit", - "in": "query" - }, - { - "type": "integer", - "name": "page", - "in": "query" - }, - { - "type": "string", - "name": "keyword", - "in": "query" - } - ], - "responses": { - "200": { - "description": "成功", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/requests.Pager" - }, - { - "type": "object", - "properties": { - "items": { - "$ref": "#/definitions/http.PostItem" - } - } - } - ] - } - } - } - } - }, - "/posts/mine": { - "get": { - "produces": [ - "application/json" - ], - "tags": [ - "Posts" - ], - "summary": "我的已购作品", - "parameters": [ - { - "type": "integer", - "name": "limit", - "in": "query" - }, - { - "type": "integer", - "name": "page", - "in": "query" - }, - { - "type": "string", - "name": "keyword", - "in": "query" - } - ], - "responses": { - "200": { - "description": "成功", - "schema": { - "allOf": [ - { - "$ref": "#/definitions/requests.Pager" - }, - { - "type": "object", - "properties": { - "items": { - "$ref": "#/definitions/http.PostItem" - } - } - } - ] - } - } - } - } - }, - "/posts/{id}/buy": { + "/v1/auth/{phone}": { "post": { "produces": [ "application/json" ], "tags": [ - "Posts" - ], - "summary": "购买作品", - "parameters": [ - { - "type": "integer", - "format": "int64", - "description": "作品 ID", - "name": "id", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "成功(余额支付返回 AppId=balance)", - "schema": { - "$ref": "#/definitions/wechat.JSAPIPayParams" - } - } - } - } - }, - "/posts/{id}/play": { - "get": { - "produces": [ - "application/json" - ], - "tags": [ - "Posts" - ], - "summary": "获取播放地址", - "parameters": [ - { - "type": "integer", - "format": "int64", - "description": "作品 ID", - "name": "id", - "in": "path", - "required": true - } + "Auth" ], + "summary": "手机验证", "responses": { "200": { "description": "成功", "schema": { - "$ref": "#/definitions/http.PlayUrl" + "allOf": [ + { + "$ref": "#/definitions/requests.Pager" + }, + { + "type": "object", + "properties": { + "items": { + "$ref": "#/definitions/http.PostItem" + } + } + } + ] } } } } }, - "/posts/{id}/show": { - "get": { - "produces": [ - "application/json" - ], - "tags": [ - "Posts" - ], - "summary": "作品详情", - "parameters": [ - { - "type": "integer", - "format": "int64", - "description": "作品 ID", - "name": "id", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "成功", - "schema": { - "$ref": "#/definitions/http.PostItem" - } - } - } - } - }, - "/users/profile": { - "get": { - "produces": [ - "application/json" - ], - "tags": [ - "Users" - ], - "summary": "获取个人信息", - "responses": { - "200": { - "description": "成功", - "schema": { - "$ref": "#/definitions/http.UserInfo" - } - } - } - } - }, - "/users/username": { - "put": { - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "Users" - ], - "summary": "修改用户名", - "parameters": [ - { - "description": "请求体", - "name": "form", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/http.ProfileForm" - } - } - ], - "responses": { - "200": { - "description": "成功", - "schema": {} - } - } - } - }, "/v1/medias/{id}": { "post": { "consumes": [ @@ -1002,6 +800,239 @@ } } } + }, + "/v1/posts": { + "get": { + "produces": [ + "application/json" + ], + "tags": [ + "Posts" + ], + "summary": "作品列表", + "parameters": [ + { + "type": "integer", + "name": "limit", + "in": "query" + }, + { + "type": "integer", + "name": "page", + "in": "query" + }, + { + "type": "string", + "name": "keyword", + "in": "query" + } + ], + "responses": { + "200": { + "description": "成功", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/requests.Pager" + }, + { + "type": "object", + "properties": { + "items": { + "$ref": "#/definitions/http.PostItem" + } + } + } + ] + } + } + } + } + }, + "/v1/posts/mine": { + "get": { + "produces": [ + "application/json" + ], + "tags": [ + "Posts" + ], + "summary": "我的已购作品", + "parameters": [ + { + "type": "integer", + "name": "limit", + "in": "query" + }, + { + "type": "integer", + "name": "page", + "in": "query" + }, + { + "type": "string", + "name": "keyword", + "in": "query" + } + ], + "responses": { + "200": { + "description": "成功", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/requests.Pager" + }, + { + "type": "object", + "properties": { + "items": { + "$ref": "#/definitions/http.PostItem" + } + } + } + ] + } + } + } + } + }, + "/v1/posts/{id}/buy": { + "post": { + "produces": [ + "application/json" + ], + "tags": [ + "Posts" + ], + "summary": "购买作品", + "parameters": [ + { + "type": "integer", + "format": "int64", + "description": "作品 ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "成功(余额支付返回 AppId=balance)", + "schema": { + "$ref": "#/definitions/wechat.JSAPIPayParams" + } + } + } + } + }, + "/v1/posts/{id}/play": { + "get": { + "produces": [ + "application/json" + ], + "tags": [ + "Posts" + ], + "summary": "获取播放地址", + "parameters": [ + { + "type": "integer", + "format": "int64", + "description": "作品 ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "成功", + "schema": { + "$ref": "#/definitions/http.PlayUrl" + } + } + } + } + }, + "/v1/posts/{id}/show": { + "get": { + "produces": [ + "application/json" + ], + "tags": [ + "Posts" + ], + "summary": "作品详情", + "parameters": [ + { + "type": "integer", + "format": "int64", + "description": "作品 ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "成功", + "schema": { + "$ref": "#/definitions/http.PostItem" + } + } + } + } + }, + "/v1/users/profile": { + "get": { + "produces": [ + "application/json" + ], + "tags": [ + "Users" + ], + "summary": "获取个人信息", + "responses": { + "200": { + "description": "成功", + "schema": { + "$ref": "#/definitions/http.UserInfo" + } + } + } + } + }, + "/v1/users/username": { + "put": { + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Users" + ], + "summary": "修改用户名", + "parameters": [ + { + "description": "请求体", + "name": "form", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/http.ProfileForm" + } + } + ], + "responses": { + "200": { + "description": "成功", + "schema": {} + } + } + } } }, "definitions": { @@ -1091,7 +1122,7 @@ "medias": { "type": "array", "items": { - "$ref": "#/definitions/models.Media" + "$ref": "#/definitions/models.Medium" } }, "price": { @@ -1329,7 +1360,7 @@ } } }, - "models.Media": { + "models.Medium": { "type": "object", "properties": { "created_at": { @@ -1342,7 +1373,10 @@ "type": "integer" }, "metas": { - "$ref": "#/definitions/types.JSONType-fields_MediaMetas" + "type": "array", + "items": { + "type": "integer" + } }, "mime_type": { "type": "string" @@ -1435,6 +1469,9 @@ "open_id": { "type": "string" }, + "phone": { + "type": "string" + }, "status": { "$ref": "#/definitions/fields.UserStatus" }, @@ -1546,9 +1583,6 @@ "types.JSONType-array_string": { "type": "object" }, - "types.JSONType-fields_MediaMetas": { - "type": "object" - }, "types.JSONType-fields_OrderMeta": { "type": "object" }, diff --git a/backend_v1/docs/swagger.yaml b/backend_v1/docs/swagger.yaml index dfa2f40..fbaca07 100644 --- a/backend_v1/docs/swagger.yaml +++ b/backend_v1/docs/swagger.yaml @@ -57,7 +57,7 @@ definitions: type: integer medias: items: - $ref: '#/definitions/models.Media' + $ref: '#/definitions/models.Medium' type: array price: type: integer @@ -220,7 +220,7 @@ definitions: username: type: string type: object - models.Media: + models.Medium: properties: created_at: type: string @@ -229,7 +229,9 @@ definitions: id: type: integer metas: - $ref: '#/definitions/types.JSONType-fields_MediaMetas' + items: + type: integer + type: array mime_type: type: string name: @@ -290,6 +292,8 @@ definitions: $ref: '#/definitions/types.JSONType-fields_UserMetas' open_id: type: string + phone: + type: string status: $ref: '#/definitions/fields.UserStatus' updated_at: @@ -363,8 +367,6 @@ definitions: type: object types.JSONType-array_string: type: object - types.JSONType-fields_MediaMetas: - type: object types.JSONType-fields_OrderMeta: type: object types.JSONType-fields_UserAuthToken: @@ -448,7 +450,7 @@ paths: - $ref: '#/definitions/requests.Pager' - properties: items: - $ref: '#/definitions/models.Media' + $ref: '#/definitions/models.Medium' type: object summary: 媒体列表 tags: @@ -828,102 +830,8 @@ paths: summary: 调整用户余额 tags: - Admin Users - /posts: - get: - parameters: - - in: query - name: limit - type: integer - - in: query - name: page - type: integer - - in: query - name: keyword - type: string - produces: - - application/json - responses: - "200": - description: 成功 - schema: - allOf: - - $ref: '#/definitions/requests.Pager' - - properties: - items: - $ref: '#/definitions/http.PostItem' - type: object - summary: 作品列表 - tags: - - Posts - /posts/{id}/buy: + /v1/auth/{phone}: post: - parameters: - - description: 作品 ID - format: int64 - in: path - name: id - required: true - type: integer - produces: - - application/json - responses: - "200": - description: 成功(余额支付返回 AppId=balance) - schema: - $ref: '#/definitions/wechat.JSAPIPayParams' - summary: 购买作品 - tags: - - Posts - /posts/{id}/play: - get: - parameters: - - description: 作品 ID - format: int64 - in: path - name: id - required: true - type: integer - produces: - - application/json - responses: - "200": - description: 成功 - schema: - $ref: '#/definitions/http.PlayUrl' - summary: 获取播放地址 - tags: - - Posts - /posts/{id}/show: - get: - parameters: - - description: 作品 ID - format: int64 - in: path - name: id - required: true - type: integer - produces: - - application/json - responses: - "200": - description: 成功 - schema: - $ref: '#/definitions/http.PostItem' - summary: 作品详情 - tags: - - Posts - /posts/mine: - get: - parameters: - - in: query - name: limit - type: integer - - in: query - name: page - type: integer - - in: query - name: keyword - type: string produces: - application/json responses: @@ -936,41 +844,9 @@ paths: items: $ref: '#/definitions/http.PostItem' type: object - summary: 我的已购作品 + summary: 手机验证 tags: - - Posts - /users/profile: - get: - produces: - - application/json - responses: - "200": - description: 成功 - schema: - $ref: '#/definitions/http.UserInfo' - summary: 获取个人信息 - tags: - - Users - /users/username: - put: - consumes: - - application/json - parameters: - - description: 请求体 - in: body - name: form - required: true - schema: - $ref: '#/definitions/http.ProfileForm' - produces: - - application/json - responses: - "200": - description: 成功 - schema: {} - summary: 修改用户名 - tags: - - Users + - Auth /v1/medias/{id}: post: consumes: @@ -1019,6 +895,149 @@ paths: summary: 演示接口 tags: - Demo + /v1/posts: + get: + parameters: + - in: query + name: limit + type: integer + - in: query + name: page + type: integer + - in: query + name: keyword + type: string + produces: + - application/json + responses: + "200": + description: 成功 + schema: + allOf: + - $ref: '#/definitions/requests.Pager' + - properties: + items: + $ref: '#/definitions/http.PostItem' + type: object + summary: 作品列表 + tags: + - Posts + /v1/posts/{id}/buy: + post: + parameters: + - description: 作品 ID + format: int64 + in: path + name: id + required: true + type: integer + produces: + - application/json + responses: + "200": + description: 成功(余额支付返回 AppId=balance) + schema: + $ref: '#/definitions/wechat.JSAPIPayParams' + summary: 购买作品 + tags: + - Posts + /v1/posts/{id}/play: + get: + parameters: + - description: 作品 ID + format: int64 + in: path + name: id + required: true + type: integer + produces: + - application/json + responses: + "200": + description: 成功 + schema: + $ref: '#/definitions/http.PlayUrl' + summary: 获取播放地址 + tags: + - Posts + /v1/posts/{id}/show: + get: + parameters: + - description: 作品 ID + format: int64 + in: path + name: id + required: true + type: integer + produces: + - application/json + responses: + "200": + description: 成功 + schema: + $ref: '#/definitions/http.PostItem' + summary: 作品详情 + tags: + - Posts + /v1/posts/mine: + get: + parameters: + - in: query + name: limit + type: integer + - in: query + name: page + type: integer + - in: query + name: keyword + type: string + produces: + - application/json + responses: + "200": + description: 成功 + schema: + allOf: + - $ref: '#/definitions/requests.Pager' + - properties: + items: + $ref: '#/definitions/http.PostItem' + type: object + summary: 我的已购作品 + tags: + - Posts + /v1/users/profile: + get: + produces: + - application/json + responses: + "200": + description: 成功 + schema: + $ref: '#/definitions/http.UserInfo' + summary: 获取个人信息 + tags: + - Users + /v1/users/username: + put: + consumes: + - application/json + parameters: + - description: 请求体 + in: body + name: form + required: true + schema: + $ref: '#/definitions/http.ProfileForm' + produces: + - application/json + responses: + "200": + description: 成功 + schema: {} + summary: 修改用户名 + tags: + - Users securityDefinitions: BasicAuth: type: basic