Browse Source

Merge branch 'yb/11.3'

hsun 2 years ago
parent
commit
884ff00405

+ 68 - 0
controller/bullet_chat/bullet_chat.go

@@ -0,0 +1,68 @@
+package bullet_chat
+
+import (
+	"fmt"
+	"github.com/gin-gonic/gin"
+	"hongze/hongze_yb/controller/response"
+	"hongze/hongze_yb/models/request"
+	responseModel "hongze/hongze_yb/models/response"
+	"hongze/hongze_yb/services/bullet_chat"
+	"hongze/hongze_yb/services/user"
+	"hongze/hongze_yb/services/wx_app"
+	"strconv"
+)
+
+// Add
+// @Description 新增弹幕
+// @Success 200 {string} string "操作成功"
+// @Router /bullet_chat/add [post]
+func Add(c *gin.Context) {
+	userInfo := user.GetInfoByClaims(c)
+	if userInfo.UserID <= 0 {
+		response.Fail("请登录后操作", c)
+		return
+	}
+
+	var req request.BulletChatAddReq
+	if c.ShouldBind(&req) != nil {
+		response.Fail("参数有误", c)
+		return
+	}
+	if req.PrimaryId <= 0 {
+		response.Fail("参数有误", c)
+		return
+	}
+	if req.Content == "" {
+		response.Fail("内容不可为空", c)
+		return
+	}
+	if len([]rune(req.Content)) > 50 {
+		response.Fail("内容不可超过50个字", c)
+		return
+	}
+	// 敏感词校验
+	// TODO:如果备用小程序提上master的话,此处要有调整(2022/11/08)
+	if userInfo.RecordInfo.OpenID != "" && userInfo.RecordInfo.CreatePlatform == 6 {
+		checkResult, e := wx_app.MsgSecCheck(userInfo.RecordInfo.OpenID, req.Content)
+		if e == nil {
+			if checkResult.Result != nil && checkResult.Result.Suggest != "pass" {
+				errMsg := "含有违禁词, 不允许发布: " + checkResult.Result.Suggest + ", 命中标签: " + strconv.Itoa(checkResult.Result.Label)
+				response.FailMsg("内容含有违禁词, 不允许发布", errMsg, c)
+				return
+			}
+		}
+	}
+
+	bc, e := bullet_chat.CreateBulletChat(int(userInfo.UserID), req.PrimaryId, req.Source, req.SourceAgent, req.Seconds, req.Content)
+	if e != nil {
+		response.FailMsg("发布失败", "新增弹幕失败, Err: "+e.Error(), c)
+		return
+	}
+	resp := new(responseModel.BulletChatItem)
+	resp.Id = bc.ID
+	resp.UserId = bc.UserID
+	resp.Content = bc.Content
+	resp.Seconds = fmt.Sprint(bc.Seconds)
+	resp.Color = bc.Color
+	response.OkData("操作成功", resp, c)
+}

+ 30 - 2
controller/community/video.go

@@ -1,9 +1,12 @@
 package community
 
 import (
+	"fmt"
 	"github.com/gin-gonic/gin"
 	"hongze/hongze_yb/controller/response"
 	"hongze/hongze_yb/models/request"
+	responseModel "hongze/hongze_yb/models/response"
+	"hongze/hongze_yb/services/bullet_chat"
 	"hongze/hongze_yb/services/community"
 	"hongze/hongze_yb/services/user"
 	"hongze/hongze_yb/utils"
@@ -38,6 +41,10 @@ func VideoList(c *gin.Context) {
 		response.FailMsg("获取失败", "VideoList ErrMsg:"+err.Error(), c)
 		return
 	}
+	idsArr := make([]int, 0)
+	for i := range list {
+		idsArr = append(idsArr, list[i].CommunityVideoID)
+	}
 
 	// 点赞/吐槽数据
 	err = community.HandleLikeOrTeaseByCommunityVideoItemList(userInfo.UserID, list)
@@ -53,6 +60,29 @@ func VideoList(c *gin.Context) {
 		return
 	}
 
+	// 弹幕数据
+	idBulletsMap, e := bullet_chat.GetListMapBySourceAndIds(bullet_chat.SourceBulletChatVideo, idsArr)
+	if e != nil {
+		response.FailMsg("获取失败", "获取视频社区弹幕列表Map失败, Err: "+e.Error(), c)
+		return
+	}
+	for i := range list {
+		ls := make([]*responseModel.BulletChatItem, 0)
+		bs := idBulletsMap[list[i].CommunityVideoID]
+		if bs != nil && len(bs) > 0 {
+			for k := range bs {
+				ls = append(ls, &responseModel.BulletChatItem{
+					Id:      bs[k].ID,
+					Content: bs[k].Content,
+					UserId:  bs[k].UserID,
+					Color:   bs[k].Color,
+					Seconds: fmt.Sprint(bs[k].Seconds),
+				})
+			}
+		}
+		list[i].BulletChatList = ls
+	}
+
 	response.OkData("获取成功", list, c)
 }
 
