Răsfoiți Sursa

Merge branch 'master' of http://8.136.199.33:3000/cxzhang/hongze_clpt into cygx_9.3.1_0

xingzai 2 ani în urmă
părinte
comite
37c180f1a9
42 a modificat fișierele cu 4002 adăugiri și 377 ștergeri
  1. 3 0
      controllers/article.go
  2. 5 1
      controllers/chart_permission.go
  3. 1 1
      controllers/home.go
  4. 345 0
      controllers/micro_roadshow.go
  5. 426 173
      controllers/report.go
  6. 2 2
      controllers/report_billboard.go
  7. 828 0
      controllers/research.go
  8. 2 1
      models/activity.go
  9. 1 1
      models/activity_special.go
  10. 3 0
      models/activity_type.go
  11. 27 7
      models/article.go
  12. 51 5
      models/article_collect.go
  13. 93 1
      models/article_department.go
  14. 80 0
      models/article_department_follow.go
  15. 156 0
      models/article_history_record_newpv.go
  16. 70 0
      models/article_type.go
  17. 129 0
      models/cygx_morning_meeting_review_chapter.go
  18. 5 0
      models/db.go
  19. 44 0
      models/home.go
  20. 56 0
      models/industrial_article_group_management.go
  21. 70 24
      models/industrial_management.go
  22. 57 0
      models/industrial_subject.go
  23. 11 0
      models/micro_roadshow.go
  24. 26 1
      models/page_history_record.go
  25. 469 45
      models/report.go
  26. 17 14
      models/report_mapping.go
  27. 105 6
      routers/commentsRouter.go
  28. 5 1
      routers/router.go
  29. 32 15
      services/activity.go
  30. 5 0
      services/activity_special.go
  31. 71 15
      services/article.go
  32. 213 0
      services/article_red.go
  33. 50 1
      services/config.go
  34. 227 44
      services/industrial_management.go
  35. 42 0
      services/industrial_subject.go
  36. 1 1
      services/report.go
  37. 1 1
      services/resource_data.go
  38. 15 3
      services/wechat.go
  39. 141 2
      services/wx_template_msg.go
  40. 79 0
      services/yan_xuan.go
  41. 15 10
      utils/config.go
  42. 23 2
      utils/constants.go

+ 3 - 0
controllers/article.go

@@ -281,6 +281,9 @@ Loop:
 	//var haveResearch bool
 	fmt.Println(hasFree)
 	fmt.Println(haveResearch)
+	if hasPermission == 1 {
+		go services.ArticleHistory(articleId, user)
+	}
 	if detail.SubCategoryName == "专项调研" {
 		detail.IsSpecialArticle = true
 	}

+ 5 - 1
controllers/chart_permission.go

@@ -6,7 +6,7 @@ import (
 	"strconv"
 )
 
-//品种
+// 品种
 type ChartPermissionController struct {
 	BaseCommonController
 }
@@ -67,6 +67,10 @@ func (this *ChartPermissionController) ListByReport() {
 		br.ErrMsg = "获取品种信息失败,Err:" + err.Error()
 		return
 	}
+	item := new(models.ChartPermissionResp)
+	item.PermissionName = utils.GU_SHOU_NAME
+	item.ChartPermissionId = utils.GU_SHOU_ID
+	list = append(list, item)
 	resp := new(models.ChartPermissionListResp)
 	resp.List = list
 	br.Ret = 200

+ 1 - 1
controllers/home.go

@@ -208,7 +208,7 @@ func (this *MobileHomeController) List() {
 			br.Msg = "获取帖子数据失败,Err:" + err.Error()
 			return
 		}
-		listPublic, err = services.HandleArticleCategoryImg(listPublic)
+		listPublic, err = services.HandleArticleCategoryImg(listPublic, user)
 		if err != nil {
 			br.Msg = "获取失败"
 			br.ErrMsg = "获取报告封面图片失败, Err:" + err.Error()

+ 345 - 0
controllers/micro_roadshow.go

@@ -104,6 +104,44 @@ func (this *MicroRoadShowController) List() {
 		}
 	}
 
+	userId := user.UserId
+	listMycollect, err := models.GetUserMicroRoadshowCollectList(userId)
+	if err != nil {
+		br.Msg = "获取数据失败"
+		br.ErrMsg = "获取数据失败,Err:" + err.Error()
+		return
+	}
+	mapaudioIds := make(map[int]int)         //活动音频
+	mapvideoIds := make(map[int]int)         // 微路演视频
+	mapactivityVideoIds := make(map[int]int) // 活动视频
+	for _, item := range listMycollect {
+		if item.ActivityVoiceId > 0 {
+			mapaudioIds[item.ActivityVoiceId] = item.ActivityVoiceId
+		} else if item.VideoId > 0 {
+			mapvideoIds[item.VideoId] = item.VideoId
+		} else if item.ActivityVideoId > 0 {
+			mapactivityVideoIds[item.ActivityVoiceId] = item.ActivityVoiceId
+		}
+	}
+	for _, item := range list {
+		if item.Type == 1 {
+			//音频
+			if mapaudioIds[item.Id] > 0 {
+				item.IsCollect = true
+			}
+		} else if item.Type == 2 {
+			//活动视频
+			if mapactivityVideoIds[item.Id] > 0 {
+				item.IsCollect = true
+			}
+		} else if item.Type == 3 {
+			//微路演视频
+			if mapvideoIds[item.Id] > 0 {
+				item.IsCollect = true
+			}
+		}
+	}
+
 	// 用户权限
 	authInfo, permissionArr, e := services.GetUserRaiPermissionInfo(user.UserId, user.CompanyId)
 	if e != nil {
@@ -308,3 +346,310 @@ func (this *MicroRoadShowController) VideoHistoryAdd() {
 	br.Msg = "操作成功"
 	return
 }
+
+// @Title 微路演新增留言
+// @Description 微路演新增留言接口
+// @Param	request	body models.AddVideoCommnetReq true "type json string"
+// @Success Ret=200 {object} models.AppointmentResp
+// @router /comment/add [post]
+func (this *MicroRoadShowController) CommentAdd() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	user := this.User
+	if user == nil {
+		br.Msg = "请登录"
+		br.ErrMsg = "请登录,用户信息为空"
+		br.Ret = 408
+		return
+	}
+	uid := user.UserId
+	var req models.AddVideoCommnetReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	content := req.Content
+	if content == "" {
+		br.Msg = "留言内容不能为空!"
+		return
+	}
+	//itemToken, err := services.WxGetToken()
+	//if err != nil {
+	//	br.Msg = "GetWxAccessToken Err:" + err.Error()
+	//	return
+	//}
+	//if itemToken.AccessToken == "" {
+	//	br.Msg = "accessToken is empty"
+	//	return
+	//}
+	//commerr, err := weapp.MSGSecCheck(itemToken.AccessToken, content)
+	//if err != nil {
+	//	br.Msg = "内容校验失败!"
+	//	br.ErrMsg = "内容校验失败,Err:" + err.Error()
+	//	return
+	//}
+	//if commerr.ErrCode != 0 {
+	//	br.Msg = "内容违规,请重新提交!"
+	//	br.ErrMsg = "内容违规,Err:" + commerr.ErrMSG
+	//	return
+	//}
+
+	sourceType := req.SourceType
+
+	if sourceType == 0 {
+		sourceType = 1
+	}
+	item := models.CygxArticleComment{
+		UserId:      uid,
+		CreateTime:  time.Now(),
+		RealName:    user.RealName,
+		Mobile:      user.Mobile,
+		Email:       user.Email,
+		CompanyId:   user.CompanyId,
+		CompanyName: user.CompanyName,
+		Content:     req.Content,
+		Title:       req.Title,
+	}
+	var resourceId int
+	if sourceType == 1 {
+		activityVoiceInfo, _ := models.GetCygxActivityVoiceById(req.Id)
+		if activityVoiceInfo == nil {
+			br.Msg = "操作失败"
+			br.ErrMsg = "活动ID错误,不存在activityId:" + strconv.Itoa(req.Id)
+			return
+		}
+		item.ActivityId = activityVoiceInfo.ActivityId
+		item.Title = activityVoiceInfo.VoiceName
+		item.ActivityVoiceId = activityVoiceInfo.ActivityVoiceId
+		resourceId = activityVoiceInfo.ActivityId
+	} else if sourceType == 2 {
+		activityInfo, _ := models.GetCygxActivityVideoById(req.Id)
+		if activityInfo == nil {
+			br.Msg = "操作失败"
+			br.ErrMsg = "活动ID错误,不存在activityId:" + strconv.Itoa(req.Id)
+			return
+		}
+		item.Title = activityInfo.Title
+		item.VideoId = activityInfo.Id
+		item.ActivityId = activityInfo.ActivityId
+		resourceId = activityInfo.ActivityId
+	} else if sourceType == 3 {
+		item.VideoId = req.Id
+		microVideo, e := models.GetMicroRoadshowVideoById(req.Id)
+		if e != nil {
+			br.Msg = "操作失败"
+			br.ErrMsg = "微路演视频信息有误, 不存在的VideoId: " + strconv.Itoa(req.Id)
+			return
+		}
+		item.Title = microVideo.VideoName
+		item.IndustryId = microVideo.IndustryId
+		resourceId = microVideo.IndustryId
+	}
+	_, err = models.AddArticleComment(&item)
+	if err != nil {
+		br.Msg = "提交失败"
+		br.ErrMsg = "提交留言失败,Err:" + err.Error()
+		return
+	}
+	services.SendWxMsgWithMicroRoadshowAsk(req, user, resourceId)
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "操作成功"
+	return
+}
+
+// @Title 微路演收藏
+// @Description 微路演收藏
+// @Param	request	body models.MicroRoadshowCollectReq true "type json string"
+// @Success 200 {object} models.FontsCollectResp
+// @router /collect [post]
+func (this *MicroRoadShowController) Collect() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	user := this.User
+	if user == nil {
+		br.Msg = "请重新登录"
+		br.Ret = 408
+		return
+	}
+	uid := user.UserId
+	var req models.MicroRoadshowCollectReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+
+	if req.SourceType == 1 {
+		_, err := models.GetCygxActivityVoiceById(req.Id)
+		if err != nil {
+			br.Msg = "获取信息失败"
+			br.ErrMsg = "获取信息失败,Err:" + err.Error()
+			return
+		}
+		count, err := models.GetVoiceCollectCount(uid, req.Id)
+		if err != nil {
+			br.Msg = "获取数据失败!"
+			br.ErrMsg = "获取数据失败,Err:" + err.Error()
+			return
+		}
+		resp := new(models.ArticleCollectResp)
+		if count <= 0 {
+			item := new(models.CygxArticleCollect)
+			item.ActivityVoiceId = req.Id
+			item.UserId = uid
+			item.CreateTime = time.Now()
+			item.Mobile = user.Mobile
+			item.Email = user.Email
+			item.CompanyId = user.CompanyId
+			item.CompanyName = user.CompanyName
+			item.RealName = user.RealName
+			_, err = models.AddCygxArticleCollect(item)
+			if err != nil {
+				br.Msg = "收藏失败"
+				br.ErrMsg = "收藏失败,Err:" + err.Error()
+				return
+			}
+			br.Msg = "收藏成功"
+			resp.Status = 1
+			// 文章收藏消息发送
+			//go services.ArticleUserRemind(user, detail, 2)
+		} else {
+			err = models.RemoveVoiceCollect(uid, req.Id)
+			if err != nil {
+				br.Msg = "取消收藏失败"
+				br.ErrMsg = "取消收藏失败,Err:" + err.Error()
+				return
+			}
+			br.Msg = "已取消收藏"
+			resp.Status = 2
+		}
+		collectTotal, err := models.GetVoiceCollectUsersCount(req.Id)
+		if err != nil {
+			br.Msg = "获取数据失败"
+			br.ErrMsg = "获取数据失败,Err:" + err.Error()
+			return
+		}
+		resp.CollectCount = collectTotal
+		br.Ret = 200
+		br.Success = true
+		br.Data = resp
+	} else if req.SourceType == 2 {
+		_, err := models.GetCygxActivityVideoById(req.Id)
+		if err != nil {
+			br.Msg = "获取信息失败"
+			br.ErrMsg = "获取信息失败,Err:" + err.Error()
+			return
+		}
+		count, err := models.GetActivityVideoCollectCount(uid, req.Id)
+		if err != nil {
+			br.Msg = "获取数据失败!"
+			br.ErrMsg = "获取数据失败,Err:" + err.Error()
+			return
+		}
+		resp := new(models.ArticleCollectResp)
+		if count <= 0 {
+			item := new(models.CygxArticleCollect)
+			item.ActivityVideoId = req.Id
+			item.UserId = uid
+			item.CreateTime = time.Now()
+			item.Mobile = user.Mobile
+			item.Email = user.Email
+			item.CompanyId = user.CompanyId
+			item.CompanyName = user.CompanyName
+			item.RealName = user.RealName
+			_, err = models.AddCygxArticleCollect(item)
+			if err != nil {
+				br.Msg = "收藏失败"
+				br.ErrMsg = "收藏失败,Err:" + err.Error()
+				return
+			}
+			br.Msg = "收藏成功"
+			resp.Status = 1
+			// 文章收藏消息发送
+			//go services.ArticleUserRemind(user, detail, 2)
+		} else {
+			err = models.RemoveActivityVideoCollect(uid, req.Id)
+			if err != nil {
+				br.Msg = "取消收藏失败"
+				br.ErrMsg = "取消收藏失败,Err:" + err.Error()
+				return
+			}
+			br.Msg = "已取消收藏"
+			resp.Status = 2
+		}
+		collectTotal, err := models.GetActivityVideoCollectUsersCount(req.Id)
+		if err != nil {
+			br.Msg = "获取数据失败"
+			br.ErrMsg = "获取数据失败,Err:" + err.Error()
+			return
+		}
+		resp.CollectCount = collectTotal
+		br.Ret = 200
+		br.Success = true
+		br.Data = resp
+	} else if req.SourceType == 3 {
+		_, err := models.GetMicroRoadshowVideoById(req.Id)
+		if err != nil {
+			br.Msg = "获取信息失败"
+			br.ErrMsg = "获取信息失败,Err:" + err.Error()
+			return
+		}
+		count, err := models.GetVideoCollectCount(uid, req.Id)
+		if err != nil {
+			br.Msg = "获取数据失败!"
+			br.ErrMsg = "获取数据失败,Err:" + err.Error()
+			return
+		}
+		resp := new(models.ArticleCollectResp)
+		if count <= 0 {
+			item := new(models.CygxArticleCollect)
+			item.VideoId = req.Id
+			item.UserId = uid
+			item.CreateTime = time.Now()
+			item.Mobile = user.Mobile
+			item.Email = user.Email
+			item.CompanyId = user.CompanyId
+			item.CompanyName = user.CompanyName
+			item.RealName = user.RealName
+			_, err = models.AddCygxArticleCollect(item)
+			if err != nil {
+				br.Msg = "收藏失败"
+				br.ErrMsg = "收藏失败,Err:" + err.Error()
+				return
+			}
+			br.Msg = "收藏成功"
+			resp.Status = 1
+			// 文章收藏消息发送
+			//go services.ArticleUserRemind(user, detail, 2)
+		} else {
+			err = models.RemoveVideoCollect(uid, req.Id)
+			if err != nil {
+				br.Msg = "取消收藏失败"
+				br.ErrMsg = "取消收藏失败,Err:" + err.Error()
+				return
+			}
+			br.Msg = "已取消收藏"
+			resp.Status = 2
+		}
+		collectTotal, err := models.GetVideoCollectUsersCount(req.Id)
+		if err != nil {
+			br.Msg = "获取数据失败"
+			br.ErrMsg = "获取数据失败,Err:" + err.Error()
+			return
+		}
+		resp.CollectCount = collectTotal
+		br.Ret = 200
+		br.Success = true
+		br.Data = resp
+	}
+}

+ 426 - 173
controllers/report.go

