kobe6258 7 ay önce
ebeveyn
işleme
83731c4981

+ 10 - 0
common/exception/exc_enums.go

@@ -56,6 +56,10 @@ const (
 	AnalystNameEmptyError
 	GetFollowingAnalystListFailed
 	TransferFollowingAnalystListFailed
+	GetUserUnReadMsgFailed
+	IllegalMessageId
+	IllegalAnalystId
+	ReadMessageFailed
 )
 
 // WechatErrCode 微信
@@ -72,6 +76,7 @@ const (
 	GetPublishedRandListFailed
 	GetPermissionListFailed
 	ReportRecordClickCountFailed
+	MediaRecordClickCountFailed
 	GetHotRandListFailed
 	QueryReportPageFailed
 	SearchReportPageFailed
@@ -119,6 +124,10 @@ var ErrorMap = map[int]string{
 	AnalystNameEmptyError:              "研究员姓名不能为空",
 	GetFollowingAnalystListFailed:      "获取关注研究员列表失败",
 	TransferFollowingAnalystListFailed: "转换关注研究员列表失败",
+	GetUserUnReadMsgFailed:             "获取未读消息列表失败",
+	IllegalMessageId:                   "非法的消息ID",
+	ReadMessageFailed:                  "已读消息失败",
+	IllegalAnalystId:                   "研究员Id非法",
 	//微信
 	WeChatServerError:    "微信服务器发生错误",
 	WechatUserInfoFailed: "获取微信用户信息失败",
@@ -129,6 +138,7 @@ var ErrorMap = map[int]string{
 	GetPublishedRandListFailed:   "获取已发布研报列表失败",
 	GetPermissionListFailed:      "获取品种列表失败",
 	ReportRecordClickCountFailed: "添加点击访问次数失败",
+	MediaRecordClickCountFailed:  "添加媒体点击访问次数失败",
 	GetHotRandListFailed:         "获取热门研报列表失败",
 	QueryReportPageFailed:        "分页查询报告列表失败",
 	SearchReportPageFailed:       "分页搜索报告列表失败",

+ 10 - 0
common/utils/string/string_utils.go

@@ -34,3 +34,13 @@ func IntToStringSlice(intSlice []int) []string {
 	}
 	return strSlice
 }
+
+func RemoveEmptyStrings(slice []string) []string {
+	var filteredSlice []string
+	for _, s := range slice {
+		if s != "" {
+			filteredSlice = append(filteredSlice, s)
+		}
+	}
+	return filteredSlice
+}

+ 45 - 2
controllers/media/media_controller.go

@@ -6,6 +6,7 @@ import (
 	"eta/eta_mini_ht_api/common/utils/page"
 	"eta/eta_mini_ht_api/controllers"
 	"eta/eta_mini_ht_api/service/media"
+	"eta/eta_mini_ht_api/service/user"
 )
 
 type MediaController struct {
@@ -112,12 +113,54 @@ func (m *MediaController) GetMedia(mediaType string, mediaId int) {
 			m.FailedResult("获取媒体详情失败", result)
 			return
 		}
-		meidaDetail, err := media.GetMediaById(mediaType, mediaId)
+		mediaDetail, err := media.GetMediaById(mediaType, mediaId)
 		if err != nil {
 			m.FailedResult("获取媒体详情失败", result)
 			return
 		}
-		m.SuccessResult("获取媒体详情成功", meidaDetail, result)
+		m.SuccessResult("获取媒体详情成功", mediaDetail, result)
 		return
 	})
 }
+
+type RecordCountReq struct {
+	MediaId   int    `json:"MediaId"`
+	MediaType string `json:"MediaType"`
+}
+
+// Count 获取品种列表
+// @Description 获取最新发布的报告列表
+// @Success 200 {object}
+// @router /count [post]
+func (m *MediaController) Count() {
+	controllers.Wrap(&m.BaseController, func() (result *controllers.WrapData, err error) {
+		result = m.InitWrapData("媒体点击记录成功")
+		var userInfo user.User
+		userInfo = m.Data["user"].(user.User)
+		recordReq := new(RecordCountReq)
+		m.GetPostParams(recordReq)
+		if recordReq.MediaType == "" || !m.CheckMediaType(recordReq.MediaType) {
+			err = exception.New(exception.MediaTypeError)
+			m.FailedResult("媒体点击记录失败", result)
+			return
+		}
+		record := convertToRecordCount(recordReq)
+		record.UserId = userInfo.Id
+		record.Mobile = userInfo.Mobile
+		err = media.CountMedia(record)
+		if err != nil {
+			err = exception.New(exception.MediaRecordClickCountFailed)
+			m.FailedResult("媒体点击记录失败", result)
+			return
+		}
+		m.SuccessResult("媒体点击记录成功", nil, result)
+		return
+	})
+}
+func convertToRecordCount(req *RecordCountReq) media.RecordCount {
+	return media.RecordCount{
+		MediaId:    req.MediaId,
+		MediaType:  req.MediaType,
+		Additional: "",
+	}
+}

