ソースを参照

Merge branch 'yb/9.3'

hsun 2 年 前
コミット
a245c9d30d

+ 106 - 0
controller/collection/collection.go

@@ -0,0 +1,106 @@
+package collection
+
+import (
+	"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"
+	"hongze/hongze_yb/services/collection"
+	"hongze/hongze_yb/services/user"
+)
+
+// List 收藏列表
+// @Description 收藏列表
+// @Param from_type query int false "来源类型:0-全部; 1-研报; 2-线上路演; 3-视频社区"
+// @Param keywords query string false "搜索关键词"
+// @Param curr_page query int false "当前页码"
+// @Param page_size query int false "每页数量"
+// @Success 200 {object}
+// @failure 400 {string} string "活动获取失败"
+// @Router /collection/list [get]
+func List(c *gin.Context) {
+	var req request.CollectionListReq
+	if err := c.Bind(&req); err != nil {
+		response.Fail("参数有误", c)
+		return
+	}
+
+	userInfo := user.GetInfoByClaims(c)
+	page := services.GetCurrPageByClaims(c)
+	pageSize := services.GetPageSizeByClaims(c)
+
+	total, list, e := collection.GetCollectionList(int(userInfo.UserID), req.FromType, page, pageSize, req.Keywords)
+	if e != nil {
+		response.FailMsg("获取收藏列表失败", "获取收藏列表失败, Err: "+e.Error(), c)
+		return
+	}
+
+	response.OkData("获取成功", &responseModel.CollectionListResp{
+		List:   list,
+		Paging: responseModel.GetPaging(page, pageSize, total),
+	}, c)
+}
+
+// Collect
+// @Description 加入收藏
+// @Success 200 {string} string "操作成功"
+// @Router /collection/collect [post]
+func Collect(c *gin.Context) {
+	var req request.CollectionCollectReq
+	if c.ShouldBind(&req) != nil {
+		response.Fail("参数有误", c)
+		return
+	}
+	if req.CollectionType <= 0 {
+		response.Fail("收藏类型有误", c)
+		return
+	}
+	if req.PrimaryId <= 0 {
+		response.Fail("参数有误", c)
+		return
+	}
+
+	userInfo := user.GetInfoByClaims(c)
+	if userInfo.UserID <= 0 {
+		response.Fail("请登录后操作", c)
+		return
+	}
+
+	collectionId, e := collection.AddCollection(int(userInfo.UserID), req.CollectionType, req.PrimaryId, req.ExtendId, req.SourceAgent)
+	if e != nil {
+		response.FailMsg("操作失败", "加入收藏失败, Err: "+e.Error(), c)
+		return
+	}
+
+	response.OkData("操作成功", collectionId, c)
+}
+
+// Cancel
+// @Description 取消收藏
+// @Success 200 {string} string "操作成功"
+// @Router /collection/cancel [post]
+func Cancel(c *gin.Context) {
+	var req request.CollectionCancelReq
+	if c.ShouldBind(&req) != nil {
+		response.Fail("参数有误", c)
+		return
+	}
+	if req.CollectionId <= 0 {
+		response.Fail("参数有误", c)
+		return
+	}
+
+	userInfo := user.GetInfoByClaims(c)
+	if userInfo.UserID <= 0 {
+		response.Fail("请登录后操作", c)
+		return
+	}
+
+	if e := collection.CancelCollection(int(userInfo.UserID), req.CollectionId); e != nil {
+		response.FailMsg("操作失败", "取消收藏失败, Err: "+e.Error(), c)
+		return
+	}
+
+	response.Ok("操作成功", c)
+}

+ 1 - 1
controller/community/video.go

@@ -34,7 +34,7 @@ func VideoList(c *gin.Context) {
 		req.PageSize = utils.PageSize20
 	}
 	userInfo := user.GetInfoByClaims(c)
