Files
toutoukan/controllers/article/getarticle.go
2025-09-24 20:57:23 +08:00

151 lines
4.9 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 数据库文章记录结构体
// 添加了与 ArticleOption 的关联
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"`
// 这是关键:定义 Has Many 关联,表示一篇文章有多个选项
Options []ArticleOption `gorm:"foreignKey:VoteArticleID;references:ArticleID"`
}
// ArticleOption 文评选项结构
type ArticleOption struct {
ID int64 `gorm:"column:id"`
VoteArticleID int64 `gorm:"column:vote_article_id"` // 外键,关联 ArticleList
OptionContent string `gorm:"column:option_content"`
OptionVotesNum int `gorm:"column:option_votes_num"`
SortOrder int `gorm:"column:sort_order"`
}
// UserVote 用户投票记录表结构
// 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:"文评ID"`
Title string `json:"文评标题"`
VoteType string `json:"投票类型"`
TotalVoters int `json:"总投票人数"`
EndTime string `json:"结束时间"`
IsEnded bool `json:"是否结束"`
PublisherID string `json:"发布者ID"`
CreateTime string `json:"创建时间"`
Options []ArticleOptionResp `json:"选项"`
UserHasVoted bool `json:"用户是否已投票"`
VotedOptionIDs []int64 `json:"用户投票的选项ID"`
}
type UserReq struct {
Uid string `json:"uid" binding:"required"`
}
// ArticleListget 获取所有文评及选项信息(包含用户投票状态)
func ArticleListget(c *gin.Context) {
var req UserReq
// 1. 解析并验证请求参数
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"error": "参数解析失败",
"detail": err.Error(),
})
return
}
// 2. 使用 Preload 一次性查询所有文章和它们的选项
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. 一次性查询当前用户的所有投票记录,并构建一个 map 方便查找
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
}
// 投票记录 mapkey: articleId, value: []optionId
userVotesMap := make(map[int64][]int64)
for _, vote := range userAllVotes {
userVotesMap[vote.VoteArticleID] = append(userVotesMap[vote.VoteArticleID], vote.OptionID)
}
// 4. 组装最终响应数据
var responseList []ArticleResponse
for _, article := range articles {
votedOptionIDs, userHasVoted := userVotesMap[article.ArticleID]
// 格式化选项数据
var optionList []ArticleOptionResp
for _, opt := range article.Options {
isVoted := false
for _, votedID := range votedOptionIDs {
if opt.ID == votedID {
isVoted = true
break
}
}
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)
}
c.JSON(http.StatusOK, gin.H{
"success": true,
"message": fmt.Sprintf("查询成功,共 %d 篇文章", len(responseList)),
"data": responseList,
})
}