@@ -2,7 +2,6 @@ package controllers
 
 import (
 	"encoding/json"
-	"fmt"
 	"github.com/rdlucklib/rdluck_tools/paging"
 	"hongze/hongze_clpt/models"
 	"hongze/hongze_clpt/services"
@@ -42,7 +41,6 @@ func (this *MobileReportController) TradeList() {
 		br.Ret = 408
 		return
 	}
-	fmt.Println(user)
 	uid := user.UserId
 	ChartPermissionId, _ := this.GetInt("ChartPermissionId")
 	if ChartPermissionId < 1 {
@@ -53,8 +51,8 @@ func (this *MobileReportController) TradeList() {
 	var list []*models.TradeReportMapping
 	var err error
 	mapCategory := make(map[int]int)
-	if ChartPermissionId == utils.CE_LUE_ID {
-		listTrade, errTrade := models.GetReportMappingStrategyHomeAll()
+	if ChartPermissionId == utils.CE_LUE_ID || ChartPermissionId == utils.GU_SHOU_ID {
+		listTrade, errTrade := models.GetReportMappingStrategyHomeAll(user.UserId, ChartPermissionId)
 		list = listTrade
 		err = errTrade
 
@@ -70,6 +68,23 @@ func (this *MobileReportController) TradeList() {
 				mapCategory[v.CategoryId] = v.CategoryId
 			}
 		}
+		for k, v := range list {
+			count, err := models.GetUserIsReadThisNewCategoryArticleCount(v.CategoryId, uid)
+			if err != nil && err.Error() != utils.ErrNoRow() {
+				br.Msg = "获取信息失败"
+				br.ErrMsg = "获取品种信息失败,Err:" + err.Error()
+				return
+			}
+			Newdetail, err := models.GetNewArticleByCategoryId(v.CategoryId)
+			if err != nil {
+				br.Msg = "获取信息失败"
+				br.ErrMsg = "获取信息失败,Err:" + err.Error()
+				return
+			}
+			if count == 0 && user.CreatedTime.Before(utils.StrTimeToTime(Newdetail.PublishDate)) && utils.StrTimeToTime(utils.OnlineTime).Before(utils.StrTimeToTime(Newdetail.PublishDate)) {
+				list[k].IsRed = true
+			}
+		}
 	} else {
 		listTrade, errTrade := models.GetTradeAll(ChartPermissionId)
 		err = errTrade
@@ -105,7 +120,7 @@ func (this *MobileReportController) TradeList() {
 			condition = ` AND a.category_id IN(` + strconv.Itoa(v.CategoryId) + `)`
 		}
 
-		if ChartPermissionId != utils.CE_LUE_ID {
+		if ChartPermissionId != utils.CE_LUE_ID && ChartPermissionId != utils.GU_SHOU_ID {
 			var pageSize int
 			//if ChartPermissionId == utils.KE_JI_ID {
 			//	pageSize = 12
@@ -306,7 +321,13 @@ func (this *MobileReportController) IndustryList() {
 		}
 	}
 
-	list, err = services.HandleIndustryList(list, user)
+	var resource string
+	if ChartPermissionId == utils.CHART_PERMISSION_ID_YANXUAN {
+		resource = utils.REOURCE_YX
+	} else {
+		resource = utils.REOURCE_HZ
+	}
+	list, err = services.HandleIndustryList(list, user, resource)
 	if err != nil {
 		br.Msg = "获取信息失败"
 		br.ErrMsg = "获取信息失败,Err:" + err.Error()
@@ -401,8 +422,10 @@ func (this *MobileReportController) ArticleCategoryList() {
 			br.ErrMsg = "获取信息失败,Err:" + err.Error()
 			return
 		}
-		if recordCount == 0 && user.CreatedTime.Before(utils.StrTimeToTime(Newdetail.PublishDate)) && utils.StrTimeToTime(utils.OnlineTime).Before(utils.StrTimeToTime(Newdetail.PublishDate)) {
-			list[k].IsRed = true
+		if Newdetail != nil {
+			if recordCount == 0 && user.CreatedTime.Before(utils.StrTimeToTime(Newdetail.PublishDate)) && utils.StrTimeToTime(utils.OnlineTime).Before(utils.StrTimeToTime(Newdetail.PublishDate)) {
+				list[k].IsRed = true
+			}
 		}
 	}
 	//标的列表
@@ -422,6 +445,13 @@ func (this *MobileReportController) ArticleCategoryList() {
 		CategoryId:    utils.TIME_CATEGORYID,
 		MatchTypeName: "时间线",
 	}
+	timeLineIsRed, err := services.GetShowTimeLineIsRed(user, industrialManagementId)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取用户权限失败, Err: " + err.Error()
+		return
+	}
+	timeLineItem.IsRed = timeLineIsRed
 	list = append([]*models.IndustrialToArticleCategoryRep{&timeLineItem}, list...)
 	resp := new(models.IndustrialToArticleCategoryListRep)
 	resp.List = list
@@ -478,7 +508,7 @@ func (this *MobileReportController) List() {
 	var total int
 	resp := new(models.TacticsListResp)
 	page := paging.GetPaging(currentIndex, pageSize, total)
-	list := make([]*models.HomeArticle, 0)
+	list := make([]*models.ArticleListResp, 0)
 
 	if categoryId == utils.TIME_CATEGORYID {
 		var err error
@@ -537,17 +567,9 @@ func (this *MobileReportController) List() {
 			imgUrlChart = vslice[len(vslice)-1]
 			mapCategoryUrl[categoryIdStr] = imgUrlChart
 		}
-		//condition += ` AND category_id_two=? `
-		//pars = append(pars, categoryId)
-
-		//categoryIdSet, errCategory := models.GetdetailByCategoryIdSet(categoryId)
-		//if errCategory != nil {
-		//	br.Msg = "获取信息失败"
-		//	br.ErrMsg = "获取信息失败,Err:" + errCategory.Error() + "categoryID 不存在:" + strconv.Itoa(categoryId)
-		//	return
-		//}
-		//fmt.Println(detail.PolymerizationId)
-		if detail.PolymerizationId != "" {
+		if detail.CeLueFieldId != "" {
+			condition = ` AND ce_lue_field_id IN(` + detail.CeLueFieldId + `)`
+		} else if detail.PolymerizationId != "" {
 			condition = ` AND category_id IN(` + detail.PolymerizationId + `)`
 		} else {
 			categoryIdSet, errCategory := models.GetdetailByCategoryIdSet(categoryId)
@@ -561,8 +583,6 @@ func (this *MobileReportController) List() {
 			} else {
 				condition = ` AND category_id IN(` + strconv.Itoa(categoryId) + `)`
 			}
-			//condition = ` AND category_id IN(` + strconv.Itoa(categoryId) + `)`
-			//condition = ` AND match_type_name  = '` + detail.MatchTypeName + `'`
 		}
 
 		if industrialManagementId > 0 {
@@ -587,7 +607,13 @@ func (this *MobileReportController) List() {
 			return
 		}
 
-		list, err = models.GetHomeList(condition, pars, startSize, pageSize)
+		list, err = models.GetHomeListNew(condition, pars, startSize, pageSize)
+		if err != nil {
+			br.Msg = "获取信息失败"
+			br.Msg = "获取帖子数据失败,Err:" + err.Error()
+			return
+		}
+		articleIdMap, err := services.GetUserArticleHistoryRecord(user)
 		if err != nil {
 			br.Msg = "获取信息失败"
 			br.Msg = "获取帖子数据失败,Err:" + err.Error()
@@ -595,6 +621,9 @@ func (this *MobileReportController) List() {
 		}
 		for k, v := range list {
 			list[k].ImgUrlPc = mapCategoryUrl[v.CategoryId]
+			if !articleIdMap[v.ArticleId] && user.CreatedTime.Before(utils.StrTimeToTime(v.PublishDate)) && utils.StrTimeToTime(utils.OnlineTime).Before(utils.StrTimeToTime(v.PublishDate)) {
+				list[k].IsRed = true
+			}
 		}
 		if categoryId > 0 {
 			detail, errCategory := models.GetdetailByCategoryId(categoryId)
@@ -607,23 +636,42 @@ func (this *MobileReportController) List() {
 		}
 		resp.CategoryImgUrlPc = mapChartPermission[detail.ChartPermissionName]
 	}
-	lenList := len(list)
-	for i := 0; i < lenList; i++ {
-		item := list[i]
-		list[i].Body = ""
-		list[i].Abstract, _ = services.GetReportContentTextSub(item.Abstract)
-		list[i].Annotation, _ = services.GetReportContentTextSub(item.Annotation)
-		list[i].PublishDate = utils.StrTimeToTime(item.PublishDate).Format(utils.FormatDate) //时间字符串格式转时间格式
-		//行业比较研究、资金流向,显示报告的摘要
-		if resp.MatchTypeName == "行业比较研究" || resp.MatchTypeName == "资金流向" {
-			list[i].Annotation = list[i].Abstract
-		}
+
+	listPublic, err := services.HandleArticleCategoryImg(list, user)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取报告封面图片失败, Err:" + err.Error()
+		return
 	}
-	if len(list) == 0 {
-		list = make([]*models.HomeArticle, 0)
+	listResp := make([]*models.HomeArticle, 0)
+	//listResp :=
+	for _, v := range listPublic {
+		listResp = append(listResp, &models.HomeArticle{
+			ArticleId:   v.ArticleId,
+			Title:       v.Title,
+			Annotation:  "核心观点:" + v.Annotation,
+			Abstract:    v.Abstract,
+			ImgUrlPc:    v.ImgUrlPc,
+			PublishDate: v.PublishDate,
+		})
+	}
+	//lenList := len(list)
+	//for i := 0; i < lenList; i++ {
+	//	item := list[i]
+	//	list[i].Body = ""
+	//	list[i].Abstract, _ = services.GetReportContentTextSub(item.Abstract)
+	//	list[i].Annotation, _ = services.GetReportContentTextSub(item.Annotation)
+	//	list[i].PublishDate = utils.StrTimeToTime(item.PublishDate).Format(utils.FormatDate) //时间字符串格式转时间格式
+	//	//行业比较研究、资金流向,显示报告的摘要
+	//	if resp.MatchTypeName == "行业比较研究" || resp.MatchTypeName == "资金流向" {
+	//		list[i].Annotation = list[i].Abstract
+	//	}
+	//}
+	if len(listResp) == 0 {
+		listResp = make([]*models.HomeArticle, 0)
 	}
 	page = paging.GetPaging(currentIndex, pageSize, total)
-	resp.List = list
+	resp.List = listResp
 	resp.Paging = page
 	br.Ret = 200
 	br.Success = true
@@ -797,6 +845,8 @@ func (this *ReportController) CategoryFllow() {
 // @Param   PageSize   query   int  true       "每页数据条数"
 // @Param   CurrentIndex   query   int  true       "当前页页码,从1开始"
 // @Param   KeyWord   query   string  true       "搜索关键词"
+// @Param   ArticleType   query   int  true       "文章类型,1弘则报告、2研选 "
+// @Param   IsAll   query   bool  true       "是否为综合 "
 // @Success 200 {object} models.ReoprtSearchResp
 // @router /searchReport [get]
 func (this *MobileReportController) SearchReport() {
@@ -813,118 +863,190 @@ func (this *MobileReportController) SearchReport() {
 	}
 	pageSize, _ := this.GetInt("PageSize")
 	currentIndex, _ := this.GetInt("CurrentIndex")
+	articleType, _ := this.GetInt("ArticleType", 1)
 	keyWord := this.GetString("KeyWord")
+	isAll, _ := this.GetBool("IsAll")
 	var condition string
-	var conditionSql string
-	//var sqlGroup string
+	var pars []interface{}
+	//var conditionSql string
 	var total int
 	var startSize int
 	if pageSize <= 0 {
 		pageSize = utils.PageSize20
 	}
+	if isAll {
+		pageSize = utils.PageSize5
+	}
 	if currentIndex <= 0 {
 		currentIndex = 1
 	}
 	startSize = paging.StartIndex(currentIndex, pageSize)
-	page := paging.GetPaging(currentIndex, pageSize, total)
+
 	resp := new(models.ReoprtSearchResp)
 	//匹配报告标题、
-	condition = ` AND ( a.title LIKE '%` + keyWord + `%' OR  a.body LIKE '%` + keyWord + `%') AND a.publish_status = 1 `
-
-	conditionSql = ` AND a.article_id <  ` + strconv.Itoa(utils.SummaryArticleId) + condition + ` OR ( article_type = 'lyjh' ` + condition + ` ) `
-	total, err := models.GetReoprtSearchCount(conditionSql)
+	articleTypeIds, err := services.GetYanXuanArticleTypeIds()
 	if err != nil {
 		br.Msg = "获取信息失败"
-		br.Msg = "获取总数失败,Err:" + err.Error()
+		br.ErrMsg = "GetYanXuanArticleTypeIds,Err:" + err.Error()
 		return
 	}
-	//listHz, err := models.GetReoprtSearchList(` AND a.article_id <  `+strconv.Itoa(utils.SummaryArticleId)+condition+` OR ( article_type = 'lyjh' `+condition+` ) `+sqlGroup, user.UserId, startSize, pageSize)
-	listHz, err := models.GetReoprtSearchList(conditionSql, user.UserId, startSize, pageSize)
-	if err != nil {
+	if articleTypeIds == "" {
 		br.Msg = "获取信息失败"
-		br.ErrMsg = "获取文章列表失败,Err:" + err.Error()
+		br.ErrMsg = "研选分类ID不能为空"
 		return
 	}
-	for k, _ := range listHz {
-		listHz[k].Source = 1
-	}
-	var articleIds string
-	for _, v := range listHz {
-		articleIds += strconv.Itoa(v.ArticleId) + ","
-	}
-	articleIds = strings.TrimRight(articleIds, ",")
-	silcearticleIds := strings.Split(articleIds, ",")
-	//获取文章关联的产业
-	var pars []interface{}
-	pars = make([]interface{}, 0)
-	articleIdList := make([]string, 0)
-	for _, v := range silcearticleIds {
-		articleIdList = append(articleIdList, v)
-	}
-	condition = ` AND mg.article_id IN (  ` + utils.GetOrmInReplace(len(silcearticleIds)) + ` )  `
-	pars = append(pars, articleIdList)
-	industrialList, err := models.GetIndustrialListByarticleId(pars, condition)
+	//处理对应的文章类型标签按钮
+	nameMap, styleMap, err := services.GetArticleTypeMap()
 	if err != nil {
-		br.Msg = "获取失败"
-		br.ErrMsg = "获取失败,GetSubjectList Err:" + err.Error()
+		br.Msg = "获取信息失败"
+		br.ErrMsg = "GetArticleTypeMap Err:" + err.Error()
 		return
 	}
-	industrialMap := make(map[int][]*models.IndustrialManagementResp)
-	if len(industrialList) > 0 {
-		for _, v := range industrialList {
-			item := new(models.IndustrialManagementResp)
-			//item.ArticleId = v.ArticleId
-			item.IndustrialManagementId = v.IndustrialManagementId
-			item.IndustryName = v.IndustryName
-			item.ChartPermissionId = v.ChartPermissionId
-			industrialMap[v.ArticleId] = append(industrialMap[v.ArticleId], item)
+	if isAll {
+		total = utils.PageSize5
+		conditionHz := `  AND ( a.title LIKE '%` + keyWord + `%' OR  a.body LIKE '%` + keyWord + `%' OR  a.annotation LIKE '%` + keyWord + `%' OR  a.abstract LIKE '%` + keyWord + `%') AND a.publish_status = 1  AND a.article_type_id NOT IN (` + articleTypeIds + `)  `
+		conditionYx := `  AND ( a.title LIKE '%` + keyWord + `%' OR  a.body LIKE '%` + keyWord + `%' OR  a.annotation LIKE '%` + keyWord + `%' OR  a.abstract LIKE '%` + keyWord + `%') AND a.publish_status = 1  AND a.article_type_id  IN (` + articleTypeIds + `)  `
+
+		listHz, err := models.GetArticleResearchListHz(conditionHz, pars, startSize, pageSize, user.UserId)
+		if err != nil {
+			br.Msg = "获取信息失败"
+			br.ErrMsg = "获取品种信息失败,Err:" + err.Error()
+			return
+		}
+		listYx, err := models.GetArticleResearchList(conditionYx, pars, startSize, pageSize, user.UserId)
+		if err != nil {
+			br.Msg = "获取信息失败"
+			br.ErrMsg = "获取品种信息失败,Err:" + err.Error()
+			return
 		}
-	}
 
-	detailCategoryUrl, err := models.GetConfigByCode("category_map_img_url")
-	if err != nil {
-		br.Msg = "获取数据失败"
-		br.ErrMsg = "行业配置信息失败,Err:" + err.Error()
-		return
-	}
-	categoryUrlList := strings.Split(detailCategoryUrl.ConfigValue, "{|}")
-	mapCategoryUrl := make(map[string]string)
-	var categoryId string
-	var imgUrlChart string
-	for _, v := range categoryUrlList {
-		vslice := strings.Split(v, "_")
-		categoryId = vslice[0]
-		imgUrlChart = vslice[len(vslice)-1]
-		mapCategoryUrl[categoryId] = imgUrlChart
-	}
+		listHz, err = services.HandleArticleCategoryImg(listHz, user)
+		if err != nil {
+			br.Msg = "获取信息失败"
+			br.ErrMsg = "HandleArticleCategoryImg,Err:" + err.Error()
+			return
+		}
+
+		listYx, err = services.HandleArticleCategoryImg(listYx, user)
+		if err != nil {
+			br.Msg = "获取信息失败"
+			br.ErrMsg = "HandleArticleCategoryImg,Err:" + err.Error()
+			return
+		}
 
-	for k, v := range listHz {
-		if len(industrialMap[v.ArticleId]) > 0 {
-			listHz[k].List = industrialMap[v.ArticleId]
+		for _, v := range listHz {
+			item := models.ArticleResearchResp{
+				ArticleId:       v.ArticleId,
+				ArticleTypeId:   v.ArticleTypeId,
+				Title:           v.Title,
+				PublishDate:     v.PublishDate,
+				DepartmentId:    v.DepartmentId,
+				NickName:        v.NickName,
+				IsCollect:       v.IsCollect,
+				Pv:              v.Pv,
+				CollectNum:      v.CollectNum,
+				Abstract:        v.Abstract,
+				Annotation:      v.Annotation,
+				ImgUrlPc:        v.ImgUrlPc,
+				ArticleTypeName: nameMap[v.ArticleTypeId],
+				ButtonStyle:     styleMap[v.ArticleTypeId],
+				List:            v.List,
+			}
+			resp.ListHz = append(resp.ListHz, &item)
+		}
+
+		for _, v := range listYx {
+			item := models.ArticleResearchResp{
+				ArticleId:       v.ArticleId,
+				ArticleTypeId:   v.ArticleTypeId,
+				Title:           v.Title,
+				PublishDate:     v.PublishDate,
+				DepartmentId:    v.DepartmentId,
+				NickName:        v.NickName,
+				IsCollect:       v.IsCollect,
+				Pv:              v.Pv,
+				CollectNum:      v.CollectNum,
+				Abstract:        v.Abstract,
+				Annotation:      v.Annotation,
+				ImgUrlPc:        v.ImgUrlPc,
+				ArticleTypeName: nameMap[v.ArticleTypeId],
+				ButtonStyle:     styleMap[v.ArticleTypeId],
+				List:            v.List,
+			}
+			resp.ListYx = append(resp.ListYx, &item)
+		}
+	} else {
+
+		//condition = `AND ( a.title LIKE '%` + keyWord + `%' OR  a.body LIKE '%` + keyWord + `%' OR  a.annotation LIKE '%` + keyWord + `%' OR  a.abstract LIKE '%` + keyWord + `%') AND a.publish_status = 1 `
+		if articleType == 1 {
+			condition = `  AND ( a.title LIKE '%` + keyWord + `%' OR  a.body LIKE '%` + keyWord + `%' OR  a.annotation LIKE '%` + keyWord + `%' OR  a.abstract LIKE '%` + keyWord + `%') AND a.publish_status = 1  AND a.article_type_id NOT IN (` + articleTypeIds + `)  `
+			total, err = models.GetReoprtSearchCountHz(condition)
+		} else {
+			condition = `  AND ( a.title LIKE '%` + keyWord + `%' OR  a.body LIKE '%` + keyWord + `%' OR  a.annotation LIKE '%` + keyWord + `%' OR  a.abstract LIKE '%` + keyWord + `%') AND a.publish_status = 1  AND a.article_type_id  IN (` + articleTypeIds + `)  `
+			total, err = models.GetReoprtSearchCountYx(condition)
+		}
+		if err != nil {
+			br.Msg = "获取信息失败"
+			br.Msg = "获取总数失败,Err:" + err.Error()
+			return
+		}
+		var list []*models.ArticleListResp
+		//list := new([]models.ArticleResearchResp)
+		if articleType == 1 {
+			list, err = models.GetArticleResearchListHz(condition, pars, startSize, pageSize, user.UserId)
 		} else {
-			listHz[k].List = make([]*models.IndustrialManagementResp, 0)
+			list, err = models.GetArticleResearchList(condition, pars, startSize, pageSize, user.UserId)
 		}
-		listHz[k].Body = ""
-		listHz[k].Abstract, _ = services.GetReportContentTextSub(v.Abstract)
-		listHz[k].Annotation, _ = services.GetReportContentTextSub(v.Annotation)
-		//行业比较研究、资金流向,显示报告的摘要
-		if listHz[k].CategoryName == "行业比较研究" || listHz[k].CategoryName == "资金流向" {
-			listHz[k].Annotation = listHz[k].Abstract
+		if err != nil {
+			br.Msg = "获取信息失败"
+			br.ErrMsg = "获取品种信息失败,Err:" + err.Error()
+			return
+		}
+		//return
+		list, err = services.HandleArticleCategoryImg(list, user)
+		if err != nil {
+			br.Msg = "获取信息失败"
+			br.ErrMsg = "HandleArticleCategoryImg,Err:" + err.Error()
+			return
+		}
+
+		for _, v := range list {
+			item := models.ArticleResearchResp{
+				ArticleId:       v.ArticleId,
+				ArticleTypeId:   v.ArticleTypeId,
+				Title:           v.Title,
+				PublishDate:     v.PublishDate,
+				DepartmentId:    v.DepartmentId,
+				NickName:        v.NickName,
+				IsCollect:       v.IsCollect,
+				Pv:              v.Pv,
+				CollectNum:      v.CollectNum,
+				Abstract:        v.Abstract,
+				Annotation:      v.Annotation,
+				ImgUrlPc:        v.ImgUrlPc,
+				ArticleTypeName: nameMap[v.ArticleTypeId],
+				ButtonStyle:     styleMap[v.ArticleTypeId],
+				List:            v.List,
+			}
+			if articleType == 1 {
+				resp.ListHz = append(resp.ListHz, &item)
+			} else {
+				resp.ListYx = append(resp.ListYx, &item)
+			}
 		}
-		listHz[k].ImgUrlPc = mapCategoryUrl[v.CategoryId]
 	}
 
 	if keyWord != "" {
 		go services.AddUserSearchLog(user, keyWord, 5)
 	}
-	if len(listHz) == 0 {
-		listHz = make([]*models.ArticleCollectionResp, 0)
+	if len(resp.ListHz) == 0 {
+		resp.ListHz = make([]*models.ArticleResearchResp, 0)
 	}
-
-	page = paging.GetPaging(currentIndex, pageSize, total)
-
+	if len(resp.ListYx) == 0 {
+		resp.ListYx = make([]*models.ArticleResearchResp, 0)
+	}
+	page := paging.GetPaging(currentIndex, pageSize, total)
 	resp.Paging = page
-	resp.ListHz = listHz
 	br.Ret = 200
 	br.Success = true
 	br.Msg = "获取成功"
@@ -963,69 +1085,51 @@ func (this *MobileReportController) SearchResource() {
 	}
 	keyWord := this.GetString("KeyWord")
 	var condition string
-	var conditionOr string
-	conditionOr += `  OR ( m.subject_names LIKE '%` + keyWord + `%' AND a.article_id < ` + strconv.Itoa(utils.SummaryArticleId) + `  AND publish_status = 1 ) `
-	condition = ` AND m.industry_name LIKE '%` + keyWord + `%' AND a.article_id < ` + strconv.Itoa(utils.SummaryArticleId) + conditionOr
 
+	articleTypeIds, err := services.GetYanXuanArticleTypeIds()
+	if err != nil {
+		br.Msg = "获取信息失败"
+		br.ErrMsg = "GetYanXuanArticleTypeIds,Err:" + err.Error()
+		return
+	}
+	if articleTypeIds == "" {
+		br.Msg = "获取信息失败"
+		br.ErrMsg = "研选分类ID不能为空"
+		return
+	}
+
+	condition = `  AND a.publish_status = 1 AND a.article_type_id NOT IN (` + articleTypeIds + `)  AND (m.industry_name LIKE '%` + keyWord + `%' OR m.subject_names LIKE '%` + keyWord + `%'  )  `
 	listHz, err := models.GetSearchResourceList(condition)
 	if err != nil {
 		br.Msg = "获取信息失败"
 		br.ErrMsg = "获取品种信息失败,Err:" + err.Error()
 		return
 	}
-	//合并产业关联的标的
-	listSubjcet, err := models.GetThemeHeatSubjectList("")
+
+	condition = `  AND a.publish_status = 1 AND a.article_type_id IN (` + articleTypeIds + `)  AND (m.industry_name LIKE '%` + keyWord + `%' OR m.subject_names LIKE '%` + keyWord + `%'  )  `
+	listYx, err := models.GetSearchResourceList(condition)
 	if err != nil {
 		br.Msg = "获取信息失败"
-		br.ErrMsg = "获取标的信息失败,Err:" + err.Error()
+		br.ErrMsg = "获取品种信息失败,Err:" + err.Error()
 		return
 	}
-	industrialIdArr := make([]int, 0)
-	for k, v := range listHz {
-		listHz[k].Source = 1
-		if fllowMap[v.IndustrialManagementId] > 0 {
-			listHz[k].IsFollow = true
-		}
-		industrialIdArr = append(industrialIdArr, v.IndustrialManagementId)
-	}
 
-	if len(industrialIdArr) > 0 {
-		//合并产业关联的标的
-		listSubjcet, err = models.GetIndustrialSubjectAllByIndustrialId(industrialIdArr)
+	if len(listYx) > 0 {
+		listYx, err = services.HandleIndustryList(listYx, user, "Yx")
 		if err != nil {
 			br.Msg = "获取信息失败"
-			br.ErrMsg = "获取标的信息失败,Err:" + err.Error()
+			br.ErrMsg = "获取信息失败,Err:" + err.Error()
 			return
 		}
-		mapIndustrial := make(map[string]int)
-		for _, v := range listSubjcet {
-			for k2, v2 := range listHz {
-				if v2.IndustrialManagementId == v.IndustrialManagementId && mapIndustrial[fmt.Sprint(v2.IndustrialManagementId, "Hz", v.SubjectName)] == 0 {
-					listHz[k2].IndustrialSubjectList = append(listHz[k2].IndustrialSubjectList, v)
-					mapIndustrial[fmt.Sprint(v2.IndustrialManagementId, "Hz", v.SubjectName)] = v2.IndustrialManagementId
-				}
-			}
-		}
 	}
-
-	mapUPdateTime := make(map[int]string)
-	articleIdArr := make([]int, 0)
-	//获取这些产业下最新更新的文章
-	fmt.Println(industrialIdArr)
-	listUpdateTime, err := models.GetNewArticleDetailByIndustrialIds(industrialIdArr)
-	if err != nil && err.Error() != utils.ErrNoRow() {
-		br.Msg = "获取信息失败"
-		br.ErrMsg = "获取信息失败 GetNewArticleDetailByIndustrialIds ,Err:" + err.Error()
-		return
-	}
-	for _, v := range listUpdateTime {
-		mapUPdateTime[v.IndustrialManagementId] = v.PublishDate
-		articleIdArr = append(articleIdArr, v.ArticleId)
-	}
-	for k, v := range listHz {
-		listHz[k].UpdateTime = utils.TimeRemoveHms(mapUPdateTime[v.IndustrialManagementId])
+	if len(listHz) > 0 {
+		listHz, err = services.HandleIndustryList(listHz, user, "Hz")
+		if err != nil {
+			br.Msg = "获取信息失败"
+			br.ErrMsg = "获取信息失败,Err:" + err.Error()
+			return
+		}
 	}
-
 	if keyWord != "" {
 		go services.AddUserSearchLog(user, keyWord, 4)
 	}
@@ -1033,7 +1137,11 @@ func (this *MobileReportController) SearchResource() {
 	if len(listHz) == 0 {
 		listHz = make([]*models.IndustrialManagement, 0)
 	}
+	if len(listYx) == 0 {
+		listYx = make([]*models.IndustrialManagement, 0)
+	}
 	resp.ListHz = listHz
+	resp.ListYx = listYx
 	br.Ret = 200
 	br.Success = true
 	br.Msg = "获取成功"
@@ -1197,12 +1305,18 @@ func (this *ReportCommonController) CompanyList() {
 // @Param   IndustrialManagementId   query   int  false       "产业ID"
 // @Success 200 {object} models.TacticsListResp
 // @router /timeline [get]
-func (this *ReportCommonController) Timeline() {
+func (this *MobileReportController) Timeline() {
 	br := new(models.BaseResponse).Init()
 	defer func() {
 		this.Data["json"] = br
 		this.ServeJSON()
 	}()
+	user := this.User
+	if user == nil {
+		br.Msg = "请重新登录"
+		br.Ret = 408
+		return
+	}
 	pageSize, _ := this.GetInt("PageSize")
 	currentIndex, _ := this.GetInt("CurrentIndex")
 	industrialManagementId, _ := this.GetInt("IndustrialManagementId")
@@ -1215,30 +1329,62 @@ func (this *ReportCommonController) Timeline() {
 	}
 	startSize = paging.StartIndex(currentIndex, pageSize)
 	var total int
-	resp := new(models.TacticsListResp)
+	resp := new(models.TacticsListTimeResp)
 	page := paging.GetPaging(currentIndex, pageSize, total)
-	list := make([]*models.HomeArticle, 0)
+	list := make([]*models.TimeLineReportItem, 0)
 	var err error
-	list, total, err = models.GetTimeLineReportIndustrialList(industrialManagementId, startSize, pageSize)
+	list, total, err = models.GetTimeLineReportIndustrialListTime(user.UserId, industrialManagementId, startSize, pageSize)
 	if err != nil {
 		br.Msg = "获取信息失败"
 		br.ErrMsg = "获取产业报告+晨会点评列表,Err:" + err.Error()
 		return
 	}
-	lenList := len(list)
-	for i := 0; i < lenList; i++ {
-		item := list[i]
-		list[i].Body = ""
-		list[i].Abstract, _ = services.GetReportContentTextSub(item.Abstract)
-		list[i].Annotation, _ = services.GetReportContentTextSub(item.Annotation)
-		list[i].PublishDate = utils.StrTimeToTime(item.PublishDate).Format(utils.FormatDate) //时间字符串格式转时间格式
-		//行业比较研究、资金流向,显示报告的摘要
-		if resp.MatchTypeName == "行业比较研究" || resp.MatchTypeName == "资金流向" {
-			list[i].Annotation = list[i].Abstract
+	//查询用户今天是否看过时间线
+	count, err := models.GetTimeLineRecordCount(user.UserId, industrialManagementId)
+	if err != nil {
+		br.Msg = "查询浏览记录数量失败"
+		br.ErrMsg = "查询浏览记录数量失败,Err:" + err.Error()
+		return
+	}
+	var recordItem *models.CygxPageHistoryRecord
+	if count > 1 {
+		recordItem, err = models.GetTimeLineRecordItem(user.UserId, industrialManagementId)
+		if err != nil {
+			br.Msg = "查询浏览记录失败"
+			br.ErrMsg = "查询浏览记录失败,Err:" + err.Error()
+			return
 		}
 	}
+
+	for k, v := range list {
+		if v.SubCategoryName != "时间线" && v.Readnum == 0 && user.CreatedTime.Before(utils.StrTimeToTime(v.PublishDate)) && utils.StrTimeToTime(utils.OnlineTime).Before(utils.StrTimeToTime(v.PublishDate)) {
+			list[k].IsRed = true
+		}
+		timeLineRed := false
+		if count < 2 && v.SubCategoryName == "时间线" {
+			timeLineRed = true
+		} else if count > 1 && recordItem.CreateTime.Before(utils.StrTimeToTime(v.PublishDate)) {
+			timeLineRed = true
+		}
+		if v.SubCategoryName == "时间线" && timeLineRed {
+			list[k].IsRed = true
+		}
+		if v.VideoUrl != "" {
+			list[k].IsHaveVideo = true
+		}
+
+	}
+
+	//添加我的日程访问记录
+	item := new(models.CygxPageHistoryRecord)
+	item.UserId = user.UserId
+	item.CreateTime = time.Now()
+	item.CompanyId = user.CompanyId
+	item.CompanyName = user.CompanyName
+	item.Router = utils.TIME_LINE_ROUTE + strconv.Itoa(industrialManagementId)
+	go models.AddCygxPageHistoryRecord(item)
 	if len(list) == 0 {
-		list = make([]*models.HomeArticle, 0)
+		list = make([]*models.TimeLineReportItem, 0)
 	}
 	page = paging.GetPaging(currentIndex, pageSize, total)
 	resp.List = list
@@ -1248,3 +1394,110 @@ func (this *ReportCommonController) Timeline() {
 	br.Msg = "获取成功"
 	br.Data = resp
 }
+
+// @Title 文章留言接口
+// @Description 文章留言接口
+// @Param	request	body models.AddCygxActivityHelpAsk true "type json string"
+// @Success 200 {object} models.TacticsListResp
+// @router /commentAdd [post]
+func (this *ReportController) CommentAdd() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	user := this.User
+	if user == nil {
+		br.Msg = "请重新登录"
+		br.Ret = 408
+		return
+	}
+	var req models.AddCygxArticleCommentReq
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	if req.ArticleId <= 0 {
+		br.Msg = "文章不存在"
+		br.ErrMsg = "文章不存在,文章ID错误"
+		return
+	}
+	if req.Content == "" {
+		br.Msg = "建议内容不可为空"
+		return
+	}
+	content := req.Content
+	if content == "" {
+		br.Msg = "留言内容不能为空!"
+		return
+	}
+
+	//itemToken, err := services.WxGetToken()
+	//if err != nil {
+	//	br.Msg = "GetWxAccessToken Err:" + err.Error()
+	//	return
+	//}
+	//if itemToken.AccessToken == "" {
+	//	br.Msg = "accessToken is empty"
+	//	return
+	//}
+	//commerr, err := weapp.MSGSecCheck(itemToken.AccessToken, content)
+	//if err != nil {
+	//	br.Msg = "内容校验失败!"
+	//	br.ErrMsg = "内容校验失败,Err:" + err.Error()
+	//	return
+	//}
+	//if commerr.ErrCode != 0 {
+	//	br.Msg = "内容违规,请重新提交!"
+	//	br.ErrMsg = "内容违规,Err:" + commerr.ErrMSG
+	//	return
+	//}
+
+	articleId := req.ArticleId
+	articleInfo, errInfo := models.GetArticleDetailById(articleId)
+	if articleInfo == nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "文章ID错误,不存在articleId:" + strconv.Itoa(articleId)
+		return
+	}
+	if errInfo != nil {
+		br.Msg = "操作失败"
+		br.ErrMsg = "操作失败,Err:" + errInfo.Error()
+		return
+	}
+
+	companyDetail, err := models.GetCompanyDetailById(user.CompanyId)
+	if err != nil {
+		br.Msg = "提交失败!"
+		br.ErrMsg = "获取客户详情失败,Err:" + err.Error()
+		return
+	}
+	if companyDetail == nil {
+		br.Msg = "提交失败!"
+		br.ErrMsg = "客户不存在,uid:" + strconv.Itoa(user.UserId)
+		return
+	}
+	item := models.CygxArticleComment{
+		UserId:      user.UserId,
+		ArticleId:   req.ArticleId,
+		CreateTime:  time.Now(),
+		Mobile:      user.Mobile,
+		Email:       user.Email,
+		CompanyId:   user.CompanyId,
+		CompanyName: companyDetail.CompanyName,
+		Content:     content,
+		Title:       articleInfo.Title,
+	}
+	_, err = models.AddArticleComment(&item)
+	if err != nil {
+		br.Msg = "提交失败"
+		br.ErrMsg = "提交留言失败,Err:" + err.Error()
+		return
+	}
+	services.SendCommentWxTemplateMsg(req, user, articleInfo)
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "提交成功"
+}

+ 2 - 2
controllers/report_billboard.go

@@ -7,7 +7,7 @@ import (
 	"time"
 )
 
-//报告榜单
+// 报告榜单
 type ReportBillboardController struct {
 	BaseAuthController
 }
@@ -134,7 +134,7 @@ func (this *MobileReportBillboardController) ReadList() {
 	}
 	var err error
 	resp := new(models.ReportBillboardListResp)
-	resp.List, err = services.HandleArticleCategoryImg(list)
+	resp.List, err = services.HandleArticleCategoryImg(list, user)
 	if err != nil {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取报告封面图片失败, Err:" + err.Error()

+ 828 - 0
controllers/research.go

@@ -0,0 +1,828 @@
+package controllers
+
+import (
+	"encoding/json"
+	"github.com/rdlucklib/rdluck_tools/paging"
+	"hongze/hongze_clpt/models"
+	"hongze/hongze_clpt/services"
+	"hongze/hongze_clpt/utils"
+	"strconv"
+	"strings"
+	"time"
+)
+
+type MobileResearchController struct {
+	BaseAuthMobileController
+}
+
+// @Title 研选文章类型列表
+// @Description 研选文章类型列表接口
+// @Success 200 {object} models.CygxArticleTypeListResp
+// @router /article/typeList [get]
+func (this *MobileResearchController) ArticleType() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	user := this.User
+	if user == nil {
+		br.Msg = "请重新登录"
+		br.Ret = 408
+		return
+	}
+	key := utils.YAN_XUAN_TAB_KEY
+	conf, e := models.GetConfigByCode(key)
+	if e != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取首页头部导航失败, Err: " + e.Error()
+		return
+	}
+	if conf.ConfigValue == "" {
+		br.Msg = "获取失败"
+		br.ErrMsg = "首页头部导航配置值有误"
+		return
+	}
+	list := new(models.CygxArticleTypeListResp)
+	if e = json.Unmarshal([]byte(conf.ConfigValue), &list); e != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "首页头部导航配置值解析失败, Err: " + e.Error()
+		return
+	}
+	resp := new(models.CygxArticleTypeListResp)
+	resp = list
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resp
+}
+
+// @Title 研选最新报告列表
+// @Description 研选最新报告列表接口
+// @Param   PageSize   query   int  true       "每页数据条数"
+// @Param   CurrentIndex   query   int  true       "当前页页码,从1开始"
+// @Param   ArticleTypeIds   query   array  true       "文章类型ID多个用  , 隔开"
+// @Success 200 {object} models.IndustrialManagementNewList
+// @router /article/newList [get]
+func (this *MobileResearchController) ArticleNewList() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	user := this.User
+	if user == nil {
+		br.Msg = "请重新登录"
+		br.Ret = 408
+		return
+	}
+	pageSize, _ := this.GetInt("PageSize")
+	currentIndex, _ := this.GetInt("CurrentIndex")
+	articleTypeIds := this.GetString("ArticleTypeIds")
+	var startSize int
+	if pageSize <= 0 {
+		pageSize = utils.PageSize20
+	}
+	if currentIndex <= 0 {
+		currentIndex = 1
+	}
+	startSize = paging.StartIndex(currentIndex, pageSize)
+	var condition string
+	var conditiontype string
+	var pars []interface{}
+	condition = `    AND publish_status = 1  `
+	if articleTypeIds == "" {
+		conditiontype = " AND is_show_yanx  = 1 "
+	} else {
+		conditiontype = ` AND   group_id IN  (` + articleTypeIds + `) `
+	}
+	listType, err := models.GetCygxArticleTypeListCondition(conditiontype)
+	if err != nil {
+		br.Msg = "获取信息失败"
+		br.ErrMsg = "获取品种信息失败,Err:" + err.Error()
+		return
+	}
+	articleTypeIds = ""
+	for _, v := range listType {
+		articleTypeIds += strconv.Itoa(v.ArticleTypeId) + ","
+	}
+	articleTypeIds = strings.TrimRight(articleTypeIds, ",")
+	condition += `   AND a.article_type_id IN (` + articleTypeIds + `) `
+	total, err := models.GetArticleResearchCount(condition, pars)
+	if err != nil {
+		br.Msg = "获取信息失败"
+		br.ErrMsg = "GetArticleResearchCount,Err:" + err.Error()
+		return
+	}
+	list, err := models.GetArticleResearchList(condition, pars, startSize, pageSize, user.UserId)
+	if err != nil {
+		br.Msg = "获取信息失败"
+		br.ErrMsg = "获取品种信息失败,Err:" + err.Error()
+		return
+	}
+	list, err = services.HandleArticleCategoryImg(list, user)
+	if err != nil {
+		br.Msg = "获取信息失败"
+		br.ErrMsg = "HandleArticleCategoryImg,Err:" + err.Error()
+		return
+	}
+	//处理对应的文章类型标签按钮
+	nameMap, styleMap, err := services.GetArticleTypeMap()
+	if err != nil {
+		br.Msg = "获取信息失败"
+		br.ErrMsg = "GetArticleTypeMap Err:" + err.Error()
+		return
+	}
+	page := paging.GetPaging(currentIndex, pageSize, total)
+	resp := new(models.ArticleResearchListResp)
+	for _, v := range list {
+
+		item := models.ArticleResearchResp{
+			ArticleId:       v.ArticleId,
+			ArticleTypeId:   v.ArticleTypeId,
+			Title:           v.Title,
+			PublishDate:     v.PublishDate,
+			DepartmentId:    v.DepartmentId,
+			NickName:        v.NickName,
+			IsCollect:       v.IsCollect,
+			Pv:              v.Pv,
+			CollectNum:      v.CollectNum,
+			Abstract:        v.Abstract,
+			Annotation:      v.Annotation,
+			ImgUrlPc:        v.ImgUrlPc,
+			ArticleTypeName: nameMap[v.ArticleTypeId],
+			ButtonStyle:     styleMap[v.ArticleTypeId],
+			List:            v.List,
+		}
+		if item.ArticleTypeName == "纪要" || item.ArticleTypeName == "沙龙" || item.ArticleTypeName == "专家访谈" {
+			item.Annotation = "核心结论:" + item.Annotation
+		} else {
+			item.Annotation = "核心观点:" + item.Annotation
+		}
+
+		resp.List = append(resp.List, &item)
+	}
+	resp.Paging = page
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resp
+}
+
+// @Title KOL榜列表
+// @Description KOL榜列表接口
+// @Param   PageSize   query   int  true       "每页数据条数"
+// @Param   CurrentIndex   query   int  true       "当前页页码,从1开始"
+// @Param   ThemeType   query   int  true       "主题类型,1关注度、2更新时间 "
+// @Success 200 {object} models.DepartmentListResp
+// @router /kolList [get]
+func (this *MobileResearchController) KolList() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	user := this.User
+	if user == nil {
+		br.Msg = "请重新登录"
+		br.Ret = 408
+		return
+	}
+	themeType, _ := this.GetInt("ThemeType")
+	pageSize, _ := this.GetInt("PageSize")
+	currentIndex, _ := this.GetInt("CurrentIndex")
+	var startSize int
+	if pageSize <= 0 {
+		pageSize = utils.PageSize15
+	}
+	if currentIndex <= 0 {
+		currentIndex = 1
+	}
+	startSize = utils.StartIndex(currentIndex, pageSize)
+
+	total, err := models.GetDepartmentlistCount("")
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取失败,Err:" + err.Error()
+		return
+	}
+	var condition string
+	var conditionOrder string
+	if themeType == 2 {
+		conditionOrder = `ORDER BY publish_date DESC  `
+	} else {
+		conditionOrder = `ORDER BY sum_num DESC `
+	}
+
+	list, err := models.GetDepartmentList(condition, conditionOrder, user.UserId, startSize, pageSize)
+	if err != nil {
+		br.Msg = "获取信息失败"
+		br.ErrMsg = "获取品种信息失败,Err:" + err.Error()
+		return
+	}
+	listIndustrial, err := models.GetIndustrialDepartmentList()
+	if err != nil {
+		br.Msg = "获取信息失败"
+		br.ErrMsg = "获取品种信息失败,Err:" + err.Error()
+		return
+	}
+	mapHot := make(map[int]bool)
+	//if themeType == 2 {
+	conditionHot := `ORDER BY sum_num DESC `
+	listhot, err := models.GetDepartmentList(condition, conditionHot, user.UserId, 0, 3)
+	if err != nil {
+		br.Msg = "获取信息失败"
+		br.ErrMsg = "获取信息失败,Err:" + err.Error()
+		return
+	}
+	for _, v := range listhot {
+		mapHot[v.DepartmentId] = true
+	}
+	//}
+
+	departmentMap := make(map[string]string)
+	for k, v := range list {
+		if v.FllowNum > 0 {
+			list[k].IsFollow = true
+		}
+		list[k].IsHot = mapHot[v.DepartmentId]
+		list[k].PublishDate = utils.StrTimeToTime(v.PublishDate).Format(utils.FormatDate) //时间字符串格式转时间格式
+		for _, v2 := range listIndustrial {
+			if v2.DepartmentId == v.DepartmentId {
+				if departmentMap["D"+strconv.Itoa(v2.DepartmentId)+"In"+strconv.Itoa(v2.IndustrialManagementId)] == "" && len(list[k].List) < 4 {
+					list[k].List = append(list[k].List, v2)
+					departmentMap["D"+strconv.Itoa(v2.DepartmentId)+"In"+strconv.Itoa(v2.IndustrialManagementId)] = v.NickName
+				}
+			}
+		}
+	}
+	resp := new(models.DepartmentListResp)
+	page := paging.GetPaging(currentIndex, pageSize, total)
+	resp.Paging = page
+	resp.List = list
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resp
+}
+
+// @Title 主题热度/近期更新更多,列表
+// @Description 主题热度/近期更新更多,列表接口
+// @Param   ThemeType   query   int  true       "主题类型,1主题热度、2近期更新 默认1"
+// @Param   PageSize   query   int  true       "每页数据条数"
+// @Param   CurrentIndex   query   int  true       "当前页页码,从1开始"
+// @Success 200 {object} models.IndustrialManagementHotListResp
+// @router /hotList [get]
+func (this *MobileResearchController) HotList() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	user := this.User
+	if user == nil {
+		br.Msg = "请重新登录"
+		br.Ret = 408
+		return
+	}
+	themeType, _ := this.GetInt("ThemeType")
+	pageSize, _ := this.GetInt("PageSize")
+	currentIndex, _ := this.GetInt("CurrentIndex")
+	var startSize int
+	if pageSize <= 0 {
+		pageSize = utils.PageSize15
+	}
+	if currentIndex <= 0 {
+		currentIndex = 1
+	}
+	startSize = utils.StartIndex(currentIndex, pageSize)
+	var condition string
+	var conditionOrder string
+	articleTypeIds, err := services.GetYanXuanArticleTypeIds()
+	if err != nil {
+		br.Msg = "获取信息失败"
+		br.ErrMsg = "GetYanXuanArticleTypeIds,Err:" + err.Error()
+		return
+	}
+	if articleTypeIds == "" {
+		br.Msg = "获取信息失败"
+		br.ErrMsg = "研选分类ID不能为空"
+		return
+	}
+	condition = ` AND a.article_type_id IN (` + articleTypeIds + `)  `
+	if themeType == 2 {
+		conditionOrder = `ORDER BY publish_date DESC  `
+	} else {
+		conditionOrder = `ORDER BY sum_num DESC   `
+	}
+
+	total, err := models.GetThemeHeatListCount(condition)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取失败,Err:" + err.Error()
+		return
+	}
+	list, err := models.GetThemeHeatList(user.UserId, condition, conditionOrder, startSize, pageSize)
+	if err != nil {
+		br.Msg = "获取信息失败"
+		br.ErrMsg = "获取品种信息失败,Err:" + err.Error()
+		return
+	}
+	listSubjcet, err := models.GetThemeHeatSubjectList(condition)
+	if err != nil {
+		br.Msg = "获取信息失败"
+		br.ErrMsg = "获取标的信息失败,Err:" + err.Error()
+		return
+	}
+	mapHot := make(map[int]bool)
+	mapNew, err := services.GetYanXuanIndustrialManagementIdNewMap(articleTypeIds)
+	if err != nil {
+		br.Msg = "获取信息失败"
+		br.ErrMsg = "GetYanXuanIndustrialManagementIdNewMap,Err:" + err.Error()
+		return
+	}
+	//if themeType == 2 {
+	mapHot, err = services.GetYanXuanIndustrialManagementIdHotMap(articleTypeIds)
+	if err != nil {
+		br.Msg = "获取信息失败"
+		br.ErrMsg = "GetYanXuanIndustrialManagementIdNewMap,Err:" + err.Error()
+		return
+	}
+	//}
+	for k, v := range list {
+		list[k].IsNew = mapNew[v.IndustrialManagementId]
+		list[k].IsHot = mapHot[v.IndustrialManagementId]
+		list[k].PublishDate = utils.StrTimeToTime(v.PublishDate).Format(utils.FormatDate) //时间字符串格式转时间格式
+		if v.FllowNum > 0 {
+			list[k].IsFollow = true
+		}
+		for _, v2 := range listSubjcet {
+			if v2.IndustrialManagementId == v.IndustrialManagementId {
+				list[k].IndustrialSubjectList = append(list[k].IndustrialSubjectList, v2)
+			}
+		}
+	}
+	page := paging.GetPaging(currentIndex, pageSize, total)
+	resp := new(models.IndustrialManagementHotListResp)
+	resp.Paging = page
+	resp.List = list
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resp
+}
+
+// @Title 主题详情
+// @Description 主题详情接口
+// @Param   IndustrialManagementId   query   int  true       "分类ID"
+// @Success 200 {object} models.GetThemeDetailResp
+// @router /theme/detail [get]
+func (this *MobileResearchController) ThemeDetail() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	user := this.User
+	if user == nil {
+		br.Msg = "请重新登录"
+		br.Ret = 408
+		return
+	}
+	industrialManagementId, _ := this.GetInt("IndustrialManagementId")
+	if industrialManagementId < 1 {
+		br.Msg = "请输入产业ID"
+		return
+	}
+	detailIndustrial, err := models.GetIndustrialManagementDetail(industrialManagementId)
+	if err != nil {
+		br.Msg = "获取信息失败"
+		br.ErrMsg = "获取信息失败,Err:" + err.Error()
+		return
+	}
+	var condition string
+
+	articleTypeIds, err := services.GetYanXuanArticleTypeIds()
+	if err != nil {
+		br.Msg = "获取信息失败"
+		br.ErrMsg = "GetYanXuanArticleTypeIds,Err:" + err.Error()
+		return
+	}
+	if articleTypeIds != "" {
+		condition = ` AND a.article_type_id IN (` + articleTypeIds + `)  `
+	} else {
+		br.Msg = "获取信息失败"
+		br.ErrMsg = "研选分类ID不能为空"
+		return
+	}
+	resp := new(models.GetThemeDetailResp)
+	list, err := models.GetThemeDetail(user.UserId, industrialManagementId, condition)
+	if err != nil {
+		br.Msg = "获取信息失败"
+		br.ErrMsg = "获取品种信息失败,Err:" + err.Error()
+		return
+	}
+	list, err = services.HandleArticleCategoryImg(list, user)
+	if err != nil {
+		br.Msg = "获取信息失败"
+		br.ErrMsg = "HandleArticleCategoryImg,Err:" + err.Error()
+		return
+	}
+	//处理对应的文章类型标签按钮
+	nameMap, styleMap, err := services.GetArticleTypeMap()
+	if err != nil {
+		br.Msg = "获取信息失败"
+		br.ErrMsg = "GetArticleTypeMap Err:" + err.Error()
+		return
+	}
+	var articleIds []int
+	for _, v := range list {
+		item := models.ArticleResearchResp{
+			ArticleId:       v.ArticleId,
+			ArticleTypeId:   v.ArticleTypeId,
+			Title:           v.Title,
+			PublishDate:     v.PublishDate,
+			DepartmentId:    v.DepartmentId,
+			NickName:        v.NickName,
+			IsCollect:       v.IsCollect,
+			Pv:              v.Pv,
+			CollectNum:      v.CollectNum,
+			Abstract:        v.Abstract,
+			Annotation:      v.Annotation,
+			ImgUrlPc:        v.ImgUrlPc,
+			ArticleTypeName: nameMap[v.ArticleTypeId],
+			ButtonStyle:     styleMap[v.ArticleTypeId],
+			List:            v.List,
+		}
+		if item.ArticleTypeName == "纪要" || item.ArticleTypeName == "沙龙" || item.ArticleTypeName == "专家访谈" {
+			item.Annotation = "核心结论:" + item.Annotation
+		} else {
+			item.Annotation = "核心观点:" + item.Annotation
+		}
+		resp.List = append(resp.List, &item)
+		articleIds = append(articleIds, v.ArticleId)
+	}
+
+	//处理用户数是否关注该产业
+	userFollowIndustrialMap, err := services.GetUserFollowIndustrialMap(user)
+	if err != nil {
+		br.Msg = "获取信息失败"
+		br.ErrMsg = "GetArticleTypeMap Err:" + err.Error()
+		return
+	}
+	if _, ok := userFollowIndustrialMap[industrialManagementId]; ok {
+		resp.IsFollow = true
+	}
+
+	listSub, err := models.GetcygxIndustrialSubject(industrialManagementId)
+	if err != nil {
+		br.Msg = "获取信息失败"
+		br.ErrMsg = "获取品种信息失败,Err:" + err.Error()
+		return
+	}
+
+	//处理文章关联的标的
+	articleGroupSubjectMap, subjectMap, err := services.GetArticleGroupSubjectMap(articleIds)
+	if err != nil {
+		br.Msg = "获取信息失败"
+		br.ErrMsg = "GetArticleTypeMap Err:" + err.Error()
+		return
+	}
+	if len(articleGroupSubjectMap) > 0 {
+		for k, v := range resp.List {
+			resp.List[k].ListSubject = articleGroupSubjectMap[v.ArticleId]
+		}
+	}
+	for _, v := range listSub {
+		itemSubJect := new(models.IndustrialSubject)
+		itemSubJect.SubjectName = v.SubjectName
+		itemSubJect.IndustrialSubjectId = v.IndustrialSubjectId
+		if subjectMap[v.IndustrialSubjectId] != "" {
+			resp.ListSubject = append(resp.ListSubject, itemSubJect)
+		}
+	}
+	resp.IndustryName = detailIndustrial.IndustryName
+	resp.IndustrialManagementId = detailIndustrial.IndustrialManagementId
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resp
+}
+
+// @Title 研选作者详情
+// @Description 研选作者详情接口
+// @Param   DepartmentId   query   int  true       "作者ID"
+// @Success 200 {object} models.DepartmentDetailResp
+// @router /departmentId/detail [get]
+func (this *MobileResearchController) DepartmentIdDetail() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	user := this.User
+	if user == nil {
+		br.Msg = "请重新登录"
+		br.Ret = 408
+		return
+	}
+	pageSize, _ := this.GetInt("PageSize")
+	currentIndex, _ := this.GetInt("CurrentIndex")
+	var startSize int
+	if pageSize <= 0 {
+		pageSize = utils.PageSize20
+	}
+	if currentIndex <= 0 {
+		currentIndex = 1
+	}
+	startSize = paging.StartIndex(currentIndex, pageSize)
+	departmentId, _ := this.GetInt("DepartmentId")
+	if departmentId < 1 {
+		br.Msg = "请输入作者ID"
+		return
+	}
+	var condition string
+	var pars []interface{}
+	articleTypeIds, err := services.GetYanXuanArticleTypeIds()
+	if err != nil {
+		br.Msg = "获取信息失败"
+		br.ErrMsg = "GetYanXuanArticleTypeIds,Err:" + err.Error()
+		return
+	}
+	if articleTypeIds != "" {
+		condition = ` AND a.article_type_id IN (` + articleTypeIds + `)  `
+	} else {
+		br.Msg = "获取信息失败"
+		br.ErrMsg = "研选分类ID不能为空"
+		return
+	}
+	resp := new(models.DepartmentDetailResp)
+	detail, err := models.GetDepartmentDetail(user.UserId, departmentId, condition)
+	if err != nil {
+		br.Msg = "获取信息失败"
+		br.ErrMsg = "获取作者信息失败,Err:" + err.Error()
+		return
+	}
+	resp.DepartmentId = detail.DepartmentId
+	resp.NickName = detail.NickName
+	resp.ImgUrl = detail.ImgUrl
+	resp.FllowNum = detail.FllowNum
+	resp.ArticleNum = detail.ArticleNum
+	resp.CollectNum = detail.CollectNum
+	if detail.MyFllowNum > 0 {
+		resp.IsFollow = true
+	}
+
+	condition += `  AND a.department_id = ` + strconv.Itoa(departmentId)
+	total, err := models.GetArticleResearchCount(condition, pars)
+	if err != nil {
+		br.Msg = "获取信息失败"
+		br.ErrMsg = "GetArticleResearchCount,Err:" + err.Error()
+		return
+	}
+	list, err := models.GetArticleResearchList(condition, pars, startSize, pageSize, user.UserId)
+	if err != nil {
+		br.Msg = "获取信息失败"
+		br.ErrMsg = "获取品种信息失败,Err:" + err.Error()
+		return
+	}
+	list, err = services.HandleArticleCategoryImg(list, user)
+	if err != nil {
+		br.Msg = "获取信息失败"
+		br.ErrMsg = "HandleArticleCategoryImg,Err:" + err.Error()
+		return
+	}
+	//处理对应的文章类型标签按钮
+	nameMap, styleMap, err := services.GetArticleTypeMap()
+	if err != nil {
+		br.Msg = "获取信息失败"
+		br.ErrMsg = "GetArticleTypeMap Err:" + err.Error()
+		return
+	}
+
+	//resp := new(models.ArticleResearchListResp)
+	for _, v := range list {
+		item := models.ArticleResearchResp{
+			ArticleId:       v.ArticleId,
+			ArticleTypeId:   v.ArticleTypeId,
+			Title:           v.Title,
+			PublishDate:     v.PublishDate,
+			DepartmentId:    v.DepartmentId,
+			NickName:        v.NickName,
+			IsCollect:       v.IsCollect,
+			Pv:              v.Pv,
+			CollectNum:      v.CollectNum,
+			Abstract:        v.Abstract,
+			Annotation:      v.Annotation,
+			ImgUrlPc:        v.ImgUrlPc,
+			ArticleTypeName: nameMap[v.ArticleTypeId],
+			ButtonStyle:     styleMap[v.ArticleTypeId],
+			List:            v.List,
+		}
+		if item.ArticleTypeName == "纪要" || item.ArticleTypeName == "沙龙" || item.ArticleTypeName == "专家访谈" {
+			item.Annotation = "核心结论:" + item.Annotation
+		} else {
+			item.Annotation = "核心观点:" + item.Annotation
+		}
+		resp.List = append(resp.List, &item)
+	}
+
+	condition = ` AND a.department_id =  ` + strconv.Itoa(departmentId)
+	listIndustrial, err := models.GetIndustrialManagementNewList(condition)
+	if err != nil {
+		br.Msg = "获取信息失败"
+		br.ErrMsg = "获取品种信息失败,Err:" + err.Error()
+		return
+	}
+	page := paging.GetPaging(currentIndex, pageSize, total)
+	resp.ListIndustrial = listIndustrial
+	resp.Paging = page
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resp
+}
+
+// @Title 关注作者/取消关注作者
+// @Description 关注作者/取消关注作者 接口
+// @Param	request	body models.CygxArticleDepartmentId true "type json string"
+// @Success 200
+// @router /fllowDepartment [post]
+func (this *MobileResearchController) FllowDepartment() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	user := this.User
+	if user == nil {
+		br.Msg = "请重新登录"
+		br.Ret = 408
+		return
+	}
+	uid := user.UserId
+	var req models.CygxArticleDepartmentId
+	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
+	if err != nil {
+		br.Msg = "参数解析异常!"
+		br.ErrMsg = "参数解析失败,Err:" + err.Error()
+		return
+	}
+	departmentId := req.DepartmentId
+	var condition string
+	countDepartment, err := models.GetDepartmentCount(departmentId)
+	if err != nil {
+		br.Msg = "获取数据失败!"
+		br.ErrMsg = "获取数据失败,Err:" + err.Error()
+		return
+	}
+	if countDepartment == 0 {
+		br.Msg = "作者不存在!"
+		br.ErrMsg = "作者ID不存在:" + strconv.Itoa(departmentId)
+		return
+	}
+	countUser, err := models.GetArticleDepartmentFollowByUid(uid)
+	count, err := models.GetArticleDepartmentFollow(uid, departmentId, condition)
+	if err != nil {
+		br.Msg = "获取数据失败!"
+		br.ErrMsg = "获取数据失败,Err:" + err.Error()
+		return
+	}
+	resp := new(models.CygxArticleDepartmentFollowResp)
+	if countUser == 0 {
+		resp.GoFollow = true
+	}
+	if count == 0 {
+		item := new(models.CygxArticleDepartmentFollow)
+		item.DepartmentId = departmentId
+		item.UserId = uid
+		item.Email = user.Email
+		item.Mobile = user.Mobile
+		item.RealName = user.RealName
+		item.CompanyId = user.CompanyId
+		item.CompanyName = user.CompanyName
+		item.Type = 1
+		item.CreateTime = time.Now()
+		item.ModifyTime = time.Now()
+		_, err = models.AddArticleDepartmentFollow(item)
+		if err != nil {
+			br.Msg = "操作失败"
+			br.ErrMsg = "操作失败,Err:" + err.Error()
+			return
+		}
+		resp.Status = 1
+	} else {
+		var doType int
+		condition = ` AND type = 1`
+		count, err = models.GetArticleDepartmentFollow(uid, departmentId, condition)
+		if err != nil {
+			br.Msg = "操作失败!"
+			br.ErrMsg = "获取数据失败,Err:" + err.Error()
+			return
+		}
+		if count == 1 {
+			resp.Status = 2
+			doType = 2
+		} else {
+			resp.Status = 1
+			doType = 1
+		}
+		err = models.RemoveArticleDepartmentFollow(uid, departmentId, doType)
+		if err != nil {
+			br.Msg = "操作失败"
+			br.ErrMsg = "取消关注失败,Err:" + err.Error()
+			return
+		}
+	}
+	br.Msg = "操作成功"
+	br.Ret = 200
+	br.Success = true
+	br.Data = resp
+}
+
+// @Title 研选月度收藏榜
+// @Description 研选月度收藏榜接口
+// @Param   PageSize   query   int  true       "每页数据条数"
+// @Success 200 {object} models.ReportBillboardListResp
+// @router /article/billboard [get]
+func (this *MobileResearchController) Billboard() {
+	br := new(models.BaseResponse).Init()
+	defer func() {
+		this.Data["json"] = br
+		this.ServeJSON()
+	}()
+	user := this.User
+	if user == nil {
+		br.Msg = "请重新登录"
+		br.Ret = 408
+		return
+	}
+	pageSize, _ := this.GetInt("PageSize", 15)
+	var condition string
+	var pars []interface{}
+	articleTypeIds, err := services.GetYanXuanArticleTypeIds()
+	if err != nil {
+		br.Msg = "获取信息失败"
+		br.ErrMsg = "GetYanXuanArticleTypeIds,Err:" + err.Error()
+		return
+	}
+	if articleTypeIds != "" {
+		condition = ` AND a.article_type_id IN (` + articleTypeIds + `)  `
+	} else {
+		br.Msg = "获取信息失败"
+		br.ErrMsg = "研选分类ID不能为空"
+		return
+	}
+	// 根据关注时间一个月前至昨日的增量数据排序
+	nowTime := time.Now().Local()
+	startTime := nowTime.AddDate(0, -1, 0)
+	endTime := nowTime.AddDate(0, 0, -1)
+	condition += ` AND ac.create_time BETWEEN ? AND ?`
+	pars = append(pars, startTime, endTime)
+	list, err := models.GetReportCollectionBillboardListYx(pageSize, pars, condition)
+	if err != nil {
+		br.Msg = "获取失败"
+		br.ErrMsg = "获取报告阅读增量排行榜失败, Err:" + err.Error()
+		return
+	}
+
+	list, err = services.HandleArticleCategoryImg(list, user)
+	if err != nil {
+		br.Msg = "获取信息失败"
+		br.ErrMsg = "HandleArticleCategoryImg,Err:" + err.Error()
+		return
+	}
+	//处理对应的文章类型标签按钮
+	nameMap, styleMap, err := services.GetArticleTypeMap()
+	if err != nil {
+		br.Msg = "获取信息失败"
+		br.ErrMsg = "GetArticleTypeMap Err:" + err.Error()
+		return
+	}
+
+	resp := new(models.ArticleResearchListResp)
+	for _, v := range list {
+		item := models.ArticleResearchResp{
+			ArticleId:       v.ArticleId,
+			ArticleTypeId:   v.ArticleTypeId,
+			Title:           v.Title,
+			PublishDate:     v.PublishDate,
+			DepartmentId:    v.DepartmentId,
+			NickName:        v.NickName,
+			IsCollect:       v.IsCollect,
+			Pv:              v.Pv,
+			CollectNum:      v.CollectNum,
+			Abstract:        v.Abstract,
+			Annotation:      v.Annotation,
+			ImgUrlPc:        v.ImgUrlPc,
+			ArticleTypeName: nameMap[v.ArticleTypeId],
+			ButtonStyle:     styleMap[v.ArticleTypeId],
+			List:            v.List,
+		}
+		resp.List = append(resp.List, &item)
+	}
+	br.Ret = 200
+	br.Success = true
+	br.Msg = "获取成功"
+	br.Data = resp
+}

+ 2 - 1
models/activity.go

@@ -211,6 +211,7 @@ type ActivityListResp struct {
 
 type ActivityArticleResp struct {
 	ReportLink string `description:"报告链接"`
+	Title      string `description:"报告标题"`
 	ArticleId  int    `description:"报告id(报告链接跳转使用)"`
 }
 
@@ -225,7 +226,7 @@ type CygxActivityResp struct {
 // 列表
 func GetCygxActivityList(condition string, pars []interface{}, sortTime string, startSize, pageSize int) (items []*CygxActivity, err error) {
 	o := orm.NewOrm()
-	sql := `SELECT	activity_id, label,temporary_label,is_show_subject_name, MAX( art.activity_time ) AS timesort, MIn( art.activity_time ) AS mintimesort , yidong_activity_id , activity_type_id 
+	sql := `SELECT	activity_id,city, label,temporary_label,is_show_subject_name, MAX( art.activity_time ) AS timesort, MIn( art.activity_time ) AS mintimesort , yidong_activity_id , activity_type_id 
 		FROM cygx_activity as art WHERE 1= 1 `
 	if condition != "" {
 		sql += condition

+ 1 - 1
models/activity_special.go

@@ -76,7 +76,7 @@ func UpdateActivitySpecialPublishStatus(publishStatus, activityId int) (err erro
 // 主题列表
 func GetActivityLabelSpecialListAll(condition string, pars []interface{}, startSize, pageSize int) (items []*CygxActivityLabelList, err error) {
 	o := orm.NewOrm()
-	sql := `SELECT	label,activity_id,is_show_subject_name
+	sql := `SELECT	label,activity_id,is_show_subject_name,days
 		FROM cygx_activity_special as art WHERE 1= 1 `
 	if condition != "" {
 		sql += condition

+ 3 - 0
models/activity_type.go

@@ -55,6 +55,9 @@ type CygxActivityLabelList struct {
 	IsExternalLabel   bool   `description:"是否为外部资源"`
 	IsShowSubjectName int    `description:"小程序内是否展示标的名称 1是 ,0否 默认0 "`
 	TemporaryLabel    string `description:"临时标签"`
+	TripStatus        int    `description:"行程进行状态 1:预报名,2:确定行程"`
+	City              string `description:"城市"`
+	Days              int    `description:"天数"`
 }
 
 // 列表

+ 27 - 7
models/article.go

@@ -59,10 +59,9 @@ func GetArticleDetailById(articleId int) (item *ArticleDetail, err error) {
 func GetArticlePermission(companyId int) (item *ChartPermission, err error) {
 	o := orm.NewOrm()
 	sql := `SELECT
-			b.* 
+			a.chart_permission_name as  permission_name
 			FROM
 			cygx_report_mapping AS a
-			INNER JOIN chart_permission AS b ON a.chart_permission_id = b.chart_permission_id 
 			WHERE
 			a.category_id = ?`
 	err = o.Raw(sql, companyId).QueryRow(&item)
@@ -76,7 +75,7 @@ type ArticleFollowDetail struct {
 	MacNum int `description:"本人是否收藏这个文章"`
 }
 
-//获取文章被关注被收藏的详情
+// 获取文章被关注被收藏的详情
 func GetArticleFollowDetail(articleId, uid int) (item *ArticleFollowDetail, err error) {
 	//d_num 作者被关注的数量 、 md_num 本人是否关注这个作者 、ac_num 文章被收藏的数量 、 mac_num 本人是否收藏这个文章
 	o := orm.NewOrm()
@@ -103,7 +102,7 @@ func GetArticleCountById(articleId int) (count int, err error) {
 	return
 }
 
-//用户收藏榜start
+// 用户收藏榜start
 type ArticleCollectionResp struct {
 	ArticleId       int                         `description:"文章id"`
 	Title           string                      `description:"标题"`
@@ -126,9 +125,10 @@ type ArticleCollectionResp struct {
 	HttpUrl         string                      `description:"文章链接跳转地址"`
 	IsNeedJump      bool                        `description:"是否需要跳转链接地址"`
 	MyCollectNum    int                         `description:"本人是否收藏数量"`
+	ArticleTypeId   int                         `description:"文章类型ID"`
 }
 
-//列表
+// 列表
 func GetArticleCollectionList(condition string, userId int) (items []*ArticleCollectionResp, err error) {
 	o := orm.NewOrm()
 	sql := `SELECT
@@ -189,7 +189,7 @@ type CygxArticleEs struct {
 	MatchTypeName    string `description:"匹配类型"`
 }
 
-//获取文章列表
+// 获取文章列表
 func GetArticleList(condition string, pars []interface{}) (items []*ArticleDetail, err error) {
 	o := orm.NewOrm()
 	sql := `SELECT	article_id FROM cygx_article  WHERE 1= 1 ` + condition
@@ -204,4 +204,24 @@ func GetArticleDetailByIdStr(articleIdStr string) (items []*ArticleDetail, err e
 			LEFT JOIN cygx_article_department AS d ON d.department_id = art.department_id  WHERE article_id IN(` + articleIdStr + `) `
 	_, err = o.Raw(sql).QueryRows(&items)
 	return
-}
+}
+
+// 检查用户是否阅读某一分类最新文章
+func GetUserIsReadThisNewCategoryArticleCount(categoryId, uid int) (count int, err error) {
+	sqlCount := `SELECT COUNT(1) as count FROM
+	cygx_article_history_record 
+	WHERE
+	article_id = ( SELECT article_id FROM cygx_article WHERE category_id = ? ORDER BY publish_date DESC LIMIT 0, 1 )
+	AND user_id = ?`
+	o := orm.NewOrm()
+	err = o.Raw(sqlCount, categoryId, uid).QueryRow(&count)
+	return
+}
+
+// 获取最新文章
+func GetNewArticleByCategoryId(categoryId int) (item *ArticleDetail, err error) {
+	o := orm.NewOrm()
+	sql := ` SELECT * FROM cygx_article WHERE  category_id = ? ORDER BY publish_date DESC LIMIT 0, 1`
+	err = o.Raw(sql, categoryId).QueryRow(&item)
+	return
+}

+ 51 - 5
models/article_collect.go

@@ -21,7 +21,7 @@ type CygxArticleCollect struct {
 	RealName        string `description:"用户实际名称"`
 }
 
-//添加收藏信息
+// 添加收藏信息
 func AddCygxArticleCollect(item *CygxArticleCollect) (lastId int64, err error) {
 	o := orm.NewOrm()
 	lastId, err = o.Insert(item)
@@ -79,7 +79,14 @@ func GetCygxArticleCollectList(condition string) (items []*CygxArticleCollect, e
 	return
 }
 
-//修改用户收藏文章的相关信息
+func GetCygxArticleCollectListByUser(userId int) (items []*CygxArticleCollect, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT * FROM cygx_article_collect  WHERE 1 =1   AND article_id > 0 AND user_id = ? `
+	_, err = o.Raw(sql, userId).QueryRows(&items)
+	return
+}
+
+// 修改用户收藏文章的相关信息
 func UpdateCygxArticleCollect(wxUser *WxUserItem) (err error) {
 	o := orm.NewOrm()
 	var sql string
@@ -98,7 +105,7 @@ type CygxArticleCollectCountRep struct {
 	Num       int `description:"数量"`
 }
 
-//获取文章被收藏的数量
+// 获取文章被收藏的数量
 func GetUserArticleCollectList() (items []*CygxArticleCollectCountRep, err error) {
 	o := orm.NewOrm()
 	sql := `SELECT
@@ -119,7 +126,7 @@ func GetUserArticleCollectList() (items []*CygxArticleCollectCountRep, err error
 	return
 }
 
-//修改文章收藏的数量
+// 修改文章收藏的数量
 func UpdateArticleCollectCountNum(num, articleId int) (err error) {
 	o := orm.NewOrm()
 	sql := `UPDATE cygx_article SET user_collection_num = ? WHERE article_id = ?`
@@ -169,4 +176,43 @@ func GetVideoCollectCount(userId, videoId int) (count int, err error) {
 	sql := `SELECT COUNT(1) AS count FROM cygx_article_collect WHERE user_id=? AND video_id=? `
 	err = orm.NewOrm().Raw(sql, userId, videoId).QueryRow(&count)
 	return
-}
+}
+
+func RemoveVoiceCollect(userId, voiceId int) (err error) {
+	o := orm.NewOrm()
+	sql := `DELETE FROM cygx_article_collect WHERE user_id=? AND activity_voice_id=? `
+	_, err = o.Raw(sql, userId, voiceId).Exec()
+	return
+}
+
+func RemoveActivityVideoCollect(userId, activityVideoId int) (err error) {
+	o := orm.NewOrm()
+	sql := `DELETE FROM cygx_article_collect WHERE user_id=? AND activity_video_id=? `
+	_, err = o.Raw(sql, userId, activityVideoId).Exec()
+	return
+}
+
+func GetActivityVideoCollectUsersCount(videoId int) (count int, err error) {
+	sql := `SELECT COUNT(user_id) AS count FROM cygx_article_collect WHERE activity_video_id=? `
+	err = orm.NewOrm().Raw(sql, videoId).QueryRow(&count)
+	return
+}
+
+func GetVoiceCollectUsersCount(voiceId int) (count int, err error) {
+	sql := `SELECT COUNT(user_id) AS count FROM cygx_article_collect WHERE activity_voice_id=? `
+	err = orm.NewOrm().Raw(sql, voiceId).QueryRow(&count)
+	return
+}
+
+func RemoveVideoCollect(userId, videoId int) (err error) {
+	o := orm.NewOrm()
+	sql := `DELETE FROM cygx_article_collect WHERE user_id=? AND video_id=? `
+	_, err = o.Raw(sql, userId, videoId).Exec()
+	return
+}
+
+func GetVideoCollectUsersCount(videoId int) (count int, err error) {
+	sql := `SELECT COUNT(user_id) AS count FROM cygx_article_collect WHERE video_id=? `
+	err = orm.NewOrm().Raw(sql, videoId).QueryRow(&count)
+	return
+}

+ 93 - 1
models/article_department.go

@@ -2,6 +2,7 @@ package models
 
 import (
 	"github.com/beego/beego/v2/client/orm"
+	"github.com/rdlucklib/rdluck_tools/paging"
 	"time"
 )
 
@@ -17,15 +18,32 @@ type CygxArticleDepartment struct {
 type DepartmentResp struct {
 	DepartmentId int    `description:"作者ID"`
 	CreateTime   string `description:"创建时间"`
+	PublishDate  string `description:"更新时间"`
 	NickName     string `description:"昵称"`
 	ImgUrl       string `description:"头像链接"`
 	IsFollow     bool   `description:"是否关注"`
+	IsHot        bool   `description:"是否标红"`
+	FllowNum     int    `description:"关注数量"`
+	List         []*IndustrialDepartmentListResp
+}
+
+type DepartmentListResp struct {
+	Paging *paging.PagingItem `description:"分页数据"`
+	List   []*DepartmentResp
 }
 
 type CygxArticleDepartmentId struct {
 	DepartmentId int `description:"作者ID"`
 }
 
+// 获取作者数量
+func GetDepartmentCount(departmentId int) (count int, err error) {
+	sqlCount := ` SELECT COUNT(1) AS count  FROM cygx_article_department WHERE department_id=? `
+	o := orm.NewOrm()
+	err = o.Raw(sqlCount, departmentId).QueryRow(&count)
+	return
+}
+
 func GetArticleDepartmentDateilById(departmentId int) (item *DepartmentResp, err error) {
 	o := orm.NewOrm()
 	sql := `SELECT * FROM cygx_article_department WHERE department_id = ? `
@@ -33,7 +51,7 @@ func GetArticleDepartmentDateilById(departmentId int) (item *DepartmentResp, err
 	return
 }
 
-//数量
+// 数量
 func GetArticleDepartmentCount(condition string) (count int, err error) {
 	o := orm.NewOrm()
 	sql := ` SELECT COUNT(*) count
@@ -54,3 +72,77 @@ func GetArticleDepartmentCount(condition string) (count int, err error) {
 type IndustrialSubjectList struct {
 	SubjectName string `description:"标的名称"`
 }
+
+// 作者列表
+func GetDepartmentList(condition, conditionOrder string, userId, startSize, pageSize int) (items []*DepartmentResp, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT
+			d.nick_name,
+			d.department_id,
+			d.img_url,
+			MAX( a.publish_date ) AS publish_date,
+			( SELECT count( 1 ) FROM cygx_article_department_follow AS f  WHERE f.department_id = d.department_id  AND user_id =?  AND f.type= 1  ) AS fllow_num,
+			( SELECT count( 1 ) FROM cygx_article_department_follow  AS f INNER JOIN wx_user AS u ON u.user_id = f.user_id  WHERE f.department_id = d.department_id AND f.type= 1 ) +( SELECT count( 1 ) FROM cygx_article_collect AS ac INNER JOIN wx_user AS u ON u.user_id = ac.user_id  WHERE ac.article_id IN (SELECT article_id FROM cygx_article WHERE department_id = d.department_id ) 	AND DATE_SUB( CURDATE(), INTERVAL 30 DAY ) <= date( ac.create_time )  ) AS sum_num
+		FROM
+		cygx_article_department AS d
+			INNER JOIN cygx_article AS a ON d.department_id = a.department_id
+		WHERE
+			1 = 1
+			AND a.article_type_id > 0  
+			AND publish_status = 1  ` + condition + `
+		GROUP BY
+					d.department_id ` + conditionOrder + ` , last_updated_time  DESC LIMIT ?,?`
+	_, err = o.Raw(sql, userId, startSize, pageSize).QueryRows(&items)
+	return
+}
+
+// 用户收藏榜start
+type DepartmentDetailResp struct {
+	DepartmentId   int    `description:"作者Id"`
+	NickName       string `description:"作者昵称"`
+	ImgUrl         string `description:"图片链接"`
+	FllowNum       int    `description:"多少人关注"`
+	ArticleNum     int    `description:"文章数量"`
+	CollectNum     int    `description:"收藏人数"`
+	IsFollow       bool   `description:"是否关注"`
+	List           []*ArticleResearchResp
+	ListIndustrial []*IndustrialManagementNewResp
+	Paging         *paging.PagingItem
+}
+
+type IndustrialManagementNewResp struct {
+	IndustrialManagementId int    `description:"产业Id"`
+	IndustryName           string `description:"产业名称"`
+	IsHot                  bool   `description:"是否是热门"`
+	ArticleReadNum         int    `description:"文章阅读数量"`
+}
+
+type DepartmentDetail struct {
+	DepartmentId int    `description:"作者Id"`
+	NickName     string `description:"作者昵称"`
+	ImgUrl       string `description:"图片链接"`
+	FllowNum     int    `description:"多少人关注"`
+	ArticleNum   int    `description:"文章数量"`
+	CollectNum   int    `description:"收藏人数"`
+	IsFollow     bool   `description:"是否关注"`
+	MyFllowNum   int    `description:"本人是否关注"`
+}
+
+// 作者详情
+func GetDepartmentDetail(userId, departmentId int, condition string) (item DepartmentDetail, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT
+			d.department_id,
+			d.nick_name,
+			d.img_url,
+			( SELECT count( 1 ) FROM cygx_article_department_follow AS af WHERE af.user_id = ? AND af.department_id = d.department_id AND af.type= 1 ) AS my_fllow_num,
+			( SELECT count( 1 ) FROM cygx_article_department_follow AS f INNER JOIN wx_user as u ON  u.user_id = f.user_id   WHERE f.department_id = d.department_id  AND f.type= 1 ) AS fllow_num,
+			( SELECT count( 1 ) FROM cygx_article AS a WHERE a.department_id = d.department_id  ` + condition + ` ) AS article_num,
+			( SELECT count( 1 ) FROM cygx_article_collect  AS c INNER JOIN wx_user as u ON  u.user_id = c.user_id   WHERE c.article_id IN (SELECT  article_id FROM cygx_article AS a WHERE a.department_id = d.department_id  ` + condition + ` )) AS collect_num
+		FROM
+			cygx_article_department AS d 
+		WHERE
+			d.department_id = ?`
+	err = o.Raw(sql, userId, departmentId).QueryRow(&item)
+	return
+} //end

+ 80 - 0
models/article_department_follow.go

@@ -0,0 +1,80 @@
+package models
+
+import (
+	"github.com/beego/beego/v2/client/orm"
+	"time"
+)
+
+type CygxArticleDepartmentFollow struct {
+	Id           int       `orm:"column(id);pk"`
+	DepartmentId int       `description:"作者ID"`
+	UserId       int       `description:"用户ID"`
+	Mobile       string    `description:"手机号"`
+	Email        string    `description:"邮箱"`
+	CompanyId    int       `description:"公司id"`
+	CompanyName  string    `description:"公司名称"`
+	Type         int       `description:"操作方式,1报名,2取消报名"`
+	CreateTime   time.Time `description:"创建时间"`
+	ModifyTime   time.Time `description:"更新时间"`
+	RealName     string    `description:"用户实际名称"`
+}
+
+type ArticleDepartmentIdRep struct {
+	DepartmentId int `description:"作者ID"`
+}
+
+// 添加
+func AddArticleDepartmentFollow(item *CygxArticleDepartmentFollow) (lastId int64, err error) {
+	o := orm.NewOrm()
+	lastId, err = o.Insert(item)
+	return
+}
+
+type CygxArticleDepartmentFollowResp struct {
+	Status   int  `description:"1:关注,2:取消关注"`
+	GoFollow bool `description:"是否去关注"`
+}
+
+func RemoveArticleDepartmentFollow(userId, industrialManagementId, doType int) (err error) {
+	o := orm.NewOrm()
+	sql := `DELETE FROM cygx_article_department_follow WHERE user_id=? AND department_id=? `
+	_, err = o.Raw(sql, userId, industrialManagementId).Exec()
+	return
+}
+
+// 获取数量
+func GetArticleDepartmentFollow(userId, departmentId int, condition string) (count int, err error) {
+	sql := `SELECT COUNT(1) AS count FROM cygx_article_department_follow WHERE user_id=? AND department_id=? ` + condition
+	err = orm.NewOrm().Raw(sql, userId, departmentId).QueryRow(&count)
+	return
+}
+
+// 获取数量
+func GetArticleDepartmentFollowByUid(userId int) (count int, err error) {
+	sql := `SELECT COUNT(1) AS count FROM cygx_article_department_follow WHERE user_id=? `
+	err = orm.NewOrm().Raw(sql, userId).QueryRow(&count)
+	return
+}
+
+// 获取列表信息根据手机号分组
+func GetArticleDepartmentFollowByMobileList(condition string) (items []*CygxArticleDepartmentFollow, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT * FROM cygx_article_department_follow  WHERE 1 =1  ` + condition + `  GROUP BY user_id  `
+	_, err = o.Raw(sql).QueryRows(&items)
+	return
+}
+
+// 修改用户关注作者的相关信息
+func UpdateCygxArticleDepartmentFollow(wxUser *WxUserItem) (err error) {
+	o := orm.NewOrm()
+	var sql string
+	if wxUser.Mobile != "" {
+		sql = `UPDATE cygx_article_department_follow SET email=?,company_id=?,company_name=?,user_id=?,real_name=? WHERE mobile=? `
+		_, err = o.Raw(sql, wxUser.Email, wxUser.CompanyId, wxUser.CompanyName, wxUser.UserId, wxUser.RealName, wxUser.Mobile).Exec()
+	} else if wxUser.Email != "" {
+		sql = `UPDATE cygx_article_department_follow SET mobile=?,company_id=?,company_name=?,user_id=?,real_name=? WHERE email=? `
+		_, err = o.Raw(sql, wxUser.Mobile, wxUser.CompanyId, wxUser.CompanyName, wxUser.UserId, wxUser.RealName, wxUser.Email).Exec()
+	}
+
+	return
+}

+ 156 - 0
models/article_history_record_newpv.go

@@ -0,0 +1,156 @@
+package models
+
+import (
+	"fmt"
+	"github.com/beego/beego/v2/client/orm"
+	"hongze/hongze_clpt/utils"
+	"time"
+)
+
+type CygxArticleHistoryRecordNewpv struct {
+	Id          int `orm:"column(id);pk"`
+	ArticleId   int
+	UserId      int
+	CreateTime  time.Time
+	ModifyTime  time.Time
+	Mobile      string `description:"手机号"`
+	Email       string `description:"邮箱"`
+	CompanyId   int    `description:"公司id"`
+	CompanyName string `description:"公司名称"`
+	StopTime    int    `description:"停留时间"`
+	OutType     int    `description:"退出方式,1正常退出,2强制关闭"`
+	Source      string `description:"来源,MOBILE:手机端,PC:电脑端"`
+}
+
+type CygxArticleHistoryRecord struct {
+	Id          int `orm:"column(id);pk"`
+	ArticleId   int
+	UserId      int
+	CreateTime  time.Time
+	Mobile      string    `description:"手机号"`
+	Email       string    `description:"邮箱"`
+	CompanyId   int       `description:"公司id"`
+	CompanyName string    `description:"公司名称"`
+	ModifyTime  time.Time `description:"修改时间"`
+	StopTime    int       `description:"停留时间"`
+	OutType     int       `description:"退出方式,1正常退出,2强制关闭"`
+}
+
+// 添加阅读记录信息
+func AddCygxArticleViewRecordNewpv(item *CygxArticleHistoryRecordNewpv) (lastId int64, err error) {
+	o, err := orm.NewOrm().Begin()
+	if err != nil {
+		return
+	}
+	defer func() {
+		fmt.Println(err)
+		if err == nil {
+			o.Commit()
+		} else {
+			o.Rollback()
+		}
+	}()
+	lastId, err = o.Insert(item)
+	if err != nil {
+		return
+	}
+
+	historyRecord := new(CygxArticleHistoryRecord)
+	historyRecord.UserId = item.UserId
+	historyRecord.ArticleId = item.ArticleId
+	historyRecord.CreateTime = time.Now()
+	historyRecord.Mobile = item.Mobile
+	historyRecord.Email = item.Email
+	historyRecord.CompanyId = item.CompanyId
+	historyRecord.CompanyName = item.CompanyName
+	lastId, err = o.Insert(historyRecord)
+	if err != nil {
+		return
+	}
+
+	//写入记录到总的统计表
+	record := new(CygxArticleHistoryRecordAll)
+	record.UserId = item.UserId
+	record.ArticleId = item.ArticleId
+	record.CreateTime = item.CreateTime.Format(utils.FormatDateTime)
+	record.ModifyTime = item.ModifyTime
+	record.Mobile = item.Mobile
+	record.Email = item.Email
+	record.CompanyId = item.CompanyId
+	record.CompanyName = item.CompanyName
+	record.StopTime = item.StopTime
+	record.OutType = item.OutType
+	record.Source = item.Source
+	record.Platfor = 1
+	lastId, err = o.Insert(record)
+	if err != nil {
+		return
+	}
+
+	// 软删除当天策略平台的文章阅读记录
+	if item.Mobile != "" {
+		sql := `UPDATE cygx_article_history_record_all 
+			SET is_del = 1 
+			WHERE
+			article_id = ? 
+			AND mobile = ?
+			AND platfor = 2
+			AND create_time >= date(NOW()) `
+		_, err = o.Raw(sql, record.ArticleId, record.Mobile).Exec()
+	}
+	return
+}
+
+type CygxArticleHistoryRecordAll struct {
+	Id             int `orm:"column(id);pk"`
+	ArticleId      int
+	UserId         int
+	CreateTime     string
+	ModifyTime     time.Time
+	Mobile         string    `description:"手机号"`
+	Email          string    `description:"邮箱"`
+	CompanyId      int       `description:"公司id"`
+	CompanyName    string    `description:"公司名称"`
+	StopTime       int       `description:"停留时间"`
+	OutType        int       `description:"退出方式,1正常退出,2强制关闭"`
+	Source         string    `description:"来源,MOBILE:手机端,PC:电脑端"`
+	RealName       string    `description:"用户实际名称"`
+	CreateDateApi  time.Time `description:"同步创建时间"`
+	CelueHistoryId int       `description:"策略平台记录的ID"`
+	Platfor        int       `description:"PV阅读记录来源,1:查研观向,2:策略平台"`
+	IsDel          int       `description:"是否删除"`
+}
+
+type EsUserInteraction struct {
+	Id                       int    `description:"主键ID"`
+	ArticleId                int    `description:"文章id"`
+	ArticleType              int    `description:"文章类型 1:查研观向, 2:策略平台"`
+	Title                    string `description:"标题"`
+	PublishDate              string `description:"发布时间"`
+	CreateTime               string `description:"创建时间"`
+	StopTime                 string `description:"阅读停留时间"`
+	RealName                 string `description:"姓名"`
+	CompanyName              string `description:"公司名称"`
+	CompanyId                int    `description:"公司ID"`
+	SellerName               string `description:"所属销售"`
+	SellerId                 int    `description:"所属销售ID"`
+	Mobile                   string `description:"手机号"`
+	Email                    string `description:"邮箱"`
+	UserId                   int    `description:"用户ID"`
+	UserArticleHistoryNum    int    `description:"用户阅读数量"`
+	CompanyArticleHistoryNum int    `description:"机构阅读数量"`
+}
+
+// GetArticleHistoryRecord 或用户阅读过的文章ID
+func GetArticleHistoryRecord(condition string, pars []interface{}) (item []*CygxArticleHistoryRecord, err error) {
+	if condition == "" {
+		return
+	}
+	o := orm.NewOrm()
+	sql := `SELECT *
+			FROM
+			cygx_article_history_record  
+			WHERE 1 = 1 ` + condition + `  GROUP BY article_id`
+	_, err = o.Raw(sql, pars).QueryRows(&item)
+	return
+}

+ 70 - 0
models/article_type.go

@@ -0,0 +1,70 @@
+package models
+
+import (
+	"github.com/beego/beego/v2/client/orm"
+	"time"
+)
+
+type CygxArticleType struct {
+	ArticleTypeId      int       `orm:"column(article_type_id);pk";description:"文章类型ID"`
+	ArticleTypeName    string    `description:"类型名称"`
+	Sort               int       `description:"排序字段"`
+	CreateTime         time.Time `description:"创建时间"`
+	ModifyTime         time.Time `description:"最后修改时间"`
+	IsSendEs           int       `description:"这种报告类型是否同步到Es"`
+	YanxPermissionId   int       `description:"研选类型所对应的ID"`
+	YanxPermissionName string    `description:"研选类型所对应的名称"`
+	IcoLink            string    `description:"图标链接地址"`
+	IcoLinkM           string    `description:"移动端图标链接地址"`
+	IsShowLinkButton   int       `description:"这种报告类型是否展示查看报告链接"`
+	ButtonStyle        string    `description:"按钮展示样式"`
+}
+
+type CygxArticleTypeResp struct {
+	ArticleTypeId   int    `description:"文章类型ID"`
+	ArticleTypeName string `description:"类型名称"`
+	ButtonStyle     string `description:"按钮展示样式"`
+}
+
+type CygxArticleTypeListResp struct {
+	List []*CygxArticleTypeResp
+}
+
+// 详情
+func GetCygxArticleTypeDetailById(activityTypeId int) (item *CygxArticleType, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT * FROM cygx_article_type WHERE article_type_id = ? `
+	err = o.Raw(sql, activityTypeId).QueryRow(&item)
+	return
+}
+
+// 获取数量
+func GetCygxArticleTypeCount(condition string) (count int, err error) {
+	o := orm.NewOrm()
+	sqlCount := `SELECT COUNT(1) AS count  FROM cygx_article_type WHERE  1=1 ` + condition
+	err = o.Raw(sqlCount).QueryRow(&count)
+	return
+}
+
+// 报告类型列表
+func GetCygxArticleTypeList() (items []*CygxArticleType, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT * FROM cygx_article_type ORDER BY sort DESC`
+	_, err = o.Raw(sql).QueryRows(&items)
+	return
+}
+
+// 报告类型列表
+func GetCygxArticleTypeListCondition(condition string) (items []*CygxArticleType, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT * FROM cygx_article_type   WHERE  1=1 ` + condition + ` ORDER BY sort DESC`
+	_, err = o.Raw(sql).QueryRows(&items)
+	return
+}
+
+func GetArticleTypeInfo(activityTypeId int) (item *CygxArticleType, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT * FROM cygx_article_type   WHERE  article_type_id=? `
+	err = o.Raw(sql, activityTypeId).QueryRow(&item)
+	return
+}

+ 129 - 0
models/cygx_morning_meeting_review_chapter.go

@@ -0,0 +1,129 @@
+package models
+
+import (
+	"github.com/beego/beego/v2/client/orm"
+	"time"
+)
+
+// CygxMorningMeetingReviewChapter [...]
+type CygxMorningMeetingReviewChapter struct {
+	Id                   int       `orm:"column(id);pk"`
+	MeetingTime          time.Time `json:"meetingTime"` // 晨会日期
+	CreateTime           time.Time `json:"createTime"`
+	ModifyTime           time.Time `json:"modifyTime"`
+	IndustryId           int       `json:"industryId"`          // 产业id
+	IndustryName         string    `json:"industryName"`        // 产业名称
+	ChartPermissionName  string    `json:"chartPermissionName"` // 行业名称
+	ChartPermissionId    int       `json:"chartPermissionId"`   // 行业id
+	IndustrialSubjectIds string    `json:"industrialSubjectId"` // 标的id
+	MeetingId            int64     `json:"meetingId"`           // 主表id
+	Content              string    `json:"content"`             // 内容
+}
+
+type AddMorningMeetingReviewItem struct {
+	ChapterId            int
+	Content              string
+	ChartPermissionId    int
+	ChartPermissionName  string
+	IndustryId           int
+	IndustryName         string
+	IndustrialSubjectIds string
+}
+
+type AddMorningMeetingReviewsReq struct {
+	List        []*AddMorningMeetingReviewItem
+	MeetingId   int
+	MeetingTime string
+	PublishTime string
+	DoType      int `description:"操作类型 0,保存 、1,发布"`
+}
+
+// 添加晨报点评章节
+func AddCygxMorningMeetingReviewChapter(item *CygxMorningMeetingReviewChapter) (err error) {
+	o := orm.NewOrm()
+	_, err = o.Insert(item)
+	return
+}
+
+// 列表
+func GetCygxMorningMeetingReviewsListById(meetingId int) (items []*CygxMorningMeetingReviewChapter, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT * FROM cygx_morning_meeting_review_chapter WHERE meeting_id = ? `
+	_, err = o.Raw(sql, meetingId).QueryRows(&items)
+	return
+}
+
+type IndustrialSubjectItem struct {
+	IndustrialSubjectId int    `orm:"column(industrial_subject_id);pk" description:"标的id"`
+	SubjectName         string `description:"标的名称"`
+}
+
+type CygxMorningMeetingReviewChapterRespItem struct {
+	Id                    int                      `orm:"column(id);pk"`
+	MeetingTime           time.Time                `json:"meetingTime"` // 晨会日期
+	CreateTime            time.Time                `json:"createTime"`
+	ModifyTime            time.Time                `json:"modifyTime"`
+	IndustryId            int                      `json:"industryId"`            // 产业id
+	IndustryName          string                   `json:"industryName"`          // 产业名称
+	ChartPermissionName   string                   `json:"chartPermissionName"`   // 行业名称
+	ChartPermissionId     int                      `json:"chartPermissionId"`     // 行业id
+	IndustrialSubjectList []*IndustrialSubjectItem `json:"industrialSubjectList"` // 标的list
+	MeetingId             int64                    `json:"meetingId"`             // 主表id
+	Content               string                   `json:"content"`               // 内容
+}
+
+type CygxMorningMeetingReviewChapterResp struct {
+	MeetingTime string
+	Status      int
+	List        []*CygxMorningMeetingReviewChapterRespItem
+}
+
+// 删除晨会点评章节
+func DeleteMorningMeetingChapter(reviewId int) (err error) {
+	o := orm.NewOrm()
+	sql := ` DELETE FROM cygx_morning_meeting_review_chapter WHERE meeting_id =? `
+	_, err = o.Raw(sql, reviewId).Exec()
+	return
+}
+
+// 更新晨报点评章节
+func UpdateCygxMorningMeetingReviewChapter(item *CygxMorningMeetingReviewChapter) (err error) {
+	o := orm.NewOrm()
+	sql := `UPDATE cygx_morning_meeting_review_chapter
+			SET
+			  meeting_time =?,
+			  modify_time = ?,
+			  industry_id = ?,
+			  industry_name = ?,
+			  chart_permission_id = ?,
+			  chart_permission_name = ?,
+			  industrial_subject_ids = ?,
+			  content = ? 
+			WHERE id = ? `
+	_, err = o.Raw(sql, item.MeetingTime, item.ModifyTime, item.IndustryId, item.IndustryName,
+		item.ChartPermissionId, item.ChartPermissionName, item.IndustrialSubjectIds, item.Content, item.Id).Exec()
+
+	return
+}
+
+func GetCygxMorningMeetingReviewsListByIdAndIndustryId(meetingId, industryId int) (item *CygxMorningMeetingReviewChapter, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT * FROM cygx_morning_meeting_review_chapter WHERE meeting_id = ? AND industry_id = ? `
+	err = o.Raw(sql, meetingId, industryId).QueryRow(&item)
+	return
+}
+
+// 删除晨会点评章节
+func DeleteMorningMeetingChapterById(chapterId int) (err error) {
+	o := orm.NewOrm()
+	sql := ` DELETE FROM cygx_morning_meeting_review_chapter WHERE id =? `
+	_, err = o.Raw(sql, chapterId).Exec()
+	return
+}
+
+func GetCygxMorningMeetingReviewsListByIndustrialIds(industrialIds string) (items []*CygxMorningMeetingReviewChapter, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT * FROM cygx_morning_meeting_review_chapter WHERE industry_id IN (` + industrialIds + `)  `
+	_, err = o.Raw(sql).QueryRows(&items)
+	return
+}

+ 5 - 0
models/db.go

@@ -55,6 +55,11 @@ func init() {
 		new(UserTemplateRecord),
 		new(CygxAdvice),
 		new(CygxPageHistoryRecord),
+		new(CygxArticleDepartmentFollow),
+		new(CygxArticleComment),
+		new(CygxArticleHistoryRecordNewpv),
+		new(CygxArticleHistoryRecord),
+		new(CygxArticleHistoryRecordAll),
 		new(CygxActivitySpecialTripBill),
 	)
 	// 记录ORM查询日志

+ 44 - 0
models/home.go

@@ -3,6 +3,7 @@ package models
 import (
 	"github.com/beego/beego/v2/client/orm"
 	"github.com/rdlucklib/rdluck_tools/paging"
+	"strconv"
 )
 
 type HomeArtAndChartListResp struct {
@@ -40,6 +41,8 @@ type HomeArticle struct {
 	Annotation      string               `description:"核心观点"`
 	ArticleTypeId   int                  `description:"文章类型ID判断是否是研选使用"`
 	HomeType        int                  `description:"数据类型:0-纪要(默认); 1-微路演音频"`
+	Readnum         int                  `description:"阅读数量"`
+	IsRed           bool                 `description:"是否标红"`
 	MicroAudio      *MicroAudioUnionList `description:"微路演音频"`
 	List            []*IndustrialManagementIdInt
 }
@@ -63,6 +66,11 @@ type ArticleListResp struct {
 	ChartPermissionName string `description:"权限名称"`
 	ArticleTypeId       int    `description:"文章类型ID判断是否是研选使用"`
 	BodyImg             string `description:"文章封面图片"`
+	DepartmentId        int    `description:"作者Id"`
+	NickName            string `description:"作者昵称"`
+	IsCollect           bool   `description:"本人是否收藏"`
+	IsRed               bool   `description:"是否标红"`
+	CollectNum          int    `description:"收藏人数"`
 	List                []*IndustrialManagementIdInt
 }
 
@@ -115,6 +123,42 @@ func GetHomeList(condition string, pars []interface{}, startSize, pageSize int)
 	return
 }
 
+func GetHomeListNew(condition string, pars []interface{}, startSize, pageSize int) (items []*ArticleListResp, err error) {
+	o := orm.NewOrm()
+	sql := ` SELECT * ,(SELECT count(1) FROM cygx_article_history_record_newpv as h WHERE h.article_id = a.article_id ) as pv
+                 FROM cygx_article AS a
+                WHERE a.publish_status=1 `
+	if condition != "" {
+		sql += condition
+	}
+	sql += ` ORDER BY publish_date DESC,article_id DESC LIMIT ?,? `
+	_, err = o.Raw(sql, pars, startSize, pageSize).QueryRows(&items)
+	return
+}
+
+// 获取产业报告列表
+func GetReportIndustrialList(condition string, pars []interface{}, categoryId, industrialManagementId, userId, startSize, pageSize int) (items []*HomeArticle, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT *,( SELECT COUNT( 1 ) FROM cygx_article_history_record AS rec WHERE rec.user_id = ` + strconv.Itoa(userId) + ` AND rec.article_id = a.article_id ) AS readnum 
+FROM
+	cygx_article AS a 
+	INNER JOIN cygx_industrial_article_group_management as man_g ON man_g.article_id = a.article_id
+WHERE
+	a.publish_status = 1 
+	AND category_id  IN (SELECT
+	category_id 
+FROM
+	cygx_report_mapping 
+WHERE
+	chart_permission_id = any( SELECT chart_permission_id FROM cygx_report_mapping WHERE category_id = ` + strconv.Itoa(categoryId) + ` ) 
+	AND match_type_name = any( SELECT match_type_name FROM cygx_report_mapping WHERE category_id = ` + strconv.Itoa(categoryId) + ` ) )
+    AND a.is_class = 1
+	AND man_g.industrial_management_id = ?` + condition
+	sql += `   GROUP BY a.article_id ORDER BY publish_date DESC LIMIT ?,? `
+	_, err = o.Raw(sql, pars, industrialManagementId, startSize, pageSize).QueryRows(&items)
+	return
+}
+
 func GetHomeListPublic(condition string, pars []interface{}, startSize, pageSize int) (items []*ArticleListResp, err error) {
 	o := orm.NewOrm()
 	sql := ` SELECT * ,(SELECT count(1) FROM cygx_article_history_record_newpv as h WHERE h.article_id = a.article_id ) as pv

+ 56 - 0
models/industrial_article_group_management.go

@@ -54,3 +54,59 @@ func GetIndustrialArticleGroupManagementList(condition string, pars []interface{
 	_, err = orm.NewOrm().Raw(sql, pars).QueryRows(&list)
 	return
 }
+
+type IndustrialDepartmentListResp struct {
+	IndustrialManagementId int    `description:"产业Id"`
+	IndustryName           string `description:"产业名称"`
+	DepartmentId           int    `description:"作者Id"`
+	List                   []*IndustrialDepartmentListResp
+}
+
+// 作者文章所关联的产业列表
+func GetIndustrialDepartmentList() (items []*IndustrialDepartmentListResp, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT
+			m.industrial_management_id,
+			m.industry_name,
+			d.department_id 
+		FROM
+			cygx_article_department AS d
+			INNER JOIN cygx_article AS a ON d.department_id = a.department_id
+			INNER JOIN cygx_industrial_article_group_management AS mg ON mg.article_id = a.article_id
+			INNER JOIN cygx_industrial_management AS m ON m.industrial_management_id = mg.industrial_management_id 
+		WHERE
+			1 = 1
+			AND a.article_type_id > 0
+			AND publish_status = 1 
+		GROUP BY
+			a.article_id 
+		ORDER BY
+			a.publish_date DESC`
+	_, err = o.Raw(sql).QueryRows(&items)
+	return
+}
+
+type CygxIndustrialArticleGroupManagementResp struct {
+	ArticleId              int       `description:"文章ID"`
+	IndustrialManagementId int       `description:"cygx_industrial_management表的主键ID"`
+	PublishDate            time.Time `description:"发布时间"`
+}
+
+// GetCygxIndustrialArticleGroupManagement  获取产业关联的所有文章
+func GetCygxIndustrialArticleGroupManagement(condition string, pars []interface{}) (list []*CygxIndustrialArticleGroupManagementResp, err error) {
+	sql := `SELECT
+			mg.industrial_management_id,
+			a.article_id,
+			a.publish_date
+		FROM
+			cygx_industrial_article_group_management AS mg
+			INNER JOIN cygx_article AS a ON a.article_id = mg.article_id 
+		WHERE
+			1 = 1 
+			AND a.publish_status = 1 `
+	if condition != `` {
+		sql += condition
+	}
+	_, err = orm.NewOrm().Raw(sql, pars).QueryRows(&list)
+	return
+}

+ 70 - 24
models/industrial_management.go

@@ -84,7 +84,7 @@ type IndustryVideoDetailResp struct {
 	AuthInfo      *UserPermissionAuthInfo
 }
 
-//产业列表
+// 产业列表
 func GetIndustrialManagementAllCount(condition string) (count int, err error) {
 	o := orm.NewOrm()
 	sql := `SELECT
@@ -106,7 +106,7 @@ func GetIndustrialManagementAllCount(condition string) (count int, err error) {
 	return
 }
 
-//获取产业下阅读数量第三的产业详情
+// 获取产业下阅读数量第三的产业详情
 func GetIndustrialManagementHot3(chartPermissionId int) (item *IndustrialManagementRep, err error) {
 	o := orm.NewOrm()
 	sql := `SELECT * FROM cygx_industrial_management WHERE chart_permission_id = ? ORDER BY article_read_num DESC LIMIT 2,1`
@@ -114,7 +114,7 @@ func GetIndustrialManagementHot3(chartPermissionId int) (item *IndustrialManagem
 	return
 }
 
-//产业列表
+// 产业列表
 func GetIndustrialManagementAll(uid int, condition, orderSrt string, startSize, pageSize int, isBillboard bool) (items []*IndustrialManagement, err error) {
 	o := orm.NewOrm()
 	var conditionBillboard string
@@ -145,7 +145,7 @@ func GetIndustrialManagementAll(uid int, condition, orderSrt string, startSize,
 	return
 }
 
-//标的列表
+// 标的列表
 func GetIndustrialSubjectAll(IndustrialManagementId int) (items []*IndustrialSubject, err error) {
 	o := orm.NewOrm()
 	sql := `SELECT * FROM cygx_industrial_subject WHERE industrial_management_id = ? `
@@ -153,7 +153,7 @@ func GetIndustrialSubjectAll(IndustrialManagementId int) (items []*IndustrialSub
 	return
 }
 
-//获取该产业下最新的文章详情
+// 获取该产业下最新的文章详情
 func GetIndustrialNewArticleDetail(industrialManagementId int) (item *ArticleDetail, err error) {
 	o := orm.NewOrm()
 	sql := `SELECT
@@ -170,12 +170,12 @@ ORDER BY
 	return
 }
 
-//获取该产业下最新的文章详情
-func GetNewArticleDetailByIndustrialIds(industrialIdArr []int) (items []*IndustrialManagementArticle, err error) {
-	arrLen := len(industrialIdArr)
-	if arrLen == 0 {
-		return
-	}
+// 获取该产业下最新的文章详情
+func GetNewArticleDetailByIndustrialIds(pars []interface{}, condition string) (items []*IndustrialManagementArticle, err error) {
+	//arrLen := len(industrialIdArr)
+	//if arrLen == 0 {
+	//	return
+	//}
 	o := orm.NewOrm()
 	sql := `SELECT
 			mg.industrial_management_id,
@@ -186,17 +186,14 @@ func GetNewArticleDetailByIndustrialIds(industrialIdArr []int) (items []*Industr
 			cygx_industrial_article_group_management AS mg
 			INNER JOIN cygx_article AS a ON mg.article_id = a.article_id 
 		WHERE
-			1 = 1
-			AND a.is_report = 1
-			AND a.is_class = 1
-			AND mg.industrial_management_id IN(` + utils.GetOrmInReplace(len(industrialIdArr)) + `)   
+			1 = 1   ` + condition + `
 		GROUP BY
 			mg.industrial_management_id `
-	_, err = o.Raw(sql, industrialIdArr).QueryRows(&items)
+	_, err = o.Raw(sql, pars).QueryRows(&items)
 	return
 }
 
-//获取产业数量
+// 获取产业数量
 func GetIndustrialManagementCount(IndustrialManagementId int) (count int, err error) {
 	sqlCount := ` SELECT COUNT(1) AS count  FROM cygx_industrial_management WHERE industrial_management_id=? `
 	o := orm.NewOrm()
@@ -204,7 +201,7 @@ func GetIndustrialManagementCount(IndustrialManagementId int) (count int, err er
 	return
 }
 
-//获取关注数量
+// 获取关注数量
 func GetCountCygxIndustryFllow(industrialManagementId, userId int, condition string) (count int, err error) {
 	sql := `SELECT COUNT(1) AS count FROM cygx_industry_fllow WHERE user_id=? AND industrial_management_id=? ` + condition
 	err = orm.NewOrm().Raw(sql, userId, industrialManagementId).QueryRow(&count)
@@ -218,7 +215,7 @@ func GetIndustrialManagementDetail(industrialManagementId int) (items *Industria
 	return
 }
 
-//获取所有的产业
+// 获取所有的产业
 func GetindustrialManagement() (items []*IndustrialManagementRep, err error) {
 	o := orm.NewOrm()
 	sql := `SELECT
@@ -232,15 +229,29 @@ func GetindustrialManagement() (items []*IndustrialManagementRep, err error) {
 	return
 }
 
-//标的列表
-func GetIndustrialSubjectAllByIndustrialId(industrialIdArr []int) (items []*IndustrialSubject, err error) {
+// 标的列表
+func GetIndustrialSubjectAllByIndustrialId(pars []interface{}, condition string) (items []*IndustrialSubject, err error) {
 	o := orm.NewOrm()
-	sql := `SELECT * FROM cygx_industrial_subject WHERE industrial_management_id IN  (` + utils.GetOrmInReplace(len(industrialIdArr)) + `)   `
-	_, err = o.Raw(sql, industrialIdArr).QueryRows(&items)
+	sql := `SELECT
+			m.subject_name,
+			m.industrial_management_id,
+			m.industrial_subject_id 
+		FROM
+			cygx_article AS a
+			INNER JOIN cygx_industrial_article_group_subject AS mg ON mg.article_id = a.article_id
+			INNER JOIN cygx_industrial_subject AS m ON m.industrial_subject_id = mg.industrial_subject_id 
+		WHERE
+			1 = 1
+			AND a.publish_status = 1  ` + condition + `
+		GROUP BY
+			m.industrial_subject_id 
+ORDER BY
+	a.publish_date DESC  `
+	_, err = o.Raw(sql, pars).QueryRows(&items)
 	return
 }
 
-//获取标的列表
+// 获取标的列表
 func GetIndustrialListByarticleId(pars []interface{}, condition string) (items []*IndustrialManagementIdInt, err error) {
 	o := orm.NewOrm()
 	sql := `SELECT
@@ -304,6 +315,17 @@ func GetTopOneMonthArtReadNumIndustry(condition string, pars []interface{}) (ite
 	return
 }
 
+// GetTopOneMonthArtReadNumIndustry 获取近一个月报告阅读数量最多的产业信息 根据行业分组
+func GetTopOneMonthArtReadNumIndustryAll(condition string, pars []interface{}) (items []*IndustrialManagement, err error) {
+	sql := `SELECT * FROM cygx_industrial_management WHERE 1 = 1 `
+	if condition != `` {
+		sql += condition
+	}
+	sql += ` ORDER BY article_read_num DESC `
+	_, err = orm.NewOrm().Raw(sql, pars).QueryRows(&items)
+	return
+}
+
 // GetTopIndustryFollowData 获取关注度最高的产业关注数据
 func GetTopIndustryFollowData(startSize, pageSize int, condition string, pars []interface{}) (list []*IndustrialManagement, err error) {
 	sql := `SELECT
@@ -366,3 +388,27 @@ func GetSourceIndustryByName(industryName string) (item *IndustrialManagement, e
 	err = orm.NewOrm().Raw(sql, industryName).QueryRow(&item)
 	return
 }
+
+// 近期更新主题列表
+func GetIndustrialManagementNewList(condition string) (items []*IndustrialManagementNewResp, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT
+			m.industrial_management_id,
+			m.industry_name,
+			m.article_read_num,
+			MAX( a.publish_date ) AS publish_date 
+		FROM
+			cygx_article AS a
+			INNER JOIN cygx_industrial_article_group_management AS mg ON mg.article_id = a.article_id
+			INNER JOIN cygx_industrial_management AS m ON m.industrial_management_id = mg.industrial_management_id 
+		WHERE
+			1 = 1
+			AND a.article_type_id > 0
+			AND publish_status = 1 ` + condition + `
+		GROUP BY
+			m.industrial_management_id 
+		ORDER BY
+			publish_date DESC LIMIT 12`
+	_, err = o.Raw(sql).QueryRows(&items)
+	return
+}

+ 57 - 0
models/industrial_subject.go

@@ -0,0 +1,57 @@
+package models
+
+import (
+	"github.com/beego/beego/v2/client/orm"
+)
+
+type IndustrialSubjectByArticle struct {
+	IndustrialSubjectId    int    `description:"标的id"`
+	IndustrialManagementId int    `description:"产业id"`
+	SubjectName            string `description:"标的名称"`
+	IndustryName           string `description:"产业名称"`
+	ArticleId              int    `description:"文章ID"`
+}
+type SubjectArticlGroupList struct {
+	SubjectName         string `description:"标的名称"`
+	ArticleId           int    `description:"cygx_article表的文章ID"`
+	IndustrialSubjectId int    `description:"cygx_industrial_subject表的文章ID"`
+}
+
+// 获取标的列表
+func GetArticleGroupSubjectList(pars []interface{}, condition string) (items []*IndustrialSubjectByArticle, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT
+			s.subject_name,
+			s.industrial_subject_id,
+			s.industrial_management_id,
+			g.article_id 
+		FROM
+			cygx_industrial_article_group_subject AS g
+			INNER JOIN cygx_industrial_subject AS s ON s.industrial_subject_id = g.industrial_subject_id 
+		WHERE
+			1 = 1 ` + condition
+	_, err = o.Raw(sql, pars).QueryRows(&items)
+	return
+}
+
+// 列表
+func GetSubjectArticlGroupList(condition string, pars []interface{}) (items []*SubjectArticlGroupList, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT
+			 s.subject_name,
+			 s.industrial_subject_id,
+			 ag.article_id
+		FROM
+			cygx_industrial_article_group_subject AS ag
+			INNER JOIN cygx_industrial_subject AS s ON s.industrial_subject_id = ag.industrial_subject_id
+			WHERE 1= 1  ` + condition
+	_, err = o.Raw(sql, pars).QueryRows(&items)
+	return
+}
+
+func GetcygxIndustrialSubject(industrialManagementId int) (items []*IndustrialSubject, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT subject_name,industrial_subject_id FROM cygx_industrial_subject  WHERE industrial_management_id = ?`
+	_, err = o.Raw(sql, industrialManagementId).QueryRows(&items)
+	return
+}

+ 11 - 0
models/micro_roadshow.go

@@ -462,3 +462,14 @@ func GetMicroRoadShowVideoPageListIkWord(startSize, pageSize int, condition stri
 	_, err = o.Raw(sql, pars, parsAct, parsAudio, startSize, pageSize).QueryRows(&list)
 	return
 }
+
+type AddVideoCommnetReq struct {
+	Id         int    `description:"活动或产业ID"`
+	SourceType int    `description:"视频来源: 1-音频; 2-活动视频; 3-微路演视频 (不传默认为1)"`
+	Content    string `description:"内容"`
+	Title      string `description:"标题"`
+}
+type MicroRoadshowCollectReq struct {
+	Id         int `description:"音频或视频ID"`
+	SourceType int `description:"视频来源: 1-音频; 2-活动视频; 3-微路演视频 (不传默认为1)"`
+}

+ 26 - 1
models/page_history_record.go

@@ -2,6 +2,7 @@ package models
 
 import (
 	"github.com/beego/beego/v2/client/orm"
+	"strconv"
 	"time"
 )
 
@@ -17,6 +18,9 @@ type CygxPageHistoryRecord struct {
 	ChartPermissionId      int       `description:"行业ID"`
 	IndustrialManagementId string    `description:"产业ID"`
 	PageType               string    `description:"页面类型,纪要:Summary,纪要搜索:SummarySearch,报告:Report,报告搜索:ReportSearch,产业列表:IndustryList,活动:Activit,活动搜索:ActivitSearch,活动详情:ActivitParticulars,报告详情:ReportParticulars,已结束活动:OverActivity"`
+	Parameter              string    `description:"参数"`
+	Router                 string    `description:"路由"`
+	PageRouter             string    `description:"前端页面路径"`
 }
 
 type CygxPageHistoryRecordRep struct {
@@ -36,9 +40,30 @@ type CygxPageHistoryRecordHtgjRep struct {
 	Sign                   string `description:"签名"`
 }
 
-//添加
+// 添加
 func AddCygxPageHistoryRecord(item *CygxPageHistoryRecord) (lastId int64, err error) {
 	o := orm.NewOrm()
 	lastId, err = o.Insert(item)
 	return
 }
+
+func GetTimeLineRecordCount(userId, industrialManagementId int) (count int, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT COUNT(1) AS count FROM cygx_page_history_record WHERE user_id=? AND router = '/api/report/industry/ArticleList?PageSize=10&CurrentIndex=1&CategoryId=99999&IndustrialManagementId=` + strconv.Itoa(industrialManagementId) + `'`
+	err = o.Raw(sql, userId).QueryRow(&count)
+	return
+}
+
+func GetTimeLineRecordItem(userId, industrialManagementId int) (item *CygxPageHistoryRecord, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT * FROM cygx_page_history_record WHERE user_id=? AND router = '/api/report/industry/ArticleList?PageSize=10&CurrentIndex=1&CategoryId=99999&IndustrialManagementId=` + strconv.Itoa(industrialManagementId) + `' ORDER BY create_time DESC LIMIT 1,1 `
+	err = o.Raw(sql, userId).QueryRow(&item)
+	return
+}
+
+func GetTimeLineRecordAllCount(userId int, date string) (items []*CygxPageHistoryRecord, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT * FROM cygx_page_history_record WHERE user_id=? AND router LIKE '%/api/report/industry/ArticleList?PageSize=10&CurrentIndex=1&CategoryId=99999&IndustrialManagementId=%' AND create_time > ?  	ORDER BY  id  DESC  LIMIT 10 `
+	_, err = o.Raw(sql, userId, date).QueryRows(&items)
+	return
+}

+ 469 - 45
models/report.go

@@ -5,6 +5,7 @@ import (
 	"github.com/rdlucklib/rdluck_tools/paging"
 	"hongze/hongze_clpt/utils"
 	"strconv"
+	"time"
 )
 
 type IndustrialManagementList struct {
@@ -51,32 +52,27 @@ type TacticsListResp struct {
 	List             []*HomeArticle
 }
 
-//报告搜索start
+type TacticsListTimeResp struct {
+	Paging           *paging.PagingItem
+	MatchTypeName    string `description:"匹配类型"`
+	CategoryImgUrlPc string `description:"图片"`
+	List             []*TimeLineReportItem
+}
+
+// 报告搜索start
 type ReoprtSearchResp struct {
 	Paging *paging.PagingItem
-	ListHz []*ArticleCollectionResp `description:"弘则报告"`
+	ListHz []*ArticleResearchResp `description:"弘则报告"`
+	ListYx []*ArticleResearchResp `description:"研选报告"`
 }
 
-//搜索资源包 start
+// 搜索资源包 start
 type SearchResourceResp struct {
 	ListHz []*IndustrialManagement `description:"弘则"`
+	ListYx []*IndustrialManagement `description:"研选"`
 }
 
-//用户收藏榜start
-//type IndustrialManagementHotResp struct {
-//	IndustrialManagementId int                  `orm:"column(industrial_management_id);pk" description:"产业id"`
-//	IndustryName           string               `description:"产业名称"`
-//	IsFollw                bool                 `description:"是否关注"`
-//	FllowNum               int                  `description:"关注数量"`
-//	IsNew                  bool                 `description:"是否新标签"`
-//	IsHot                  bool                 `description:"是否新标签"`
-//	PublishDate            string               `description:"发布时间"`
-//	ArticleReadNum         int                  `description:"文章阅读数量"`
-//	Source                 int                  `description:"来源 1:弘则资源包(报告)、2:研选主题(报告)"`
-//	IndustrialSubjectList  []*IndustrialSubject `description:"标的列表"`
-//}
-
-//获取列表数量
+// 获取列表数量
 func GetReoprtSearchCount(condition string) (count int, err error) {
 	o := orm.NewOrm()
 	sql := `SELECT
@@ -93,7 +89,42 @@ func GetReoprtSearchCount(condition string) (count int, err error) {
 	return
 }
 
-//列表
+func GetReoprtSearchCountYx(condition string) (count int, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT
+			COUNT( 1 ) AS count 
+		FROM
+			cygx_article AS a 
+			INNER JOIN cygx_industrial_article_group_management AS mg ON mg.article_id = a.article_id
+			INNER JOIN cygx_industrial_management AS m ON m.industrial_management_id = mg.industrial_management_id
+			INNER JOIN cygx_article_department AS d ON d.department_id = a.department_id 
+		WHERE
+			1 = 1`
+	if condition != "" {
+		sql += condition
+	}
+	err = o.Raw(sql).QueryRow(&count)
+	return
+}
+
+func GetReoprtSearchCountHz(condition string) (count int, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT
+			COUNT( 1 ) AS count 
+		FROM
+			cygx_article AS a 
+			INNER JOIN cygx_industrial_article_group_management AS mg ON mg.article_id = a.article_id
+			INNER JOIN cygx_industrial_management AS m ON m.industrial_management_id = mg.industrial_management_id
+		WHERE
+			1 = 1`
+	if condition != "" {
+		sql += condition
+	}
+	err = o.Raw(sql).QueryRow(&count)
+	return
+}
+
+// 列表
 func GetReoprtSearchList(condition string, userId, startSize, pageSize int) (items []*ArticleCollectionResp, err error) {
 	o := orm.NewOrm()
 	sql := `SELECT
@@ -124,7 +155,7 @@ func GetReoprtSearchList(condition string, userId, startSize, pageSize int) (ite
 	return
 } //end
 
-//列表
+// 列表
 func GetSearchResourceList(condition string) (items []*IndustrialManagement, err error) {
 	o := orm.NewOrm()
 	sql := `SELECT
@@ -145,7 +176,7 @@ func GetSearchResourceList(condition string) (items []*IndustrialManagement, err
 	return
 }
 
-//标的列表
+// 标的列表
 func GetThemeHeatSubjectList(condition string) (items []*IndustrialSubject, err error) {
 	o := orm.NewOrm()
 	sql := `SELECT
@@ -170,7 +201,7 @@ func GetThemeHeatSubjectList(condition string) (items []*IndustrialSubject, err
 	return
 } //end
 
-//产业下所关联的文章分类列表
+// 产业下所关联的文章分类列表
 func IndustrialToArticleCategory(industrialManagementId, chartPermissionId int) (items []*IndustrialToArticleCategoryRep, err error) {
 	o := orm.NewOrm()
 	sql := `SELECT map.match_type_name,map.category_id
@@ -188,7 +219,7 @@ func IndustrialToArticleCategory(industrialManagementId, chartPermissionId int)
 	return
 }
 
-//判断用户是否阅读该产业下,某一分类的文章
+// 判断用户是否阅读该产业下,某一分类的文章
 func IndustrialUserRecordArticleCount(userId, industrialManagementId, categoryId int) (count int, err error) {
 	o := orm.NewOrm()
 	sql := `SELECT
@@ -196,21 +227,33 @@ func IndustrialUserRecordArticleCount(userId, industrialManagementId, categoryId
 FROM
 	cygx_article_history_record 
 WHERE
-	article_id = ( SELECT article_id FROM cygx_article WHERE article_id IN (SELECT article_id FROM cygx_industrial_article_group_management WHERE industrial_management_id = ? ) AND category_id = ? ORDER BY publish_date DESC LIMIT 0, 1 ) 
+	article_id = ( SELECT article_id FROM cygx_article WHERE article_id IN (SELECT article_id FROM cygx_industrial_article_group_management WHERE industrial_management_id = ? )  	AND article_id < 1000000 AND category_id  IN (SELECT
+	category_id 
+FROM
+	cygx_report_mapping 
+WHERE
+	chart_permission_id = any( SELECT chart_permission_id FROM cygx_report_mapping WHERE category_id = ? ) 
+	AND match_type_name = any( SELECT match_type_name FROM cygx_report_mapping WHERE category_id = ? ) ) ORDER BY publish_date DESC LIMIT 0, 1 )
 	AND user_id = ? `
-	err = o.Raw(sql, industrialManagementId, categoryId, userId).QueryRow(&count)
+	err = o.Raw(sql, industrialManagementId, categoryId, categoryId, userId).QueryRow(&count)
 	return
 }
 
-//获取最新文章
+// 获取最新文章
 func GetNewIndustrialUserRecordArticle(industrialManagementId, categoryId int) (item *ArticleDetail, err error) {
 	o := orm.NewOrm()
-	sql := ` SELECT * FROM cygx_article WHERE article_id IN (SELECT article_id FROM cygx_industrial_article_group_management WHERE industrial_management_id = ? ) AND category_id = ? ORDER BY publish_date DESC LIMIT 0, 1`
-	err = o.Raw(sql, industrialManagementId, categoryId).QueryRow(&item)
+	sql := ` SELECT * FROM cygx_article WHERE article_id IN (SELECT article_id FROM cygx_industrial_article_group_management WHERE industrial_management_id = ? ) AND category_id  IN (SELECT
+	category_id 
+FROM
+	cygx_report_mapping 
+WHERE
+	chart_permission_id = any( SELECT chart_permission_id FROM cygx_report_mapping WHERE category_id = ? ) 
+	AND match_type_name = any( SELECT match_type_name FROM cygx_report_mapping WHERE category_id = ? ) ) ORDER BY publish_date DESC LIMIT 0, 1`
+	err = o.Raw(sql, industrialManagementId, categoryId, categoryId).QueryRow(&item)
 	return
 }
 
-//列表
+// 列表
 func GetReoprtSearchListHz(condition string, userId int) (items []*ArticleCollectionResp, err error) {
 	o := orm.NewOrm()
 	sql := `SELECT
@@ -236,7 +279,7 @@ func GetReoprtSearchListHz(condition string, userId int) (items []*ArticleCollec
 	return
 } //end
 
-//产业列表
+// 产业列表
 func GetSearchResourceListHz(condition string, startSize, pageSize int) (items []*IndustrialManagementHotResp, err error) {
 	o := orm.NewOrm()
 	sql := `SELECT
@@ -259,28 +302,29 @@ func GetSearchResourceListHz(condition string, startSize, pageSize int) (items [
 	return
 }
 
-//用户收藏榜start
+// 用户收藏榜start
 type IndustrialManagementHotResp struct {
 	IndustrialManagementId int                  `orm:"column(industrial_management_id);pk" description:"产业id"`
 	IndustryName           string               `description:"产业名称"`
-	IsFollw                bool                 `description:"是否关注"`
+	IsFollow               bool                 `description:"是否关注"`
 	FllowNum               int                  `description:"关注数量"`
 	IsNew                  bool                 `description:"是否新标签"`
 	IsHot                  bool                 `description:"是否新标签"`
 	PublishDate            string               `description:"发布时间"`
 	ArticleReadNum         int                  `description:"文章阅读数量"`
 	Source                 int                  `description:"来源 1:弘则资源包(报告)、2:研选主题(报告)"`
+	MinReportTime          string               `description:"报告最早发布时间"`
 	IndustrialSubjectList  []*IndustrialSubject `description:"标的列表"`
 }
 
-//搜索资源包 start
+// 搜索资源包 start
 type SearchReportAndResourceResp struct {
 	ListHzResource []*IndustrialManagement  `description:"弘则资源包"`
 	ListHzReport   []*ArticleCollectionResp `description:"弘则报告"`
 	Paging         *paging.PagingItem       `description:"弘则报告分页"`
 }
 
-//报告收藏榜单列表
+// 报告收藏榜单列表
 func GetReportCollectionBillboardList(limit int, pars []interface{}, condition string) (items []*ArticleListResp, err error) {
 	o := orm.NewOrm()
 	sql := `SELECT
@@ -308,35 +352,45 @@ func GetReportCollectionBillboardList(limit int, pars []interface{}, condition s
 	return
 }
 
-//研选报告收藏榜单列表
+// 研选报告收藏榜单列表
 func GetReportCollectionBillboardListYx(limit int, pars []interface{}, condition string) (items []*ArticleListResp, err error) {
 	o := orm.NewOrm()
 	sql := `SELECT
 			ac.id,
-			a.article_id,
 			a.category_id,
+			'买方研选' as chart_permission_name,
+			a.article_id,
 			a.title,
+			a.body,
 			a.annotation,
+			a.abstract,
 			a.publish_date,
-			'买方研选' as chart_permission_name,
-			COUNT(ac.id) AS collection_num
+			a.article_type_id,
+			d.nick_name,
+			d.department_id,
+			( SELECT count( 1 ) FROM cygx_article_history_record_newpv AS h WHERE h.article_id = a.article_id ) AS pv,
+			( SELECT count( 1 ) FROM cygx_article_collect AS ac  INNER JOIN wx_user as u ON  u.user_id = ac.user_id  WHERE ac.article_id = a.article_id  ) AS collect_num, 
+			( SELECT count( 1 ) FROM cygx_article_collect AS ac  INNER JOIN wx_user as u ON  u.user_id = ac.user_id  WHERE ac.article_id = a.article_id AND DATE_SUB( CURDATE(), INTERVAL 30 DAY ) <= date( ac.create_time )  ) AS collection_num
 		FROM
 			cygx_article AS a
 			INNER JOIN cygx_article_collect AS ac ON ac.article_id = a.article_id 
+			INNER JOIN cygx_industrial_article_group_management AS mg ON mg.article_id = a.article_id
+			INNER JOIN cygx_industrial_management AS m ON m.industrial_management_id = mg.industrial_management_id
+			INNER JOIN cygx_article_department AS d ON d.department_id = a.department_id 
 		WHERE
 			1 = 1 
-			AND a.publish_status = 1  AND a.article_id >= ` + strconv.Itoa(utils.SummaryArticleId)
+			AND a.publish_status = 1  `
 	if condition != "" {
 		sql += condition
 	}
-	sql += ` GROUP BY a.article_id ORDER BY collection_num DESC, ac.id DESC, a.publish_date DESC`
+	sql += ` GROUP BY a.article_id ORDER BY collection_num DESC,  a.publish_date DESC`
 	sql += ` LIMIT ?`
 	_, err = o.Raw(sql, pars, limit).QueryRows(&items)
 	return
 }
 
-//获取产业报告+晨会点评列表
-func GetTimeLineReportIndustrialList(industrialManagementId, startSize, pageSize int) (items []*HomeArticle, total int, err error) {
+// 获取产业报告+晨会点评列表
+func GetTimeLineReportIndustrialList(industrialManagementId, startSize, pageSize int) (items []*ArticleListResp, total int, err error) {
 	o := orm.NewOrm()
 	sql := `SELECT
 			a.id,
@@ -369,12 +423,120 @@ func GetTimeLineReportIndustrialList(industrialManagementId, startSize, pageSize
 	return
 }
 
+type TimeLineReportItem struct {
+	Id        int    `description:"文章或晨报点评id"`
+	ArticleId int    `description:"文章id"`
+	Title     string `description:"标题"`
+	//PublishTime     string `description:"发布时间"`
+	PublishDate     string `description:"发布时间"`
+	Content         string `description:"内容"`
+	VideoUrl        string `description:"视频链接"`
+	IsHaveVideo     bool   `description:"是否包含视频"`
+	ImgUrlPc        string `description:"pc图片"`
+	SubCategoryName string `description:"二级分类"`
+	IsRed           bool   `description:"是否标红"`
+	Readnum         int    `description:"阅读数量"`
+}
+
+// 获取产业报告+晨会点评列表
+func GetTimeLineReportIndustrialListTime(userId, industrialManagementId, startSize, pageSize int) (items []*TimeLineReportItem, total int, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT
+	* 
+FROM
+	(
+		SELECT
+		a.article_id AS id,
+		a.article_id,
+		a.title,
+		a.publish_date,
+		a.video_url,
+		a.sub_category_name,
+		'' AS content,
+		( SELECT COUNT( 1 ) FROM cygx_article_history_record AS rec WHERE rec.user_id = ` + strconv.Itoa(userId) + ` AND rec.article_id = a.article_id ) AS readnum 
+	FROM
+		cygx_article AS a
+		INNER JOIN cygx_industrial_article_group_management AS man_g ON man_g.article_id = a.article_id 
+	WHERE
+		a.publish_status = 1 
+		AND a.is_class = 1 
+		AND man_g.industrial_management_id = ? GROUP BY id UNION ALL
+	SELECT
+		mmc.id,
+		0 as  article_id,
+		mmc.content AS title,
+		mm.publish_time AS publish_date,
+		'' AS video_url,
+		'时间线' AS sub_category_name,
+		'' AS content,
+		0  AS readnum 
+	FROM
+		cygx_morning_meeting_review_chapter AS mmc
+		INNER JOIN cygx_morning_meeting_reviews AS mm 
+	WHERE
+		mm.id = mmc.meeting_id 
+		AND mm.STATUS = 1 
+		AND mmc.industry_id = ? 
+	) AS t`
+	totalSql := `SELECT COUNT(1) total FROM (` + sql + `) z `
+	err = o.Raw(totalSql, industrialManagementId, industrialManagementId).QueryRow(&total)
+	sql += ` ORDER BY 
+	t.publish_date DESC LIMIT ?,? `
+	_, err = o.Raw(sql, industrialManagementId, industrialManagementId, startSize, pageSize).QueryRows(&items)
+	return
+}
+
+// 获取产业报告+晨会点评列表
+func GetTimeLineReportIndustrialListRed(userId, industrialManagementId, startSize, pageSize int) (items []*TimeLineReportItem, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT
+	* 
+FROM
+	(
+		SELECT
+		a.article_id AS id,
+		a.title,
+		a.publish_date ,
+		a.video_url,
+		a.sub_category_name,
+		'' AS content,
+		( SELECT COUNT( 1 ) FROM cygx_article_history_record AS rec WHERE rec.user_id = ` + strconv.Itoa(userId) + ` AND rec.article_id = a.article_id ) AS readnum 
+	FROM
+		cygx_article AS a
+		INNER JOIN cygx_industrial_article_group_management AS man_g ON man_g.article_id = a.article_id 
+	WHERE
+		a.publish_status = 1 
+		AND a.is_class = 1 
+		AND man_g.industrial_management_id = ? GROUP BY id UNION ALL
+	SELECT
+		mmc.id,
+		'' AS title,
+		mm.publish_time AS publish_date,
+		'' AS video_url,
+		'时间线' AS sub_category_name,
+		mmc.content,
+		0  AS readnum 
+	FROM
+		cygx_morning_meeting_review_chapter AS mmc
+		INNER JOIN cygx_morning_meeting_reviews AS mm 
+	WHERE
+		mm.id = mmc.meeting_id 
+		AND mm.STATUS = 1 
+		AND mmc.industry_id = ? 
+	) AS t 
+`
+	sql += ` ORDER BY 
+	t.publish_date DESC LIMIT ?,? `
+	_, err = o.Raw(sql, industrialManagementId, industrialManagementId, startSize, pageSize).QueryRows(&items)
+	return
+}
+
 type IndustrialPublishdate struct {
 	PublishDate            string `description:"发布时间"`
 	IndustrialManagementId int    `description:"产业D"`
 }
 
-//标的列表
+// 标的列表
 func GetTimeLineReportIndustrialPublishdateList(industrialIdArr []int) (items []*IndustrialPublishdate, err error) {
 	o := orm.NewOrm()
 	sql := `SELECT	
@@ -395,7 +557,7 @@ func GetTimeLineReportIndustrialPublishdateList(industrialIdArr []int) (items []
 	return
 }
 
-//报告榜单start
+// 报告榜单start
 type ArticleReportBillboardResp struct {
 	ArticleId      int    `description:"文章id"`
 	Title          string `description:"标题"`
@@ -413,4 +575,266 @@ type ArticleReportBillboardResp struct {
 type ArticleReportBillboardLIstPageResp struct {
 	List   []*ArticleReportBillboardResp
 	Paging *paging.PagingItem
-}
+}
+
+type ArticleResearchListResp struct {
+	Paging *paging.PagingItem
+	List   []*ArticleResearchResp
+}
+
+type ArticleResearchResp struct {
+	ArticleId       int                          `description:"文章id"`
+	Title           string                       `description:"标题"`
+	Annotation      string                       `description:"核心观点"`
+	Abstract        string                       `description:"摘要"`
+	PublishDate     string                       `description:"发布时间"`
+	DepartmentId    int                          `description:"作者Id"`
+	NickName        string                       `description:"作者昵称"`
+	IsCollect       bool                         `description:"本人是否收藏"`
+	Pv              int                          `description:"PV"`
+	CollectNum      int                          `description:"收藏人数"`
+	Source          int                          `description:"来源 1:弘则资源包(报告)、2:研选主题(报告)"`
+	ArticleTypeId   int                          `description:"文章类型ID"`
+	ArticleTypeName string                       `description:"类型名称"`
+	ButtonStyle     string                       `description:"按钮展示样式"`
+	ImgUrlPc        string                       `description:"图片链接"`
+	List            []*IndustrialManagementIdInt `description:"产业列表"`
+	ListSubject     []*IndustrialSubject         `description:"标的列表"`
+}
+
+// 获取数量
+func GetArticleResearchCount(condition string, pars []interface{}) (count int, err error) {
+	o := orm.NewOrm()
+	sqlCount := `SELECT COUNT( 1 ) AS count FROM
+			cygx_article AS a
+		WHERE
+			1 = 1  AND a.publish_status = 1` + condition
+	err = o.Raw(sqlCount, pars).QueryRow(&count)
+	return
+}
+
+func GetArticleResearchList(condition string, pars []interface{}, startSize, pageSize, userId int) (items []*ArticleListResp, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT
+			a.article_id,
+			a.title,
+			a.body,
+			a.annotation,
+			a.abstract,
+			a.publish_date,
+			a.article_type_id,
+			d.nick_name,
+			d.department_id,
+			( SELECT count( 1 ) FROM cygx_article_history_record_newpv AS h WHERE h.article_id = a.article_id ) AS pv,
+			( SELECT count( 1 ) FROM cygx_article_collect AS ac  INNER JOIN wx_user as u ON  u.user_id = ac.user_id  WHERE ac.article_id = a.article_id  ) AS collect_num, 
+			( SELECT count( 1 ) FROM cygx_article_collect AS ac  INNER JOIN wx_user as u ON  u.user_id = ac.user_id  WHERE ac.article_id = a.article_id AND DATE_SUB( CURDATE(), INTERVAL 30 DAY ) <= date( ac.create_time )  ) AS collect_num_order, 
+			( SELECT count( 1 ) FROM cygx_article_collect AS ac WHERE ac.article_id = a.article_id  AND user_id = ? ) AS my_collect_num
+		FROM
+			cygx_article AS a
+			INNER JOIN cygx_industrial_article_group_management AS mg ON mg.article_id = a.article_id
+			INNER JOIN cygx_industrial_management AS m ON m.industrial_management_id = mg.industrial_management_id
+			INNER JOIN cygx_article_department AS d ON d.department_id = a.department_id 
+		WHERE
+			1 = 1  AND a.publish_status = 1  `
+	if condition != "" {
+		sql += condition
+	}
+	sql += ` GROUP BY a.article_id ORDER  BY   a.publish_date DESC  LIMIT ?,? `
+	_, err = o.Raw(sql, userId, pars, startSize, pageSize).QueryRows(&items)
+	return
+}
+
+func GetArticleResearchListHz(condition string, pars []interface{}, startSize, pageSize, userId int) (items []*ArticleListResp, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT
+			a.article_id,
+			a.title,
+			a.body,
+			a.annotation,
+			a.abstract,
+			a.publish_date,
+			a.category_id,
+			a.article_type_id,
+			( SELECT count( 1 ) FROM cygx_article_history_record_newpv AS h WHERE h.article_id = a.article_id ) AS pv,
+			( SELECT count( 1 ) FROM cygx_article_collect AS ac  INNER JOIN wx_user as u ON  u.user_id = ac.user_id  WHERE ac.article_id = a.article_id  ) AS collect_num, 
+			( SELECT count( 1 ) FROM cygx_article_collect AS ac  INNER JOIN wx_user as u ON  u.user_id = ac.user_id  WHERE ac.article_id = a.article_id AND DATE_SUB( CURDATE(), INTERVAL 30 DAY ) <= date( ac.create_time )  ) AS collect_num_order, 
+			( SELECT count( 1 ) FROM cygx_article_collect AS ac WHERE ac.article_id = a.article_id  AND user_id = ? ) AS my_collect_num
+		FROM
+			cygx_article AS a
+			INNER JOIN cygx_industrial_article_group_management AS mg ON mg.article_id = a.article_id
+			INNER JOIN cygx_industrial_management AS m ON m.industrial_management_id = mg.industrial_management_id
+		WHERE
+			1 = 1  AND a.publish_status = 1  `
+	if condition != "" {
+		sql += condition
+	}
+	sql += ` GROUP BY a.article_id ORDER  BY   a.publish_date DESC  LIMIT ?,? `
+	_, err = o.Raw(sql, userId, pars, startSize, pageSize).QueryRows(&items)
+	return
+}
+
+type IndustrialManagementHotListResp struct {
+	Paging *paging.PagingItem `description:"分页数据"`
+	List   []*IndustrialManagementHotResp
+}
+
+// 获取数量
+func GetThemeHeatListCount(condition string) (count int, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT   COUNT( DISTINCT m.industrial_management_id ) FROM
+			cygx_industrial_management AS m
+			LEFT JOIN cygx_industrial_article_group_management AS mg ON mg.industrial_management_id = m.industrial_management_id
+			LEFT JOIN cygx_article AS a ON a.article_id = mg.article_id 
+			LEFT JOIN cygx_industrial_activity_group_management as ag ON ag.industrial_management_id = mg.industrial_management_id
+		WHERE
+			1 = 1 AND a.publish_status = 1  ` + condition
+	err = o.Raw(sql).QueryRow(&count)
+	return
+}
+
+// 产业列表
+func GetThemeHeatList(userId int, condition, conditionOrder string, startSize, pageSize int) (items []*IndustrialManagementHotResp, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT
+			m.industry_name,
+			m.industrial_management_id,
+			m.article_read_num,
+          	MAX( a.publish_date ) AS publish_date,
+			MIN(a.publish_date) AS min_report_time,
+			( SELECT count( 1 ) FROM cygx_industry_fllow AS f  WHERE f.industrial_management_id = m.industrial_management_id  AND user_id =? AND f.type = 1  ) AS fllow_num,
+			m.yanxuan_article_read_num + m.activity_num AS sum_num
+		FROM
+			cygx_industrial_management AS m
+			LEFT JOIN cygx_industrial_article_group_management AS mg ON mg.industrial_management_id = m.industrial_management_id
+			LEFT JOIN cygx_article AS a ON a.article_id = mg.article_id 
+			LEFT JOIN cygx_industrial_activity_group_management as ag ON ag.industrial_management_id = mg.industrial_management_id
+		WHERE
+			1 = 1
+			AND publish_status = 1  ` + condition + `  GROUP BY m.industrial_management_id ` + conditionOrder + ` , last_updated_time  DESC LIMIT ?,?`
+	_, err = o.Raw(sql, userId, startSize, pageSize).QueryRows(&items)
+	return
+}
+
+type GetThemeAericleListResp struct {
+	ArticleId           int    `description:"文章id"`
+	Title               string `description:"标题"`
+	PublishDate         string `description:"发布时间"`
+	SubjectName         string `description:"标的名称"`
+	IndustrialSubjectId int    `description:"标的ID"`
+	DepartmentId        int    `description:"作者Id"`
+	NickName            string `description:"作者昵称"`
+	Pv                  int    `description:"PV"`
+	CollectNum          int    `description:"收藏人数"`
+	FllowNum            int    `description:"关注数量"`
+	MyCollectNum        int    `description:"本人是否收藏"`
+	IsCollect           bool   `description:"本人是否收藏"`
+}
+
+// 主题详情start
+type GetThemeDetailResp struct {
+	IndustrialManagementId int                  `description:"产业Id"`
+	IndustryName           string               `description:"产业名称"`
+	IsFollow               bool                 `description:"是否关注"`
+	ListSubject            []*IndustrialSubject `description:"标的列表"`
+	List                   []*ArticleResearchResp
+}
+
+// 主题详情start
+type GetThemeDetailListResp struct {
+	ArticleId              int    `description:"文章id"`
+	Title                  string `description:"标题"`
+	PublishDate            string `description:"发布时间"`
+	SubjectName            string `description:"标的名称"`
+	IndustrialSubjectId    int    `description:"标的id"`
+	DepartmentId           int    `description:"作者Id"`
+	NickName               string `description:"作者昵称"`
+	Pv                     int    `description:"PV"`
+	CollectNum             int    `description:"收藏人数"`
+	IndustrialManagementId int    `description:"产业Id"`
+	IndustryName           string `description:"产业名称"`
+	FllowNum               int    `description:"关注数量"`
+	MyCollectNum           int    `description:"本人是否收藏"`
+	IsCollect              bool   `description:"本人是否收藏"`
+}
+
+type GetThemeAericleListBuSubjectResp struct {
+	SubjectName string `description:"标的名称"`
+	List        []*GetThemeAericleListResp
+}
+
+// 列表
+func GetThemeDetail(userId, industrialManagementId int, condition string) (items []*ArticleListResp, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT
+			a.article_id,
+			a.title,
+			a.body,
+			a.annotation,
+			a.abstract,
+			a.publish_date,
+			a.article_type_id,
+			d.nick_name,
+			d.department_id,
+			( SELECT count( 1 ) FROM cygx_article_history_record_newpv AS h WHERE h.article_id = a.article_id ) AS pv,
+			( SELECT count( 1 ) FROM cygx_article_collect AS ac WHERE ac.article_id = a.article_id ) AS collect_num,
+			( SELECT count( 1 ) FROM cygx_article_collect AS ac WHERE ac.article_id = a.article_id and user_id = ? ) AS my_collect_num
+		FROM
+			cygx_article AS a
+			INNER JOIN cygx_industrial_article_group_management AS mg ON mg.article_id = a.article_id
+			INNER JOIN cygx_industrial_management AS m ON m.industrial_management_id = mg.industrial_management_id
+			INNER JOIN cygx_article_department AS d ON d.department_id = a.department_id
+		WHERE
+			1 = 1
+			AND m.industrial_management_id = ? 
+			AND publish_status = 1 ` + condition + `
+		ORDER BY
+			publish_date DESC`
+	_, err = o.Raw(sql, userId, industrialManagementId).QueryRows(&items)
+	return
+} //end
+
+func GetDepartmentlistCount(condition string) (count int, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT
+	count(*) AS count 
+FROM
+	(
+	SELECT
+		COUNT( 1 ) AS count 
+	FROM
+		cygx_article_department AS d
+		INNER JOIN cygx_article AS a ON d.department_id = a.department_id 
+	WHERE
+		1 = 1 
+		AND a.article_type_id > 0 
+		AND publish_status = 1 
+	GROUP BY
+	d.department_id 
+	) c `
+	err = o.Raw(sql).QueryRow(&count)
+	return
+}
+
+type IndustrialReadNum struct {
+	IndustrialManagementId int `description:"产业id"`
+	Readnum                int `description:"阅读次数"`
+}
+
+// 获取该产业下文章的用户阅读次数-小红点用
+func GetReportIndustrialReadNumList(userId int, industrialIds string, createtime time.Time) (items []*IndustrialReadNum, err error) {
+	o := orm.NewOrm()
+	sql := `SELECT a.industrial_management_id, MIN(a.readnum) AS readnum FROM (
+SELECT man_g.industrial_management_id,( SELECT COUNT( 1 ) FROM cygx_article_history_record AS rec WHERE rec.user_id = ` + strconv.Itoa(userId) + ` AND rec.article_id = a.article_id ) AS readnum 
+FROM
+	cygx_article AS a 
+	INNER JOIN cygx_industrial_article_group_management as man_g ON man_g.article_id = a.article_id
+WHERE
+	a.publish_status = 1 
+	AND a.is_class = 1
+	AND man_g.industrial_management_id IN (` + industrialIds + `)  
+	AND a.publish_date > ? 
+GROUP BY a.article_id ORDER BY publish_date DESC
+) AS a GROUP BY industrial_management_id`
+	_, err = o.Raw(sql, createtime).QueryRows(&items)
+	return
+}

+ 17 - 14
models/report_mapping.go

@@ -2,6 +2,7 @@ package models
 
 import (
 	"github.com/beego/beego/v2/client/orm"
+	"strconv"
 )
 
 type ReportMapping struct {
@@ -14,6 +15,7 @@ type ReportMapping struct {
 	PermissionType      int    `description:"1主观,2客观"`
 	CategoryIdSet       int    `description:"分类映射id"`
 	PolymerizationId    string `description:"分类聚合ID"`
+	CeLueFieldId        string `description:"策略平台领域ID"`
 }
 
 type ReportMappingHome struct {
@@ -56,22 +58,23 @@ func GetReportMappingStrategyAll() (items []*ReportMapping, err error) {
 }
 
 // 获取策略下面的所有分类
-func GetReportMappingStrategyHomeAll() (items []*TradeReportMapping, err error) {
+func GetReportMappingStrategyHomeAll(userId, ChartPermissionId int) (items []*TradeReportMapping, err error) {
 	o := orm.NewOrm()
 	sql := `SELECT
-MAX( art.publish_date ) AS update_time,
-	re.category_id,re.sub_category_name,re.match_type_name
-FROM
-	cygx_report_mapping AS re
-	INNER JOIN cygx_article AS art ON art.category_id = re.category_id 
-WHERE
-	re.report_type = 1 
-	AND re.chart_permission_id = 23 
-GROUP  BY
-	re.match_type_name
-ORDER BY
-	sort DESC , art.publish_date DESC`
-	_, err = o.Raw(sql).QueryRows(&items)
+			MAX( art.publish_date ) AS update_time,
+			(SELECT COUNT(1) FROM cygx_article_history_record AS rec WHERE rec.user_id = ` + strconv.Itoa(userId) + ` AND  rec.article_id=art.article_id) AS readnum,
+			re.category_id,re.sub_category_name,re.match_type_name
+			FROM
+				cygx_report_mapping AS re
+				INNER JOIN cygx_article AS art ON art.category_id = re.category_id 
+			WHERE
+				re.report_type = 1 
+				AND re.chart_permission_id = ? 
+			GROUP  BY
+				re.match_type_name
+			ORDER BY
+				sort DESC , art.publish_date DESC`
+	_, err = o.Raw(sql, ChartPermissionId).QueryRows(&items)
 	return
 }
 

+ 105 - 6
routers/commentsRouter.go

@@ -259,6 +259,24 @@ func init() {
             Filters: nil,
             Params: nil})
 
+    beego.GlobalControllerRouter["hongze/hongze_clpt/controllers:MicroRoadShowController"] = append(beego.GlobalControllerRouter["hongze/hongze_clpt/controllers:MicroRoadShowController"],
+        beego.ControllerComments{
+            Method: "Collect",
+            Router: `/collect`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["hongze/hongze_clpt/controllers:MicroRoadShowController"] = append(beego.GlobalControllerRouter["hongze/hongze_clpt/controllers:MicroRoadShowController"],
+        beego.ControllerComments{
+            Method: "CommentAdd",
+            Router: `/comment/add`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
     beego.GlobalControllerRouter["hongze/hongze_clpt/controllers:MicroRoadShowController"] = append(beego.GlobalControllerRouter["hongze/hongze_clpt/controllers:MicroRoadShowController"],
         beego.ControllerComments{
             Method: "Detail",
@@ -367,6 +385,15 @@ func init() {
             Filters: nil,
             Params: nil})
 
+    beego.GlobalControllerRouter["hongze/hongze_clpt/controllers:MobileReportController"] = append(beego.GlobalControllerRouter["hongze/hongze_clpt/controllers:MobileReportController"],
+        beego.ControllerComments{
+            Method: "Timeline",
+            Router: `/timeline`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
     beego.GlobalControllerRouter["hongze/hongze_clpt/controllers:MobileReportController"] = append(beego.GlobalControllerRouter["hongze/hongze_clpt/controllers:MobileReportController"],
         beego.ControllerComments{
             Method: "ArticleCategoryList",
@@ -385,6 +412,78 @@ func init() {
             Filters: nil,
             Params: nil})
 
+    beego.GlobalControllerRouter["hongze/hongze_clpt/controllers:MobileResearchController"] = append(beego.GlobalControllerRouter["hongze/hongze_clpt/controllers:MobileResearchController"],
+        beego.ControllerComments{
+            Method: "Billboard",
+            Router: `/article/billboard`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["hongze/hongze_clpt/controllers:MobileResearchController"] = append(beego.GlobalControllerRouter["hongze/hongze_clpt/controllers:MobileResearchController"],
+        beego.ControllerComments{
+            Method: "ArticleNewList",
+            Router: `/article/newList`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["hongze/hongze_clpt/controllers:MobileResearchController"] = append(beego.GlobalControllerRouter["hongze/hongze_clpt/controllers:MobileResearchController"],
+        beego.ControllerComments{
+            Method: "ArticleType",
+            Router: `/article/typeList`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["hongze/hongze_clpt/controllers:MobileResearchController"] = append(beego.GlobalControllerRouter["hongze/hongze_clpt/controllers:MobileResearchController"],
+        beego.ControllerComments{
+            Method: "DepartmentIdDetail",
+            Router: `/departmentId/detail`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["hongze/hongze_clpt/controllers:MobileResearchController"] = append(beego.GlobalControllerRouter["hongze/hongze_clpt/controllers:MobileResearchController"],
+        beego.ControllerComments{
+            Method: "FllowDepartment",
+            Router: `/fllowDepartment`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["hongze/hongze_clpt/controllers:MobileResearchController"] = append(beego.GlobalControllerRouter["hongze/hongze_clpt/controllers:MobileResearchController"],
+        beego.ControllerComments{
+            Method: "HotList",
+            Router: `/hotList`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["hongze/hongze_clpt/controllers:MobileResearchController"] = append(beego.GlobalControllerRouter["hongze/hongze_clpt/controllers:MobileResearchController"],
+        beego.ControllerComments{
+            Method: "KolList",
+            Router: `/kolList`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["hongze/hongze_clpt/controllers:MobileResearchController"] = append(beego.GlobalControllerRouter["hongze/hongze_clpt/controllers:MobileResearchController"],
+        beego.ControllerComments{
+            Method: "ThemeDetail",
+            Router: `/theme/detail`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
     beego.GlobalControllerRouter["hongze/hongze_clpt/controllers:MobileSearchController"] = append(beego.GlobalControllerRouter["hongze/hongze_clpt/controllers:MobileSearchController"],
         beego.ControllerComments{
             Method: "BrowseHistoryList",
@@ -421,19 +520,19 @@ func init() {
             Filters: nil,
             Params: nil})
 
-    beego.GlobalControllerRouter["hongze/hongze_clpt/controllers:ReportCommonController"] = append(beego.GlobalControllerRouter["hongze/hongze_clpt/controllers:ReportCommonController"],
+    beego.GlobalControllerRouter["hongze/hongze_clpt/controllers:ReportController"] = append(beego.GlobalControllerRouter["hongze/hongze_clpt/controllers:ReportController"],
         beego.ControllerComments{
-            Method: "Timeline",
-            Router: `/timeline`,
-            AllowHTTPMethods: []string{"get"},
+            Method: "CategoryFllow",
+            Router: `/category/fllow`,
+            AllowHTTPMethods: []string{"post"},
             MethodParams: param.Make(),
             Filters: nil,
             Params: nil})
 
     beego.GlobalControllerRouter["hongze/hongze_clpt/controllers:ReportController"] = append(beego.GlobalControllerRouter["hongze/hongze_clpt/controllers:ReportController"],
         beego.ControllerComments{
-            Method: "CategoryFllow",
-            Router: `/category/fllow`,
+            Method: "CommentAdd",
+            Router: `/commentAdd`,
             AllowHTTPMethods: []string{"post"},
             MethodParams: param.Make(),
             Filters: nil,

+ 5 - 1
routers/router.go

@@ -101,7 +101,11 @@ func init() {
 				&controllers.AdviceController{},
 			),
 		),
-
+		web.NSNamespace("/research",
+			web.NSInclude(
+				&controllers.MobileResearchController{},
+			),
+		),
 	)
 	web.AddNamespace(ns)
 }

+ 32 - 15
services/activity.go

@@ -8,6 +8,7 @@ import (
 	"strconv"
 	"strings"
 	"time"
+	"unicode/utf8"
 )
 
 // 获取活动列表查询权限的SQL
@@ -357,11 +358,14 @@ func HandleActivityTypeHomeList(listType []*models.ActivityTypeHome, listActivit
 		if v.YidongActivityId != "" {
 			item.IsExternalLabel = true
 		}
+		item.City = v.City
+		if utf8.RuneCountInString(v.City) != 2 {
+			item.City = ""
+		}
 		item.IsNew = newLabelMap[v.ActivityId]
 		mapActivity[v.ActivityTypeId] = append(mapActivity[v.ActivityTypeId], item)
 		mapkeyWord[fmt.Sprint(v.ActivityTypeId, "-", item.KeyWord)] = item.KeyWord
 	}
-
 	for _, v := range listType {
 		v.Resource = 1
 		if len(mapActivity[v.ActivityTypeId]) > 0 {
@@ -370,9 +374,7 @@ func HandleActivityTypeHomeList(listType []*models.ActivityTypeHome, listActivit
 			v.List = make([]*models.CygxActivityLabelList, 0)
 		}
 	}
-
 	items = listType
-	fmt.Println(len(mapActivity))
 	return
 }
 
@@ -639,19 +641,34 @@ func ActivityDetaailShow(activityInfo *models.ActivityListResp) (itemActivity *m
 	if activityInfo.SignupNum > activityInfo.LimitPeopleNum {
 		activityInfo.SignupNum = activityInfo.LimitPeopleNum
 	}
+	//if activityInfo.ReportLink != "" {
+	//	artList := strings.Split(activityInfo.ReportLink, "{|}")
+	//	if len(artList) > 0 {
+	//		for _, v := range artList {
+	//			artitem := new(models.ActivityArticleResp)
+	//			artitem.ReportLink = v
+	//			artIdSlice := strings.Split(v, "/")
+	//			if len(artIdSlice) > 0 {
+	//				articleId, _ := strconv.Atoi(artIdSlice[len(artIdSlice)-1])
+	//				artitem.ArticleId = articleId
+	//			}
+	//			activityInfo.ArticleList = append(activityInfo.ArticleList, artitem)
+	//		}
+	//	}
+	//} else {
+	//	activityInfo.ArticleList = make([]*models.ActivityArticleResp, 0)
+	//}
+
 	if activityInfo.ReportLink != "" {
-		artList := strings.Split(activityInfo.ReportLink, "{|}")
-		if len(artList) > 0 {
-			for _, v := range artList {
-				artitem := new(models.ActivityArticleResp)
-				artitem.ReportLink = v
-				artIdSlice := strings.Split(v, "/")
-				if len(artIdSlice) > 0 {
-					articleId, _ := strconv.Atoi(artIdSlice[len(artIdSlice)-1])
-					artitem.ArticleId = articleId
-				}
-				activityInfo.ArticleList = append(activityInfo.ArticleList, artitem)
-			}
+		artList, e := GetActivityReportLinkToArticleList(activityInfo)
+		if e != nil && e.Error() != utils.ErrNoRow() {
+			err = e
+			return
+		}
+		if len(artList) == 0 {
+			activityInfo.ArticleList = make([]*models.ActivityArticleResp, 0)
+		} else {
+			activityInfo.ArticleList = artList
 		}
 	} else {
 		activityInfo.ArticleList = make([]*models.ActivityArticleResp, 0)

+ 5 - 0
services/activity_special.go

@@ -255,6 +255,11 @@ func GetActivityLabelSpecialList(user *models.WxUserItem, conditionActivitySpeci
 	//}
 	for k2, v2 := range specialList {
 		v2.Resource = 2
+		if v2.Days == 0 {
+			specialList[k2].TripStatus = 1
+		} else {
+			specialList[k2].TripStatus = 2
+		}
 		specialList[k2].KeyWord = LabelStr(v2.KeyWord, v2.IsShowSubjectName, v2.TemporaryLabel)
 		specialList[k2].ImgUrlBg = "https://hzstatic.hzinsights.com/static/temp/20220426202204/20220426/XDLLsjC9XAAy8LIzQr7GsjrBbtX6.png"
 		specialList[k2].ImgUrlBg = utils.ACTIVITY_ZXDY_ImgUrl3

+ 71 - 15
services/article.go

@@ -31,7 +31,7 @@ func FixArticleImgUrl(body string) (contentSub string, err error) {
 	return
 }
 
-//GetReportContentTextSubByarticle 解析文章内容
+// GetReportContentTextSubByarticle 解析文章内容
 func GetReportContentTextSubByarticle(content, abstract string, articleId int) (contentSub string, err error) {
 	var lenabstract int
 	//如果不是研选就这么展示
@@ -81,8 +81,8 @@ func GetReportContentTextArticleBody(content string) (contentSub string) {
 	return
 }
 
-//HandleArticleCategoryImg 预处理文章的封面图片
-func HandleArticleCategoryImg(list []*models.ArticleListResp) (items []*models.ArticleListResp, err error) {
+// HandleArticleCategoryImg 预处理文章的封面图片
+func HandleArticleCategoryImg(list []*models.ArticleListResp, user *models.WxUserItem) (items []*models.ArticleListResp, err error) {
 	//研选的五张图片
 	detailResearch, e := models.GetConfigByCode("category_research_img_url")
 	if e != nil {
@@ -117,6 +117,7 @@ func HandleArticleCategoryImg(list []*models.ArticleListResp) (items []*models.A
 	for _, v := range reportMappingList {
 		mapChartPerssion[strconv.Itoa(v.CategoryId)] = v.ChartPermissionName
 	}
+
 	for k, v := range list {
 		if list[k].Annotation == "" {
 			imgurl, _ := FixArticleImgUrl(html.UnescapeString(list[k].Body))
@@ -134,7 +135,7 @@ func HandleArticleCategoryImg(list []*models.ArticleListResp) (items []*models.A
 
 		list[k].ChartPermissionName = mapChartPerssion[v.CategoryId]
 		//如果是研选系列的任意取五张图片的中的一张
-		if v.CategoryId == "0" || v.ArticleId > utils.SummaryArticleId {
+		if v.CategoryId == "0" || v.ArticleId >= utils.SummaryArticleId {
 			knum := v.ArticleId % 5
 			list[k].ImgUrlPc = researchList[knum]
 		} else {
@@ -187,12 +188,22 @@ func HandleArticleCategoryImg(list []*models.ArticleListResp) (items []*models.A
 			})
 		}
 	}
+	// 处理文章收藏字段
+	mapCollect, e := GetUserAticleCollectMap(user)
+	if e != nil {
+		err = errors.New("GetUserAticleCollectMap" + e.Error())
+		return
+	}
+
 	for k, v := range list {
 		if len(industryMap[v.ArticleId]) > 0 {
 			list[k].List = industryMap[v.ArticleId]
 		} else {
 			list[k].List = make([]*models.IndustrialManagementIdInt, 0)
 		}
+		if _, ok := mapCollect[v.ArticleId]; ok {
+			list[k].IsCollect = true
+		}
 	}
 
 	if len(list) == 0 {
@@ -202,7 +213,7 @@ func HandleArticleCategoryImg(list []*models.ArticleListResp) (items []*models.A
 	return
 }
 
-//HandleArticleStock 处理报告关联的个股标签
+// HandleArticleStock 处理报告关联的个股标签
 func HandleArticleStock(stock string) (items []*models.ComapnyNameResp) {
 	sliceSubjects := strings.Split(stock, "/")
 	if len(sliceSubjects) > 0 {
@@ -216,7 +227,7 @@ func HandleArticleStock(stock string) (items []*models.ComapnyNameResp) {
 	return
 }
 
-//弘则报告发布日期在三个月以内的
+// 弘则报告发布日期在三个月以内的
 func GetArticNewLabelWhithActivity3Month() (labelMap map[int]bool, err error) {
 	var condition string
 	var pars []interface{}
@@ -265,7 +276,7 @@ func GetArticNewLabelWhithActivity3Month() (labelMap map[int]bool, err error) {
 	return
 }
 
-//GetSpecialArticleDetailUserPower 处理用户查看专项调研文章详情的权限
+// GetSpecialArticleDetailUserPower 处理用户查看专项调研文章详情的权限
 func GetSpecialArticleDetailUserPower(user *models.WxUserItem, articleInfo *models.ArticleDetail) (havePower bool, err error) {
 	permissionStr, e := GetCompanyPermissionUpgrade(user.CompanyId)
 	if e != nil {
@@ -316,7 +327,7 @@ func GetReportContentTextSubNew(content string) (contentSub string, err error) {
 	return
 }
 
-//处理核心观点的展示规则
+// 处理核心观点的展示规则
 func ArticleAnnotation(item *models.ArticleListResp) (annotation string) {
 	if item.ArticleId >= utils.SummaryArticleId {
 		item.Annotation = YxArticleAnnotation(item)
@@ -335,6 +346,7 @@ func ArticleAnnotation(item *models.ArticleListResp) (annotation string) {
 		doc, _ := goquery.NewDocumentFromReader(strings.NewReader(annotation))
 		docText := doc.Text()
 		mapDoc := make(map[int]string)
+		mapSortRepeat := make(map[string]string)
 		var mapSort []int
 		p := doc.Find("p")
 		p.Each(func(tk int, pd *goquery.Selection) {
@@ -342,8 +354,11 @@ func ArticleAnnotation(item *models.ArticleListResp) (annotation string) {
 			pdText = strings.Replace(pdText, " ", "", -1)
 			if pdText != "" {
 				textLen := strings.Index(docText, pdText)
-				mapDoc[(strings.Index(docText, pdText))] = pdText
-				mapSort = append(mapSort, textLen)
+				if mapSortRepeat[strconv.Itoa(textLen)] == "" {
+					mapDoc[(strings.Index(docText, pdText))] = pdText
+					mapSort = append(mapSort, textLen)
+					mapSortRepeat[strconv.Itoa(textLen)] = strconv.Itoa(textLen)
+				}
 			}
 		})
 		li := doc.Find("li")
@@ -352,8 +367,11 @@ func ArticleAnnotation(item *models.ArticleListResp) (annotation string) {
 			liText = strings.Replace(liText, " ", "", -1)
 			if liText != "" {
 				textLen := strings.Index(docText, liText)
-				mapDoc[(strings.Index(docText, liText))] = strconv.Itoa(tk+1) + "." + liText
-				mapSort = append(mapSort, textLen)
+				if mapSortRepeat[strconv.Itoa(textLen)] == "" {
+					mapDoc[(strings.Index(docText, liText))] = strconv.Itoa(tk+1) + "." + liText
+					mapSort = append(mapSort, textLen)
+					mapSortRepeat[strconv.Itoa(textLen)] = strconv.Itoa(textLen)
+				}
 			}
 		})
 
@@ -363,8 +381,11 @@ func ArticleAnnotation(item *models.ArticleListResp) (annotation string) {
 			ulText = strings.Replace(ulText, " ", "", -1)
 			if ulText != "" {
 				textLen := strings.Index(docText, ulText)
-				mapDoc[(strings.Index(docText, ulText))] = ulText
-				mapSort = append(mapSort, textLen)
+				if mapSortRepeat[strconv.Itoa(textLen)] == "" {
+					mapDoc[(strings.Index(docText, ulText))] = ulText
+					mapSort = append(mapSort, textLen)
+					mapSortRepeat[strconv.Itoa(textLen)] = strconv.Itoa(textLen)
+				}
 			}
 		})
 		if len(mapSort) == 0 {
@@ -388,7 +409,7 @@ func ArticleAnnotation(item *models.ArticleListResp) (annotation string) {
 	return
 }
 
-//解析研选内容中的核心观点
+// 解析研选内容中的核心观点
 func YxArticleAnnotation(article *models.ArticleListResp) (annotation string) {
 	//如果不规范,就获取内容主体
 	if strings.Count(article.Body, "<hr") == 0 {
@@ -439,3 +460,38 @@ func YxArticleAnnotation(article *models.ArticleListResp) (annotation string) {
 	annotation = body
 	return
 }
+
+// 获取研选类型的文章分类Id
+func GetYanXuanArticleTypeIds() (articleTypeIds string, err error) {
+	var condition string
+	condition = " AND is_show_yanx  = 1 "
+	listType, e := models.GetCygxArticleTypeListCondition(condition)
+	if e != nil {
+		err = errors.New("GetCygxArticleTypeListCondition, Err: " + e.Error())
+		return
+	}
+	for _, v := range listType {
+		articleTypeIds += strconv.Itoa(v.ArticleTypeId) + ","
+	}
+	articleTypeIds = strings.TrimRight(articleTypeIds, ",")
+	if articleTypeIds == "" {
+		err = errors.New("研选分类ID不能为空")
+		return
+	}
+	return
+}
+
+// GetUserAticleCollectMap 获取用户收藏的文章ID
+func GetUserAticleCollectMap(user *models.WxUserItem) (respMap map[int]int, err error) {
+	list, e := models.GetCygxArticleCollectListByUser(user.UserId)
+	if e != nil {
+		err = errors.New("GetCygxArticleCollectListByUser, Err: " + e.Error())
+		return
+	}
+	articleMap := make(map[int]int)
+	for _, v := range list {
+		articleMap[v.ArticleId] = v.ArticleId
+	}
+	respMap = articleMap
+	return
+}

+ 213 - 0
services/article_red.go

@@ -0,0 +1,213 @@
+package services
+
+import (
+	"errors"
+	"fmt"
+	"hongze/hongze_clpt/models"
+	"hongze/hongze_clpt/utils"
+	"strconv"
+	"time"
+)
+
+//处理文章小红点
+
+func GetShowTimeLineIsRed(user *models.WxUserItem, industrialManagementId int) (isRed bool, err error) {
+	//时间线
+	timeLineItem := models.IndustrialToArticleCategoryRep{
+		CategoryId:    99999,
+		MatchTypeName: "时间线",
+	}
+	timeLineList, e := models.GetTimeLineReportIndustrialListRed(user.UserId, industrialManagementId, 0, 30)
+	if e != nil {
+		err = errors.New("GetTimeLineReportIndustrialListRed, Err: " + e.Error())
+		return
+	}
+	//查询用户今天是否看过时间线
+	haveMorningMeeting := false
+	var morningMeetingTime string
+	count, e := models.GetTimeLineRecordCount(user.UserId, industrialManagementId)
+	if e != nil {
+		err = errors.New("GetTimeLineRecordCount, Err: " + e.Error())
+		return
+	}
+	var recordItem *models.CygxPageHistoryRecord
+	if count > 1 {
+		recordItem, e = models.GetTimeLineRecordItem(user.UserId, industrialManagementId)
+		if e != nil {
+			err = errors.New("GetTimeLineRecordCount, Err: " + e.Error())
+			return
+		}
+	}
+
+	for _, v := range timeLineList {
+		if v.Readnum == 0 && user.CreatedTime.Before(utils.StrTimeToTime(v.PublishDate)) && utils.StrTimeToTime(utils.OnlineTime).Before(utils.StrTimeToTime(v.PublishDate)) {
+			if v.SubCategoryName == "时间线" {
+				haveMorningMeeting = true
+				morningMeetingTime = v.PublishDate
+				continue
+			}
+			timeLineItem.IsRed = true
+		}
+	}
+	//因为无法记录用户是否看过晨会点评,所以用用户今天是否看过时间线来判断是否显示小红点,这里是判断分类的小红点
+	timeLineRed := false
+	if count < 2 {
+		timeLineRed = true
+	} else if count > 1 && recordItem.CreateTime.Before(utils.StrTimeToTime(morningMeetingTime)) {
+		timeLineRed = true
+	}
+	if !timeLineItem.IsRed && timeLineRed && haveMorningMeeting {
+		timeLineItem.IsRed = true
+	}
+	isRed = timeLineItem.IsRed
+	return
+
+}
+
+// UserViewRedisData 阅读数据
+type UserViewRedisData struct {
+	Mobile      string `json:"mobile"`
+	Email       string `json:"email"`
+	RealName    string `json:"real_name"`
+	CompanyName string `json:"company_name"`
+	ViewTime    string `json:"view_time" description:"阅读时间,格式:2022-02-17 13:06:13"`
+	ProductId   int    `json:"product_id" description:"报告所属产品,ficc:1,权益:2"`
+	CompanyId   int    `json:"company_id" description:"客户id"`
+}
+
+type ReportViewRecord struct {
+	Id          int       `orm:"column(id);pk"`
+	UserId      int       `description:"用户id"`
+	ReportId    int       `description:"报告id"`
+	Mobile      string    `description:"手机号"`
+	Email       string    `description:"邮箱"`
+	RealName    string    `description:"用户实际姓名"`
+	CompanyName string    `description:"公司名称"`
+	CreateTime  time.Time `description:"创建时间"`
+}
+
+// PushViewRecordNewRedisData 阅读数据加入到redis
+func PushViewRecordNewRedisData(reportViewRecord *ReportViewRecord, companyId int) bool {
+	data := &UserViewRedisData{
+		Mobile:      reportViewRecord.Mobile,
+		Email:       reportViewRecord.Email,
+		RealName:    reportViewRecord.RealName,
+		CompanyName: reportViewRecord.CompanyName,
+		ViewTime:    reportViewRecord.CreateTime.Format(utils.FormatDateTime),
+		ProductId:   2,
+		CompanyId:   companyId,
+	}
+	if utils.Re == nil {
+		err := utils.Rc.LPush(utils.CACHE_KEY_USER_VIEW, data)
+		if err != nil {
+			fmt.Println("PushViewRecordNewRedisData LPush Err:" + err.Error())
+		}
+		return true
+	}
+	return false
+}
+
+// 记录用户文章浏览记录
+func ArticleHistory(articleId int, user *models.WxUserItem) (err error) {
+	defer func() {
+		if err != nil {
+			go utils.SendAlarmMsg("记录用户文章浏览记录,失败"+err.Error(), 2)
+		}
+	}()
+	uid := user.UserId
+	if uid == 0 {
+		return
+	}
+	record := new(models.CygxArticleHistoryRecordNewpv)
+	record.UserId = uid
+	record.ArticleId = articleId
+	record.CreateTime = time.Now()
+	record.ModifyTime = time.Now()
+	record.Mobile = user.Mobile
+	record.Email = user.Email
+	record.CompanyId = user.CompanyId
+	record.CompanyName = user.CompanyName
+	record.StopTime = 0
+	record.OutType = 1
+	record.Source = "WEB"
+
+	recordRedis := new(ReportViewRecord)
+	recordRedis.UserId = user.UserId
+	recordRedis.ReportId = articleId
+	recordRedis.Mobile = user.Mobile
+	recordRedis.Email = user.Email
+	recordRedis.RealName = user.RealName
+	recordRedis.CompanyName = user.CompanyName
+	recordRedis.CreateTime = time.Now()
+	go PushViewRecordNewRedisData(recordRedis, user.CompanyId)
+	_, err = models.AddCygxArticleViewRecordNewpv(record)
+	return
+}
+
+// GetUserArticleHistoryRecord 获取用户已经阅读的文章ID
+func GetUserArticleHistoryRecord(user *models.WxUserItem) (articleIdMap map[int]bool, err error) {
+	var condition string
+	var pars []interface{}
+	condition = " AND user_id = ? "
+	pars = append(pars, user.UserId)
+	articleIdMap = make(map[int]bool, 0)
+	list, err := models.GetArticleHistoryRecord(condition, pars)
+	if err != nil && err.Error() != utils.ErrNoRow() {
+		return
+	}
+	for _, v := range list {
+		articleIdMap[v.ArticleId] = true
+	}
+	return
+}
+
+// GetUserArticleHistoryIndustrialNewPublishDate  获取产业关联的的文章用户是否阅读
+func GetUserArticleHistoryIndustrialNewPublishDate(user *models.WxUserItem, industrialIdArr []int, articleTypeIds, resource string) (mapIndustrialArticleHistory map[int]bool, err error) {
+	if len(industrialIdArr) == 0 {
+		return
+	}
+	var condition string
+	var pars []interface{}
+	articleIdMap, err := GetUserArticleHistoryRecord(user)
+	if err != nil {
+		return
+	}
+	if resource == utils.REOURCE_YX {
+		condition = ` AND a.publish_status = 1 AND a.article_type_id  IN (` + articleTypeIds + `)	`
+	} else {
+		condition = ` AND a.article_type_id  = 0	 AND  a.article_id < ` + strconv.Itoa(utils.SummaryArticleId)
+	}
+	var startTime time.Time
+	if utils.StrTimeToTime(utils.OnlineTime).After(user.CreatedTime) {
+		startTime = utils.StrTimeToTime(utils.OnlineTime)
+	} else {
+		startTime = user.CreatedTime
+	}
+
+	condition += ` AND mg.industrial_management_id  IN (` + utils.GetOrmInReplace(len(industrialIdArr)) + `) AND a.publish_date > ? `
+	pars = append(pars, industrialIdArr, startTime)
+
+	list, err := models.GetCygxIndustrialArticleGroupManagement(condition, pars)
+	if err != nil {
+		return
+	}
+	mapIndustrialArticle := make(map[int][]*models.CygxIndustrialArticleGroupManagementResp)
+	//mapIndustrialArticleMax := make(map[int]int, 0)
+	mapIndustrialArticleHistory = make(map[int]bool, 0)
+	//mapIndustrialArticleMaxTime := make(map[int]time.Time)
+	for _, v := range list {
+		item := new(models.CygxIndustrialArticleGroupManagementResp)
+		item.IndustrialManagementId = v.IndustrialManagementId
+		item.ArticleId = v.ArticleId
+		item.PublishDate = v.PublishDate
+		mapIndustrialArticle[v.IndustrialManagementId] = append(mapIndustrialArticle[v.IndustrialManagementId], item)
+	}
+	for k, v := range mapIndustrialArticle {
+		for _, item := range v {
+			if !articleIdMap[item.ArticleId] {
+				mapIndustrialArticleHistory[k] = true
+			}
+		}
+	}
+	return
+}

+ 50 - 1
services/config.go

@@ -1,11 +1,15 @@
 package services
 
 import (
+	"errors"
 	"fmt"
 	"hongze/hongze_clpt/models"
+	"hongze/hongze_clpt/utils"
+	"strconv"
+	"strings"
 )
 
-//是否展示限免标签
+// 是否展示限免标签
 func GetShowSustainable() (isShowSustainable bool) {
 	total, err := models.GetShowSustainable()
 	if err != nil {
@@ -29,3 +33,48 @@ func GetShowSustainableNew() (isShowSustainable bool, err error) {
 	}
 	return
 }
+
+// 解析活动填写的报告链接
+func GetActivityReportLinkToArticleList(item *models.ActivityListResp) (items []*models.ActivityArticleResp, err error) {
+	reportLink := item.ReportLink
+	//处理活动的
+	var articleIds []int
+	var articleList []string
+	if strings.Contains(reportLink, ";") {
+		articleList = strings.Split(reportLink, ";")
+	} else {
+		articleList = strings.Split(reportLink, ";")
+	}
+	for _, v := range articleList {
+		linkList := strings.Split(v, "/")
+		if linkList[len(linkList)-1] != "" {
+			linkArticleId, _ := strconv.Atoi(linkList[len(linkList)-1])
+			articleIds = append(articleIds, linkArticleId)
+		}
+	}
+
+	lenarticleIds := len(articleIds)
+	if lenarticleIds == 0 {
+		return
+	}
+	var condition string
+	var pars []interface{}
+	pars = make([]interface{}, 0)
+	condition = ` AND a.article_id IN (` + utils.GetOrmInReplace(lenarticleIds) + `)`
+	pars = append(pars, articleIds)
+
+	listArticle, e := models.GetHomeList(condition, pars, 0, len(articleIds))
+	if e != nil {
+		err = errors.New("GetResourceDataList, Err: " + e.Error())
+		return
+	}
+	if len(listArticle) > 0 {
+		for _, v := range listArticle {
+			artItem := new(models.ActivityArticleResp)
+			artItem.ArticleId = v.ArticleId
+			artItem.Title = v.Title
+			items = append(items, artItem)
+		}
+	}
+	return
+}

+ 227 - 44
services/industrial_management.go

@@ -5,10 +5,12 @@ import (
 	"fmt"
 	"hongze/hongze_clpt/models"
 	"hongze/hongze_clpt/utils"
+	"strconv"
+	"strings"
 	"time"
 )
 
-//根据行业处理所选的全部赛道字段
+// 根据行业处理所选的全部赛道字段
 func DoXzsChooseSend(chartPermissionName string) string {
 	var allIn string
 	if chartPermissionName == utils.YI_YAO_NAME {
@@ -25,7 +27,7 @@ func DoXzsChooseSend(chartPermissionName string) string {
 	return allIn
 }
 
-//行业关注或者取消关注的时候,对于用户全部赛道的影响
+// 行业关注或者取消关注的时候,对于用户全部赛道的影响
 func IndustryFllowWithTrack(industrialManagementId, count, uid int) (err error) {
 	defer func() {
 		if err != nil {
@@ -76,8 +78,8 @@ func IndustryFllowWithTrack(industrialManagementId, count, uid int) (err error)
 	return err
 }
 
-//HandleIndustryList预处理产业列表字段
-func HandleIndustryList(list []*models.IndustrialManagement, user *models.WxUserItem) (items []*models.IndustrialManagement, err error) {
+// HandleIndustryList预处理产业列表字段
+func HandleIndustryList(list []*models.IndustrialManagement, user *models.WxUserItem, resource string) (items []*models.IndustrialManagement, err error) {
 	userId := user.UserId
 	fllowList, err := models.GetUserFllowIndustrialList(userId)
 	if err != nil {
@@ -89,6 +91,27 @@ func HandleIndustryList(list []*models.IndustrialManagement, user *models.WxUser
 			fllowMap[v.IndustrialManagementId] = v.IndustrialManagementId
 		}
 	}
+
+	hotMap, e := IndustrialManagementHotMapGropuPermission()
+	if e != nil {
+		err = errors.New("获取hot标签失败,IndustrialManagementHotMapGropuPermission " + e.Error())
+		return
+	}
+	var condition string
+	var pars []interface{}
+	articleTypeIds, _ := GetYanXuanArticleTypeIds()
+	//给默认值
+	if resource != "Yx" {
+		resource = "Hz"
+	}
+	if articleTypeIds != "" {
+		if resource == "Yx" {
+			condition = ` AND a.publish_status = 1 AND a.article_type_id  IN (` + articleTypeIds + `)	`
+		} else {
+			condition = ` AND a.article_type_id  NOT  IN (` + articleTypeIds + `)  AND  a.article_id <  1000000	`
+		}
+	}
+
 	mapindustrialId, e := GetMicroRoadshowVideoMap()
 	if e != nil {
 		err = e
@@ -105,6 +128,7 @@ func HandleIndustryList(list []*models.IndustrialManagement, user *models.WxUser
 		if fllowMap[v.IndustrialManagementId] > 0 {
 			list[k].IsFollow = true
 		}
+		v.IsHot = hotMap[v.IndustrialManagementId]
 		industrialIdArr = append(industrialIdArr, v.IndustrialManagementId)
 		if _, ok := mapindustrialId[v.IndustrialManagementId]; !ok {
 			continue
@@ -119,11 +143,11 @@ func HandleIndustryList(list []*models.IndustrialManagement, user *models.WxUser
 		}
 		v.AuthInfo = au
 	}
-	mapUPdateTime := make(map[int]string)
-	mapHistroyArticleId := make(map[int]int)
 	if len(industrialIdArr) > 0 {
 		//合并产业关联的标的
-		listSubjcet, err = models.GetIndustrialSubjectAllByIndustrialId(industrialIdArr)
+		conditionSubject := condition + ` AND 	m.industrial_management_id  IN (` + utils.GetOrmInReplace(len(industrialIdArr)) + `)`
+		pars = append(pars, industrialIdArr)
+		listSubjcet, err = models.GetIndustrialSubjectAllByIndustrialId(pars, conditionSubject)
 		if err != nil {
 			return
 		}
@@ -136,20 +160,32 @@ func HandleIndustryList(list []*models.IndustrialManagement, user *models.WxUser
 				}
 			}
 		}
-
-		articleIdArr := make([]int, 0)
-		//获取这些产业下最新更新的文章
-		if len(industrialIdArr) > 0 {
-			listUpdateTime, e := models.GetNewArticleDetailByIndustrialIds(industrialIdArr)
-			if e != nil && e.Error() != utils.ErrNoRow() {
-				err = e
-				return
-			}
-			for _, v := range listUpdateTime {
-				mapUPdateTime[v.IndustrialManagementId] = v.PublishDate
-				articleIdArr = append(articleIdArr, v.ArticleId)
-			}
+	}
+	//获取产业关联的的文章用户是否阅读
+	mapIndustrialArticleHistory, err := GetUserArticleHistoryIndustrialNewPublishDate(user, industrialIdArr, articleTypeIds, resource)
+	if err != nil {
+		err = errors.New("获取产业关联的的文章用户是否阅读失败 " + err.Error())
+		return
+	}
+	mapUPdateTime := make(map[int]string)
+	articleIdArr := make([]int, 0)
+	//获取这些产业下最新更新的文章
+	var conditionindustrial string
+	var parsindustrial []interface{}
+	var industrialIds string
+	if len(industrialIdArr) > 0 {
+		conditionindustrial = condition + ` AND mg.industrial_management_id  IN (` + utils.GetOrmInReplace(len(industrialIdArr)) + `)`
+		parsindustrial = append(parsindustrial, industrialIdArr)
+		listUpdateTime, e := models.GetNewArticleDetailByIndustrialIds(parsindustrial, conditionindustrial)
+		if e != nil && e.Error() != utils.ErrNoRow() {
+			err = errors.New("GetNewArticleDetailByIndustrialIds Err " + err.Error())
+			return
+		}
+		for _, v := range listUpdateTime {
+			mapUPdateTime[v.IndustrialManagementId] = v.PublishDate
+			articleIdArr = append(articleIdArr, v.ArticleId)
 		}
+
 		//时间线的更新时间
 		//	maptimelineUPdateTime := make(map[int]string)
 		listtimelinePublishdate, e := models.GetTimeLineReportIndustrialPublishdateList(industrialIdArr)
@@ -164,47 +200,92 @@ func HandleIndustryList(list []*models.IndustrialManagement, user *models.WxUser
 				}
 			}
 		}
-
-		if userId > 0 {
-			listArticleHistory, e := models.GetUserToArticleHistory(userId, industrialIdArr)
-			if e != nil && e.Error() != utils.ErrNoRow() {
-				err = errors.New("获取产业关联的视频失败,GetindustryVideo " + e.Error())
-				return
-			}
-			for _, v := range listArticleHistory {
-				mapHistroyArticleId[v.ArticleId] = v.ArticleId
-			}
+		for _, id := range industrialIdArr {
+			industrialIds += strconv.Itoa(id) + ","
+		}
+		industrialIds = strings.TrimRight(industrialIds, ",")
+		articleList, e := models.GetReportIndustrialReadNumList(userId, industrialIds, user.CreatedTime)
+		if e != nil && e.Error() != utils.ErrNoRow() {
+			err = e
+			return
+		}
+		mapHistroyindustrialId := make(map[int]int)
+		for _, v := range articleList {
+			mapHistroyindustrialId[v.IndustrialManagementId] = v.Readnum
 		}
 	}
 	nowTime := time.Now().Local()
 	threeMonBefore := nowTime.AddDate(0, -3, 0)
-	for k, v := range list {
-		list[k].UpdateTime = utils.TimeRemoveHms(mapUPdateTime[v.IndustrialManagementId])
-		if userId > 0 {
-			//如果文章没有阅读,而且,文章的发布时间晚于项目的上线时间,而且文章的发布时间晚于用户的注册时间,就进行标红处理
-			if mapHistroyArticleId[v.ArticleId] == 0 && user.CreatedTime.Before(utils.StrTimeToTime(mapUPdateTime[v.IndustrialManagementId])) && utils.StrTimeToTime(utils.OnlineTime).Before(utils.StrTimeToTime(mapUPdateTime[v.IndustrialManagementId])) {
-				list[k].IsRed = true
+
+	//查询用户今天是否看过时间线
+	//haveMorningMeeting := false
+	//var morningMeetingTime string
+	recrodList, err := models.GetTimeLineRecordAllCount(user.UserId, time.Now().Format(utils.FormatDate))
+	if err != nil {
+		return
+	}
+	var industrialManagementIdstr string
+	industrialIdMap := make(map[string]time.Time)
+	for _, v := range recrodList {
+		//fmt.Println(v.Router)
+		sliceindustrial := strings.Split(v.Router, "=")
+		//industrialManagementIdstr = strings.TrimLeft(v.Router, utils.TIME_LINE_ROUTE)
+		industrialManagementIdstr = sliceindustrial[len(sliceindustrial)-1]
+		//fmt.Println(industrialManagementIdstr)
+		if createTime, ok := industrialIdMap[industrialManagementIdstr]; ok {
+			if createTime.Before(v.CreateTime) {
+				industrialIdMap[industrialManagementIdstr] = v.CreateTime
 			}
 		} else {
-			if utils.StrTimeToTime(utils.OnlineTime).Before(utils.StrTimeToTime(mapUPdateTime[v.IndustrialManagementId])) {
-				list[k].IsRed = true
-			}
-			list[k].IsFollow = false
+			industrialIdMap[industrialManagementIdstr] = v.CreateTime
 		}
-
+	}
+	morningMeetingTimeMap := make(map[int]time.Time)
+	if industrialIds != "" {
+		mmList, e := models.GetCygxMorningMeetingReviewsListByIndustrialIds(industrialIds)
+		if e != nil {
+			err = e
+			return
+		}
+		for _, v := range mmList {
+			morningMeetingTimeMap[v.IndustryId] = v.CreateTime
+		}
+	}
+	timeLineRedMap := make(map[int]bool, 0)
+	for _, industrialId := range industrialIdArr {
+		//if createTime, ok := industrialIdMap[strconv.Itoa(industrialId)]; ok {
+		//	if createTime.Before(morningMeetingTimeMap[industrialId]) {
+		//		timeLineRedMap[industrialId] = true
+		//	}
+		//}
+		if industrialIdMap[strconv.Itoa(industrialId)].Before(morningMeetingTimeMap[industrialId]) {
+			timeLineRedMap[industrialId] = true
+		}
+	}
+	//fmt.Println(industrialIdMap["90"])
+	//fmt.Println(timeLineRedMap[90])
+	//fmt.Println(mapIndustrialArticleHistory[90])
+	for k, v := range list {
 		list[k].UpdateTime = utils.TimeRemoveHms(mapUPdateTime[v.IndustrialManagementId])
 		if userId > 0 {
 			//如果文章没有阅读,而且,文章的发布时间晚于项目的上线时间,而且文章的发布时间晚于用户的注册时间,就进行标红处理
-			if mapHistroyArticleId[v.ArticleId] == 0 && user.CreatedTime.Before(utils.StrTimeToTime(mapUPdateTime[v.IndustrialManagementId])) && utils.StrTimeToTime(utils.OnlineTime).Before(utils.StrTimeToTime(mapUPdateTime[v.IndustrialManagementId])) {
-				list[k].IsRed = true
+			if mapIndustrialArticleHistory[v.IndustrialManagementId] || timeLineRedMap[v.IndustrialManagementId] {
+				//if mapHistroyindustrialId[v.IndustrialManagementId] == 0 || timeLineRedMap[v.IndustrialManagementId] {
+				if user.CreatedTime.Before(utils.StrTimeToTime(mapUPdateTime[v.IndustrialManagementId])) && utils.StrTimeToTime(utils.OnlineTime).Before(utils.StrTimeToTime(mapUPdateTime[v.IndustrialManagementId])) {
+					list[k].IsRed = true
+				}
 			}
 		} else {
 			if utils.StrTimeToTime(utils.OnlineTime).Before(utils.StrTimeToTime(mapUPdateTime[v.IndustrialManagementId])) {
 				list[k].IsRed = true
 			}
-			list[k].IsFollow = false
+			list[k].IsFollow = true
 		}
+		list[k].UpdateTime = utils.TimeRemoveHms(mapUPdateTime[v.IndustrialManagementId])
 
+		if resource == "Yx" {
+			list[k].IsRed = false
+		}
 		// 关联报告发布时间均在3个月内则标记New
 		if v.MinReportTime != "" {
 			t, e := time.Parse(utils.FormatDateTime, v.MinReportTime)
@@ -220,3 +301,105 @@ func HandleIndustryList(list []*models.IndustrialManagement, user *models.WxUser
 	items = list
 	return
 }
+
+// 通过文章ID获取文章所关联的产业
+func GetArticleIndustrialByArticleId(articleIds []int) (itemMap map[int][]*models.IndustrialManagementResp, err error) {
+	lenarticleIds := len(articleIds)
+	if lenarticleIds == 0 {
+		return
+	}
+	var condition string
+	var pars []interface{}
+	condition = ` AND mg.article_id IN (` + utils.GetOrmInReplace(lenarticleIds) + `)`
+	pars = append(pars, articleIds)
+	industrialList, err := models.GetIndustrialListByarticleId(pars, condition)
+	if err != nil {
+		return
+	}
+	industrialMap := make(map[int][]*models.IndustrialManagementResp)
+	if len(industrialList) > 0 {
+		for _, v := range industrialList {
+			item := new(models.IndustrialManagementResp)
+			item.IndustrialManagementId = v.IndustrialManagementId
+			item.IndustryName = v.IndustryName
+			item.ChartPermissionId = v.ChartPermissionId
+			industrialMap[v.ArticleId] = append(industrialMap[v.ArticleId], item)
+		}
+	}
+	itemMap = industrialMap
+	return
+}
+
+// 获取研选文章类型的配置信息
+func GetArticleTypeMap() (nameMapResp map[int]string, buttonStyleMapResp map[int]string, err error) {
+	condition := " AND is_show_yanx  = 1 "
+	list, e := models.GetCygxArticleTypeListCondition(condition)
+	if e != nil {
+		err = errors.New("报告最早发布时间有误,GetindustryVideo " + e.Error())
+		return
+	}
+	nameMap := make(map[int]string)
+	buttonStyleMap := make(map[int]string)
+	if len(list) > 0 {
+		for _, v := range list {
+			nameMap[v.ArticleTypeId] = v.ArticleTypeName
+			buttonStyleMap[v.ArticleTypeId] = v.ButtonStyle
+		}
+	}
+	nameMapResp = nameMap
+	buttonStyleMapResp = buttonStyleMap
+	return
+}
+
+// GetUserFollowIndustrialMap获取用户关注的产业
+func GetUserFollowIndustrialMap(user *models.WxUserItem) (mapResp map[int]int, err error) {
+	list, e := models.GetUserFllowIndustrialList(user.UserId)
+	if e != nil {
+		err = errors.New("GetUserFllowIndustrialList " + e.Error())
+		return
+	}
+	fllowMap := make(map[int]int)
+	if len(list) > 0 {
+		for _, v := range list {
+			fllowMap[v.IndustrialManagementId] = v.IndustrialManagementId
+		}
+	}
+	mapResp = fllowMap
+	return
+}
+
+// IndustrialManagementHotMapGropuPermission获取近一个月报告阅读数量最多的产业信息 根据行业分组
+func IndustrialManagementHotMapGropuPermission() (mapResp map[int]bool, err error) {
+	var topCond string
+	var topPars []interface{}
+	toplist, err := models.GetTopOneMonthArtReadNumIndustryAll(topCond, topPars)
+	if err != nil {
+		return
+	}
+	mapPermission := make(map[int][]*models.IndustrialManagement)
+	mapPermissionMax := make(map[int]int)
+
+	for _, v := range toplist {
+		item := new(models.IndustrialManagement)
+		item.ChartPermissionId = v.ChartPermissionId
+		item.IndustrialManagementId = v.IndustrialManagementId
+		item.ArticleReadNum = v.ArticleReadNum
+		mapPermission[v.ChartPermissionId] = append(mapPermission[v.ChartPermissionId], item)
+	}
+	for k, v := range mapPermission {
+		for _, item := range v {
+			//mapPermissionMax[k] = item.ArticleReadNum
+			if item.ArticleReadNum > mapPermissionMax[k] {
+				mapPermissionMax[k] = item.ArticleReadNum
+			}
+		}
+	}
+
+	mapResp = make(map[int]bool, 0)
+	for _, v := range toplist {
+		if v.ArticleReadNum == mapPermissionMax[v.ChartPermissionId] {
+			mapResp[v.IndustrialManagementId] = true
+		}
+	}
+	return
+}

+ 42 - 0
services/industrial_subject.go

@@ -0,0 +1,42 @@
+package services
+
+import (
+	"errors"
+	"hongze/hongze_clpt/models"
+	"hongze/hongze_clpt/utils"
+)
+
+// GetArticleGroupSubjectMap 获取文章所关联的标的
+func GetArticleGroupSubjectMap(articleIds []int) (mapResp map[int][]*models.IndustrialSubject, subjectMap map[int]string, err error) {
+	lenArticleIds := len(articleIds)
+	if lenArticleIds == 0 {
+		return
+	}
+	var condition string
+	var pars []interface{}
+	condition = ` AND g.article_id IN (` + utils.GetOrmInReplace(len(articleIds)) + `)`
+	pars = append(pars, articleIds)
+	list, e := models.GetArticleGroupSubjectList(pars, condition)
+	if e != nil {
+		err = errors.New("GetArticleGroupSubjectList " + e.Error())
+		return
+	}
+	listMap := make(map[int][]*models.IndustrialSubject)
+	subMap := make(map[int]string)
+	mapName := make(map[int]int)
+	if len(list) > 0 {
+		for _, v := range list {
+			item := models.IndustrialSubject{
+				IndustrialSubjectId:    v.IndustrialSubjectId,
+				IndustrialManagementId: v.IndustrialManagementId,
+				SubjectName:            v.SubjectName,
+			}
+			listMap[v.ArticleId] = append(listMap[v.ArticleId], &item)
+			subMap[v.IndustrialSubjectId] = v.SubjectName
+			mapName[v.IndustrialSubjectId] = v.IndustrialManagementId
+		}
+	}
+	mapResp = listMap
+	subjectMap = subMap
+	return
+}

+ 1 - 1
services/report.go

@@ -97,7 +97,7 @@ func GetSearchResourceListHz(condition string, user *models.WxUserItem) (items [
 	if err != nil {
 		return
 	}
-	listHz, err = HandleIndustryList(listHz, user)
+	listHz, err = HandleIndustryList(listHz, user, "")
 	items = listHz
 	return
 }

+ 1 - 1
services/resource_data.go

@@ -101,7 +101,7 @@ func GetResourceDataList(condition string, pars []interface{}, startSize, pageSi
 			return
 		}
 
-		articleList, e = HandleArticleCategoryImg(articleList)
+		articleList, e = HandleArticleCategoryImg(articleList, user)
 		if e != nil {
 			err = errors.New("HandleArticleCategoryImg, Err: " + e.Error())
 			return

+ 15 - 3
services/wechat.go

@@ -64,7 +64,7 @@ type WxToken struct {
 //	return
 //}
 
-//小助手
+// 小助手
 func WxGetUserOpenIdByCode(code string) (item *WxAccessToken, err error) {
 	if code == "" {
 		err = errors.New("code is empty")
@@ -173,7 +173,7 @@ func GetWxTicket(accessToken string) (string, error) {
 	}
 }
 
-//获取测试环境的AccessToken
+// 获取测试环境的AccessToken
 func GetWxAccessToken() (accessTokenStr string, err error) {
 	o := orm.NewOrm()
 	sql := `SELECT * FROM wx_token LIMIT 1`
@@ -219,7 +219,7 @@ func GetWxAccessToken() (accessTokenStr string, err error) {
 	}
 }
 
-//开放平台
+// 开放平台
 func WxGetUserOpenIdByOpenCode(code string) (item *WxAccessToken, err error) {
 	if code == "" {
 		err = errors.New("code is empty")
@@ -281,3 +281,15 @@ func GetWxAccessOpenToken(code string) (item *WxAccessToken, err error) {
 	//accessTokenStr = WxAccessToken.AccessToken
 	return
 }
+
+func WxGetTokenXcx() (item *WxToken, err error) {
+	requestUrl := `https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s`
+	requestUrl = fmt.Sprintf(requestUrl, utils.WxAppId, utils.WxAppSecret)
+	result, err := http.Get(requestUrl)
+	if err != nil {
+		utils.FileLog.Info("WxGetToken Result:%s ", string(result))
+		return nil, err
+	}
+	err = json.Unmarshal(result, &item)
+	return
+}

+ 141 - 2
services/wx_template_msg.go

@@ -3,6 +3,7 @@ package services
 import (
 	"bytes"
 	"encoding/json"
+	"errors"
 	"fmt"
 	"hongze/hongze_clpt/models"
 	"hongze/hongze_clpt/utils"
@@ -12,7 +13,7 @@ import (
 	"time"
 )
 
-//发送报告提问消息提醒
+// 发送报告提问消息提醒
 func SendWxMsgWithAsk(name, askTime, askMsg, title string, openIdList []*models.OpenIdList, articleId int) (err error) {
 	var msg string
 	defer func() {
@@ -125,7 +126,7 @@ func SendTemplateMsg(sendUrl string, data []byte, resource string, sendType int,
 	return
 }
 
-//活动带问提醒
+// 活动带问提醒
 func SendActivityAskApplyTemplateMsgV2(keyword1, keyword2, keyword3, keyword4, remark string, itemOpenid *models.OpenIdList, itemAct *models.ActivityDetail) (err error) {
 	var msg string
 	defer func() {
@@ -181,3 +182,141 @@ func SendActivityAskApplyTemplateMsgV2(keyword1, keyword2, keyword3, keyword4, r
 	fmt.Println("send end")
 	return
 }
+
+// 微路演新增留言提问消息提醒
+func SendWxMsgWithMicroRoadshowAsk(req models.AddVideoCommnetReq, user *models.WxUserItem, resourceId int) (err error) {
+	var msg string
+	defer func() {
+		if err != nil || msg != "" {
+			go utils.SendEmail("发送模版消息失败"+"【"+utils.APPNAME+"】"+time.Now().Format("2006-01-02 15:04:05"), msg+";Err:"+err.Error(), utils.EmailSendToUsers)
+			go utils.SendAlarmMsg(fmt.Sprint("发送微路演新增留言提问消息提醒失败,用户名", req.Title, "ID:", req.Id), 2)
+			utils.FileLog.Info("发送模版消息失败,Err:%s", err.Error())
+		}
+	}()
+
+	companyItem, e := models.GetSellerDetailAllByCompanyId(user.CompanyId)
+	if e != nil {
+		return
+	}
+	if companyItem == nil {
+		msg = "获取客户所属销售信息失败,UserID:" + strconv.Itoa(user.UserId)
+	}
+	var first string
+	var keyword1 string
+	var keyword2 string
+	var keyword3 string
+	var keyword4 string
+	var remark string
+	first = req.Title + "有新的留言,请及时处理"
+	keyword1 = user.CompanyName + "——" + user.RealName + "(" + companyItem.SellerName + ")"
+	keyword3 = time.Now().Format(utils.FormatDateTime)
+	keyword2 = ""
+	keyword4 = req.Content
+
+	mobile := companyItem.Mobile + "," + utils.WxMsgTemplateIdAskMsgMobilePublic
+	openIdList, e := models.GetWxOpenIdByMobileList(mobile)
+	if e != nil {
+		err = errors.New("GetWxOpenIdByMobileList, Err: " + e.Error())
+		return
+	}
+	openIdArr := make([]string, 0)
+	for _, v := range openIdList {
+		openIdArr = append(openIdArr, v.OpenId)
+	}
+
+	//SourceType int    `description:"视频来源: 1-音频; 2-活动视频; 3-微路演视频 (不传默认为1)"`
+	redirectUrl := ""
+	if req.SourceType == 3 {
+		redirectUrl = utils.WX_MSG_PATH_ACTIVITY_INDUSTRYR_EPORT + strconv.Itoa(resourceId)
+		remark = "点击进入产业资源包详情页"
+	} else {
+		redirectUrl = utils.WX_MSG_PATH_ACTIVITY_DETAIL + strconv.Itoa(resourceId)
+		remark = "点击查看活动详情"
+	}
+	sendInfo := new(SendWxTemplate)
+	sendInfo.First = first
+	sendInfo.Keyword1 = keyword1
+	sendInfo.Keyword2 = keyword2
+	sendInfo.Keyword3 = keyword3
+	sendInfo.Keyword4 = keyword4
+	sendInfo.Remark = remark
+	sendInfo.TemplateId = utils.WxMsgTemplateIdAskMsgXzs
+	sendInfo.RedirectUrl = redirectUrl
+	sendInfo.RedirectTarget = 3
+	sendInfo.Resource = strconv.Itoa(req.Id)
+	sendInfo.SendType = utils.TEMPLATE_MSG_CYGX_COMMENT
+	sendInfo.OpenIdArr = openIdArr
+	err = PublicSendTemplateMsg(sendInfo)
+	if err != nil {
+		return
+	}
+	return
+}
+
+func SendCommentWxTemplateMsg(req models.AddCygxArticleCommentReq, user *models.WxUserItem, articleInfo *models.ArticleDetail) (err error) {
+	var msg string
+	defer func() {
+		if err != nil {
+			go utils.SendEmail("发送模版消息失败"+"【"+utils.APPNAME+"】"+time.Now().Format("2006-01-02 15:04:05"), msg+";Err:"+err.Error(), utils.EmailSendToUsers)
+			go utils.SendAlarmMsg(fmt.Sprint("发送用户用户留言提醒失败,文章ID:", req.ArticleId), 2)
+			utils.FileLog.Info("发送模版消息失败,Err:%s", err.Error())
+		}
+	}()
+
+	companyItem, e := models.GetSellerDetailAllByCompanyId(user.CompanyId)
+	if e != nil {
+		return
+	}
+	if companyItem == nil {
+		msg = "获取客户所属销售信息失败,UserID:" + strconv.Itoa(user.UserId)
+	}
+	var first string
+	var keyword1 string
+	var keyword2 string
+	var keyword3 string
+	var keyword4 string
+	var remark string
+	var redirectUrl string
+	var mobile string
+
+	first = "【" + articleInfo.Title + "】有新的留言,请及时处理"
+	keyword1 = user.CompanyName + "——" + user.RealName + "(" + companyItem.SellerName + ")"
+	keyword2 = "-"
+	keyword3 = time.Now().Format(utils.FormatDateTime)
+	keyword4 = req.Content
+	remark = "点击查看报告详情"
+	if articleInfo.ArticleId >= utils.SummaryArticleId {
+		//研选报告添加汪洋
+		mobile = companyItem.Mobile + "," + utils.WxMsgTemplateIdAskMsgMobilePublic + "," + utils.ActSendMsgMobile
+	} else {
+		mobile = companyItem.Mobile + "," + utils.WxMsgTemplateIdAskMsgMobilePublic
+	}
+	openIdList, e := models.GetWxOpenIdByMobileList(mobile)
+	if e != nil {
+		err = errors.New("GetWxOpenIdByMobileList, Err: " + e.Error())
+		return
+	}
+	openIdArr := make([]string, 0)
+	for _, v := range openIdList {
+		openIdArr = append(openIdArr, v.OpenId)
+	}
+	redirectUrl = utils.WX_MSG_PATH_ARTICLE_DETAIL + strconv.Itoa(articleInfo.ArticleId)
+	sendInfo := new(SendWxTemplate)
+	sendInfo.First = first
+	sendInfo.Keyword1 = keyword1
+	sendInfo.Keyword2 = keyword2
+	sendInfo.Keyword3 = keyword3
+	sendInfo.Keyword4 = keyword4
+	sendInfo.Remark = remark
+	sendInfo.TemplateId = utils.WxMsgTemplateIdAskMsgXzs
+	sendInfo.RedirectUrl = redirectUrl
+	sendInfo.RedirectTarget = 3
+	sendInfo.Resource = strconv.Itoa(req.ArticleId)
+	sendInfo.SendType = utils.TEMPLATE_MSG_CYGX_COMMENT
+	sendInfo.OpenIdArr = openIdArr
+	err = PublicSendTemplateMsg(sendInfo)
+	if err != nil {
+		return
+	}
+	return
+}

+ 79 - 0
services/yan_xuan.go

@@ -0,0 +1,79 @@
+package services
+
+import (
+	"errors"
+	"hongze/hongze_clpt/models"
+	"hongze/hongze_clpt/utils"
+	"strings"
+)
+
+// 处理研选关联的新标签
+func GetYanXuanIndustrialManagementIdNewMap(articleTypeIds string) (respMap map[int]bool, err error) {
+	var condition string
+	if articleTypeIds == "" {
+		return
+	}
+	condition = ` AND a.article_type_id IN (` + articleTypeIds + `)  `
+	list, e := models.GetIndustrialManagementNewList(condition)
+	if e != nil {
+		err = errors.New("GetIndustrialManagementNewList, Err: " + e.Error())
+		return
+	}
+	newMap := make(map[int]bool)
+	for _, v := range list {
+		newMap[v.IndustrialManagementId] = true
+	}
+	respMap = newMap
+	return
+}
+
+// 处理研选关联的hot标签
+func GetYanXuanIndustrialManagementIdHotMap(articleTypeIds string) (respMap map[int]bool, err error) {
+	var condition string
+	var conditionOrder string
+	if articleTypeIds == "" {
+		return
+	}
+	condition = ` AND a.article_type_id IN (` + articleTypeIds + `)  `
+	conditionOrder = ` ORDER BY sum_num DESC `
+	listHot, e := models.GetThemeHeatList(0, condition, conditionOrder, 0, 3)
+	if e != nil {
+		err = errors.New("GetIndustrialManagementNewList, Err: " + e.Error())
+		return
+	}
+	hotMap := make(map[int]bool)
+	for _, v := range listHot {
+		hotMap[v.IndustrialManagementId] = true
+	}
+	respMap = hotMap
+	return
+}
+
+// GetArticleSubjectName 获取文章关联的多个标的名称
+func GetArticleSubjectName(articleIds []int) (respMap, subjectMap map[int]string, err error) {
+	lenarticleIds := len(articleIds)
+	if lenarticleIds == 0 {
+		return
+	}
+	var condition string
+	var pars []interface{}
+	condition = ` AND ag.article_id IN (` + utils.GetOrmInReplace(len(articleIds)) + `)`
+	pars = append(pars, articleIds)
+	list, e := models.GetSubjectArticlGroupList(condition, pars)
+	if e != nil {
+		err = errors.New("GetIndustrialManagementNewList, Err: " + e.Error())
+		return
+	}
+	artMap := make(map[int]string)
+	subMap := make(map[int]string)
+	for _, v := range list {
+		artMap[v.ArticleId] += v.SubjectName + "/"
+		subMap[v.IndustrialSubjectId] = v.SubjectName
+	}
+	for _, v := range list {
+		artMap[v.ArticleId] = strings.TrimRight(artMap[v.ArticleId], "/")
+	}
+	respMap = artMap
+	subjectMap = subMap
+	return
+}

+ 15 - 10
utils/config.go

@@ -26,16 +26,17 @@ var (
 	WxPublicAppId     string //查研观向小助手公众号
 	WxPublicAppSecret string //查研观向小助手公众号
 
-	WxOpenAppId                      string //公众平台AppId
-	WxOpenAppSecret                  string //公众平台AppSecret
-	HeadimgurlDefault                string //默认头像
-	WxMsgTemplateIdApplyXzs          string //申请待处理(小助手)
-	WxMsgTemplateIdApplyCancelXzs    string //预约取消提醒(小助手)
-	WxMsgTemplateIdApply             string //申请待处理
-	WxMsgTemplateIdAskMsgMobile      string //手机号用户【XXX】发送模板消息
-	WxMsgTemplateIdAskMsgXzs         string //手机号用户【XXX】发送模板消息模板ID(小助手)
-	WxMsgTemplateIdArticleUserRemind string //用户阅读报告通知-模板ID
-	IndexName                        string
+	WxOpenAppId                       string //公众平台AppId
+	WxOpenAppSecret                   string //公众平台AppSecret
+	HeadimgurlDefault                 string //默认头像
+	WxMsgTemplateIdApplyXzs           string //申请待处理(小助手)
+	WxMsgTemplateIdApplyCancelXzs     string //预约取消提醒(小助手)
+	WxMsgTemplateIdApply              string //申请待处理
+	WxMsgTemplateIdAskMsgMobile       string //手机号用户【XXX】发送模板消息
+	WxMsgTemplateIdAskMsgXzs          string //手机号用户【XXX】发送模板消息模板ID(小助手)
+	IndexName                         string
+	WxMsgTemplateIdAskMsgMobilePublic string //手机号用户【XXX】发送模板消rm --
+	WxMsgTemplateIdArticleUserRemind  string //用户阅读报告通知-模板ID
 
 	ActSendMsgMobile string //活动带问发送模板消息接收者的手机号
 
@@ -44,6 +45,7 @@ var (
 	YiDongZhengTongYunSecret string //易董 证通云请求secret
 	YiDongHuaWeiYunUrl       string //易董 华为云请求域名
 	YiDonggetOriginalLink    string //易董 短连接转为长链接
+
 )
 
 // 模板消息推送
@@ -88,6 +90,9 @@ func init() {
 		fmt.Println(Re)
 		panic(Re)
 	}
+	WxAppId = "wxcc32b61f96720d2f"
+	WxAppSecret = "06894933fafb24dafead7eaae09c08e0"
+	WxMsgTemplateIdAskMsgMobilePublic = "15557270714,18767183922,18621268829"
 	if RunMode == "release" {
 		WxPublicAppId = "wxb7cb8a15abad5b8e"                                          //查研观向小助手
 		WxPublicAppSecret = "f425ba2863084249722af1e2a5cfffd3"                        //查研观向小助手

+ 23 - 2
utils/constants.go

@@ -59,6 +59,12 @@ var (
 	AccessKeySecret string = "12kk1ptCHoGWedhBnKRVW5hRJzq9Fq"
 )
 
+// 缓存key
+const (
+	CACHE_KEY_USER_VIEW           = "user_view_record"           //用户阅读数据
+	CACHE_KEY_ARTICLE_ID_TEMPLATE = "ce_lue_article_id_template" //策略平台同步过来的文章ID,做微信模板消息推送,同一篇报告12小时只推送一次
+)
+
 const (
 	CE_LUE_NAME                      string = "策略"
 	CE_LUE_ID                        int    = 23
@@ -85,6 +91,10 @@ const (
 	HONG_GUAN_ID                     int    = 1
 	HZ_COMPANY_ID                    int    = 16
 	YAN_XUAN_ARTICLE_TYPE_IDS        string = "1,2,12" // 属于研选的报告类型ID
+	REOURCE_YX                       string = "Yx"
+	REOURCE_HZ                       string = "Hz"
+	GU_SHOU_NAME                     string = "固收"
+	GU_SHOU_ID                       int    = 100000 // 自定义权限类型ID ,十万起步
 )
 
 // 模板消息推送类型
@@ -92,6 +102,7 @@ const (
 	TEMPLATE_MSG_CYGX_ACTIVITY_ADD = 12 //查研观向小程序活动更新推送 12
 	TEMPLATE_MSG_CYGX_ARTICLE_ADD  = 13 //查研观向报告更新推送  13
 	TEMPLATE_MSG_CYGX_APPLY        = 14 //查研观向审批通知
+	TEMPLATE_MSG_CYGX_COMMENT      = 15 //查研观向留言通知
 )
 
 const (
@@ -119,6 +130,9 @@ const (
 
 var YAN_XUAN_ARTICLE_TYPE_ID = []int{1, 2, 12}
 
+const (
+	YAN_XUAN_TAB_KEY = "yanxuan_header_tab"
+)
 const (
 	YD_TOKEN = "yidong_token"
 )
@@ -143,11 +157,18 @@ const (
 
 // 模板消息地址路由
 const (
-	WX_MSG_PATH_ARTICLE_DETAIL          = "pageMy/reportDetail/reportDetail?id="          //文章详情模板消息地址
-	WX_MSG_PATH_ACTIVITY_SPECIAL_DETAIL = "activityPages/specialDetail/specialDetail?id=" //专项调研活动模板消息地址
+	WX_MSG_PATH_ARTICLE_DETAIL           = "pageMy/reportDetail/reportDetail?id="            //文章详情模板消息地址
+	WX_MSG_PATH_ACTIVITY_SPECIAL_DETAIL  = "activityPages/specialDetail/specialDetail?id="   //专项调研活动模板消息地址
+	WX_MSG_PATH_ACTIVITY_INDUSTRYR_EPORT = "reportPages/IndustryReport/IndustryReport?id="   //产业文章列表模板消息地址
+	WX_MSG_PATH_ACTIVITY_DETAIL          = "activityPages/activityDetail/activityDetail?id=" //活动模板消息地址
 )
 
 // 微信模板消息推送公共接口的秘钥
 const (
 	SendTemplateMsgAuthorization = "dc855fce962a639faa779cbdd4cd332f"
 )
+
+// 时间线路由
+const (
+	TIME_LINE_ROUTE = "/api/report/industry/ArticleList?PageSize=10&CurrentIndex=1&CategoryId=99999&IndustrialManagementId="
+)