Files
toutoukan/controllers/article/getarticle.go
2025-09-27 23:15:44 +08:00

172 lines
5.3 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package article
import (
"fmt"
"net/http"
"time"
"toutoukan/init/databaseInit"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
)
// ArticleList 数据库文章记录结构体
type ArticleList struct {
ArticleID int64 `gorm:"column:articleId;primaryKey;autoIncrement"`
PublishUserID string `gorm:"column:publish_user_id"`
Title string `gorm:"column:title"`
VoteType string `gorm:"column:vote_type"`
EndTime time.Time `gorm:"column:end_time"`
IsEnded bool `gorm:"column:is_ended"`
TotalVotersNum int `gorm:"column:total_voters_num"`
CreateTime time.Time `gorm:"column:create_time"`
Options []ArticleOption `gorm:"foreignKey:VoteArticleID;references:ArticleID"`
}
// ArticleOption 文评选项结构
type ArticleOption struct {
ID int64 `gorm:"column:id"`
VoteArticleID int64 `gorm:"column:vote_article_id"`
OptionContent string `gorm:"column:option_content"`
OptionVotesNum int `gorm:"column:option_votes_num"`
SortOrder int `gorm:"column:sort_order"`
}
// ArticleOptionResp 格式化后的选项响应结构
type ArticleOptionResp struct {
ID int64 `json:"id"`
Name string `json:"name"`
Votes int `json:"votes"`
IsVotedByUser bool `json:"is_voted"`
}
// ArticleResponse 单个文评的响应结构
type ArticleResponse struct {
ID int64 `json:"article_id"`
Title string `json:"article_title"`
VoteType string `json:"vote_type"`
TotalVoters int `json:"total_voters"`
EndTime string `json:"end_time"`
IsEnded bool `json:"is_ended"`
PublisherID string `json:"publisher_id"`
CreateTime string `json:"create_time"`
Options []ArticleOptionResp `json:"options"`
UserHasVoted bool `json:"user_has_voted"`
VotedOptionIDs []int64 `json:"user_voted_option_ids"`
}
// UserReq 请求参数结构体允许uid为空
type UserReq struct {
Uid string `json:"uid" binding:"omitempty"` // 允许uid为空空字符串也合法
}
// ArticleListget 获取所有文评及选项信息支持空uid场景
func ArticleListget(c *gin.Context) {
var req UserReq
// 1. 解析请求参数uid为空也能通过校验
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"error": "参数解析失败",
"detail": err.Error(),
})
return
}
// 2. 查询所有文章及关联的选项
var articles []ArticleList
if err := databaseInit.UserDB.Model(&ArticleList{}).
Preload("Options", func(db *gorm.DB) *gorm.DB {
return db.Order("sort_order ASC")
}).
Find(&articles).Error; err != nil {
c.JSON(http.StatusInternalServerError, gin.H{
"error": "查询文评失败: " + err.Error(),
})
return
}
// 3. 根据uid是否存在包括空字符串决定是否查询投票记录
userVotesMap := make(map[int64][]int64)
// 判断uid是否有效非空字符串
uidValid := req.Uid != ""
if uidValid {
// 3.1 仅当uid有效时查询用户投票记录
var userAllVotes []UserVote
if err := databaseInit.UserDB.Table("user_votes").
Where("user_id = ?", req.Uid).
Find(&userAllVotes).Error; err != nil && err != gorm.ErrRecordNotFound {
c.JSON(http.StatusInternalServerError, gin.H{
"error": "查询用户投票记录失败: " + err.Error(),
})
return
}
// 构建投票记录映射
for _, vote := range userAllVotes {
userVotesMap[vote.VoteArticleID] = append(userVotesMap[vote.VoteArticleID], vote.OptionID)
}
}
// 3.2 当uid为空时不执行任何投票查询保持映射为空
// 4. 组装响应数据
var responseList []ArticleResponse
for _, article := range articles {
// 处理投票状态
var votedOptionIDs []int64
var userHasVoted bool
if uidValid {
votedOptionIDs, userHasVoted = userVotesMap[article.ArticleID]
} else {
// uid为空时默认未投票
votedOptionIDs = []int64{}
userHasVoted = false
}
// 处理选项列表
var optionList []ArticleOptionResp
for _, opt := range article.Options {
isVoted := false
if uidValid {
// 仅在uid有效时检查是否投票
for _, votedID := range votedOptionIDs {
if opt.ID == votedID {
isVoted = true
break
}
}
}
// uid为空时isVoted保持false
optionList = append(optionList, ArticleOptionResp{
ID: opt.ID,
Name: opt.OptionContent,
Votes: opt.OptionVotesNum,
IsVotedByUser: isVoted,
})
}
// 组装文章响应
articleData := ArticleResponse{
ID: article.ArticleID,
Title: article.Title,
VoteType: article.VoteType,
TotalVoters: article.TotalVotersNum,
EndTime: article.EndTime.Format("2006-01-02 15:04:05"),
IsEnded: article.IsEnded,
PublisherID: article.PublishUserID,
CreateTime: article.CreateTime.Format("2006-01-02 15:04:05"),
Options: optionList,
UserHasVoted: userHasVoted,
VotedOptionIDs: votedOptionIDs,
}
responseList = append(responseList, articleData)
}
// 5. 返回响应
c.JSON(http.StatusOK, gin.H{
"success": true,
"message": fmt.Sprintf("查询成功,共 %d 篇文章", len(responseList)),
"data": responseList,
})
}