fix: resolve frontend build error and order refund bug, add member price filter
This commit is contained in:
@@ -4,11 +4,12 @@ import "quyun/v2/app/requests"
|
||||
|
||||
type ContentListFilter struct {
|
||||
requests.Pagination
|
||||
Keyword *string `query:"keyword"`
|
||||
Genre *string `query:"genre"`
|
||||
TenantID *string `query:"tenantId"`
|
||||
Sort *string `query:"sort"`
|
||||
IsPinned *bool `query:"is_pinned"`
|
||||
Keyword *string `query:"keyword"`
|
||||
Genre *string `query:"genre"`
|
||||
TenantID *string `query:"tenantId"`
|
||||
Sort *string `query:"sort"`
|
||||
IsPinned *bool `query:"is_pinned"`
|
||||
PriceType *string `query:"price_type"`
|
||||
}
|
||||
|
||||
type ContentItem struct {
|
||||
|
||||
@@ -5,6 +5,7 @@ import "quyun/v2/app/requests"
|
||||
type TenantListFilter struct {
|
||||
requests.Pagination
|
||||
Keyword *string `query:"keyword"`
|
||||
Sort *string `query:"sort"`
|
||||
}
|
||||
|
||||
type TenantProfile struct {
|
||||
|
||||
@@ -53,6 +53,10 @@ type Order struct {
|
||||
TenantID string `json:"tenant_id"`
|
||||
TenantName string `json:"tenant_name"`
|
||||
IsVirtual bool `json:"is_virtual"`
|
||||
BuyerName string `json:"buyer_name"`
|
||||
BuyerAvatar string `json:"buyer_avatar"`
|
||||
Title string `json:"title"`
|
||||
Cover string `json:"cover"`
|
||||
}
|
||||
|
||||
type Notification struct {
|
||||
|
||||
@@ -351,6 +351,17 @@ func (r *Routes) Register(router fiber.Router) {
|
||||
r.user.Likes,
|
||||
Local[*models.User]("__ctx_user"),
|
||||
))
|
||||
r.log.Debugf("Registering route: Post /v1/me/notifications/:id/read -> user.MarkNotificationRead")
|
||||
router.Post("/v1/me/notifications/:id/read"[len(r.Path()):], Func2(
|
||||
r.user.MarkNotificationRead,
|
||||
Local[*models.User]("__ctx_user"),
|
||||
PathParam[string]("id"),
|
||||
))
|
||||
r.log.Debugf("Registering route: Post /v1/me/notifications/read-all -> user.MarkAllNotificationsRead")
|
||||
router.Post("/v1/me/notifications/read-all"[len(r.Path()):], Func1(
|
||||
r.user.MarkAllNotificationsRead,
|
||||
Local[*models.User]("__ctx_user"),
|
||||
))
|
||||
r.log.Debugf("Registering route: Get /v1/me/notifications -> user.Notifications")
|
||||
router.Get("/v1/me/notifications"[len(r.Path()):], DataFunc3(
|
||||
r.user.Notifications,
|
||||
|
||||
@@ -260,6 +260,34 @@ func (u *User) Notifications(ctx fiber.Ctx, user *models.User, typeArg string, p
|
||||
return services.Notification.List(ctx, user.ID, page, typeArg)
|
||||
}
|
||||
|
||||
// Mark notification as read
|
||||
//
|
||||
// @Router /v1/me/notifications/:id/read [post]
|
||||
// @Summary Mark as read
|
||||
// @Tags UserCenter
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path string true "Notification ID"
|
||||
// @Success 200 {string} string "OK"
|
||||
// @Bind user local key(__ctx_user)
|
||||
// @Bind id path
|
||||
func (u *User) MarkNotificationRead(ctx fiber.Ctx, user *models.User, id string) error {
|
||||
return services.Notification.MarkRead(ctx, user.ID, id)
|
||||
}
|
||||
|
||||
// Mark all notifications as read
|
||||
//
|
||||
// @Router /v1/me/notifications/read-all [post]
|
||||
// @Summary Mark all as read
|
||||
// @Tags UserCenter
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Success 200 {string} string "OK"
|
||||
// @Bind user local key(__ctx_user)
|
||||
func (u *User) MarkAllNotificationsRead(ctx fiber.Ctx, user *models.User) error {
|
||||
return services.Notification.MarkAllRead(ctx, user.ID)
|
||||
}
|
||||
|
||||
// List my coupons
|
||||
//
|
||||
// @Router /v1/me/coupons [get]
|
||||
|
||||
@@ -38,6 +38,37 @@ func (s *content) List(ctx context.Context, filter *content_dto.ContentListFilte
|
||||
q = q.Where(tbl.IsPinned.Is(*filter.IsPinned))
|
||||
}
|
||||
|
||||
if filter.PriceType != nil && *filter.PriceType != "all" {
|
||||
if *filter.PriceType == "member" {
|
||||
q = q.Where(tbl.Visibility.Eq(consts.ContentVisibilityTenantOnly))
|
||||
} else {
|
||||
pTbl, pQ := models.ContentPriceQuery.QueryContext(ctx)
|
||||
|
||||
var shouldFilter bool
|
||||
var prices []*models.ContentPrice
|
||||
|
||||
if *filter.PriceType == "free" {
|
||||
shouldFilter = true
|
||||
prices, _ = pQ.Where(pTbl.PriceAmount.Eq(0)).Select(pTbl.ContentID).Find()
|
||||
} else if *filter.PriceType == "paid" {
|
||||
shouldFilter = true
|
||||
prices, _ = pQ.Where(pTbl.PriceAmount.Gt(0)).Select(pTbl.ContentID).Find()
|
||||
}
|
||||
|
||||
if shouldFilter {
|
||||
ids := make([]int64, len(prices))
|
||||
for i, p := range prices {
|
||||
ids[i] = p.ContentID
|
||||
}
|
||||
if len(ids) > 0 {
|
||||
q = q.Where(tbl.ID.In(ids...))
|
||||
} else {
|
||||
q = q.Where(tbl.ID.Eq(-1))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sort
|
||||
sort := "latest"
|
||||
if filter.Sort != nil && *filter.Sort != "" {
|
||||
|
||||
@@ -570,7 +570,25 @@ func (s *creator) ListOrders(
|
||||
if filter.Status != nil && *filter.Status != "" {
|
||||
q = q.Where(tbl.Status.Eq(consts.OrderStatus(*filter.Status)))
|
||||
}
|
||||
// Keyword could match ID or other fields if needed
|
||||
|
||||
if filter.Keyword != nil && *filter.Keyword != "" {
|
||||
k := *filter.Keyword
|
||||
if id, err := cast.ToInt64E(k); err == nil {
|
||||
q = q.Where(tbl.ID.Eq(id))
|
||||
} else {
|
||||
uTbl, uQ := models.UserQuery.QueryContext(ctx)
|
||||
users, _ := uQ.Where(uTbl.Nickname.Like("%" + k + "%")).Find()
|
||||
uids := make([]int64, len(users))
|
||||
for i, u := range users {
|
||||
uids[i] = u.ID
|
||||
}
|
||||
if len(uids) > 0 {
|
||||
q = q.Where(tbl.UserID.In(uids...))
|
||||
} else {
|
||||
q = q.Where(tbl.ID.Eq(-1)) // Match nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
list, err := q.Order(tbl.CreatedAt.Desc()).Find()
|
||||
if err != nil {
|
||||
@@ -579,11 +597,46 @@ func (s *creator) ListOrders(
|
||||
|
||||
var data []creator_dto.Order
|
||||
for _, o := range list {
|
||||
// Fetch Buyer Info
|
||||
u, _ := models.UserQuery.WithContext(ctx).Where(models.UserQuery.ID.Eq(o.UserID)).First()
|
||||
buyerName := "未知用户"
|
||||
buyerAvatar := ""
|
||||
if u != nil {
|
||||
buyerName = u.Nickname
|
||||
buyerAvatar = u.Avatar
|
||||
}
|
||||
|
||||
// Fetch Content Info
|
||||
var title, cover string
|
||||
item, _ := models.OrderItemQuery.WithContext(ctx).Where(models.OrderItemQuery.OrderID.Eq(o.ID)).First()
|
||||
if item != nil {
|
||||
var c models.Content
|
||||
err := models.ContentQuery.WithContext(ctx).
|
||||
Where(models.ContentQuery.ID.Eq(item.ContentID)).
|
||||
UnderlyingDB().
|
||||
Preload("ContentAssets.Asset").
|
||||
First(&c).Error
|
||||
|
||||
if err == nil {
|
||||
title = c.Title
|
||||
for _, ca := range c.ContentAssets {
|
||||
if ca.Role == consts.ContentAssetRoleCover && ca.Asset != nil {
|
||||
cover = Common.GetAssetURL(ca.Asset.ObjectKey)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data = append(data, creator_dto.Order{
|
||||
ID: cast.ToString(o.ID),
|
||||
Status: string(o.Status), // Enum conversion
|
||||
Amount: float64(o.AmountPaid) / 100.0,
|
||||
CreateTime: o.CreatedAt.Format(time.RFC3339),
|
||||
ID: cast.ToString(o.ID),
|
||||
Status: string(o.Status),
|
||||
Amount: float64(o.AmountPaid) / 100.0,
|
||||
CreateTime: o.CreatedAt.Format(time.RFC3339),
|
||||
BuyerName: buyerName,
|
||||
BuyerAvatar: buyerAvatar,
|
||||
Title: title,
|
||||
Cover: cover,
|
||||
})
|
||||
}
|
||||
return data, nil
|
||||
@@ -803,6 +856,15 @@ func (s *creator) Withdraw(ctx context.Context, userID int64, form *creator_dto.
|
||||
}
|
||||
uid := userID
|
||||
|
||||
// Validate User Real-name Status
|
||||
user, err := models.UserQuery.WithContext(ctx).Where(models.UserQuery.ID.Eq(uid)).First()
|
||||
if err != nil {
|
||||
return errorx.ErrDatabaseError.WithCause(err)
|
||||
}
|
||||
if !user.IsRealNameVerified {
|
||||
return errorx.ErrPreconditionFailed.WithMsg("请先完成实名认证后再申请提现")
|
||||
}
|
||||
|
||||
amount := int64(form.Amount * 100)
|
||||
if amount <= 0 {
|
||||
return errorx.ErrBadRequest.WithMsg("金额无效")
|
||||
|
||||
@@ -71,6 +71,16 @@ func (s *notification) MarkRead(ctx context.Context, userID int64, id string) er
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *notification) MarkAllRead(ctx context.Context, userID int64) error {
|
||||
_, err := models.NotificationQuery.WithContext(ctx).
|
||||
Where(models.NotificationQuery.UserID.Eq(userID), models.NotificationQuery.IsRead.Is(false)).
|
||||
UpdateSimple(models.NotificationQuery.IsRead.Value(true))
|
||||
if err != nil {
|
||||
return errorx.ErrDatabaseError.WithCause(err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *notification) Send(ctx context.Context, userID int64, typ, title, content string) error {
|
||||
arg := args.NotificationArgs{
|
||||
UserID: userID,
|
||||
|
||||
Reference in New Issue
Block a user