@@ -86,5 +116,3 @@ func VideoPlayLog(c *gin.Context) {
 	}
 	response.OkData("操作成功", newId, c)
 }
-
-

+ 31 - 0
controller/road/video.go

@@ -1,9 +1,12 @@
 package road
 
 import (
+	"fmt"
 	"github.com/gin-gonic/gin"
 	"hongze/hongze_yb/controller/response"
 	"hongze/hongze_yb/models/request"
+	responseModel "hongze/hongze_yb/models/response"
+	"hongze/hongze_yb/services/bullet_chat"
 	"hongze/hongze_yb/services/community"
 	"hongze/hongze_yb/services/user"
 	"hongze/hongze_yb/utils"
@@ -57,6 +60,34 @@ func VideoList(c *gin.Context) {
 		return
 	}
 
+	idsArr := make([]int, 0)
+	for i := range list.List {
+		idsArr = append(idsArr, list.List[i].RoadVideoID)
+	}
+
+	// 弹幕数据
+	idBulletsMap, e := bullet_chat.GetListMapBySourceAndIds(bullet_chat.SourceBulletChatRoadVideo, idsArr)
+	if e != nil {
+		response.FailMsg("获取失败", "获取视频社区弹幕列表Map失败, Err: "+e.Error(), c)
+		return
+	}
+	for i := range list.List {
+		ls := make([]*responseModel.BulletChatItem, 0)
+		bs := idBulletsMap[list.List[i].RoadVideoID]
+		if bs != nil && len(bs) > 0 {
+			for k := range bs {
+				ls = append(ls, &responseModel.BulletChatItem{
+					Id:      bs[k].ID,
+					Content: bs[k].Content,
+					UserId:  bs[k].UserID,
+					Color:   bs[k].Color,
+					Seconds: fmt.Sprint(bs[k].Seconds),
+				})
+			}
+		}
+		list.List[i].BulletChatList = ls
+	}
+
 	response.OkData("获取成功", list, c)
 }
 

+ 2 - 0
init_serve/router.go

@@ -75,5 +75,7 @@ func InitRouter() (r *gin.Engine) {
 	routers.InitRoad(r)
 	// 收藏路由
 	routers.InitCollection(r)
+	// 弹幕路由
+	routers.InitBulletChat(r)
 	return
 }

+ 10 - 0
models/request/bullet_chat.go

@@ -0,0 +1,10 @@
+package request
+
+// BulletChatAddReq 新增弹幕请求体
+type BulletChatAddReq struct {
+	Content     string  `json:"content" description:"弹幕内容"`
+	Seconds     float64 `json:"seconds" description:"时间点"`
+	Source      int     `json:"source" description:"弹幕来源: 1-视频社区; 2-线上路演"`
+	SourceAgent int     `json:"source_agent" description:"来源: 1-小程序; 2-小程序PC端; 3-弘则研究公众号; 4-Web PC"`
+	PrimaryId   int     `json:"primary_id" description:"视频社区/线上路演ID"`
+}

+ 10 - 0
models/response/bullet_chat.go