+ 79 - 0
controllers/user/user_controller.go

@@ -211,6 +211,85 @@ func (u *UserController) FollowingAnalystList() {
 	})
 }
 
+// UnReadMessageList  获取未读消息
+// @Summary 获取未读消息
+// @Description 获取未读消息
+// @Success 200 {object} controllers.BaseResponse
+// @router /message [get]
+func (u *UserController) UnReadMessageList() {
+	controllers.Wrap(&u.BaseController, func() (result *controllers.WrapData, err error) {
+		result = u.InitWrapData("获取我的未读消息失败")
+		userInfo := u.Data["user"].(user.User)
+		messages, err := user.GetUnReadMessageList(userInfo.Id)
+		if err != nil {
+			u.FailedResult("获取我的未读消息失败", result)
+			return
+		}
+		u.SuccessResult("获取我的未读消息成功", messages, result)
+		return
+	})
+}
+
+type ReadMessageReq struct {
+	AnalystId int `json:"analystId"`
+	MessageId int `json:"MessageId"`
+}
+
+// ReadMessage  获取未读消息
+// @Summary 获取未读消息
+// @Description 获取未读消息
+// @Success 200 {object} controllers.BaseResponse
+// @router /readMessage [post]
+func (u *UserController) ReadMessage() {
+	controllers.Wrap(&u.BaseController, func() (result *controllers.WrapData, err error) {
+		result = u.InitWrapData("获取我的未读消息失败")
+		readMessageReq := new(ReadMessageReq)
+		u.GetPostParams(readMessageReq)
+		if readMessageReq.MessageId <= 0 {
+			logger.Error("消息Id非法")
+			err = exception.New(exception.IllegalMessageId)
+			u.FailedResult("已读消息失败", result)
+			return
+		}
+		userInfo := u.Data["user"].(user.User)
+		if user.ReadMessage(userInfo.Id, readMessageReq.MessageId) {
+			u.SuccessResult("已读消息成功", nil, result)
+			return
+		} else {
+			err = exception.New(exception.ReadMessageFailed)
+			u.FailedResult("已读消息失败", result)
+			return
+		}
+	})
+}
+
+// ReadMessages  获取未读消息
+// @Summary 获取未读消息
+// @Description 获取未读消息
+// @Success 200 {object} controllers.BaseResponse
+// @router /readMessages [post]
+func (u *UserController) ReadMessages() {
+	controllers.Wrap(&u.BaseController, func() (result *controllers.WrapData, err error) {
+		result = u.InitWrapData("获取我的未读消息失败")
+		readMessageReq := new(ReadMessageReq)
+		u.GetPostParams(readMessageReq)
+		if readMessageReq.AnalystId <= 0 {
+			logger.Error("研究员Id非法")
+			err = exception.New(exception.IllegalAnalystId)
+			u.FailedResult("已读消息失败", result)
+			return
+		}
+		userInfo := u.Data["user"].(user.User)
+		if user.ReadMessages(userInfo.Id, readMessageReq.AnalystId) {
+			u.SuccessResult("已读消息成功", nil, result)
+			return
+		} else {
+			err = exception.New(exception.ReadMessageFailed)
+			u.FailedResult("已读消息失败", result)
+			return
+		}
+	})
+}
 func covertToUserProfile(user user.User) UserProfileReq {
 	return UserProfileReq{
 		UserName: user.Username,

+ 11 - 15
domian/report/report_service.go

@@ -75,16 +75,6 @@ type PermissionDTO struct {
 	ParentID int
 }
 
-type RecordCountDTO struct {
-	UserId     int
-	Mobile     string
-	ReportId   int
-	IpAddress  string
-	Location   string
-	Referer    string
-	Additional string
-}
-
 func GetGetReportById(reportId int) (ReportDTO ReportDTO, err error) {
 	report, err := reportDao.GetReportById(reportId)
 	if err == nil {
@@ -243,8 +233,13 @@ func SyncETAReportList(list []eta.ETAReport) (err error) {
 	var reports []reportDao.Report
 	var esReports []es.ESBase
 	for _, etaRp := range list {
-		destRp := convertEtaReport(etaRp)
-		reports = append(reports, destRp)
+		authorNames := strings.Split(etaRp.Author, ",")
+		authorNamesWithOutEmpty := stringUtils.RemoveEmptyStrings(authorNames)
+		for _, authorName := range authorNamesWithOutEmpty {
+			destRp := convertEtaReport(etaRp)
+			destRp.Author = authorName
+			reports = append(reports, destRp)
+		}
 	}
 	err = reportDao.BatchInsertReport(&reports)
 	if err != nil {
@@ -269,9 +264,10 @@ func SyncETAReportList(list []eta.ETAReport) (err error) {
 		if len(userIds) > 0 {
 			usersStr := stringUtils.IntToStringSlice(userIds)
 			Meta := userService.MetaData{
-				AuthorName: report.Author,
-				AuthorId:   author.Id,
-				SourceId:   report.ID,
+				AuthorName:    report.Author,
+				AuthorId:      author.Id,
+				SourceId:      report.ID,
+				PublishedTime: report.PublishedTime,
 			}
 			metaStr, _ := json.Marshal(Meta)
 			toStr := strings.Join(usersStr, ",")

+ 0 - 54
domian/report/user_report_click_flow_service.go

@@ -1,54 +0,0 @@
-package report
-
-import (
-	logger "eta/eta_mini_ht_api/common/component/log"
-	reportDao "eta/eta_mini_ht_api/models/user"
-)
-
-func CountReport(record RecordCountDTO) (err error) {
-	dao := convertUserToReportFlow(record)
-	err = reportDao.CountReportClicks(dao)
-	if err != nil {
-		logger.Error("插入用户研报点击记录失败:%v", err)
-		return
-	}
-	return
-}
-
-type HotReportDTO struct {
-	ReportId int `gorm:"column:report_id"`
-	Count    int `gorm:"column:count"`
-}
-
-func GetHotReports(begin string, end string, limit int) (dtoList []HotReportDTO) {
-	counts, err := reportDao.GetTimeDurationReportCountsById(begin, end, limit)
-	if err != nil {
-		logger.Error("获取最热研报数据失败:%v", err)
-		return
-	}
-	if counts == nil {
-		return []HotReportDTO{}
-	}
-	for _, count := range counts {
-		dtoList = append(dtoList, convertUserToHotReportDTO(count))
-	}
-	return
-}
-func convertUserToReportFlow(report RecordCountDTO) reportDao.UserReportClickFlow {
-	return reportDao.UserReportClickFlow{
-		UserID:         report.UserId,
-		Mobile:         report.Mobile,
-		ReportID:       report.ReportId,
-		IPAddress:      report.IpAddress,
-		Location:       report.Location,
-		Referer:        report.Referer,
-		AdditionalData: report.Additional,
-	}
-}
-
-func convertUserToHotReportDTO(flow reportDao.CountClickFlowById) HotReportDTO {
-	return HotReportDTO{
-		ReportId: flow.ReportId,
-		Count:    flow.Count,
-	}
-}

+ 10 - 3
domian/user/meta_info.go

@@ -5,6 +5,7 @@ import (
 )
 
 type MetaInfoDTO struct {
+	Id         int    `json:"id"`
 	Uid        string `json:"Uid,omitempty"`
 	Meta       string `json:"Meta,omitempty"`
 	From       string `json:"From,omitempty"`
@@ -14,9 +15,10 @@ type MetaInfoDTO struct {
 }
 
 type MetaData struct {
-	SourceId   int    `json:"reportId"`
-	AuthorId   int    `json:"AuthorId"`
-	AuthorName string `json:"authorName"`
+	SourceId      int    `json:"reportId"`
+	AuthorId      int    `json:"AuthorId"`
+	AuthorName    string `json:"authorName"`
+	PublishedTime string `json:"publishedTime"`
 }
 
 func CreateMetaInfo(dto MetaInfoDTO) (err error) {
@@ -34,6 +36,7 @@ func convertToMetaInfo(dto MetaInfoDTO) userDao.MetaInfo {
 }
 func convertToMetaDTO(dto userDao.MetaInfo) MetaInfoDTO {
 	return MetaInfoDTO{
+		Id:         dto.Id,
 		Uid:        dto.Uid,
 		Meta:       dto.Meta,
 		From:       dto.From,
@@ -50,3 +53,7 @@ func GetInitMetaInfos() (list []MetaInfoDTO) {
 	}
 	return
 }
+
+func PendingMetaInfo(id int) bool {
+	return userDao.PendingMetaInfo(id)
+}

+ 55 - 11
domian/user/user_message_service.go

@@ -17,6 +17,13 @@ type MessageDTO struct {
 	Status  string `gorm:"column:status;type:enum('UNREAD','READ')"`
 }
 
+type MyMessage struct {
+	Id       int    `json:"messageId"`
+	SourceId int    `json:"SourceId"`
+	Type     string `json:"Type"`
+	Message  string `json:"Message"`
+}
+
 const (
 	ReportMessageTemplate = "您关注的研究员%v更新了一篇报告"
 	VideoMessageTemplate  = "您关注的研究员%v更新了一个视频"
@@ -31,13 +38,13 @@ func CreateMessage(meta MetaInfoDTO) (err error) {
 	messageType := userDao.SourceType(meta.SourceType)
 	var messageList []userDao.UserMessage
 	users := strings.Split(meta.To, ",")
-	if err != nil {
-		logger.Error("unmarshal meta info error")
-		return
-	}
 	var message string
 	var content MetaData
 	err = json.Unmarshal([]byte(meta.Meta), &content)
+	if err != nil {
+		logger.Error("生成消息信息失败:%v", err)
+		userDao.FailedMetaInfo(meta.Id)
+	}
 	switch userDao.SourceType(meta.SourceType) {
 	case userDao.ReportSourceType:
 		message = fmt.Sprintf(ReportMessageTemplate, content.AuthorName)
@@ -50,14 +57,51 @@ func CreateMessage(meta MetaInfoDTO) (err error) {
 	for _, user := range users {
 		id, _ := strconv.Atoi(user)
 		userMessage := userDao.UserMessage{
-			From:     content.AuthorId,
-			To:       id,
-			Message:  message,
-			SourceId: content.SourceId,
-			Type:     messageType,
-			Status:   userDao.UnReadStatus,
+			AnalystId: content.AuthorId,
+			UserId:    id,
+			Message:   message,
+			SourceId:  content.SourceId,
+			Type:      messageType,
+			Status:    userDao.UnReadStatus,
 		}
 		messageList = append(messageList, userMessage)
 	}
-	return userDao.BatchInsertMessage(messageList)
+	if userDao.BatchInsertMessage(messageList) {
+		userDao.FinishMetaInfo(meta.Id)
+	} else {
+		logger.Error("生成消息信息失败:%v", err)
+		userDao.FailedMetaInfo(meta.Id)
+	}
+	return
+}
+
+func NeedNotice(userId int, analystId int) bool {
+	return userDao.NeedNotice(userId, analystId)
+}
+
+func ReadMessage(userId int, messageId int) bool {
+	return userDao.ReadMessage(userId, messageId)
+}
+func ReadMessages(userId int, analystId int) bool {
+	return userDao.ReadMessages(userId, analystId)
+}
+func GetUnReadMessageList(userId int) (messageList []MyMessage, err error) {
+	list, err := userDao.GetUnReadMessageList(userId)
+	if err != nil {
+		logger.Error("获取我的未读消息失败:%v", err)
+		return
+	}
+	for _, message := range list {
+		messageList = append(messageList, convertToMyMessage(message))
+	}
+	return
+}
+
+func convertToMyMessage(message userDao.UserMessage) MyMessage {
+	return MyMessage{
+		Id:       message.Id,
+		SourceId: message.SourceId,
+		Type:     string(message.Type),
+		Message:  message.Message,
+	}
 }

+ 83 - 0
domian/user/user_source_click_flow_service.go

@@ -0,0 +1,83 @@
+package user
+
+import (
+	logger "eta/eta_mini_ht_api/common/component/log"
+	userDao "eta/eta_mini_ht_api/models/user"
+)
+
+type RecordCountDTO struct {
+	UserId     int
+	Mobile     string
+	SourceId   int
+	SourceType userDao.SourceType
+	IpAddress  string
+	Location   string
+	Referer    string
+	Additional string
+}
+
+func CountReport(record RecordCountDTO) (err error) {
+	dao := convertUserToReportFlow(record)
+	err = userDao.CountSourceClicks(dao)
+	if err != nil {
+		logger.Error("插入用户研报点击记录失败:%v", err)
+		return
+	}
+	return
+}
+
+func CountMedia(record RecordCountDTO) (err error) {
+	dao := convertUserToMediaFlow(record)
+	err = userDao.CountSourceClicks(dao)
+	if err != nil {
+		logger.Error("插入用户研报点击记录失败:%v", err)
+		return
+	}
+	return
+}
+
+type HotReportDTO struct {
+	ReportId int `gorm:"column:report_id"`
+	Count    int `gorm:"column:count"`
+}
+
+func GetHotReports(begin string, end string, limit int) (dtoList []HotReportDTO) {
+	counts, err := userDao.GetTimeDurationReportCountsById(begin, end, limit, userDao.ReportSourceType)
+	if err != nil {
+		logger.Error("获取最热研报数据失败:%v", err)
+		return
+	}
+	if counts == nil {
+		return []HotReportDTO{}
+	}
+	for _, count := range counts {
+		dtoList = append(dtoList, convertUserToHotReportDTO(count))
+	}
+	return
+}
+func convertUserToReportFlow(report RecordCountDTO) userDao.UserSourceClickFlow {
+	return userDao.UserSourceClickFlow{
+		UserID:         report.UserId,
+		Mobile:         report.Mobile,
+		SourceId:       report.SourceId,
+		SourceType:     userDao.ReportSourceType,
+		IPAddress:      report.IpAddress,
+		Location:       report.Location,
+		Referer:        report.Referer,
+		AdditionalData: report.Additional,
+	}
+}
+func convertUserToMediaFlow(media RecordCountDTO) userDao.UserSourceClickFlow {
+	return userDao.UserSourceClickFlow{
+		UserID:     media.UserId,
+		Mobile:     media.Mobile,
+		SourceId:   media.SourceId,
+		SourceType: media.SourceType,
+	}
+}
+func convertUserToHotReportDTO(flow userDao.CountClickFlowById) HotReportDTO {
+	return HotReportDTO{
+		ReportId: flow.SourceId,
+		Count:    flow.Count,
+	}
+}

+ 21 - 0
models/user/meta_info.go

@@ -57,3 +57,24 @@ func GetInitMetaInfos() (list []MetaInfo) {
 	}
 	return list
 }
+
+func PendingMetaInfo(id int) bool {
+	return updateStatus(id, PendingStatusType)
+}
+
+func FinishMetaInfo(id int) bool {
+	return updateStatus(id, FinishStatusType)
+}
+func FailedMetaInfo(id int) bool {
+	return updateStatus(id, FailedStatusType)
+}
+
+func updateStatus(id int, status StatusType) bool {
+	db := models.Main()
+	err := db.Model(&MetaInfo{}).Where("id = ?", id).Update("status", status).Error
+	if err != nil {
+		logger.Error("更新meta数据失败:%v", err)
+		return false
+	}
+	return true
+}

+ 1 - 1
models/user/user_analyst_follow_list.go

@@ -30,7 +30,7 @@ type UserAnalystFollowList struct {
 
 func GetPostUser(authorName string, PublishTime string) (ids []int) {
 	db := models.Main()
-	err := db.Model(&UserAnalystFollowList{}).Select("user_id").Where("financial_analyst_name = ? and followed = ? and followed_time <=?", authorName, Following, PublishTime).Order("followed_time desc").Find(&ids).Error
+	err := db.Model(&UserAnalystFollowList{}).Select("user_id").Where("financial_analyst_name = ? and followed = ? and followed_time <=Date(?)", authorName, Following, PublishTime).Order("id asc").Find(&ids).Error
 	if err != nil {
 		return []int{}
 	}

+ 45 - 9
models/user/user_message.go

@@ -10,16 +10,17 @@ import (
 type MessageType string
 
 const (
-	UnReadStatus StatusType = "UNREAD"
-	ReadStatus   StatusType = "READ"
-	MaxBatchNum             = 1000
+	UnReadStatus     StatusType = "UNREAD"
+	ReadStatus       StatusType = "READ"
+	MaxBatchNum                 = 1000
+	MyMessageColumns            = "id,source_id,type,message"
 )
 
 // UserMessage 表示 user_message 表的模型
 type UserMessage struct {
 	Id          int        `gorm:"primaryKey;autoIncrement;column:id"`
-	From        int        `gorm:"column:from"`
-	To          int        `gorm:"column:to"`
+	AnalystId   int        `gorm:"column:analyst_id"`
+	UserId      int        `gorm:"column:user_id"`
 	SourceId    int        `gorm:"column:source_id"`
 	Message     string     `gorm:"column:message"`
 	Type        SourceType `gorm:"column:type;type:enum('REPORT','VIDEO','AUDIO')"`
@@ -38,16 +39,51 @@ func CreateMessage(message UserMessage) (err error) {
 	return db.Create(&message).Error
 }
 
-func BatchInsertMessage(messages []UserMessage) (err error) {
+func BatchInsertMessage(messages []UserMessage) bool {
 	db := models.Main()
 	//手动事务
 	tx := db.Begin()
-	err = db.CreateInBatches(messages, MaxBatchNum).Error
+	err := db.CreateInBatches(messages, MaxBatchNum).Error
 	if err != nil {
 		logger.Error("批量插入消息失败:%v", err)
 		tx.Rollback()
-		return
+		return false
 	}
 	tx.Commit()
-	return nil
+	return true
+}
+
+func NeedNotice(userId int, analystId int) bool {
+	db := models.Main()
+	var count int
+	err := db.Model(&UserMessage{}).Select("count(*)").Where("user_id =? and analyst_id =? and status=?", userId, analystId, UnReadStatus).Scan(&count).Error
+	if err != nil {
+		logger.Error("统计未读消息失败:%v", err)
+		return false
+	}
+	return count > 0
+}
+
+func GetUnReadMessageList(userId int) (messages []UserMessage, err error) {
+	db := models.Main()
+	err = db.Select(MyMessageColumns).Where("user_id=?  and status=?", userId, UnReadStatus).Order("created_time desc").Find(&messages).Error
+	return
+}
+
+func ReadMessage(userId int, messageId int) bool {
+	db := models.Main()
+	err := db.Model(&UserMessage{}).Where("id=? and user_id=?", messageId, userId).Update("status", ReadStatus).Error
+	if err != nil {
+		return false
+	}
+	return true
+}
+
+func ReadMessages(userId int, analystId int) bool {
+	db := models.Main()
+	err := db.Model(&UserMessage{}).Where("user_id=? and analyst_id =?", userId, analystId).Update("status", ReadStatus).Error
+	if err != nil {
+		return false
+	}
+	return true
 }

+ 0 - 46
models/user/user_report_click_flow.go

@@ -1,46 +0,0 @@
-package user
-
-import (
-	"eta/eta_mini_ht_api/models"
-	"gorm.io/gorm"
-	"time"
-)
-
-const (
-	userReportClickFlows = "user_report_click_flows"
-)
-
-// UserReportClickFlow 用户点击研报流水记录
-type UserReportClickFlow struct {
-	ID             int       `gorm:"column:id;primaryKey;autoIncrement:'id'"`
-	UserID         int       `gorm:"column:user_id"` // 用户ID\
-	Mobile         string    `gorm:"column:mobile"`
-	ReportID       int       `gorm:"column:report_id"`       // 研报ID
-	ClickTime      time.Time `gorm:"column:click_time"`      // 点击时间
-	IPAddress      string    `gorm:"column:ip_address"`      // IP地址
-	Location       string    `gorm:"column:location"`        // 地理位置
-	Referer        string    `gorm:"column:referer"`         // 来源页面
-	AdditionalData string    `gorm:"column:additional_data"` // 额外数据
-}
-
-func (v *UserReportClickFlow) BeforeCreate(tx *gorm.DB) (err error) {
-	v.ClickTime = time.Now()
-	return
-}
-
-func CountReportClicks(count UserReportClickFlow) (err error) {
-	db := models.Main()
-	err = db.Create(&count).Error
-	return
-}
-
-type CountClickFlowById struct {
-	ReportId int `gorm:"column:report_id"`
-	Count    int `gorm:"column:count"`
-}
-
-func GetTimeDurationReportCountsById(begin string, end string, limit int) (ids []CountClickFlowById, err error) {
-	db := models.Main()
-	err = db.Table(userReportClickFlows).Select("report_id,count(*) count").Where("DATE(click_time) BETWEEN ? AND ?", begin, end).Group("report_id").Order("count desc").Limit(limit).Scan(&ids).Error
-	return
-}

+ 47 - 0
models/user/user_source_click_flow.go

@@ -0,0 +1,47 @@
+package user
+
+import (
+	"eta/eta_mini_ht_api/models"
+	"gorm.io/gorm"
+	"time"
+)
+
+const (
+	userSourceClickFlows = "user_source_click_flows"
+)
+
+// UserReportClickFlow 用户点击研报流水记录
+type UserSourceClickFlow struct {
+	ID             int        `gorm:"column:id;primaryKey;autoIncrement:'id'"`
+	UserID         int        `gorm:"column:user_id"` // 用户ID\
+	Mobile         string     `gorm:"column:mobile"`
+	SourceId       int        `gorm:"column:source_id"` // 研报ID
+	SourceType     SourceType `gorm:"column:source_type;type:enum('REPORT','VIDEO','AUDIO')"`
+	ClickTime      time.Time  `gorm:"column:click_time"`      // 点击时间
+	IPAddress      string     `gorm:"column:ip_address"`      // IP地址
+	Location       string     `gorm:"column:location"`        // 地理位置
+	Referer        string     `gorm:"column:referer"`         // 来源页面
+	AdditionalData string     `gorm:"column:additional_data"` // 额外数据
+}
+
+func (v *UserSourceClickFlow) BeforeCreate(tx *gorm.DB) (err error) {
+	v.ClickTime = time.Now()
+	return
+}
+
+func CountSourceClicks(count UserSourceClickFlow) (err error) {
+	db := models.Main()
+	err = db.Create(&count).Error
+	return
+}
+
+type CountClickFlowById struct {
+	SourceId int `gorm:"column:source_id"`
+	Count    int `gorm:"column:count"`
+}
+
+func GetTimeDurationReportCountsById(begin string, end string, limit int, sourceType SourceType) (ids []CountClickFlowById, err error) {
+	db := models.Main()
+	err = db.Table(userSourceClickFlows).Select("source_id,count(*) count").Where("source_type=? and DATE(click_time) BETWEEN ? AND ?", sourceType, begin, end).Group("source_id").Order("count desc").Limit(limit).Scan(&ids).Error
+	return
+}

+ 36 - 0
routers/commentsRouter.go

@@ -7,6 +7,15 @@ import (
 
 func init() {
 
+    beego.GlobalControllerRouter["eta/eta_mini_ht_api/controllers/media:MediaController"] = append(beego.GlobalControllerRouter["eta/eta_mini_ht_api/controllers/media:MediaController"],
+        beego.ControllerComments{
+            Method: "Count",
+            Router: `/count`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
     beego.GlobalControllerRouter["eta/eta_mini_ht_api/controllers/media:MediaController"] = append(beego.GlobalControllerRouter["eta/eta_mini_ht_api/controllers/media:MediaController"],
         beego.ControllerComments{
             Method: "List",
@@ -273,6 +282,15 @@ func init() {
             Filters: nil,
             Params: nil})
 
+    beego.GlobalControllerRouter["eta/eta_mini_ht_api/controllers/user:UserController"] = append(beego.GlobalControllerRouter["eta/eta_mini_ht_api/controllers/user:UserController"],
+        beego.ControllerComments{
+            Method: "UnReadMessageList",
+            Router: `/message`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
     beego.GlobalControllerRouter["eta/eta_mini_ht_api/controllers/user:UserController"] = append(beego.GlobalControllerRouter["eta/eta_mini_ht_api/controllers/user:UserController"],
         beego.ControllerComments{
             Method: "Profile",
@@ -282,4 +300,22 @@ func init() {
             Filters: nil,
             Params: nil})
 
+    beego.GlobalControllerRouter["eta/eta_mini_ht_api/controllers/user:UserController"] = append(beego.GlobalControllerRouter["eta/eta_mini_ht_api/controllers/user:UserController"],
+        beego.ControllerComments{
+            Method: "ReadMessage",
+            Router: `/readMessage`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta/eta_mini_ht_api/controllers/user:UserController"] = append(beego.GlobalControllerRouter["eta/eta_mini_ht_api/controllers/user:UserController"],
+        beego.ControllerComments{
+            Method: "ReadMessages",
+            Router: `/readMessages`,
+            AllowHTTPMethods: []string{"post"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
 }

+ 46 - 0
service/media/media_service.go

@@ -6,10 +6,56 @@ import (
 	"eta/eta_mini_ht_api/common/utils/page"
 	stringUtils "eta/eta_mini_ht_api/common/utils/string"
 	mediaService "eta/eta_mini_ht_api/domian/media"
+	userService "eta/eta_mini_ht_api/domian/user"
+	"eta/eta_mini_ht_api/models/user"
 	"strings"
 	"sync"
 )
 
+const (
+	video = "video"
+	audio = "audio"
+)
+
+type RecordCount struct {
+	UserId     int
+	Mobile     string
+	MediaId    int
+	MediaType  string
+	IpAddress  string
+	Location   string
+	Referer    string
+	Additional string
+}
+
+func convertToMediaCountDTO(record RecordCount, sourceType user.SourceType) (dto userService.RecordCountDTO) {
+	return userService.RecordCountDTO{
+		UserId:     record.UserId,
+		Mobile:     record.Mobile,
+		SourceId:   record.MediaId,
+		SourceType: sourceType,
+	}
+}
+func getSourceType(mediaType string) user.SourceType {
+	switch mediaType {
+	case video:
+		return user.VideoSourceType
+	case audio:
+		return user.AudioSourceType
+	default:
+		return ""
+	}
+}
+func CountMedia(count RecordCount) (err error) {
+	media, err := mediaService.GetMediaById(count.MediaType, count.MediaId)
+	sourceType := getSourceType(media.MediaType)
+	if sourceType == "" {
+		err = exception.New(exception.MediaTypeError)
+		return
+	}
+	dto := convertToMediaCountDTO(count, sourceType)
+	return userService.CountMedia(dto)
+}
 func GetTotalPageCount(mediaType string) (count int64, latestId int64) {
 	if mediaType == "" {
 		return

+ 6 - 5
service/report/report_service.go

@@ -7,6 +7,7 @@ import (
 	"eta/eta_mini_ht_api/common/utils/date"
 	"eta/eta_mini_ht_api/common/utils/page"
 	reportService "eta/eta_mini_ht_api/domian/report"
+	userService "eta/eta_mini_ht_api/domian/user"
 	"sync"
 	"time"
 )
@@ -166,12 +167,12 @@ func GetReportPageByAnalyst(pageInfo page.PageInfo, analyst string) (list []repo
 }
 func CountReport(count RecordCount) error {
 	dto := convertToRecordCountDTO(count)
-	return reportService.CountReport(dto)
+	return userService.CountReport(dto)
 }
 func GetRandedReportByWeeklyHot(limit int) (reports []HotRankedReport, err error) {
 	end := time.Now()
 	begin := date.GetBeginOfTheWeek(end, time.Monday)
-	hotReports := reportService.GetHotReports(begin.Format(time.DateOnly), end.Format(time.DateOnly), limit)
+	hotReports := userService.GetHotReports(begin.Format(time.DateOnly), end.Format(time.DateOnly), limit)
 	if len(hotReports) > 0 {
 		var dtoList []reportService.ReportDTO
 		var ids []int
@@ -312,11 +313,11 @@ func convertToPublishRankedReportList(dtoList []reportService.ReportDTO) (report
 	return
 }
 
-func convertToRecordCountDTO(record RecordCount) (dto reportService.RecordCountDTO) {
-	return reportService.RecordCountDTO{
+func convertToRecordCountDTO(record RecordCount) (dto userService.RecordCountDTO) {
+	return userService.RecordCountDTO{
 		UserId:     record.UserId,
 		Mobile:     record.Mobile,
-		ReportId:   record.ReportId,
+		SourceId:   record.ReportId,
 		IpAddress:  record.IpAddress,
 		Location:   record.Location,
 		Referer:    record.Referer,

+ 37 - 1
service/user/user_service.go

@@ -5,6 +5,8 @@ import (
 	"eta/eta_mini_ht_api/common/exception"
 	analystService "eta/eta_mini_ht_api/domian/financial_analyst"
 	userService "eta/eta_mini_ht_api/domian/user"
+	"sort"
+	"sync"
 	"time"
 )
 
@@ -67,6 +69,25 @@ func GetFollowingAnalystList(userId int) (analysts []FollowAnalystDTO, err error
 		err = exception.New(exception.GetFollowingAnalystListFailed)
 	}
 	analysts, err = convertToAnalystList(dtoList)
+	var wg sync.WaitGroup
+	wg.Add(len(analysts))
+	for i := 0; i < len(analysts); i++ {
+		go func(followDTo *FollowAnalystDTO) {
+			defer wg.Done()
+			followDTo.NeedNotice = userService.NeedNotice(userId, followDTo.AnalystId)
+		}(&analysts[i])
+	}
+	wg.Wait()
+	//排序
+	sort.Slice(analysts, func(i, j int) bool {
+		// 首先按 NeedNotice 排序
+		if analysts[i].NeedNotice == analysts[j].NeedNotice {
+			// 对于 NeedNotice 相同的情况下,进行倒序排列
+			return analysts[i].FollowedTime.After(analysts[j].FollowedTime)
+		}
+		// NeedNotice 为 true 的排在 false 的前面
+		return analysts[i].NeedNotice
+	})
 	if err != nil {
 		logger.Error("转换研究员列表失败:%v", err)
 		err = exception.New(exception.TransferFollowingAnalystListFailed)
@@ -74,11 +95,26 @@ func GetFollowingAnalystList(userId int) (analysts []FollowAnalystDTO, err error
 	return
 }
 
+func GetUnReadMessageList(userId int) (messages []userService.MyMessage, err error) {
+	messages, err = userService.GetUnReadMessageList(userId)
+	if err != nil {
+		err = exception.New(exception.GetUserUnReadMsgFailed)
+	}
+	return
+}
+func ReadMessage(userId int, messageId int) bool {
+	return userService.ReadMessage(userId, messageId)
+}
+
+func ReadMessages(userId int, analystId int) bool {
+	return userService.ReadMessages(userId, analystId)
+}
+
 type FollowAnalystDTO struct {
 	AnalystId    int       `json:"analystId"`
 	AnalystName  string    `json:"analystName"`
 	HeadImgUrl   string    `json:"headImgUrl"`
-	FollowedTime time.Time `json:"-"`
+	FollowedTime time.Time `json:"followedTime"`
 	NeedNotice   bool      `json:"needNotice"`
 }
 

+ 1 - 1
task/eta/author/eta_author_task.go

@@ -55,6 +55,6 @@ func convert(author eta.ReportAuthor) financial_analyst.FinancialAnalystDTO {
 	}
 }
 func init() {
-	authorTask := base.NewTask(taskName, cron, new(AuthorTask), base.PROD)
+	authorTask := base.NewTask(taskName, cron, new(AuthorTask), base.DEV)
 	base.RegisterTask(&authorTask)
 }

+ 1 - 6
task/eta/report/eta_report_task.go

@@ -7,7 +7,6 @@ import (
 	"eta/eta_mini_ht_api/domian/report"
 	"eta/eta_mini_ht_api/models/eta"
 	"eta/eta_mini_ht_api/task/base"
-	"go/types"
 )
 
 var (
@@ -15,10 +14,6 @@ var (
 	cron                   = "0/10 * * * * *"
 )
 
-var (
-	reportChan types.Chan
-)
-
 // Execute Task ETA取研报的数据
 func (re *ReportTask) Execute(taskDetail *base.TaskDetail) error {
 	logger.Info(contants.TaskFormat, "同步ETA研报库开始")
@@ -50,6 +45,6 @@ type ReportTask struct {
 }
 
 func init() {
-	reportTask := base.NewTask(taskName, cron, new(ReportTask), base.PROD)
+	reportTask := base.NewTask(taskName, cron, new(ReportTask), base.DEV)
 	base.RegisterTask(&reportTask)
 }

+ 10 - 4
task/message/notice_task.go

@@ -14,7 +14,7 @@ var (
 )
 
 // Execute Task ETA取研报的数据
-func (au *NoticeTask) Execute(taskDetail *base.TaskDetail) error {
+func (au *NoticeTask) Execute(taskDetail *base.TaskDetail) (err error) {
 	logger.Info(contants.TaskFormat, "监听更新通知开始")
 	metaInfoList := userService.GetInitMetaInfos()
 	var wg sync.WaitGroup
@@ -22,17 +22,23 @@ func (au *NoticeTask) Execute(taskDetail *base.TaskDetail) error {
 	for _, metaInfo := range metaInfoList {
 		go func(metaInfo userService.MetaInfoDTO) {
 			defer wg.Done()
-			userService.CreateMessage(metaInfo)
+			if !userService.PendingMetaInfo(metaInfo.Id) {
+				return
+			}
+			msgErr := userService.CreateMessage(metaInfo)
+			if msgErr != nil {
+				logger.Error("生成消息失败:%v", err)
+			}
 		}(metaInfo)
 	}
 	//报告和媒体
-	return nil
+	return
 }
 
 type NoticeTask struct {
 }
 
 func init() {
-	reportTask := base.NewTask(taskName, cron, new(NoticeTask), base.PROD)
+	reportTask := base.NewTask(taskName, cron, new(NoticeTask), base.DEV)
 	base.RegisterTask(&reportTask)
 }