第 5 阶段:纠纷、通知与后台-4

This commit is contained in:
yml
2026-05-22 17:04:28 +08:00
parent e72decebc8
commit 3f5f18b43e
14 changed files with 332 additions and 18 deletions
+115 -9
View File
@@ -5,8 +5,10 @@ import (
"time"
"hfb_sys/backend/internal/model"
"hfb_sys/backend/internal/modules/notification"
"gorm.io/gorm"
"gorm.io/gorm/clause"
)
type Repository struct {
@@ -102,6 +104,49 @@ func (r *Repository) SubmitReview(ownerID uint64, listingID uint64) (*ListingDTO
if err != nil {
return err
}
if listing.Status == "rented" {
return ErrListingLocked
}
listing.Status = "draft"
listing.ReviewStatus = "pending"
listing.ReviewReason = ""
listing.PublishedAt = nil
account.Status = "draft"
if err := tx.Save(account).Error; err != nil {
return err
}
if err := tx.Save(listing).Error; err != nil {
return err
}
dto = toDTO(*account, *listing)
return nil
})
return dto, err
}
func (r *Repository) ListPendingReview() ([]ListingDTO, error) {
var rows []listingRow
err := r.baseQuery().
Where("l.review_status = ?", "pending").
Order("l.updated_at ASC, l.id ASC").
Limit(200).
Scan(&rows).Error
if err != nil {
return nil, err
}
return rowsToDTO(rows), nil
}
func (r *Repository) Approve(listingID uint64) (*ListingDTO, error) {
var dto *ListingDTO
err := r.db.Transaction(func(tx *gorm.DB) error {
listing, account, err := r.findForReviewUpdate(tx, listingID)
if err != nil {
return err
}
if listing.Status == "rented" {
return ErrListingLocked
}
now := time.Now()
listing.Status = "published"
listing.ReviewStatus = "approved"
@@ -114,6 +159,55 @@ func (r *Repository) SubmitReview(ownerID uint64, listingID uint64) (*ListingDTO
if err := tx.Save(listing).Error; err != nil {
return err
}
listingID := listing.ID
if err := notification.Append(tx, notification.Entry{
UserID: listing.OwnerID,
Type: "listing_review",
Title: "发布审核通过",
Content: "你的租号发布已审核通过并上架。",
BizType: "listing",
BizID: &listingID,
}); err != nil {
return err
}
dto = toDTO(*account, *listing)
return nil
})
return dto, err
}
func (r *Repository) Reject(listingID uint64, req ReviewRequest) (*ListingDTO, error) {
var dto *ListingDTO
err := r.db.Transaction(func(tx *gorm.DB) error {
listing, account, err := r.findForReviewUpdate(tx, listingID)
if err != nil {
return err
}
if listing.Status == "rented" {
return ErrListingLocked
}
listing.Status = "draft"
listing.ReviewStatus = "rejected"
listing.ReviewReason = req.Reason
listing.PublishedAt = nil
account.Status = "draft"
if err := tx.Save(account).Error; err != nil {
return err
}
if err := tx.Save(listing).Error; err != nil {
return err
}
listingID := listing.ID
if err := notification.Append(tx, notification.Entry{
UserID: listing.OwnerID,
Type: "listing_review",
Title: "发布审核未通过",
Content: "你的租号发布未通过审核,请根据原因修改后重新提交。",
BizType: "listing",
BizID: &listingID,
}); err != nil {
return err
}
dto = toDTO(*account, *listing)
return nil
})
@@ -140,9 +234,7 @@ func (r *Repository) Offline(ownerID uint64, listingID uint64) error {
func (r *Repository) ListPublic() ([]ListingDTO, error) {
var rows []listingRow
err := r.db.Table("rental_listings AS l").
Select("l.*, a.title, a.description, a.game_name, a.server_region, a.login_platform, a.rank_level, a.haf_coin_amount").
Joins("JOIN game_accounts AS a ON a.id = l.account_id").
err := r.baseQuery().
Where("l.status = ? AND l.review_status = ?", "published", "approved").
Order("l.published_at DESC, l.id DESC").
Limit(100).
@@ -155,9 +247,7 @@ func (r *Repository) ListPublic() ([]ListingDTO, error) {
func (r *Repository) ListMine(ownerID uint64) ([]ListingDTO, error) {
var rows []listingRow
err := r.db.Table("rental_listings AS l").
Select("l.*, a.title, a.description, a.game_name, a.server_region, a.login_platform, a.rank_level, a.haf_coin_amount").
Joins("JOIN game_accounts AS a ON a.id = l.account_id").
err := r.baseQuery().
Where("l.owner_id = ?", ownerID).
Order("l.id DESC").
Scan(&rows).Error
@@ -189,9 +279,7 @@ func (r *Repository) findOwnedForUpdate(tx *gorm.DB, ownerID uint64, listingID u
func (r *Repository) findDTO(where string, args ...any) (*ListingDTO, error) {
var row listingRow
err := r.db.Table("rental_listings AS l").
Select("l.*, a.title, a.description, a.game_name, a.server_region, a.login_platform, a.rank_level, a.haf_coin_amount").
Joins("JOIN game_accounts AS a ON a.id = l.account_id").
err := r.baseQuery().
Where(where, args...).
First(&row).Error
if err != nil {
@@ -201,6 +289,24 @@ func (r *Repository) findDTO(where string, args ...any) (*ListingDTO, error) {
return &dto, nil
}
func (r *Repository) baseQuery() *gorm.DB {
return r.db.Table("rental_listings AS l").
Select("l.*, a.title, a.description, a.game_name, a.server_region, a.login_platform, a.rank_level, a.haf_coin_amount").
Joins("JOIN game_accounts AS a ON a.id = l.account_id")
}
func (r *Repository) findForReviewUpdate(tx *gorm.DB, listingID uint64) (*model.RentalListing, *model.GameAccount, error) {
var listing model.RentalListing
if err := tx.Clauses(clause.Locking{Strength: "UPDATE"}).First(&listing, listingID).Error; err != nil {
return nil, nil, err
}
var account model.GameAccount
if err := tx.Clauses(clause.Locking{Strength: "UPDATE"}).First(&account, listing.AccountID).Error; err != nil {
return nil, nil, err
}
return &listing, &account, nil
}
type listingRow struct {
model.RentalListing
Title string