@@ -0,0 +1,10 @@
+package response
+
+// BulletChatItem 弹幕响应体
+type BulletChatItem struct {
+	Id      int    `json:"id" description:"弹幕ID"`
+	Content string `json:"content" description:"弹幕内容"`
+	UserId  int    `json:"user_id" description:"用户ID"`
+	Color   string `json:"color" description:"颜色"`
+	Seconds string `json:"seconds" description:"时间点(秒)"`
+}

+ 2 - 0
models/response/community.go

@@ -92,6 +92,7 @@ type CommunityVideoItem struct {
 	CommentTotal        int                                 `json:"comment_total" description:"总共评论数"`
 	CommentList         []*CommunityQuestionCommentListItem `json:"comment_list"`
 	CollectionId        int                                 `description:"收藏ID: 大于0则表示已收藏" json:"collection_id"`
+	BulletChatList      []*BulletChatItem                   `json:"bullet_chat_list" description:"弹幕列表"`
 }
 
 // RoadVideoItem 线上路演
@@ -115,6 +116,7 @@ type RoadVideoItem struct {
 	TeaseTotal          int                                 `json:"tease_total" description:"吐槽数"`
 	CommentTotal        int                                 `json:"comment_total" description:"总共评论数"`
 	CommentList         []*CommunityQuestionCommentListItem `json:"comment_list"`
+	BulletChatList      []*BulletChatItem                   `json:"bullet_chat_list" description:"弹幕列表"`
 }
 
 type RoadVideoItemResp struct {

+ 30 - 0
models/tables/yb_bullet_chat/entity.go

@@ -0,0 +1,30 @@
+package yb_bullet_chat
+
+import "time"
+
+// YbBulletChat 研报-弹幕表
+type YbBulletChat struct {
+	ID          int       `gorm:"primaryKey;column:id;type:int(10) unsigned;not null" json:"-"`                                     // 弹幕ID
+	UserID      int       `gorm:"index:idx_user_id;column:user_id;type:int(10) unsigned;not null;default:0" json:"userId"`          // 用户ID
+	PrimaryID   int       `gorm:"index:idx_primary_id;column:primary_id;type:int(10) unsigned;not null;default:0" json:"primaryId"` // 视频社区/线上路演ID
+	Content     string    `gorm:"column:content;type:varchar(255);not null;default:''" json:"content"`                              // 弹幕内容
+	Seconds     float64   `gorm:"column:seconds;type:decimal(10,2);not null;default:0.00" json:"seconds"`                           // 时间点(秒)
+	Color       string    `gorm:"column:color;type:varchar(100);not null;default:''" json:"color"`                                  // 颜色#号
+	Title       string    `gorm:"column:title;type:varchar(255);not null;default:''" json:"title"`                                  // 标题(冗余)
+	Source      int       `gorm:"column:source;type:tinyint(4) unsigned;not null;default:0" json:"source"`                          // 来源:1-视频社区;2-线上路演
+	SourceAgent int       `gorm:"column:source_agent;type:tinyint(4) unsigned;not null;default:0" json:"sourceAgent"`               // 来源:1-小程序 2-小程序 PC 3-弘则研究公众号 4-Web PC
+	CreateTime  time.Time `gorm:"column:create_time;type:datetime" json:"createTime"`                                               // 创建时间
+	ModifyTime  time.Time `gorm:"column:modify_time;type:datetime" json:"modifyTime"`                                               // 更新时间
+	OpAdminID   int       `gorm:"column:op_admin_id;type:int(10) unsigned;not null;default:0" json:"opAdminId"`                     // 删除操作管理员ID
+	IsDeleted   int       `gorm:"column:is_deleted;type:tinyint(4) unsigned;not null;default:0" json:"isDeleted"`                   // 是否已删除:0-未删除 1-已删除
+	DeleteTime  time.Time `gorm:"column:delete_time;type:datetime" json:"deleteTime"`                                               // 删除时间
+}
+
+func (m *YbBulletChat) TableName() string {
+	return "yb_bullet_chat"
+}
+
+const (
+	SourceBulletVideo = iota + 1
+	SourceBulletChatVideo
+)

+ 21 - 0
models/tables/yb_bullet_chat/model.go

@@ -0,0 +1,21 @@
+package yb_bullet_chat
+
+import "hongze/hongze_yb/global"
+
+func (m *YbBulletChat) Create() (err error) {
+	err = global.DEFAULT_MYSQL.Create(m).Error
+	return
+}
+
+func (m *YbBulletChat) Update(cols string) (err error) {
+	err = global.DEFAULT_MYSQL.Model(m).Select(cols).Updates(*m).Error
+	return
+}
+
+func GetList(condition string, pars []interface{}) (list []*YbBulletChat, err error) {
+	err = global.DEFAULT_MYSQL.Model(YbBulletChat{}).
+		Where(condition, pars...).
+		Where("is_deleted = 0").
+		Scan(&list).Error
+	return
+}

+ 17 - 0
models/tables/yb_config/entity.go

@@ -0,0 +1,17 @@
+package yb_config
+
+import "time"
+
+// YbConfig 研报相关配置表
+type YbConfig struct {
+	ConfigID    int       `gorm:"primaryKey;column:config_id;type:int(11);not null" json:"-"`
+	ConfigCode  string    `gorm:"column:config_code;type:varchar(50);default:''" json:"configCode"` // 配置编码
+	ConfigValue string    `gorm:"column:config_value;type:text" json:"configValue"`                 // 配置值
+	Remark      string    `gorm:"column:remark;type:varchar(255);default:''" json:"remark"`         // 备注信息
+	CreateTime  time.Time `gorm:"column:create_time;type:datetime" json:"createTime"`               // 创建时间
+}
+
+// TableName get sql table name.获取数据库表名
+func (m *YbConfig) TableName() string {
+	return "yb_config"
+}

+ 22 - 0
models/tables/yb_config/model.go

@@ -0,0 +1,22 @@
+package yb_config
+
+import "hongze/hongze_yb/global"
+
+func (m *YbConfig) Create() (err error) {
+	err = global.DEFAULT_MYSQL.Create(m).Error
+	return
+}
+
+func (m *YbConfig) Update(cols string) (err error) {
+	err = global.DEFAULT_MYSQL.Model(m).Select(cols).Updates(*m).Error
+	return
+}
+
+func (m *YbConfig) Delete() (err error) {
+	return
+}
+
+func (m *YbConfig) Fetch(condition string, pars []interface{}) (item *YbConfig, err error) {
+	err = global.DEFAULT_MYSQL.Model(m).Where(condition, pars).First(&item).Error
+	return
+}

+ 12 - 0
routers/bullet_chat.go

@@ -0,0 +1,12 @@
+package routers
+
+import (
+	"github.com/gin-gonic/gin"
+	"hongze/hongze_yb/controller/bullet_chat"
+	"hongze/hongze_yb/middleware"
+)
+
+func InitBulletChat(r *gin.Engine) {
+	rGroup := r.Group("/api/bullet_chat").Use(middleware.Token())
+	rGroup.POST("/add", bullet_chat.Add)
+}

+ 146 - 0
services/bullet_chat/bullet_chat.go

@@ -0,0 +1,146 @@
+package bullet_chat
+
+import (
+	"encoding/json"
+	"errors"
+	"hongze/hongze_yb/models/tables/yb_bullet_chat"
+	"hongze/hongze_yb/models/tables/yb_community_video"
+	"hongze/hongze_yb/models/tables/yb_config"
+	"hongze/hongze_yb/models/tables/yb_road_video"
+	"math/rand"
+	"time"
+)
+
+const (
+	ConfBulletChatColor = "bullet_chat_color"
+)
+
+var (
+	SourceBulletChatVideo     int
+	SourceBulletChatRoadVideo int
+)
+
+func init() {
+	SourceBulletChatVideo = yb_bullet_chat.SourceBulletVideo
+	SourceBulletChatRoadVideo = yb_bullet_chat.SourceBulletChatVideo
+}
+
+// BulletChatColor 弹幕颜色
+type BulletChatColor struct {
+	Id     int    `json:"id" description:"颜色ID"`
+	Color  string `json:"color" description:"颜色#"`
+	Remark string `json:"remark" description:"备注"`
+}
+
+// GetRandomColor 随机获取弹幕颜色
+func GetRandomColor() (color *BulletChatColor, err error) {
+	// 读取配置
+	var cond string
+	var pars []interface{}
+	cond += `config_code = ?`
+	pars = append(pars, ConfBulletChatColor)
+	confDao := new(yb_config.YbConfig)
+	conf, e := confDao.Fetch(cond, pars)
+	if e != nil {
+		err = errors.New("获取弹幕颜色配置失败, Err: " + e.Error())
+		return
+	}
+	if conf.ConfigID <= 0 {
+		err = errors.New("获取弹幕颜色配置失败, ID为空")
+		return
+	}
+	if conf.ConfigValue == "" {
+		err = errors.New("弹幕颜色配置有误")
+		return
+	}
+	colors := make([]*BulletChatColor, 0)
+	if e = json.Unmarshal([]byte(conf.ConfigValue), &colors); e != nil {
+		err = errors.New("弹幕颜色配置格式有误, Err: " + e.Error())
+		return
+	}
+
+	defaultColor := &BulletChatColor{
+		Id:     1,
+		Color:  "#FFFFFF",
+		Remark: "白色",
+	}
+	colorLen := len(colors)
+	if colorLen == 0 {
+		color = defaultColor
+		return
+	}
+
+	// 随机获取
+	rand.Seed(time.Now().UnixNano())
+	x := rand.Intn(colorLen)
+	color = colors[x]
+	return
+}
+
+// GetListMapBySourceAndIds 通过来源及IDs获取弹幕列表Map
+func GetListMapBySourceAndIds(source int, primaryIds []int) (idBulletsMap map[int][]*yb_bullet_chat.YbBulletChat, err error) {
+	var cond string
+	var pars []interface{}
+	cond += `source = ? AND primary_id IN ?`
+	pars = append(pars, source, primaryIds)
+
+	list, e := yb_bullet_chat.GetList(cond, pars)
+	if e != nil {
+		err = errors.New("获取弹幕列表失败, Err: " + e.Error())
+		return
+	}
+	idBulletsMap = make(map[int][]*yb_bullet_chat.YbBulletChat, 0)
+	for i := range primaryIds {
+		idBulletsMap[primaryIds[i]] = make([]*yb_bullet_chat.YbBulletChat, 0)
+	}
+	for i := range list {
+		idBulletsMap[list[i].PrimaryID] = append(idBulletsMap[list[i].PrimaryID], list[i])
+	}
+	return
+}
+
+// CreateBulletChat 新增弹幕
+func CreateBulletChat(userId, primaryId, source, sourceAgent int, seconds float64, content string) (item *yb_bullet_chat.YbBulletChat, err error) {
+	// 随机颜色
+	color, e := GetRandomColor()
+	if e != nil {
+		err = errors.New("获取弹幕随机颜色失败, Err: " + e.Error())
+		return
+	}
+
+	title := ""
+	if source == 1 {
+		vd, e := yb_community_video.GetItemById(primaryId)
+		if e != nil {
+			err = errors.New("获取视频失败, Err: " + e.Error())
+			return
+		}
+		title = vd.Title
+	} else {
+		rv, e := yb_road_video.GetItemById(primaryId)
+		if e != nil {
+			err = errors.New("获取路演视频失败, Err: " + e.Error())
+			return
+		}
+		title = rv.Title
+	}
+
+	nowTime := time.Now().Local()
+	bc := new(yb_bullet_chat.YbBulletChat)
+	bc.UserID = userId
+	bc.PrimaryID = primaryId
+	bc.Content = content
+	bc.Seconds = seconds
+	bc.Color = color.Color
+	bc.Title = title
+	bc.Source = source
+	bc.SourceAgent = sourceAgent
+	bc.CreateTime = nowTime
+	bc.ModifyTime = nowTime
+	if e := bc.Create(); e != nil {
+		err = errors.New("新增弹幕失败, Err: " + e.Error())
+		return
+	}
+	item = bc
+	return
+}