fix: resolve frontend build error and order refund bug, add member price filter

This commit is contained in:
2026-01-07 21:49:04 +08:00
parent 5b45f7d5c4
commit a1de16bc01
18 changed files with 772 additions and 282 deletions

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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,

View File

@@ -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]

View File

@@ -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 != "" {

View File

@@ -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("金额无效")

View File

@@ -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,