364 lines
7.8 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 controller
import (
"fmt"
"github.com/gin-gonic/gin"
"net/http"
"sort"
"strconv"
"time"
"vote-api/api/dao"
"vote-api/api/dto"
"vote-api/api/model"
"vote-api/api/requests"
"vote-api/api/responses"
"vote-api/api/service"
"vote-api/consts"
"vote-api/global"
"vote-api/utils"
)
type Video struct{}
// GetVideoPage 获取视频列表-分页
func (r *Video) GetVideoPage(c *gin.Context) {
videoRequest := requests.VideoRequest{}
req := videoRequest.GetVideoPage
if err := c.ShouldBind(&req); err != nil {
responses.FailWithMessage(err.Error(), c)
return
}
// 参数验证
if err := global.Validate.Struct(req); err != nil {
responses.FailWithMessage(utils.Translate(err), c)
return
}
if req.Page == 0 {
req.Page = 1
}
if req.PageSize == 0 {
req.PageSize = 20
}
// 获取数据
videoDao := dao.VideoDao{}
videos, total, err := videoDao.GetVideoPageSearch(req, req.Page, req.PageSize)
if err != nil {
responses.FailWithMessage(err.Error(), c)
return
}
// 处理返回值
g := dto.GetVideoListDto(videos)
// 检测用户今日是否投票
userId := c.GetInt64("UserId")
if userId != 0 {
userService := service.UserService{}
for _, videoDto := range g {
videoId, err := strconv.ParseInt(videoDto.VideoId, 10, 64)
if err != nil {
continue
}
videoDto.IsVote = userService.CheckUserVoteDay(userId, videoId, 2)
}
}
result := make(map[string]interface{})
result["page"] = req.Page
result["page_size"] = req.PageSize
result["total"] = total
result["data"] = g
responses.OkWithData(result, c)
}
// GetVideo 获取视频详情
func (r *Video) GetVideo(c *gin.Context) {
id := c.Param("video_id")
if id == "" {
responses.FailWithMessage("缺少参数", c)
return
}
// 将 id 转换为 int64 类型
videoId, err := strconv.ParseInt(id, 10, 64)
if err != nil {
responses.Fail(c)
return
}
// 获取数据
videoDao := dao.VideoDao{}
video, err := videoDao.GetVideoById(videoId)
if err != nil {
responses.FailWithMessage("文章错误", c)
return
}
// 获取视频作者
videoAuthorDao := dao.VideoAuthorDao{}
videoAuthors, err := videoAuthorDao.GetVideoAuthorListPreloadByVideoId(videoId)
if err != nil {
responses.FailWithMessage("文章错误", c)
return
}
video.VideoAuthor = videoAuthors
// 处理返回值
g := dto.GetVideoDto(video)
// 获取排名开关限制
systemConfigDao := dao.SystemConfigDao{}
systemConfig, err := systemConfigDao.GetSystemConfigById(1)
if err != nil {
responses.OkWithData(nil, c)
return
}
if systemConfig.IsDisplayRank == 1 {
// 获取大于某一投票数的文章
maps := make(map[string]interface{})
maps["article_status"] = 1
videos, err := videoDao.GetVideoListGtVoteNum(maps, video.VoteNum)
if err == nil {
rank := len(videos) + 1
// 加载数据-作者排名
g.LoadRank(rank)
}
}
// 加载数据-作者
g.LoadVideoAuthor(video.VideoAuthor)
// 检测用户今日是否投票
userId := c.GetInt64("UserId")
if userId != 0 {
userService := service.UserService{}
isVote := userService.CheckUserVoteDay(userId, videoId, 2)
// 加载数据-投票状态
g.LoadVoteStatus(isVote)
}
responses.OkWithData(g, c)
}
// GetVideoRankList 获取视频排名列表
func (r *Video) GetVideoRankList(c *gin.Context) {
// 获取排名开关限制
systemConfigDao := dao.SystemConfigDao{}
systemConfig, err := systemConfigDao.GetSystemConfigById(1)
if err != nil {
responses.OkWithData(nil, c)
return
}
if systemConfig.IsDisplayRank == 0 {
responses.OkWithData(nil, c)
return
}
// 获取数据
videoDao := dao.VideoDao{}
maps := make(map[string]interface{})
maps["video_status"] = 1
videos, err := videoDao.GetVideoRankList(maps, "vote_num desc", 15)
if err != nil {
responses.OkWithData(nil, c)
return
}
// 处理数据
for i, video := range videos {
// 判断最后两位票数是否相同
if i == 14 {
maps = make(map[string]interface{})
maps["article_status"] = 1
maps["vote_num"] = video.VoteNum
results, err := videoDao.GetVideoList(maps)
if err != nil {
responses.OkWithData(nil, c)
return
}
for _, result := range results {
if result.VideoId == video.VideoId {
continue
}
videos = append(videos, result)
}
}
}
// 处理返回值
g := dto.GetVideoListDto(videos)
// 检测用户今日是否投票
userId := c.GetInt64("UserId")
if userId != 0 {
userService := service.UserService{}
for _, videoDto := range g {
videoId, err := strconv.ParseInt(videoDto.VideoId, 10, 64)
if err != nil {
continue
}
videoDto.IsVote = userService.CheckUserVoteDay(userId, videoId, 2)
}
}
// 根据 VoteNum 降序排序
sort.SliceStable(g, func(i, j int) bool {
return g[i].VoteNum > g[j].VoteNum
})
// 计算排名
var currentRank int
for k, v := range g {
if k == 0 {
// 第一个元素排名设为1
currentRank = 1
} else if g[k].VoteNum < g[k-1].VoteNum {
currentRank = k + 1
}
// 为当前元素设置 Rank
rank := currentRank // 创建一个新的变量来保存排名
v.Rank = &rank // 将新的变量的地址赋给 Rank
}
responses.OkWithData(g, c)
}
// AddVideoVote 视频投票
func (r *Video) AddVideoVote(c *gin.Context) {
id := c.Param("video_id")
if id == "" {
responses.FailWithMessage("缺少参数", c)
return
}
// 将 id 转换为 int64 类型
videoId, err := strconv.ParseInt(id, 10, 64)
if err != nil {
responses.Fail(c)
return
}
userId := c.GetInt64("UserId")
if userId == 0 {
c.JSON(http.StatusUnauthorized, gin.H{
"message": "请登录后投票",
"code": consts.TokenError,
"data": "",
})
return
}
// 检测并发请求
redisKey := "AddVideoVote" + fmt.Sprintf("%d", userId) + fmt.Sprintf("%d", videoId)
res, _ := global.Redis.Get(c, redisKey).Result()
if res != "" {
responses.FailWithMessage("请勿重复操作", c)
return
}
defer func(redisKey string) {
global.Redis.Del(c, redisKey)
}(redisKey)
// 添加缓存
_, err = global.Redis.Set(c, redisKey, "1", (1)*time.Second).Result()
if err != nil {
responses.FailWithMessage("投票失败", c)
return
}
// 获取数据
videoDao := dao.VideoDao{}
video, err := videoDao.GetVideoById(videoId)
if err != nil || video == nil {
responses.FailWithMessage("非法数据", c)
return
}
// 检测投票有效期
systemTimeService := service.SystemTimeService{}
isValid := systemTimeService.CheckVoteValidStatus()
if isValid == false {
responses.FailWithMessage("投票已结束", c)
return
}
// 检测用户今日是否投票
userService := service.UserService{}
isVote := userService.CheckUserVoteDay(userId, videoId, 2)
if isVote == true {
responses.FailWithMessage("请勿重复投票", c)
return
}
// 开始事务
tx := global.Db.Begin()
defer func() {
if r := recover(); r != nil {
tx.Rollback()
utils.LogJsonErr("投票失败", r)
responses.FailWithMessage("投票失败", c)
return
}
}()
// 增加投票数
err = videoDao.Inc(tx, videoId, "vote_num", 1)
if err != nil {
tx.Rollback()
responses.FailWithMessage("投票失败", c)
return
}
// 增加投票记录
nowDay, _ := time.Parse("2006-01-02", time.Now().Format("2006-01-02"))
votedAt := model.LocalTime(nowDay)
videoVoteDay := &model.VideoVoteDay{
VideoId: videoId,
UserId: userId,
VotedAt: &votedAt,
}
videoVoteDayDao := dao.VideoVoteDayDao{}
videoVoteDay, err = videoVoteDayDao.AddVideoVoteDay(tx, videoVoteDay)
if err != nil {
tx.Rollback()
responses.FailWithMessage("投票失败", c)
return
}
// 增加数据表-投票数量
dataDao := dao.DataDao{}
err = dataDao.Inc(tx, 1, "vote_num", 1)
if err != nil {
tx.Rollback()
responses.FailWithMessage("投票失败", c)
return
}
// 新增投票缓存
result := userService.AddUserVoteDayCache(userId, videoId, 2)
if result == false {
tx.Rollback()
responses.FailWithMessage("投票失败", c)
return
}
tx.Commit()
responses.Ok(c)
}