-	list, err := community.GetVideoList(req.PageIndex, req.PageSize, req.VideoId, req.VarietyTagId, req.Keywords)
+	list, err := community.GetVideoList(int(userInfo.UserID), req.PageIndex, req.PageSize, req.VideoId, req.VarietyTagId, req.Keywords)
 	if err != nil {
 		response.FailMsg("获取失败", "VideoList ErrMsg:"+err.Error(), c)
 		return

+ 2 - 0
init_serve/router.go

@@ -73,5 +73,7 @@ func InitRouter() (r *gin.Engine) {
 	routers.InitVoiceBroadcast(r)
 	//线上路演
 	routers.InitRoad(r)
+	// 收藏路由
+	routers.InitCollection(r)
 	return
 }

+ 22 - 0
models/request/collection.go

@@ -0,0 +1,22 @@
+package request
+
+// CollectionCollectReq 收藏请求体
+type CollectionCollectReq struct {
+	CollectionType int `json:"collection_type" description:"收藏类型:1-研报; 2-视频社区; 3-微路演视频"`
+	PrimaryId      int `json:"primary_id" description:"收藏类型主ID"`
+	ExtendId       int `json:"extend_id" description:"扩展ID-如研报章节"`
+	SourceAgent    int `json:"source_agent" description:"操作来源:1-小程序 2-小程序 PC 3-弘则研究公众号 4-Web PC"`
+}
+
+// CollectionCancelReq 取消收藏请求体
+type CollectionCancelReq struct {
+	CollectionId int `json:"collection_id" description:"收藏ID"`
+}
+
+// CollectionListReq 收藏列表请求体
+type CollectionListReq struct {
+	CurrPage int    `json:"curr_page" form:"curr_page" description:"当前页码"`
+	PageSize int    `json:"page_size" form:"page_size" description:"每页数据量"`
+	FromType int    `json:"from_type" form:"from_type" description:"来源类型:0-全部; 1-研报; 2-线上路演; 3-视频社区"`
+	Keywords string `json:"keywords" form:"keywords" description:"搜索关键词"`
+}

+ 22 - 0
models/response/collection.go

@@ -0,0 +1,22 @@
+package response
+
+// CollectionListResp 问答留言列表接口返回
+type CollectionListResp struct {
+	List   []*CollectionList `json:"list"`
+	Paging *PagingItem       `json:"paging"`
+}
+
+// CollectionList 收藏列表
+type CollectionList struct {
+	CollectionId       int    `description:"收藏ID"`
+	CollectionType     int    `description:"收藏类型: 1-研报; 2-视频社区; 3-微路演视频"`
+	PrimaryId          int    `description:"不同收藏类型的ID"`
+	ExtendId           int    `description:"扩展ID: 如晨周报章节的ID, 大于0则详情页跳转章节详情"`
+	Title              string `description:"标题"`
+	PublishTime        string `description:"发布时间"`
+	CreateTime         string `description:"收藏时间"`
+	ClassifyName       string `description:"报告类型名称"`
+	ClassifySecondName string `description:"报告二级分类名称"`
+	Author             string `description:"作者"`
+	ImgUrl             string `description:"图片地址"`
+}

+ 5 - 2
models/response/community.go

@@ -91,6 +91,7 @@ type CommunityVideoItem struct {
 	TeaseTotal          int                                 `json:"tease_total" description:"吐槽数"`
 	CommentTotal        int                                 `json:"comment_total" description:"总共评论数"`
 	CommentList         []*CommunityQuestionCommentListItem `json:"comment_list"`
+	CollectionId        int                                 `description:"收藏ID: 大于0则表示已收藏" json:"collection_id"`
 }
 
 // RoadVideoItem 线上路演
@@ -108,12 +109,14 @@ type RoadVideoItem struct {
 	PublishTime         string `json:"publish_time"`
 	CreateTime          string `json:"create_time"`
 	ModifyTime          string `json:"modify_time"`
+	CollectionId        int    `description:"收藏ID: 大于0则表示已收藏" json:"collection_id"`
 }
 
 type RoadVideoItemResp struct {
-	List []*RoadVideoItem `json:"list"`
-	Paging *PagingItem  	`json:"paging"`
+	List   []*RoadVideoItem `json:"list"`
+	Paging *PagingItem      `json:"paging"`
 }
+
 // RespCommunityQuestionLikeTease
 type RespCommunityQuestionLikeTease struct {
 	LikeTotal  int64 `description:"点赞总数" json:"like_total"`

+ 32 - 33
models/response/paging.go

@@ -13,50 +13,49 @@ type PagingItem struct {
 	PageSize      int  `description:"每页数据条数" json:"page_size"`
 }
 
-func GetPaging(currentIndex,pageSize,total int)(item *PagingItem)  {
-	if pageSize<=0 {
-		pageSize=utils.PageSize20
+func GetPaging(currentIndex, pageSize, total int) (item *PagingItem) {
+	if pageSize <= 0 {
+		pageSize = utils.PageSize20
 	}
-	if currentIndex<=0 {
-		currentIndex=1
+	if currentIndex <= 0 {
+		currentIndex = 1
 	}
-	item=new(PagingItem)
-	item.PageSize=pageSize
-	item.Totals=total
-	item.CurrentIndex=currentIndex
+	item = new(PagingItem)
+	item.PageSize = pageSize
+	item.Totals = total
+	item.CurrentIndex = currentIndex
 
-	if total<=0 {
-		item.IsStart=true
-		item.IsEnd=true
+	if total <= 0 {
+		item.IsStart = true
+		item.IsEnd = true
 		return
 	}
-	pages:=utils.PageCount(total,pageSize)
-	item.Pages=pages
-	if pages<=1 {
-		item.IsStart=true
-		item.IsEnd=true
-		item.PreviousIndex=1
-		item.NextIndex=1
+	pages := utils.PageCount(total, pageSize)
+	item.Pages = pages
+	if pages <= 1 {
+		item.IsStart = true
+		item.IsEnd = true
+		item.PreviousIndex = 1
+		item.NextIndex = 1
 		return
 	}
 	if pages == currentIndex {
-		item.IsStart=false
-		item.IsEnd=true
-		item.PreviousIndex=currentIndex-1
-		item.NextIndex=currentIndex
+		item.IsStart = false
+		item.IsEnd = true
+		item.PreviousIndex = currentIndex - 1
+		item.NextIndex = currentIndex
 		return
 	}
-	if currentIndex==1 {
-		item.IsStart=true
-		item.IsEnd=false
-		item.PreviousIndex=1
-		item.NextIndex=currentIndex+1
+	if currentIndex == 1 {
+		item.IsStart = true
+		item.IsEnd = false
+		item.PreviousIndex = 1
+		item.NextIndex = currentIndex + 1
 		return
 	}
-	item.IsStart=false
-	item.IsEnd=false
-	item.PreviousIndex=currentIndex-1
-	item.NextIndex=currentIndex+1
+	item.IsStart = false
+	item.IsEnd = false
+	item.PreviousIndex = currentIndex - 1
+	item.NextIndex = currentIndex + 1
 	return
 }
-

+ 2 - 0
models/response/report.go

@@ -12,6 +12,7 @@ type ReportDetail struct {
 	LikeNum           int64                    `description:"点赞总数" json:"like_num"`
 	LikeEnabled       int8                     `description:"是否已点赞: 0-未点赞 1-已点赞" json:"like_enabled"`
 	ReportShowType    int                      `descritpion:"展示形式:1-列表 2-专栏" json:"report_show_type"`
+	CollectionId      int                      `description:"收藏ID: 大于0则表示已收藏" json:"collection_id"`
 }
 
 type ReportChapterListItem struct {
@@ -80,6 +81,7 @@ type ReportChapterDetail struct {
 	AuthOk                bool                 `json:"auth_ok"`
 	LikeNum               int64                `description:"点赞总数" json:"like_num"`
 	LikeEnabled           int8                 `description:"是否已点赞: 0-未点赞 1-已点赞" json:"like_enabled"`
+	CollectionId          int                  `description:"收藏ID: 大于0则表示已收藏" json:"collection_id"`
 }
 
 type ReportChapterMenu struct {

+ 36 - 19
models/tables/rddp/report/query.go

@@ -40,7 +40,7 @@ GROUP BY
 }
 
 // GetReportsByClassifyIdSecondsAndDate 根据时间和报告分类筛选出合适的记录
-func GetReportsByClassifyIdSecondsAndDate( classifyIdSeconds []int, publishTime string) (reportList []*Report, err error) {
+func GetReportsByClassifyIdSecondsAndDate(classifyIdSeconds []int, publishTime string) (reportList []*Report, err error) {
 	err = global.MYSQL["rddp"].Model(Report{}).
 		Select("id, classify_name_first").
 		Where("classify_id_second in (?) and state = 2 and publish_time > ? ", classifyIdSeconds, publishTime).Scan(&reportList).Error
@@ -48,7 +48,7 @@ func GetReportsByClassifyIdSecondsAndDate( classifyIdSeconds []int, publishTime
 }
 
 // GetListByIDsAndClassifyIdFirst 分页查询
-func GetListByIDsAndClassifyIdFirst( ids []int, classifyIdFirst int,  offset , limit int) (reportList []*Report, err error) {
+func GetListByIDsAndClassifyIdFirst(ids []int, classifyIdFirst int, offset, limit int) (reportList []*Report, err error) {
 	err = global.MYSQL["rddp"].Model(Report{}).
 		Select("id, classify_id_first, classify_name_first, classify_id_second, classify_name_second, title, stage, publish_time").
 		Where("id in (?) and classify_id_first=? and state = 2 ", ids, classifyIdFirst).
@@ -60,7 +60,7 @@ func GetListByIDsAndClassifyIdFirst( ids []int, classifyIdFirst int,  offset , l
 }
 
 // GetListCountByIDsAndClassifyIdFirst 分页查询
-func GetListCountByIDsAndClassifyIdFirst( ids []int, classifyIdFirst int) (total int64, err error) {
+func GetListCountByIDsAndClassifyIdFirst(ids []int, classifyIdFirst int) (total int64, err error) {
 	err = global.MYSQL["rddp"].Model(Report{}).
 		Select("id, classify_id_first, classify_name_first, classify_id_second, classify_name_second, title, stage, publish_time").
 		Where("id in (?) and classify_id_first=? and state = 2 ", ids, classifyIdFirst).
@@ -69,7 +69,7 @@ func GetListCountByIDsAndClassifyIdFirst( ids []int, classifyIdFirst int) (total
 }
 
 // GetListByClassifyIdSeconds 分页查询
-func GetListByClassifyIdSeconds( classifyIdSeconds []int, offset , limit int) (reportList []*Report, err error) {
+func GetListByClassifyIdSeconds(classifyIdSeconds []int, offset, limit int) (reportList []*Report, err error) {
 	err = global.MYSQL["rddp"].Model(Report{}).
 		Select("id, classify_id_first, classify_name_first, classify_id_second, classify_name_second, title, stage, publish_time").
 		Where("classify_id_second in (?) and state = 2 ", classifyIdSeconds).
@@ -81,7 +81,7 @@ func GetListByClassifyIdSeconds( classifyIdSeconds []int, offset , limit int) (r
 }
 
 // GetListCountByClassifyIdSeconds
-func GetListCountByClassifyIdSeconds( classifyIdSeconds []int) (total int64, err error) {
+func GetListCountByClassifyIdSeconds(classifyIdSeconds []int) (total int64, err error) {
 	err = global.MYSQL["rddp"].Model(Report{}).
 		Select("id, classify_id_first, classify_name_first, classify_id_second, classify_name_second, title, stage, publish_time").
 		Where("classify_id_second in (?) and state = 2 ", classifyIdSeconds).
@@ -90,7 +90,7 @@ func GetListCountByClassifyIdSeconds( classifyIdSeconds []int) (total int64, err
 }
 
 // GetListByClassifyIdFirst 按照类型分页查询
-func GetListByClassifyIdFirst(classifyIdFirst int,  offset , limit int) (reportList []*Report, err error) {
+func GetListByClassifyIdFirst(classifyIdFirst int, offset, limit int) (reportList []*Report, err error) {
 	err = global.MYSQL["rddp"].Model(Report{}).
 		Select("id, classify_id_first, classify_name_first, classify_id_second, classify_name_second, title, stage, publish_time").
 		Where("classify_id_first=? and state = 2 ", classifyIdFirst).
@@ -139,7 +139,10 @@ func GetByReportId(id int) (item *Report, err error) {
 
 // GetByReportIds 根据id获取报告
 func GetByReportIds(ids []int) (list []*Report, err error) {
-	err = global.MYSQL["rddp"].Model(Report{}).Where("id in (?) and state = 2", ids).Select("id, create_time").Scan(&list).Error
+	err = global.MYSQL["rddp"].Model(Report{}).
+		Where("id in (?) and state = 2", ids).
+		Select("id, create_time").
+		Scan(&list).Error
 	if err == utils.ErrNoRow {
 		err = nil
 	}
@@ -195,7 +198,7 @@ func GetReportListByCondition(condition string, pars []interface{}) (list []*Rep
 }
 
 // GetListByClassifyIdSecond 按照二级类型分页查询
-func GetListByClassifyIdSecond(classifyIdSecond int,  offset , limit int) (reportList []*Report, err error) {
+func GetListByClassifyIdSecond(classifyIdSecond int, offset, limit int) (reportList []*Report, err error) {
 	err = global.MYSQL["rddp"].Model(Report{}).
 		Select("id, classify_id_first, classify_name_first, classify_id_second, classify_name_second, title, stage, publish_time, author, video_name, video_url, video_play_seconds, abstract").
 		Where("classify_id_second = ? and state = 2 ", classifyIdSecond).
@@ -209,7 +212,6 @@ func GetListByClassifyIdSecond(classifyIdSecond int,  offset , limit int) (repor
 	return
 }
 
-
 // GetListCountByClassifyIdSecond 按照二级分类总条数
 func GetListCountByClassifyIdSecond(classifyIdSecond int) (total int64, err error) {
 	err = global.MYSQL["rddp"].Model(Report{}).
@@ -220,9 +222,8 @@ func GetListCountByClassifyIdSecond(classifyIdSecond int) (total int64, err erro
 	return
 }
 
-
 // GetReportList 获取报告列表
-func GetReportList(condition string, pars []interface{}, offset , limit int) (list []*Report, err error) {
+func GetReportList(condition string, pars []interface{}, offset, limit int) (list []*Report, err error) {
 	err = global.MYSQL["rddp"].Model(Report{}).
 		Select("id, classify_id_first, classify_name_first, classify_id_second, classify_name_second, title, stage, publish_time, author, create_time, video_url, video_name, video_play_seconds, abstract").
 		Where(condition, pars...).
@@ -241,7 +242,7 @@ func GetReportListCount(condition string, pars []interface{}) (total int64, err
 }
 
 // GetReportCollectListByPermission 根据权限相关的分类查询报告和章节
-func GetReportCollectListByPermission(classifyIdSeconds []int, typeIds []int, offset , limit int) (list []*response.ReportCollectListItem, err error)  {
+func GetReportCollectListByPermission(classifyIdSeconds []int, typeIds []int, offset, limit int) (list []*response.ReportCollectListItem, err error) {
 	sql := `( SELECT
 id AS report_id,
 0 AS report_chapter_id,
@@ -285,8 +286,9 @@ WHERE
 	err = global.MYSQL["rddp"].Raw(sql, classifyIdSeconds, typeIds, limit, offset).Scan(&list).Error
 	return
 }
+
 // GetReportCollectCountByPermission 查询汇总报告总页数
-func GetReportCollectCountByPermission(classifyIdSeconds []int, typeIds []int) (total int64, err error)  {
+func GetReportCollectCountByPermission(classifyIdSeconds []int, typeIds []int) (total int64, err error) {
 	sql := `select count(*) from ( ( SELECT
 id AS report_id,
 0 AS report_chapter_id
@@ -316,7 +318,7 @@ WHERE
 }
 
 // GetReportByOldReportId 根据老后台的research_report_id查找新的报告ID
-func GetReportByOldReportId(oldReportId uint64)(item *Report, err error)  {
+func GetReportByOldReportId(oldReportId uint64) (item *Report, err error) {
 	err = global.MYSQL["rddp"].Model(Report{}).
 		Where("old_report_id=?", oldReportId).First(&item).Error
 	if err == utils.ErrNoRow {
@@ -326,7 +328,7 @@ func GetReportByOldReportId(oldReportId uint64)(item *Report, err error)  {
 }
 
 // GetLatestReportByPermission 根据权限相关的分类查询最新的三篇专栏报告
-func GetLatestReportByPermission(classifyIdSeconds []int) (list []*pc.LatestReport, err error)  {
+func GetLatestReportByPermission(classifyIdSeconds []int) (list []*pc.LatestReport, err error) {
 	sql := `SELECT
 id AS report_id,
 0 AS report_chapter_id,
@@ -353,7 +355,7 @@ WHERE
 }
 
 // GetLatestReport 获取最新专栏信息
-func GetLatestReport() (list *pc.LatestReport, err error)  {
+func GetLatestReport() (list *pc.LatestReport, err error) {
 	sql := `SELECT
 r.id AS report_id,
 0 AS report_chapter_id,
@@ -408,7 +410,7 @@ ORDER BY
 }
 
 // GetCommoditiesReportCollectListByPermission 根据权限相关的分类查询大宗商品报告
-func GetCommoditiesReportCollectListByPermission(classifyIdSeconds []int, offset , limit int) (list []*Report, err error)  {
+func GetCommoditiesReportCollectListByPermission(classifyIdSeconds []int, offset, limit int) (list []*Report, err error) {
 	sql := ` SELECT
 id, classify_id_first, classify_name_first, classify_id_second, classify_name_second, title, stage, publish_time, author, create_time, video_url, video_name, video_play_seconds, abstract  
 FROM
@@ -425,7 +427,7 @@ WHERE
 }
 
 // GetCommoditiesReportCollectCountByPermission 查询大宗商品报告总页数
-func GetCommoditiesReportCollectCountByPermission(classifyIdSeconds []int) (total int64, err error)  {
+func GetCommoditiesReportCollectCountByPermission(classifyIdSeconds []int) (total int64, err error) {
 	sql := `select count(*) 
 FROM
         report
@@ -438,4 +440,19 @@ WHERE
 	`
 	err = global.MYSQL["rddp"].Raw(sql, classifyIdSeconds).Count(&total).Error
 	return
-}
+}
+
+// GetListByReportIds 根据IDs获取列表
+func GetListByReportIds(reportIds []int) (list []*Report, err error) {
+	var where string
+	where = `state = 2`
+	if len(reportIds) > 0 {
+		where += ` AND id IN (?)`
+	}
+
+	err = global.MYSQL["rddp"].Model(Report{}).
+		Where(where, reportIds).
+		Order("id asc").
+		Scan(&list).Error
+	return
+}

+ 36 - 13
models/tables/rddp/report_chapter/query.go

@@ -24,11 +24,11 @@ ORDER BY
 }
 
 // GetListByReportId 根据报告ID获取章节列表
-func GetListByReportId(reportId int, classifyNameFirst string) (list []*ReportChapter, err error)  {
+func GetListByReportId(reportId int, classifyNameFirst string) (list []*ReportChapter, err error) {
 	var where string
-	if  classifyNameFirst == "周报"{
+	if classifyNameFirst == "周报" {
 		where = "report_id = ? AND is_edit = 1 AND publish_state = 2"
-	}else{
+	} else {
 		where = "report_id = ? AND publish_state = 2"
 	}
 
@@ -41,11 +41,11 @@ func GetListByReportId(reportId int, classifyNameFirst string) (list []*ReportCh
 }
 
 // GetListByReportIdTypeIds 根据报告ID、章节类型ID获取章节列表
-func GetListByReportIdTypeIds(reportId int, typeIds []int, classifyNameFirst string) (list []*ReportChapter, err error)  {
+func GetListByReportIdTypeIds(reportId int, typeIds []int, classifyNameFirst string) (list []*ReportChapter, err error) {
 	var where string
-	if  classifyNameFirst == "周报"{
+	if classifyNameFirst == "周报" {
 		where = "report_id = ? AND type_id in (?) AND is_edit = 1 AND publish_state = 2 "
-	}else{
+	} else {
 		where = "report_id = ? AND type_id in (?) AND publish_state = 2 "
 	}
 
@@ -58,7 +58,7 @@ func GetListByReportIdTypeIds(reportId int, typeIds []int, classifyNameFirst str
 }
 
 // GetContentById 根据ID获取章节详情
-func GetContentById(id int, typeIds []int) (info *ReportChapter, err error)  {
+func GetContentById(id int, typeIds []int) (info *ReportChapter, err error) {
 	err = global.MYSQL["rddp"].Model(ReportChapter{}).Select("report_chapter_id, report_id,  is_edit, classify_name_first, classify_id_first, content, trend, type_id, type_name, abstract, title, author, stage, publish_time, content, content_sub, video_url, video_name, video_play_seconds, video_size, report_type, video_size").
 		Where("report_chapter_id = ? and type_id in (?) AND publish_state = 2 ", id, typeIds).
 		First(&info).Error
@@ -82,7 +82,7 @@ func GetReportIdsByTypeIdsAndClass(typeIds []int, classifyNameFirst string) (rep
 }
 
 // GetTypeIdById 根据ID获取章节类型
-func GetTypeIdById(id int) (info *ReportChapter, err error)  {
+func GetTypeIdById(id int) (info *ReportChapter, err error) {
 	err = global.MYSQL["rddp"].Model(ReportChapter{}).Select("report_chapter_id, report_id, type_id").
 		Where("report_chapter_id = ? AND publish_state = 2 ", id).
 		First(&info).Error
@@ -92,13 +92,12 @@ func GetTypeIdById(id int) (info *ReportChapter, err error)  {
 	return
 }
 
-
 // GetByTypeIdsAndReportIds 根据章节ID和ReportIds查询报告
-func GetByTypeIdsAndReportIds(typeIds []int,  reportIds []int, classifyNameFirst string) (list []*ReportChapter, err error) {
+func GetByTypeIdsAndReportIds(typeIds []int, reportIds []int, classifyNameFirst string) (list []*ReportChapter, err error) {
 	var where string
-	if  classifyNameFirst == "周报"{
+	if classifyNameFirst == "周报" {
 		where = "report_id in (?) AND type_id in (?) AND is_edit = 1 AND publish_state = 2 "
-	}else{
+	} else {
 		where = "report_id in (?) AND type_id in (?) AND publish_state = 2 "
 	}
 
@@ -123,7 +122,7 @@ func GetChapterByReportIdTypeId(reportId, typeId int) (chapter *ReportChapter, e
 		Where("report_id = ? and type_id = ?", reportId, typeId).
 		First(&chapter).Error
 	if err == utils.ErrNoRow {
-		err =nil
+		err = nil
 	}
 	return
 }
@@ -170,4 +169,28 @@ ORDER BY
 	sql = fmt.Sprintf(sql, firstName)
 	err = global.MYSQL["rddp"].Raw(sql).First(&items).Error
 	return
+}
+
+// GetItemById 主键获取章节
+func GetItemById(chapterId int) (item *ReportChapter, err error) {
+	err = global.MYSQL["rddp"].Model(ReportChapter{}).
+		Where("report_chapter_id = ? AND publish_state = 2", chapterId).
+		First(&item).Error
+	return
+}
+
+// GetListByChapterIds 根据章节IDs获取列表
+func GetListByChapterIds(chapterIds []int) (list []*ReportChapter, err error) {
+	var where string
+	where = `publish_state = 2`
+	if len(chapterIds) > 0 {
+		where += ` AND report_chapter_id IN (?)`
+	}
+
+	err = global.MYSQL["rddp"].Model(ReportChapter{}).
+		//Select("report_id, type_id, report_chapter_id, classify_name_first, classify_id_first, video_url, video_name, video_play_seconds, video_size, sort").
+		Where(where, chapterIds).
+		Order("sort asc, report_chapter_id asc").
+		Scan(&list).Error
+	return
 }

+ 15 - 0
models/tables/yb_community_video/model.go

@@ -39,3 +39,18 @@ func GetItemById(videoId int) (item *YbCommunityVideo, err error) {
 		First(&item).Error
 	return
 }
+
+// GetListByVideoIds 根据视频IDs获取列表
+func GetListByVideoIds(videoIds []int) (list []*YbCommunityVideo, err error) {
+	var where string
+	where = `publish_state = 1 AND is_deleted = 0`
+	if len(videoIds) > 0 {
+		where += ` AND community_video_id IN (?)`
+	}
+
+	err = global.DEFAULT_MYSQL.Model(YbCommunityVideo{}).
+		Where(where, videoIds).
+		Order("community_video_id asc").
+		Scan(&list).Error
+	return
+}

+ 15 - 0
models/tables/yb_road_video/model.go

@@ -37,3 +37,18 @@ func GetItemById(videoId int) (item *YbRoadVideo, err error) {
 		First(&item).Error
 	return
 }
+
+// GetListByVideoIds 根据视频IDs获取列表
+func GetListByVideoIds(videoIds []int) (list []*YbRoadVideo, err error) {
+	var where string
+	where = `publish_state = 1 AND is_deleted = 0`
+	if len(videoIds) > 0 {
+		where += ` AND road_video_id IN (?)`
+	}
+
+	err = global.DEFAULT_MYSQL.Model(YbRoadVideo{}).
+		Where(where, videoIds).
+		Order("road_video_id asc").
+		Scan(&list).Error
+	return
+}

+ 52 - 0
models/tables/yb_user_collection/entity.go

@@ -0,0 +1,52 @@
+package yb_user_collection
+
+import (
+	"time"
+)
+
+// YbUserCollection 研报-用户收藏表
+type YbUserCollection struct {
+	CollectionID   int       `gorm:"primaryKey;column:collection_id;type:int(10) unsigned;not null" json:"-"`
+	CollectionType int       `gorm:"column:collection_type;type:tinyint(4) unsigned;not null;default:0" json:"collectionType"`         // 收藏类型:1-研报; 2-视频社区; 3-微路演视频
+	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
+	ExtendID       int       `gorm:"index:idx_extend_id;column:extend_id;type:int(10) unsigned;not null;default:0" json:"extendId"`    // 扩展ID-如晨周报章节ID
+	State          int       `gorm:"column:state;type:tinyint(4) unsigned;not null;default:0" json:"state"`                            // 状态:1-已收藏;0-取消收藏;
+	SourceAgent    int       `gorm:"column:source_agent;type:tinyint(4) unsigned;not null;default:0" json:"sourceAgent"`               // 操作来源:1-小程序 2-小程序 PC 3-弘则研究公众号 4-Web PC
+	Title          string    `gorm:"column:title;type:varchar(255);not null;default:''" json:"title"`                                  // 研报/视频标题-冗余
+	PublishTime    time.Time `gorm:"column:publish_time;type:datetime" json:"publishTime"`                                             // 研报/视频发布时间-冗余
+	CreateTime     time.Time `gorm:"column:create_time;type:datetime" json:"createTime"`                                               // 创建时间
+	ModifyTime     time.Time `gorm:"column:modify_time;type:datetime" json:"modifyTime"`                                               // 修改时间
+}
+
+// TableName get sql table name.获取数据库表名
+func (m *YbUserCollection) TableName() string {
+	return "yb_user_collection"
+}
+
+// YbUserCollectionColumns get sql column name.获取数据库列名
+var YbUserCollectionColumns = struct {
+	CollectionID   string
+	CollectionType string
+	UserID         string
+	PrimaryID      string
+	ExtendID       string
+	State          string
+	SourceAgent    string
+	Title          string
+	PublishTime    string
+	CreateTime     string
+	ModifyTime     string
+}{
+	CollectionID:   "collection_id",
+	CollectionType: "collection_type",
+	UserID:         "user_id",
+	PrimaryID:      "primary_id",
+	ExtendID:       "extend_id",
+	State:          "state",
+	SourceAgent:    "source_agent",
+	Title:          "title",
+	PublishTime:    "publish_time",
+	CreateTime:     "create_time",
+	ModifyTime:     "modify_time",
+}

+ 56 - 0
models/tables/yb_user_collection/model.go

@@ -0,0 +1,56 @@
+package yb_user_collection
+
+import "hongze/hongze_yb/global"
+
+func (item *YbUserCollection) Create() (err error) {
+	err = global.DEFAULT_MYSQL.Create(item).Error
+	return
+}
+
+func (item *YbUserCollection) Update(updateCols []string) (err error) {
+	err = global.DEFAULT_MYSQL.Model(item).Select(updateCols).Updates(*item).Error
+	return
+}
+
+// GetPageListByCondition 获取收藏列表-分页
+func GetPageListByCondition(condition string, pars []interface{}, pageIndex, pageSize int) (list []*YbUserCollection, err error) {
+	offset := (pageIndex - 1) * pageSize
+	err = global.DEFAULT_MYSQL.Model(YbUserCollection{}).
+		Where(condition, pars...).
+		Offset(offset).Limit(pageSize).
+		Order("create_time DESC").
+		Scan(&list).Error
+	return
+}
+
+// GetPageListTotalByCondition 获取收藏列表总数-分页
+func GetPageListTotalByCondition(condition string, pars []interface{}) (total int64, err error) {
+	err = global.DEFAULT_MYSQL.Model(YbUserCollection{}).
+		Where(condition, pars...).
+		Count(&total).Error
+	return
+}
+
+// GetItemById 主键获取收藏
+func GetItemById(collectionId int) (item *YbUserCollection, err error) {
+	err = global.DEFAULT_MYSQL.Model(YbUserCollection{}).
+		Where("collection_id = ? AND state = 1", collectionId).
+		First(&item).Error
+	return
+}
+
+// GetItemByCondition 条件获取收藏
+func GetItemByCondition(condition string, pars []interface{}) (item *YbUserCollection, err error) {
+	err = global.DEFAULT_MYSQL.Model(YbUserCollection{}).
+		Where(condition, pars...).
+		First(&item).Error
+	return
+}
+
+// GetListByCondition 条件获取收藏列表
+func GetListByCondition(condition string, pars []interface{}) (list []*YbUserCollection, err error) {
+	err = global.DEFAULT_MYSQL.Model(YbUserCollection{}).
+		Where(condition, pars...).
+		Scan(&list).Error
+	return
+}

+ 14 - 0
routers/collection.go

@@ -0,0 +1,14 @@
+package routers
+
+import (
+	"github.com/gin-gonic/gin"
+	"hongze/hongze_yb/controller/collection"
+	"hongze/hongze_yb/middleware"
+)
+
+func InitCollection(r *gin.Engine) {
+	rGroup := r.Group("/api/collection").Use(middleware.Token())
+	rGroup.GET("/list", collection.List)
+	rGroup.POST("/collect", collection.Collect)
+	rGroup.POST("/cancel", collection.Cancel)
+}

+ 438 - 0
services/collection/collection.go

@@ -0,0 +1,438 @@
+package collection
+
+import (
+	"errors"
+	"fmt"
+	"hongze/hongze_yb/models/response"
+	"hongze/hongze_yb/models/tables/rddp/report"
+	"hongze/hongze_yb/models/tables/rddp/report_chapter"
+	"hongze/hongze_yb/models/tables/yb_community_video"
+	"hongze/hongze_yb/models/tables/yb_road_video"
+	"hongze/hongze_yb/models/tables/yb_user_collection"
+	"hongze/hongze_yb/utils"
+	"strings"
+	"sync"
+	"time"
+)
+
+// 收藏类型
+const (
+	CollectionTypeReport    = iota + 1 // 研报
+	CollectionTypeVideo                // 视频社区
+	CollectionTypeRoadVideo            // 微路演视频
+)
+
+// AddCollection 加入收藏
+func AddCollection(userId, collectionType, primaryId, extendId, sourceAgent int) (collectionId int, err error) {
+	if userId <= 0 || collectionType <= 0 || primaryId <= 0 {
+		return
+	}
+
+	title := ""
+	nowTime := time.Now().Local()
+	publishTime := nowTime
+
+	// 判断是否曾收藏过
+	var cond string
+	var pars []interface{}
+	cond += `user_id = ?`
+	pars = append(pars, userId)
+	cond += ` AND collection_type = ?`
+	pars = append(pars, collectionType)
+	cond += ` AND primary_id = ?`
+	pars = append(pars, primaryId)
+	if extendId > 0 {
+		cond += ` AND extend_id = ?`
+		pars = append(pars, extendId)
+	}
+	exist, e := yb_user_collection.GetItemByCondition(cond, pars)
+	if e != nil && e != utils.ErrNoRow {
+		err = errors.New("获取用户收藏失败, Err: " + e.Error())
+		return
+	}
+	if exist != nil && exist.CollectionID > 0 {
+		// 可能手快重复收藏
+		collectionId = exist.CollectionID
+		if exist.State == 1 {
+			return
+		}
+		// 重新收藏
+		exist.State = 1
+		exist.CreateTime = nowTime
+		exist.ModifyTime = nowTime
+		updateCols := []string{"State", "CreateTime", "ModifyTime"}
+		if e = exist.Update(updateCols); e != nil {
+			collectionId = 0
+			err = errors.New("重新收藏失败, Err: " + e.Error())
+			return
+		}
+		return
+	}
+
+	// 收藏类型:1-研报; 2-视频社区; 3-微路演视频
+	switch collectionType {
+	case CollectionTypeReport:
+		// 晨周报章节
+		if extendId > 0 {
+			chapter, e := report_chapter.GetItemById(extendId)
+			if e != nil {
+				err = errors.New("获取章节失败, Err: " + e.Error())
+				return
+			}
+			title = chapter.Title
+			publishTime = chapter.PublishTime
+			break
+		}
+		rp, e := report.GetPublishByReportId(primaryId)
+		if e != nil {
+			err = errors.New("获取报告失败, Err: " + e.Error())
+			return
+		}
+		title = rp.Title
+		publishTime = rp.PublishTime
+	case CollectionTypeVideo:
+		video, e := yb_community_video.GetItemById(primaryId)
+		if e != nil {
+			err = errors.New("获取视频失败, Err: " + e.Error())
+			return
+		}
+		title = video.Title
+		publishTime = video.PublishTime
+	case CollectionTypeRoadVideo:
+		roadVideo, e := yb_road_video.GetItemById(primaryId)
+		if e != nil {
+			err = errors.New("获取路演视频失败, Err: " + e.Error())
+			return
+		}
+		title = roadVideo.Title
+		publishTime = roadVideo.PublishTime
+	default:
+		err = errors.New(fmt.Sprintf("收藏类型有误, 当前收藏类型%d", collectionType))
+		return
+	}
+
+	// 新增收藏
+	item := &yb_user_collection.YbUserCollection{
+		CollectionType: collectionType,
+		UserID:         userId,
+		PrimaryID:      primaryId,
+		ExtendID:       extendId,
+		State:          1,
+		SourceAgent:    sourceAgent,
+		Title:          title,
+		PublishTime:    publishTime,
+		CreateTime:     nowTime,
+		ModifyTime:     nowTime,
+	}
+	if e := item.Create(); e != nil {
+		err = errors.New("新增收藏失败, Err: " + e.Error())
+		return
+	}
+	collectionId = item.CollectionID
+	return
+}
+
+// CancelCollection 取消收藏
+func CancelCollection(userId, collectionId int) (err error) {
+	item, e := yb_user_collection.GetItemById(collectionId)
+	if e != nil {
+		err = errors.New("获取收藏失败, Err: " + e.Error())
+		return
+	}
+	if item.CollectionID <= 0 {
+		err = errors.New("收藏信息有误")
+		return
+	}
+	if item.State != 1 {
+		err = errors.New("收藏状态有误")
+		return
+	}
+	if item.UserID != userId {
+		err = errors.New(fmt.Sprintf("收藏人信息有误, 操作人ID: %d, 被操作人ID: %d", userId, item.UserID))
+		return
+	}
+	updateCols := []string{"State", "ModifyTime"}
+	item.State = 0
+	item.ModifyTime = time.Now().Local()
+	if e = item.Update(updateCols); e != nil {
+		err = errors.New("更新收藏失败, Err: " + e.Error())
+		return
+	}
+	return
+}
+
+// GetCollectionList 收藏列表
+func GetCollectionList(userId, fromType, currPage, pageSize int, keywords string) (total int, respList []*response.CollectionList, err error) {
+	respList = make([]*response.CollectionList, 0)
+	if fromType <= 0 {
+		fromType = 0
+	}
+
+	// 查询收藏列表
+	var cond string
+	var pars []interface{}
+	cond += `state = 1 AND user_id = ?`
+	pars = append(pars, userId)
+	if fromType > 0 {
+		cond += ` AND collection_type = ?`
+		pars = append(pars, fromType)
+	}
+	if keywords != "" {
+		cond += ` AND title LIKE ?`
+		pars = append(pars, fmt.Sprint("%", keywords, "%"))
+	}
+	collectionTotal, e := yb_user_collection.GetPageListTotalByCondition(cond, pars)
+	if e != nil {
+		err = errors.New("获取收藏列表总数失败, Err: " + e.Error())
+		return
+	}
+	total = int(collectionTotal)
+	collections, e := yb_user_collection.GetPageListByCondition(cond, pars, currPage, pageSize)
+	if e != nil {
+		err = errors.New("获取收藏列表失败, Err: " + e.Error())
+		return
+	}
+
+	// 遍历收藏列表取出各类型的ID
+	reportIdArr := make([]int, 0)
+	chapterIdArr := make([]int, 0)
+	videoIdArr := make([]int, 0)
+	roadVideoIdArr := make([]int, 0)
+	for i := range collections {
+		switch collections[i].CollectionType {
+		case CollectionTypeReport:
+			if collections[i].ExtendID > 0 {
+				chapterIdArr = append(chapterIdArr, collections[i].ExtendID)
+				break
+			}
+			reportIdArr = append(reportIdArr, collections[i].PrimaryID)
+		case CollectionTypeVideo:
+			videoIdArr = append(videoIdArr, collections[i].PrimaryID)
+		case CollectionTypeRoadVideo:
+			roadVideoIdArr = append(roadVideoIdArr, collections[i].PrimaryID)
+		}
+	}
+
+	// 查询相应收藏类型详情
+	var chapterErr, reportErr, videoErr, roadVideoErr error
+	chapterMap := make(map[int]*report_chapter.ReportChapter, 0)
+	reportMap := make(map[int]*report.Report, 0)
+	videoMap := make(map[int]*yb_community_video.YbCommunityVideo, 0)
+	roadVideoMap := make(map[int]*yb_road_video.YbRoadVideo, 0)
+
+	wg := sync.WaitGroup{}
+
+	// 章节
+	wg.Add(1)
+	go func() {
+		defer wg.Done()
+
+		if len(chapterIdArr) == 0 {
+			return
+		}
+		chapters, e := report_chapter.GetListByChapterIds(chapterIdArr)
+		if e != nil {
+			chapterErr = errors.New("获取章节失败, Err: " + e.Error())
+			return
+		}
+		for i := range chapters {
+			chapterMap[chapters[i].ReportChapterId] = chapters[i]
+		}
+	}()
+
+	// 报告
+	wg.Add(1)
+	go func() {
+		defer wg.Done()
+
+		if len(reportIdArr) == 0 {
+			return
+		}
+		reports, e := report.GetListByReportIds(reportIdArr)
+		if e != nil {
+			reportErr = errors.New("获取报告失败, Err: " + e.Error())
+			return
+		}
+		for i := range reports {
+			reportMap[reports[i].Id] = reports[i]
+		}
+	}()
+
+	// 视频
+	wg.Add(1)
+	go func() {
+		defer wg.Done()
+
+		if len(videoIdArr) == 0 {
+			return
+		}
+		videos, e := yb_community_video.GetListByVideoIds(videoIdArr)
+		if e != nil {
+			videoErr = errors.New("获取视频失败, Err: " + e.Error())
+			return
+		}
+		for i := range videos {
+			videoMap[videos[i].CommunityVideoID] = videos[i]
+		}
+	}()
+
+	// 路演视频
+	wg.Add(1)
+	go func() {
+		defer wg.Done()
+
+		if len(roadVideoIdArr) == 0 {
+			return
+		}
+		roadVideos, e := yb_road_video.GetListByVideoIds(roadVideoIdArr)
+		if e != nil {
+			roadVideoErr = errors.New("获取视频失败, Err: " + e.Error())
+			return
+		}
+		for i := range roadVideos {
+			roadVideoMap[roadVideos[i].RoadVideoID] = roadVideos[i]
+		}
+	}()
+
+	wg.Wait()
+
+	if chapterErr != nil {
+		err = chapterErr
+		return
+	}
+	if reportErr != nil {
+		err = reportErr
+		return
+	}
+	if videoErr != nil {
+		err = videoErr
+		return
+	}
+	if roadVideoErr != nil {
+		err = roadVideoErr
+		return
+	}
+
+	// 响应列表
+	titlePre := `<div style="-webkit-line-clamp: 2;-webkit-box-orient: vertical;display: -webkit-box;overflow: hidden;text-overflow: ellipsis;">`
+	titleSuf := `</div>`
+	highlightPre := `<span style="color:#E3B377">`
+	highlightSuf := `</span>`
+	for i := range collections {
+		v := &response.CollectionList{
+			CollectionId:   collections[i].CollectionID,
+			CollectionType: collections[i].CollectionType,
+			PrimaryId:      collections[i].PrimaryID,
+			ExtendId:       collections[i].ExtendID,
+			CreateTime:     collections[i].CreateTime.Format(utils.FormatDate),
+		}
+		// 收藏类型:1-研报; 2-视频社区; 3-微路演视频
+		switch collections[i].CollectionType {
+		case CollectionTypeReport:
+			// 晨周报章节
+			if collections[i].ExtendID > 0 {
+				cp := chapterMap[collections[i].ExtendID]
+				if cp != nil {
+					v.PublishTime = cp.PublishTime.Format(utils.FormatDate)
+					v.ClassifyName = utils.REPORT_CHAPTER_TYPE_NAME_MAP[cp.ReportType]
+					v.Author = cp.Author
+					v.Title = cp.Title
+				}
+				break
+			}
+			rp := reportMap[collections[i].PrimaryID]
+			if rp != nil {
+				v.PublishTime = rp.PublishTime.Format(utils.FormatDate)
+				v.ClassifyName = rp.ClassifyNameFirst
+				v.ClassifySecondName = rp.ClassifyNameSecond
+				v.Author = rp.Author
+				v.Title = rp.Title
+			}
+		case CollectionTypeVideo:
+			vd := videoMap[collections[i].PrimaryID]
+			if vd != nil {
+				v.PublishTime = vd.PublishTime.Format(utils.FormatDate)
+				v.ImgUrl = vd.CoverImgURL
+				v.Title = vd.Title
+			}
+		case CollectionTypeRoadVideo:
+			rv := roadVideoMap[collections[i].PrimaryID]
+			if rv != nil {
+				v.PublishTime = rv.PublishTime.Format(utils.FormatDate)
+				v.ImgUrl = rv.CoverImgURL
+				v.Author = rv.AdminRealName
+				v.Title = rv.Title
+			}
+		default:
+			break
+		}
+		// 标题富文本及高亮
+		v.Title = fmt.Sprint(titlePre, v.Title, titleSuf)
+		if keywords != "" {
+			kw := fmt.Sprint(highlightPre, keywords, highlightSuf)
+			v.Title = strings.ReplaceAll(v.Title, keywords, kw)
+		}
+		respList = append(respList, v)
+	}
+
+	return
+}
+
+// GetUserCollectByItem 获取用户是否已收藏
+func GetUserCollectByItem(userId, collectionType, primaryId, extendId int) (collectionId int, err error) {
+	if userId <= 0 || collectionType <= 0 || primaryId <= 0 {
+		return
+	}
+
+	var cond string
+	var pars []interface{}
+	cond += `state = 1 AND user_id = ?`
+	pars = append(pars, userId)
+	cond += ` AND collection_type = ?`
+	pars = append(pars, collectionType)
+	cond += ` AND primary_id = ?`
+	pars = append(pars, primaryId)
+	if extendId > 0 {
+		cond += ` AND extend_id = ?`
+		pars = append(pars, extendId)
+	}
+
+	item, e := yb_user_collection.GetItemByCondition(cond, pars)
+	if e != nil && e != utils.ErrNoRow {
+		err = errors.New("获取用户收藏失败, Err: " + e.Error())
+		return
+	}
+	if item != nil && item.CollectionID > 0 {
+		collectionId = item.CollectionID
+	}
+	return
+}
+
+// GetUserCollectByItem 获取用户是否已收藏-列表(视频列表、路演视频列表)
+func GetUserCollectByList(userId, collectionType int, primaryIds []int) (collectMap map[int]int, err error) {
+	collectMap = make(map[int]int, 0)
+	if userId <= 0 || collectionType <= 0 || len(primaryIds) == 0 {
+		return
+	}
+
+	var cond string
+	var pars []interface{}
+	cond += `state = 1 AND user_id = ?`
+	pars = append(pars, userId)
+	cond += ` AND collection_type = ?`
+	pars = append(pars, collectionType)
+	cond += ` AND primary_id IN (?)`
+	pars = append(pars, primaryIds)
+
+	list, e := yb_user_collection.GetListByCondition(cond, pars)
+	if e != nil {
+		err = errors.New("获取用户收藏列表失败, Err: " + e.Error())
+		return
+	}
+	for i := range list {
+		if utils.InArrayByInt(primaryIds, list[i].PrimaryID) {
+			collectMap[list[i].PrimaryID] = list[i].CollectionID
+		}
+	}
+	return
+}

+ 28 - 1
services/community/video.go

@@ -11,6 +11,7 @@ import (
 	"hongze/hongze_yb/models/tables/yb_community_video"
 	"hongze/hongze_yb/models/tables/yb_community_video_play_log"
 	"hongze/hongze_yb/models/tables/yb_road_video"
+	"hongze/hongze_yb/services/collection"
 	"hongze/hongze_yb/services/company"
 	"hongze/hongze_yb/services/user"
 	"hongze/hongze_yb/utils"
@@ -20,7 +21,7 @@ import (
 )
 
 // GetVideoList 获取视频列表
-func GetVideoList(pageIndex, pageSize, videoId, varietyTagId int, keywords string) (resp []*response.CommunityVideoItem, err error) {
+func GetVideoList(userId, pageIndex, pageSize, videoId, varietyTagId int, keywords string) (resp []*response.CommunityVideoItem, err error) {
 	condition := make(map[string]interface{})
 	// 分享点进来的直接定位到具体视频
 	if videoId > 0 {
@@ -42,6 +43,7 @@ func GetVideoList(pageIndex, pageSize, videoId, varietyTagId int, keywords strin
 	if len(list) <= 0 {
 		return
 	}
+	videoIds := make([]int, 0)
 	for _, v := range list {
 		item := &response.CommunityVideoItem{
 			CommunityVideoID:    v.CommunityVideoID,
@@ -58,6 +60,17 @@ func GetVideoList(pageIndex, pageSize, videoId, varietyTagId int, keywords strin
 			ChartPermissionName: v.VarietyTagName,
 		}
 		resp = append(resp, item)
+		videoIds = append(videoIds, v.CommunityVideoID)
+	}
+
+	// 收藏
+	collectMap, e := collection.GetUserCollectByList(userId, collection.CollectionTypeVideo, videoIds)
+	if e != nil {
+		err = e
+		return
+	}
+	for i := range resp {
+		resp[i].CollectionId = collectMap[resp[i].CommunityVideoID]
 	}
 	return
 }
@@ -329,6 +342,8 @@ func GetRoadVideoList(userInfo user.UserInfo, pageIndex, pageSize, videoId, char
 		}
 	}
 	var chartPermissionNames string
+
+	videoIds := make([]int, 0)
 	for _, v := range videoList {
 		chartPermissionNames = ""
 		itemParentPermissionNum := make(map[string]int)
@@ -389,7 +404,19 @@ func GetRoadVideoList(userInfo user.UserInfo, pageIndex, pageSize, videoId, char
 			ModifyTime:          v.ModifyTime.Format(utils.FormatDateTime),
 		}
 		list = append(list, item)
+		videoIds = append(videoIds, item.RoadVideoID)
 	}
+
+	// 收藏
+	collectMap, e := collection.GetUserCollectByList(int(userInfo.UserID), collection.CollectionTypeRoadVideo, videoIds)
+	if e != nil {
+		err = e
+		return
+	}
+	for i := range list {
+		list[i].CollectionId = collectMap[list[i].RoadVideoID]
+	}
+
 	resp.List = list
 	resp.Paging = response.GetPaging(pageIndex, pageSize, int(total))
 	return

+ 9 - 0
services/report/report.go

@@ -21,6 +21,7 @@ import (
 	"hongze/hongze_yb/models/tables/report_chapter_type"
 	"hongze/hongze_yb/models/tables/report_chapter_type_permission"
 	"hongze/hongze_yb/services"
+	"hongze/hongze_yb/services/collection"
 	"hongze/hongze_yb/services/company"
 	elasticService "hongze/hongze_yb/services/elastic"
 	"hongze/hongze_yb/services/user"
@@ -508,6 +509,14 @@ func GetReportDetail(userinfo user.UserInfo, reportId int) (reportDetail respons
 	reportDetail.LikeNum = likeNum
 	reportDetail.LikeEnabled = likeEnabled
 	reportDetail.ReportShowType = int(firstClassify.ShowType)
+
+	// 收藏
+	collectionId, e := collection.GetUserCollectByItem(int(userinfo.UserID), collection.CollectionTypeReport, reportId, 0)
+	if e != nil {
+		err = e
+		return
+	}
+	reportDetail.CollectionId = collectionId
 	return
 }
 

+ 9 - 0
services/report/report_chapter.go

@@ -13,6 +13,7 @@ import (
 	"hongze/hongze_yb/models/tables/rddp/report_chapter"
 	"hongze/hongze_yb/models/tables/report_chapter_type"
 	"hongze/hongze_yb/services"
+	"hongze/hongze_yb/services/collection"
 	"hongze/hongze_yb/services/company"
 	"hongze/hongze_yb/services/user"
 	"hongze/hongze_yb/utils"
@@ -295,6 +296,14 @@ func GetChapterDetail(user user.UserInfo, reportChapterId int) (reportChapterDet
 	reportChapterDetail.AuthOk = authOk
 	reportChapterDetail.LikeNum = likeNum
 	reportChapterDetail.LikeEnabled = likeEnabled
+
+	// 收藏
+	collectionId, e := collection.GetUserCollectByItem(int(user.UserID), collection.CollectionTypeReport, reportChapterItem.ReportId, reportChapterId)
+	if e != nil {
+		err = e
+		return
+	}
+	reportChapterDetail.CollectionId = collectionId
 	return
 }
 

+ 25 - 3
utils/common.go

@@ -963,8 +963,8 @@ func InArray(needle interface{}, hyStack interface{}) bool {
 
 // bit转MB 保留小数
 func Bit2MB(bitSize int64, prec int) (size float64) {
-	mb := float64(bitSize)/float64(1024*1024)
-	size, _ = strconv.ParseFloat(strconv.FormatFloat(mb,'f',prec,64), 64)
+	mb := float64(bitSize) / float64(1024*1024)
+	size, _ = strconv.ParseFloat(strconv.FormatFloat(mb, 'f', prec, 64), 64)
 	return
 }
 
@@ -977,4 +977,26 @@ func SubStr(str string, subLen int) string {
 	}
 	str = string(strRune[:bodyRuneLen])
 	return str
-}
+}
+
+// InArrayByInt php中的in_array(判断Int类型的切片中是否存在该int值)
+func InArrayByInt(idIntList []int, searchId int) (has bool) {
+	for _, id := range idIntList {
+		if id == searchId {
+			has = true
+			return
+		}
+	}
+	return
+}
+
+// InArrayByStr php中的in_array(判断String类型的切片中是否存在该string值)
+func InArrayByStr(idStrList []string, searchId string) (has bool) {
+	for _, id := range idStrList {
+		if id == searchId {
+			has = true
+			return
+		}
+	}
+	return
+}

+ 11 - 0
utils/constants.go

@@ -208,3 +208,14 @@ var SystemSourceList = []int{
 const (
 	SendTemplateMsgAuthorization = "dc855fce962a639faa779cbdd4cd332f"
 )
+
+// 研报类型标识
+var (
+	REPORT_TYPE_DAY  = "day"
+	REPORT_TYPE_WEEK = "week"
+)
+
+var REPORT_CHAPTER_TYPE_NAME_MAP = map[string]string{
+	REPORT_TYPE_DAY:  "晨报",
+	REPORT_TYPE_WEEK: "周报",
+}