fix: 完成 Gitea 目录改组收尾(import、构建与 LICENSE)
同步包路径与路由,去掉 SPA 构建步骤,对齐 Gitea 式 LICENSE,并更新规格/规则与占位 SSR。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,9 +1,9 @@
|
||||
package service
|
||||
package services
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"git.iioio.com/freefire/jiang13-forum/model"
|
||||
"git.iioio.com/freefire/jiang13-forum/models"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
@@ -19,27 +19,27 @@ const bountyRefundBlockReason = "已有用户回复,无法自行取消悬赏
|
||||
// CountEligibleBountyReplies 统计他人已发布的有效回复数(不含楼主)
|
||||
func CountEligibleBountyReplies(db *gorm.DB, postID, authorID uint) (int64, error) {
|
||||
if db == nil {
|
||||
db = model.DB
|
||||
db = models.DB
|
||||
}
|
||||
var n int64
|
||||
err := db.Model(&model.Comment{}).
|
||||
Where("post_id = ? AND status = ? AND user_id != ?", postID, model.ContentStatusPublished, authorID).
|
||||
err := db.Model(&models.Comment{}).
|
||||
Where("post_id = ? AND status = ? AND user_id != ?", postID, models.ContentStatusPublished, authorID).
|
||||
Count(&n).Error
|
||||
return n, err
|
||||
}
|
||||
|
||||
// CanRefundBounty 当前查看者是否可取消悬赏(管理员始终可强制取消)
|
||||
func CanRefundBounty(post *model.Post, viewerIsAdmin bool) (bool, string) {
|
||||
if post == nil || post.PostType != model.PostTypeBounty {
|
||||
func CanRefundBounty(post *models.Post, viewerIsAdmin bool) (bool, string) {
|
||||
if post == nil || post.PostType != models.PostTypeBounty {
|
||||
return false, ""
|
||||
}
|
||||
if post.BountyStatus != model.BountyStatusOpen || post.BountyPoints < 1 {
|
||||
if post.BountyStatus != models.BountyStatusOpen || post.BountyPoints < 1 {
|
||||
return false, ""
|
||||
}
|
||||
if viewerIsAdmin {
|
||||
return true, ""
|
||||
}
|
||||
n, err := CountEligibleBountyReplies(model.DB, post.ID, post.UserID)
|
||||
n, err := CountEligibleBountyReplies(models.DB, post.ID, post.UserID)
|
||||
if err != nil {
|
||||
return false, ""
|
||||
}
|
||||
@@ -54,42 +54,42 @@ func EscrowBounty(tx *gorm.DB, userID, postID uint, points int) error {
|
||||
if points < 1 {
|
||||
return ErrBountyInvalidPoint
|
||||
}
|
||||
_, err := AdjustPointsTx(tx, userID, -points, model.PointReasonBountyEscrow, "post", postID, "发布悬赏帖")
|
||||
_, err := AdjustPointsTx(tx, userID, -points, models.PointReasonBountyEscrow, "post", postID, "发布悬赏帖")
|
||||
return err
|
||||
}
|
||||
|
||||
// AwardBounty 采纳评论并发放悬赏
|
||||
func AwardBounty(postID, operatorID uint, isAdmin bool, commentID uint) error {
|
||||
var post model.Post
|
||||
if err := model.DB.First(&post, postID).Error; err != nil {
|
||||
var post models.Post
|
||||
if err := models.DB.First(&post, postID).Error; err != nil {
|
||||
return ErrPostNotFound
|
||||
}
|
||||
if post.PostType != model.PostTypeBounty {
|
||||
if post.PostType != models.PostTypeBounty {
|
||||
return errors.New("非悬赏帖")
|
||||
}
|
||||
if !isAdmin && post.UserID != operatorID {
|
||||
return ErrPermissionDenied
|
||||
}
|
||||
if post.BountyStatus != model.BountyStatusOpen || post.BountyPoints < 1 {
|
||||
if post.BountyStatus != models.BountyStatusOpen || post.BountyPoints < 1 {
|
||||
return ErrBountyNotOpen
|
||||
}
|
||||
var comment model.Comment
|
||||
if err := model.DB.First(&comment, commentID).Error; err != nil {
|
||||
var comment models.Comment
|
||||
if err := models.DB.First(&comment, commentID).Error; err != nil {
|
||||
return errors.New("评论不存在")
|
||||
}
|
||||
if comment.PostID != postID || comment.Status != model.ContentStatusPublished {
|
||||
if comment.PostID != postID || comment.Status != models.ContentStatusPublished {
|
||||
return errors.New("评论无效")
|
||||
}
|
||||
if comment.UserID == post.UserID {
|
||||
return ErrBountySelfAward
|
||||
}
|
||||
points := post.BountyPoints
|
||||
return model.DB.Transaction(func(tx *gorm.DB) error {
|
||||
if _, err := AdjustPointsTx(tx, comment.UserID, points, model.PointReasonBountyAward, "post", postID, "悬赏采纳"); err != nil {
|
||||
return models.DB.Transaction(func(tx *gorm.DB) error {
|
||||
if _, err := AdjustPointsTx(tx, comment.UserID, points, models.PointReasonBountyAward, "post", postID, "悬赏采纳"); err != nil {
|
||||
return err
|
||||
}
|
||||
return tx.Model(&post).Updates(map[string]interface{}{
|
||||
"bounty_status": model.BountyStatusAwarded,
|
||||
"bounty_status": models.BountyStatusAwarded,
|
||||
"bounty_comment_id": commentID,
|
||||
}).Error
|
||||
})
|
||||
@@ -97,21 +97,21 @@ func AwardBounty(postID, operatorID uint, isAdmin bool, commentID uint) error {
|
||||
|
||||
// RefundBounty 取消悬赏并退回积分
|
||||
func RefundBounty(postID, operatorID uint, isAdmin bool) error {
|
||||
var post model.Post
|
||||
if err := model.DB.First(&post, postID).Error; err != nil {
|
||||
var post models.Post
|
||||
if err := models.DB.First(&post, postID).Error; err != nil {
|
||||
return ErrPostNotFound
|
||||
}
|
||||
if post.PostType != model.PostTypeBounty {
|
||||
if post.PostType != models.PostTypeBounty {
|
||||
return errors.New("非悬赏帖")
|
||||
}
|
||||
if !isAdmin && post.UserID != operatorID {
|
||||
return ErrPermissionDenied
|
||||
}
|
||||
if post.BountyStatus != model.BountyStatusOpen || post.BountyPoints < 1 {
|
||||
if post.BountyStatus != models.BountyStatusOpen || post.BountyPoints < 1 {
|
||||
return ErrBountyNotOpen
|
||||
}
|
||||
if !isAdmin {
|
||||
n, err := CountEligibleBountyReplies(model.DB, post.ID, post.UserID)
|
||||
n, err := CountEligibleBountyReplies(models.DB, post.ID, post.UserID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -120,31 +120,31 @@ func RefundBounty(postID, operatorID uint, isAdmin bool) error {
|
||||
}
|
||||
}
|
||||
points := post.BountyPoints
|
||||
return model.DB.Transaction(func(tx *gorm.DB) error {
|
||||
if _, err := AdjustPointsTx(tx, post.UserID, points, model.PointReasonBountyRefund, "post", postID, "悬赏退回"); err != nil {
|
||||
return models.DB.Transaction(func(tx *gorm.DB) error {
|
||||
if _, err := AdjustPointsTx(tx, post.UserID, points, models.PointReasonBountyRefund, "post", postID, "悬赏退回"); err != nil {
|
||||
return err
|
||||
}
|
||||
return tx.Model(&post).Updates(map[string]interface{}{
|
||||
"bounty_status": model.BountyStatusRefunded,
|
||||
"bounty_status": models.BountyStatusRefunded,
|
||||
"bounty_points": 0,
|
||||
}).Error
|
||||
})
|
||||
}
|
||||
|
||||
// RefundBountyIfOpen 删帖时自动退回未采纳悬赏
|
||||
func RefundBountyIfOpen(tx *gorm.DB, post *model.Post) error {
|
||||
if post == nil || post.PostType != model.PostTypeBounty {
|
||||
func RefundBountyIfOpen(tx *gorm.DB, post *models.Post) error {
|
||||
if post == nil || post.PostType != models.PostTypeBounty {
|
||||
return nil
|
||||
}
|
||||
if post.BountyStatus != model.BountyStatusOpen || post.BountyPoints < 1 {
|
||||
if post.BountyStatus != models.BountyStatusOpen || post.BountyPoints < 1 {
|
||||
return nil
|
||||
}
|
||||
points := post.BountyPoints
|
||||
if _, err := AdjustPointsTx(tx, post.UserID, points, model.PointReasonBountyRefund, "post", post.ID, "删帖退回悬赏"); err != nil {
|
||||
if _, err := AdjustPointsTx(tx, post.UserID, points, models.PointReasonBountyRefund, "post", post.ID, "删帖退回悬赏"); err != nil {
|
||||
return err
|
||||
}
|
||||
return tx.Model(post).Updates(map[string]interface{}{
|
||||
"bounty_status": model.BountyStatusRefunded,
|
||||
"bounty_status": models.BountyStatusRefunded,
|
||||
"bounty_points": 0,
|
||||
}).Error
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user