package controller import ( "fmt" "github.com/gin-gonic/gin" "net/http" "sort" "strconv" "time" "vote-video-api/api/dao" "vote-video-api/api/dto" "vote-video-api/api/model" "vote-video-api/api/requests" "vote-video-api/api/responses" "vote-video-api/api/service" "vote-video-api/consts" "vote-video-api/global" "vote-video-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["video_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 } var videoIds []int64 for _, video := range videos { videoIds = append(videoIds, video.VideoId) } // 处理数据 for i, video := range videos { videoIds = append(videoIds, video.VideoId) // 判断最后两位票数是否相同 if i == 14 { maps = make(map[string]interface{}) maps["video_status"] = 1 maps["vote_num"] = video.VoteNum results, err := videoDao.GetVideoListNotIn(maps, videoIds) if err != nil { responses.OkWithData(nil, c) return } for _, result := range results { 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) }