kobe6258 7 ماه پیش
والد
کامیت
0665cf7ae6

+ 32 - 14
common/exception/exc_enums.go

@@ -33,6 +33,7 @@ const (
 	AnalystNotFound
 	IllegalAreaCode
 	MediaTypeError
+	GetAnalystListFailed
 )
 
 // UserErrCode 用户
@@ -52,6 +53,9 @@ const (
 	UserFollowAnalystFailed
 	GetNoticeFileError
 	GetDisclaimerFileError
+	AnalystNameEmptyError
+	GetFollowingAnalystListFailed
+	TransferFollowingAnalystListFailed
 )
 
 // WechatErrCode 微信
@@ -75,6 +79,13 @@ const (
 	SearchKeyEmptyError
 )
 
+const (
+	MediaErrCode int = iota + 60000 // iota 自动递增,从 1 开始
+	MediaFoundFailed
+	GetMediaListFailed
+	GetAnalystMediaListFailed
+)
+
 // ErrorMap 用于存储错误码和错误信息的映射
 var ErrorMap = map[int]string{
 	UnknownError:          "未知错误",
@@ -90,21 +101,24 @@ var ErrorMap = map[int]string{
 	GetAreaCodesFailed:    "获取手机区号失败",
 	IllegalAreaCode:       "无效的区号",
 	MediaTypeError:        "媒体类型非法",
-
+	GetAnalystListFailed:  "获取研究员列表失败",
 	//用户
-	TemplateUserNotFound:     "临时用户记录不存在",
-	TemplateUserCreateFailed: "创建临时用户失败",
-	GenerateTokenFailed:      "创建token失败",
-	JWTTokenDecodeFailed:     "token解析失败",
-	JWTTokenExpired:          "token已过期",
-	JWTTokenInvalid:          "token无效",
-	NotCurrentUserError:      "用户信息不一致,非当前手机用户操作",
-	FeedBackMsgEmpty:         "反馈信息不能为空",
-	FeedBackError:            "提交反馈信息失败",
-	IllegalFollowType:        "无效的关注类型",
-	UserFollowAnalystFailed:  "关注研究员失败",
-	GetNoticeFileError:       "获取注册须知失败",
-	GetDisclaimerFileError:   "获取免责声明失败",
+	TemplateUserNotFound:               "临时用户记录不存在",
+	TemplateUserCreateFailed:           "创建临时用户失败",
+	GenerateTokenFailed:                "创建token失败",
+	JWTTokenDecodeFailed:               "token解析失败",
+	JWTTokenExpired:                    "token已过期",
+	JWTTokenInvalid:                    "token无效",
+	NotCurrentUserError:                "用户信息不一致,非当前手机用户操作",
+	FeedBackMsgEmpty:                   "反馈信息不能为空",
+	FeedBackError:                      "提交反馈信息失败",
+	IllegalFollowType:                  "无效的关注类型",
+	UserFollowAnalystFailed:            "关注研究员失败",
+	GetNoticeFileError:                 "获取注册须知失败",
+	GetDisclaimerFileError:             "获取免责声明失败",
+	AnalystNameEmptyError:              "研究员姓名不能为空",
+	GetFollowingAnalystListFailed:      "获取关注研究员列表失败",
+	TransferFollowingAnalystListFailed: "转换关注研究员列表失败",
 	//微信
 	WeChatServerError:    "微信服务器发生错误",
 	WechatUserInfoFailed: "获取微信用户信息失败",
@@ -120,6 +134,10 @@ var ErrorMap = map[int]string{
 	SearchReportPageFailed:       "分页搜索报告列表失败",
 	GetReportFailed:              "获取研报详情失败",
 	SearchKeyEmptyError:          "搜索关键字不能为空",
+	//媒体
+	MediaFoundFailed:          "查询媒体信息失败",
+	GetMediaListFailed:        "查询媒体列表失败",
+	GetAnalystMediaListFailed: "查询研究员媒体列表失败",
 }
 
 func Equals(code int, message string) bool {

+ 1 - 1
common/utils/page/page_utils.go

@@ -13,7 +13,7 @@ type PageResult struct {
 	Data interface{}
 }
 type Page struct {
-	LatestId  int64 `json:"latestId"`
+	LatestId  int64 `json:"latestId,omitempty"`
 	Current   int   `json:"current"`
 	PageSize  int   `json:"pageSize"`
 	Total     int64 `json:"total"`

+ 13 - 0
controllers/list_contoller.go

@@ -12,6 +12,11 @@ type ListController struct {
 	PageInfo page.PageInfo
 }
 
+const (
+	video = "video"
+	audio = "audio"
+)
+
 func (l *ListController) Prepare() {
 	pageSize, _ := l.GetInt("pageSize")
 	currentIndex, _ := l.GetInt("currentIndex")
@@ -48,6 +53,14 @@ func (l *ListController) TransPermissionIds(permissionIds string) (permissionIdL
 	}
 	return
 }
+
+func (l *ListController) CheckMediaType(mediaType string) bool {
+	if mediaType == video || mediaType == audio {
+		return true
+	}
+	return false
+}
+
 func (l *ListController) Finish() {
 	l.PageInfo.Reset()
 }

+ 26 - 55
controllers/media/media_controller.go

@@ -1,24 +1,17 @@
 package media
 
 import (
-	"encoding/json"
 	logger "eta_mini_ht_api/common/component/log"
 	"eta_mini_ht_api/common/exception"
 	"eta_mini_ht_api/common/utils/page"
 	"eta_mini_ht_api/controllers"
 	"eta_mini_ht_api/service/media"
-	"eta_mini_ht_api/service/report"
 )
 
 type MediaController struct {
 	controllers.ListController
 }
 
-const (
-	video = "video"
-	audio = "audio"
-)
-
 // Search 搜索报告列表
 // @Description 搜索报告列表
 // @Success 200 {object}
@@ -31,7 +24,7 @@ func (m *MediaController) Search(mediaType string, key string) {
 			m.FailedResult("分页搜索报告列表失败", result)
 			return
 		}
-		if mediaType == "" || !checkMediaType(mediaType) {
+		if mediaType == "" || !m.CheckMediaType(mediaType) {
 			err = exception.New(exception.MediaTypeError)
 			m.FailedResult("分页查询媒体列表失败", result)
 			return
@@ -68,7 +61,7 @@ func (m *MediaController) Search(mediaType string, key string) {
 func (m *MediaController) List(mediaType string, permissionIds string) {
 	controllers.Wrap(&m.BaseController, func() (result *controllers.WrapData, err error) {
 		result = m.InitWrapData("分页查询媒体列表失败")
-		if mediaType == "" || !checkMediaType(mediaType) {
+		if mediaType == "" || !m.CheckMediaType(mediaType) {
 			err = exception.New(exception.MediaTypeError)
 			m.FailedResult("分页查询媒体列表失败", result)
 			return
@@ -99,54 +92,32 @@ func (m *MediaController) List(mediaType string, permissionIds string) {
 			m.FailedResult("分页查询媒体列表失败", result)
 			return
 		}
-		reports := new(page.PageResult)
-		reports.Data = list
-		reports.Page = pageRes
-		m.SuccessResult("分页查询媒体列表成功", reports, result)
+		mediaList := new(page.PageResult)
+		mediaList.Data = list
+		mediaList.Page = pageRes
+		m.SuccessResult("分页查询媒体列表成功", mediaList, result)
 		return
 	})
 }
 
-type RecordCountReq struct {
-	ReportId   int         `json:"reportId"`
-	IpAddress  string      `json:"ipAddress"`
-	Location   string      `json:"location"`
-	Referer    string      `json:"referer"`
-	Additional interface{} `json:"additional"`
-}
-
-// // GetReport 获取研报详情
-// // @Description 获取研报详情
-// // @Success 200 {object}
-// // @router /report [get]
-//
-//	func (r *ReportController) GetReport(reportId int) {
-//		controllers.Wrap(&r.BaseController, func() (result *controllers.WrapData, err error) {
-//			result = r.InitWrapData("获取研报详情失败")
-//			fmt.Println(reportId)
-//			reportDetail, err := report.GetReportById(reportId)
-//			if err != nil {
-//				err = exception.New(exception.GetReportFailed)
-//				return
-//			}
-//			r.SuccessResult("获取研报详情成功", reportDetail, result)
-//			return
-//		})
-//	}
-func convertToRecordCount(req *RecordCountReq) report.RecordCount {
-	additionStr, _ := json.Marshal(req.Additional)
-	return report.RecordCount{
-		ReportId:   req.ReportId,
-		IpAddress:  req.IpAddress,
-		Location:   req.Location,
-		Referer:    req.Referer,
-		Additional: string(additionStr),
-	}
-}
-
-func checkMediaType(mediaType string) bool {
-	if mediaType == video || mediaType == audio {
-		return true
-	}
-	return false
+// GetMedia 获取媒体详情
+// @Description 获取媒体详情
+// @Success 200 {object}
+// @router /media [get]
+func (m *MediaController) GetMedia(mediaType string, mediaId int) {
+	controllers.Wrap(&m.BaseController, func() (result *controllers.WrapData, err error) {
+		result = m.InitWrapData("获取媒体详情失败")
+		if mediaType == "" || !m.CheckMediaType(mediaType) {
+			err = exception.New(exception.MediaTypeError)
+			m.FailedResult("获取媒体详情失败", result)
+			return
+		}
+		meidaDetail, err := media.GetMediaById(mediaType, mediaId)
+		if err != nil {
+			m.FailedResult("获取媒体详情失败", result)
+			return
+		}
+		m.SuccessResult("获取媒体详情成功", meidaDetail, result)
+		return
+	})
 }

+ 0 - 32
controllers/report/report_controller.go

@@ -159,38 +159,6 @@ func (r *ReportController) PublishRanked(limit int, week bool) {
 	})
 }
 
-// AnalystReportList @Title 获取研究员报告列表
-// @Description 获取研究员报告列表
-// @Success 200 {object}
-// @router /AnalystReportList [get]
-//func (r *ReportController) AnalystReportList(authorId int) {
-//	controllers.Wrap(&r.BaseController, func() (result *controllers.WrapData, err error) {
-//		result = r.InitWrapData("分页获取研究员报告列表失败")
-//		pageRes := page.Page{
-//			Current:  r.PageInfo.Current,
-//			PageSize: r.PageInfo.PageSize,
-//		}
-//		if r.PageInfo.LatestId == 0 {
-//			pageRes.LatestId, _ = report.GetTotalPageCount([]int{})
-//			r.PageInfo.LatestId = pageRes.LatestId
-//		} else {
-//			pageRes.LatestId = r.PageInfo.LatestId
-//		}
-//		pageRes.Total = pageRes.LatestId
-//		pageRes.TotalPage = page.TotalPages(pageRes.Total, pageRes.PageSize)
-//		list, err := report.GetReportPageByAlayyst(r.PageInfo)
-//		if err != nil {
-//			r.FailedResult("分页查询报告列表失败", result)
-//			return
-//		}
-//		reports := new(page.PageResult)
-//		reports.Data = list
-//		reports.Page = pageRes
-//		r.SuccessResult("查询报告列表成功", reports, result)
-//		return
-//	})
-//}
-
 // GetPermissions  @Title 获取品种列表
 // @Description 获取最新发布的报告列表
 // @Success 200 {object}

+ 136 - 0
controllers/user/analyst_controller.go

@@ -0,0 +1,136 @@
+package user
+
+import (
+	"eta_mini_ht_api/common/exception"
+	"eta_mini_ht_api/common/utils/page"
+	"eta_mini_ht_api/controllers"
+	"eta_mini_ht_api/service/analyst"
+	"eta_mini_ht_api/service/media"
+	"eta_mini_ht_api/service/report"
+	"eta_mini_ht_api/service/user"
+	"fmt"
+)
+
+type AnalystController struct {
+	controllers.ListController
+}
+
+// AnalystList  研究员列表
+// @Summary 研究员列表
+// @Description 研究员列表
+// @Success 200 {object} controllers.BaseResponse
+// @router /list [get]
+func (an *AnalystController) AnalystList() {
+	controllers.Wrap(&an.BaseController, func() (result *controllers.WrapData, err error) {
+		result = an.InitWrapData("获取研究员列表失败")
+		var userInfo user.User
+		userInfo = an.Data["user"].(user.User)
+		pageRes := page.Page{
+			Current:  an.PageInfo.Current,
+			PageSize: an.PageInfo.PageSize,
+		}
+		pageRes.Total = analyst.GetAnalystCount()
+		an.PageInfo.Total = pageRes.Total
+		pageRes.TotalPage = page.TotalPages(pageRes.Total, pageRes.PageSize)
+		list, err := analyst.GetAnalystList(pageRes, userInfo.Id)
+		if err != nil {
+			an.FailedResult("获取研究员列表失败", result)
+			return
+		}
+		analystList := new(page.PageResult)
+		analystList.Data = list
+		analystList.Page = pageRes
+		an.SuccessResult("获取研究员列表成功", analystList, result)
+		return
+	})
+}
+
+// AnalystDetail  研究员详情
+// @Summary 研究员详情
+// @Description 研究员详情
+// @Success 200 {object} controllers.BaseResponse
+// @router /analystDetail [get]
+func (an *AnalystController) AnalystDetail(analystId int) {
+	controllers.Wrap(&an.BaseController, func() (result *controllers.WrapData, err error) {
+		result = an.InitWrapData("获取研究员详情失败")
+		fmt.Println(analystId)
+		userInfo := an.Data["user"].(user.User)
+		detail, err := user.GetAnalystDetail(userInfo.Id, analystId)
+		if err != nil {
+			an.FailedResult("获取研究员详情失败", result)
+			return
+		}
+		an.SuccessResult("获取研究员详情成功", detail, result)
+		return
+	})
+}
+
+// AnalystReportList @Title 获取研究员报告列表
+// @Description 获取研究员报告列表
+// @Success 200 {object}
+// @router /reportList [get]
+func (an *AnalystController) AnalystReportList(analystName string) {
+	controllers.Wrap(&an.BaseController, func() (result *controllers.WrapData, err error) {
+		result = an.InitWrapData("分页获取研究员报告列表失败")
+		pageRes := page.Page{
+			Current:  an.PageInfo.Current,
+			PageSize: an.PageInfo.PageSize,
+		}
+		if an.PageInfo.LatestId == 0 {
+			pageRes.Total, pageRes.LatestId = report.GetTotalPageCountByAnalyst(analystName)
+			an.PageInfo.LatestId = pageRes.LatestId
+		} else {
+			pageRes.LatestId = an.PageInfo.LatestId
+			pageRes.Total = an.PageInfo.Total
+		}
+		pageRes.TotalPage = page.TotalPages(pageRes.Total, pageRes.PageSize)
+		list, err := report.GetReportPageByAnalyst(an.PageInfo, analystName)
+		if err != nil {
+			an.FailedResult("分页获取研究员报告列表失败", result)
+			return
+		}
+		reports := new(page.PageResult)
+		reports.Data = list
+		reports.Page = pageRes
+		an.SuccessResult("分页获取研究员报告列表成功", reports, result)
+		return
+	})
+}
+
+// MediaList 获取研究员媒体列表
+// @Description 获取研究员媒体列表
+// @Success 200 {object}
+// @router /mediaList [get]
+func (an *AnalystController) MediaList(mediaType string, analystId int) {
+	controllers.Wrap(&an.BaseController, func() (result *controllers.WrapData, err error) {
+		result = an.InitWrapData("分页查询研究员媒体列表失败")
+		if mediaType == "" || !an.CheckMediaType(mediaType) {
+			err = exception.New(exception.MediaTypeError)
+			an.FailedResult("分页查询研究员媒体列表失败", result)
+			return
+		}
+		pageRes := page.Page{
+			Current:  an.PageInfo.Current,
+			PageSize: an.PageInfo.PageSize,
+		}
+		if an.PageInfo.LatestId == 0 {
+			pageRes.Total, pageRes.LatestId = media.GetTotalPageCountByAnalystId(mediaType, analystId)
+			an.PageInfo.LatestId = pageRes.LatestId
+			an.PageInfo.Total = pageRes.Total
+		} else {
+			pageRes.LatestId = an.PageInfo.LatestId
+			pageRes.Total = an.PageInfo.Total
+		}
+		pageRes.TotalPage = page.TotalPages(pageRes.Total, pageRes.PageSize)
+		list, err := media.GetMediaPageByAnalystId(mediaType, an.PageInfo, analystId)
+		if err != nil {
+			an.FailedResult("分页查询研究员媒体列表失败", result)
+			return
+		}
+		mediaList := new(page.PageResult)
+		mediaList.Data = list
+		mediaList.Page = pageRes
+		an.SuccessResult("分页查询研究员媒体列表成功", mediaList, result)
+		return
+	})
+}

+ 35 - 24
controllers/user/user_controller.go

@@ -41,9 +41,11 @@ type FeedbackReq struct {
 }
 
 type FollowAnalystReq struct {
-	AnalystId  int    `json:"analystId"`
-	FollowType string `json:"followType"`
-	Mobile     string `json:"mobile"`
+	AnalystId   int    `json:"analystId"`
+	AnalystName string `json:"analystName"`
+	FollowType  string `json:"followType"`
+	Mobile      string `json:"mobile"`
+	ByName      bool   `json:"byName"`
 }
 
 // Feedback  用户意见反馈
@@ -123,7 +125,17 @@ func (u *UserController) FollowAnalyst() {
 		case "unfollowed":
 			msg = "取消关注研究员"
 		}
-		err = user.FollowAnalyst(userInfo.Id, followAnalyst.AnalystId, followAnalyst.FollowType)
+		if followAnalyst.ByName {
+			logger.Info("通过研究员姓名关注")
+			if followAnalyst.AnalystName == "" {
+				u.FailedResult("通过研究员姓名关注失败", result)
+				err = exception.New(exception.AnalystNameEmptyError)
+				return
+			}
+			err = user.FollowAnalystByName(userInfo.Id, followAnalyst.AnalystName, followAnalyst.FollowType)
+		} else {
+			err = user.FollowAnalyst(userInfo.Id, followAnalyst.AnalystId, followAnalyst.FollowType)
+		}
 		if err != nil {
 			u.FailedResult(msg+"失败", result)
 			return
@@ -141,26 +153,6 @@ func checkFollowType(followType string) bool {
 	return followType == "following" || followType == "unfollowed"
 }
 
-// AnalystDetail  研究员详情
-// @Summary 研究员详情
-// @Description 研究员详情
-// @Success 200 {object} controllers.BaseResponse
-// @router /analystDetail [get]
-func (u *UserController) AnalystDetail(analystId int) {
-	controllers.Wrap(&u.BaseController, func() (result *controllers.WrapData, err error) {
-		result = u.InitWrapData("获取研究员详情失败")
-		fmt.Println(analystId)
-		userInfo := u.Data["user"].(user.User)
-		detail, err := user.GetAnalystDetail(userInfo.Id, analystId)
-		if err != nil {
-			u.FailedResult("获取研究员详情失败", result)
-			return
-		}
-		u.SuccessResult("获取研究员详情成功", detail, result)
-		return
-	})
-}
-
 // FollowingAnalysts  关注研究员列表
 // @Summary 研究员详情
 // @Description 研究员详情
@@ -200,6 +192,25 @@ func (u *UserController) Profile() {
 	})
 }
 
+// FollowingAnalystList  获取关注动态列表
+// @Summary 获取关注动态列表
+// @Description 获取关注动态列表
+// @Success 200 {object} controllers.BaseResponse
+// @router /followingAnalystList [get]
+func (u *UserController) FollowingAnalystList() {
+	controllers.Wrap(&u.BaseController, func() (result *controllers.WrapData, err error) {
+		result = u.InitWrapData("获取研究员详情失败")
+		userInfo := u.Data["user"].(user.User)
+		detail, err := user.GetFollowingAnalystList(userInfo.Id)
+		if err != nil {
+			u.FailedResult("获取研究员详情失败", result)
+			return
+		}
+		u.SuccessResult("获取研究员详情成功", detail, result)
+		return
+	})
+}
+
 func covertToUserProfile(user user.User) UserProfileReq {
 	return UserProfileReq{
 		UserName: user.Username,

+ 26 - 0
domian/financial_analyst/financial_analyst_service.go

@@ -2,17 +2,28 @@ package financial_analyst
 
 import (
 	logger "eta_mini_ht_api/common/component/log"
+	"eta_mini_ht_api/common/utils/page"
 	financialAnalystDao "eta_mini_ht_api/models/financial_analyst"
 )
 
 type FinancialAnalystDTO struct {
+	Id           int
 	ETAId        int
 	Name         string
+	HeadImgUrl   string
 	Introduction string
 	Status       bool
 	Deleted      bool
 }
 
+func GetAnalystList(pageInfo page.Page) (analystsDTO []FinancialAnalystDTO, err error) {
+	offset := page.StartIndex(pageInfo.Current, pageInfo.PageSize)
+	anaylsts, err := financialAnalystDao.GetAnalystList(offset, pageInfo.PageSize)
+	for _, analyst := range anaylsts {
+		analystsDTO = append(analystsDTO, convertToBaseDTO(analyst))
+	}
+	return
+}
 func GetAnalystById(id int) (financialAnalyst FinancialAnalystDTO, err error) {
 	analyst, err := financialAnalystDao.GetAnalystById(id)
 	if err != nil {
@@ -22,6 +33,18 @@ func GetAnalystById(id int) (financialAnalyst FinancialAnalystDTO, err error) {
 	financialAnalyst = convertToBaseDTO(analyst)
 	return
 }
+func GetCount() (total int64) {
+	return financialAnalystDao.GetCount()
+}
+func GetAnalystByName(name string) (financialAnalyst FinancialAnalystDTO, err error) {
+	analyst, err := financialAnalystDao.GetAnalystByName(name)
+	if err != nil {
+		logger.Error("获取研究研失败: %v", err)
+		return
+	}
+	financialAnalyst = convertToBaseDTO(analyst)
+	return
+}
 func SyncAnalyst(list []FinancialAnalystDTO) (err error) {
 	var financialAnalystList []financialAnalystDao.CrmFinancialAnalyst
 	for _, dto := range list {
@@ -47,6 +70,9 @@ func convert(dto FinancialAnalystDTO) (financialAnalyst financialAnalystDao.CrmF
 }
 func convertToBaseDTO(financialAnalyst financialAnalystDao.CrmFinancialAnalyst) (dto FinancialAnalystDTO) {
 	return FinancialAnalystDTO{
+		Id:           financialAnalyst.Id,
+		ETAId:        financialAnalyst.ETAId,
+		HeadImgUrl:   financialAnalyst.HeadImgURL,
 		Name:         financialAnalyst.Name,
 		Introduction: financialAnalyst.Introduction,
 	}

+ 49 - 21
domian/media/media_service.go

@@ -31,17 +31,19 @@ func elastic() *es.ESClient {
 }
 
 type MediaDTO struct {
-	MediaId          int      `json:"mediaId"`
-	AuthorName       string   `json:"authorName,omitempty"`
-	MediaType        string   `json:"mediaType"`
-	Src              string   `json:"src"`
-	MediaName        string   `json:"mediaName"`
-	SourceType       string   `json:"sourceType"`
-	MediaPlaySeconds int      `json:"mediaPlaySeconds"`
-	PublishedTime    string   `json:"publishedTime"`
-	PermissionIDs    string   `json:"permissionIds"`
-	PermissionNames  []string `json:"permissionNames,omitempty"`
-	Highlight        []string `json:"highlight,omitempty"`
+	MediaId                int      `json:"mediaId"`
+	AuthorId               int      `json:"authorId"`
+	AuthorName             string   `json:"authorName,omitempty"`
+	MediaType              string   `json:"mediaType"`
+	Src                    string   `json:"src"`
+	MediaName              string   `json:"mediaName"`
+	SourceType             string   `json:"sourceType"`
+	MediaPlaySeconds       int      `json:"-"`
+	MediaPlayMillisSeconds int      `json:"mediaPlayMillisSeconds"`
+	PublishedTime          string   `json:"publishedTime"`
+	PermissionIDs          string   `json:"permissionIds"`
+	PermissionNames        []string `json:"permissionNames,omitempty"`
+	Highlight              []string `json:"highlight,omitempty"`
 }
 
 func SearchMediaList(mediaType string, key string, from int, size int, max int64) (reports []MediaDTO, err error) {
@@ -64,6 +66,7 @@ func SearchMediaList(mediaType string, key string, from int, size int, max int64
 		}
 		meida.Highlight = content[ESColumn]
 		meida.PublishedTime = meida.PublishedTime[:10]
+		meida.MediaPlayMillisSeconds = meida.MediaPlaySeconds * 1000
 		reports = append(reports, meida)
 	}
 	return
@@ -113,6 +116,9 @@ func GetMediaPermissionMappingByPermissionIds(mediaType string, permissionIds []
 func GetTotalPageCount(mediaType string) (count int64, latestId int64) {
 	return mediaDao.GetCountByMediaType(mediaType)
 }
+func GetTotalPageCountByAnalystId(mediaType string, analystId int) (count int64, latestId int64) {
+	return mediaDao.GetCountByMediaTypeByAnalystId(mediaType, analystId)
+}
 func GetMediaPageByIds(mediaType string, pageInfo page.PageInfo, mediaIds []int) (list []MediaDTO, err error) {
 	offset := page.StartIndex(pageInfo.Current, pageInfo.PageSize)
 	medias, err := mediaDao.GetMediaPageByIds(pageInfo.LatestId, pageInfo.PageSize, offset, mediaType, mediaIds)
@@ -124,20 +130,42 @@ func GetMediaPageByIds(mediaType string, pageInfo page.PageInfo, mediaIds []int)
 	}
 	return
 }
+
+func GetMediaPageByAnalystId(mediaType string, pageInfo page.PageInfo, analystId int) (list []MediaDTO, err error) {
+	offset := page.StartIndex(pageInfo.Current, pageInfo.PageSize)
+	medias, err := mediaDao.GetMediaPageByAnalystId(pageInfo.LatestId, pageInfo.PageSize, offset, mediaType, analystId)
+	if err == nil && medias != nil {
+		for _, media := range medias {
+			dto := convertMediaDTO(media)
+			list = append(list, dto)
+		}
+	}
+	return
+}
 func convertMediaDTO(media mediaDao.Media) MediaDTO {
 	return MediaDTO{
-		MediaId:          media.Id,
-		AuthorName:       media.AuthorName,
-		MediaType:        string(media.MediaType),
-		Src:              media.Src,
-		MediaName:        media.MediaName,
-		SourceType:       media.SourceType,
-		MediaPlaySeconds: media.MediaPlaySeconds,
-		PermissionIDs:    media.PermissionIDs,
-		PublishedTime:    media.PublishedTime.Format(time.DateOnly),
+		MediaId:                media.Id,
+		AuthorId:               media.AuthorID,
+		AuthorName:             media.AuthorName,
+		MediaType:              string(media.MediaType),
+		Src:                    media.Src,
+		MediaName:              media.MediaName,
+		SourceType:             media.SourceType,
+		MediaPlaySeconds:       media.MediaPlaySeconds,
+		MediaPlayMillisSeconds: media.MediaPlaySeconds * 1000,
+		PermissionIDs:          media.PermissionIDs,
+		PublishedTime:          media.PublishedTime.Format(time.DateOnly),
 	}
 }
-
+func GetMediaById(mediaType string, mediaId int) (mediaDTO MediaDTO, err error) {
+	media, err := mediaDao.GetMediaById(mediaType, mediaId)
+	if err != nil {
+		logger.Error("查询媒体信息失败:%v", err)
+		return
+	}
+	mediaDTO = convertMediaDTO(media)
+	return
+}
 func GetPermissionsByIds(ids []int) (permissionDTOs []reportService.PermissionDTO, err error) {
 	return reportService.GetFirstPermissionsByIds(ids)
 }

+ 49 - 1
domian/report/report_service.go

@@ -90,6 +90,9 @@ func GetGetReportById(reportId int) (ReportDTO ReportDTO, err error) {
 func GetTotalPageCount() (total int64) {
 	return reportDao.GetTotalPageCount()
 }
+func GetTotalPageCountByAnalyst(analyst string) (total int64, latestId int64) {
+	return reportDao.GetTotalPageCountByAnalyst(analyst)
+}
 func SearchMaxReportId(key string) (total int64, reportId int64) {
 	sort := []string{"reportId:desc"}
 	request := matchAll(sort, key)
@@ -148,7 +151,22 @@ func SearchReportList(key string, from int, size int, max int64) (reports []Repo
 	}
 	return
 }
-
+func GetReportPageByAnalyst(pageInfo page.PageInfo, analyst string) (list []ReportDTO, err error) {
+	offset := page.StartIndex(pageInfo.Current, pageInfo.PageSize)
+	reports, err := reportDao.GetReportPageByAnalyst(pageInfo.LatestId, pageInfo.PageSize, offset, analyst)
+	if err != nil {
+		logger.Error("分页查询报告列表失败:%v", err)
+		return
+	}
+	list = make([]ReportDTO, 0)
+	if reports != nil {
+		for _, report := range reports {
+			dto := convertReportDTO(report)
+			list = append(list, dto)
+		}
+	}
+	return
+}
 func GetReportPageByOrgIds(pageInfo page.PageInfo, orgIds []int) (list []ReportDTO, err error) {
 	offset := page.StartIndex(pageInfo.Current, pageInfo.PageSize)
 	reports, err := reportDao.GetReportPageByOrgIds(pageInfo.LatestId, pageInfo.PageSize, offset, orgIds)
@@ -165,6 +183,17 @@ func GetReportPageByOrgIds(pageInfo page.PageInfo, orgIds []int) (list []ReportD
 	}
 	return
 }
+
+func GetNewReportByPublishTime(time time.Time) (reports []ReportDTO) {
+	list := reportDao.GetNewReportByPublishTime(time)
+	if list != nil {
+		for _, report := range list {
+			dto := convertReportDTO(report)
+			reports = append(reports, dto)
+		}
+	}
+	return
+}
 func GetReportPage(pageInfo page.PageInfo) (list []ReportDTO, err error) {
 	offset := page.StartIndex(pageInfo.Current, pageInfo.PageSize)
 	reports, err := reportDao.GetReportPage(pageInfo.LatestId, pageInfo.PageSize, offset)
@@ -227,9 +256,28 @@ func SyncETAReportList(list []eta.ETAReport) (err error) {
 		logger.Error("同步ETA研报到es失败:%v", err)
 		return
 	}
+	//生产meta信息
+	//for _, report := range reports {
+	//userIds := userService.GetPostUser(report.Author, report.PublishedTime)
+	//usersStr := stringUtils.IntToStringSlice(userIds)
+	//Meta :=
+	//toStr := strings.Join(usersStr, ",")
+	////user.SyncMeta(etaReportList[i])
+	//userService.MetaInfoDTO{
+	//	From:       "ETA",
+	//	Meta:       string(list),
+	//	MetaType:   "USER_NOTICE",
+	//	SourceType: "REPORT",
+	//	To:         toStr,
+	//	Uid:        userIds[0],
+	//}
+	//}
 	return
 }
 
+type reportMeta struct {
+}
+
 func GetListOrderByConditionWeekly(week bool, column string, limit int, order models.Order) (dtoList []ReportDTO, err error) {
 	reports, err := reportDao.GetListOrderByCondition(week, column, limit, order)
 	if err != nil {

+ 10 - 0
domian/user/meta_info.go

@@ -0,0 +1,10 @@
+package user
+
+type MetaInfoDTO struct {
+	Uid        int
+	Meta       string
+	From       string
+	To         string
+	SourceType string
+	MetaType   string
+}

+ 71 - 0
domian/user/user_following_service.go

@@ -0,0 +1,71 @@
+package user
+
+import (
+	userDao "eta_mini_ht_api/models/user"
+	"time"
+)
+
+type FollowDTO struct {
+	UserId       int
+	AnalystId    int
+	AnalystName  string
+	FollowType   string
+	FollowedTime time.Time
+}
+
+func convertToCrmFollowingAnalyst(dto FollowDTO) userDao.UserAnalystFollowList {
+	return userDao.UserAnalystFollowList{
+		FinancialAnalystID:   dto.AnalystId,
+		FinancialAnalystName: dto.AnalystName,
+		FollowedTime:         time.Now(),
+		Followed:             followType(dto.FollowType),
+		UserID:               dto.UserId,
+	}
+}
+
+func GetPostUser(authorName string, PublishTime string) (ids []int) {
+	return userDao.GetPostUser(authorName, PublishTime)
+}
+
+func convertToFollowDTO(follow userDao.UserAnalystFollowList) (dto FollowDTO) {
+	return FollowDTO{
+		UserId:       follow.UserID,
+		AnalystId:    follow.FinancialAnalystID,
+		AnalystName:  follow.FinancialAnalystName,
+		FollowType:   string(follow.Followed),
+		FollowedTime: follow.FollowedTime,
+	}
+}
+func followType(followType string) userDao.FollowingType {
+	switch followType {
+	case "following":
+		return userDao.Following
+	case "unfollowed":
+		return userDao.Unfollowed
+	default:
+		return ""
+	}
+}
+
+func GetFollowingAnalystList(userId int) (dtoList []FollowDTO, err error) {
+	list, err := userDao.GetFollowingAnalystList(userId)
+	if err != nil {
+		return
+	}
+	for _, follow := range list {
+		dtoList = append(dtoList, convertToFollowDTO(follow))
+	}
+	return
+}
+
+func GetFollowed(userId int, analystId int) string {
+	return userDao.GetFollowed(userId, analystId)
+}
+func FollowAnalyst(dto FollowDTO) (err error) {
+	follow := convertToCrmFollowingAnalyst(dto)
+	return userDao.FollowAnalyst(follow)
+}
+
+func GetFollowing(userId int, analystId int) string {
+	return userDao.GetFollowing(userId, analystId)
+}

+ 0 - 35
domian/user/user_serivce.go

@@ -5,7 +5,6 @@ import (
 	logger "eta_mini_ht_api/common/component/log"
 	userDao "eta_mini_ht_api/models/user"
 	"gorm.io/gorm"
-	"time"
 )
 
 type UserDTO struct {
@@ -21,12 +20,6 @@ type FeedbackDTO struct {
 	UserId  int    `json:"userId"`
 	Message string `json:"message"`
 }
-type FollowDTO struct {
-	UserId      int
-	AnalystId   int
-	AnalystName string
-	FollowType  string
-}
 
 func convertUserDTO(user userDao.TemplateUser) UserDTO {
 	return UserDTO{
@@ -78,13 +71,6 @@ func FeedBack(dto FeedbackDTO) (err error) {
 	return userDao.InsertFeedBack(feedBackEntity)
 }
 
-func GetFollowed(userId int, analystId int) string {
-	return userDao.GetFollowed(userId, analystId)
-}
-func FollowAnalyst(dto FollowDTO) (err error) {
-	follow := convertToCrmFollowingAnalyst(dto)
-	return userDao.FollowAnalyst(follow)
-}
 func convertToTemplateUser(dto *UserDTO) userDao.TemplateUser {
 	return userDao.TemplateUser{
 		Username: dto.Username,
@@ -101,24 +87,3 @@ func convertToUserDTO(templateUser userDao.TemplateUser, dto *UserDTO) {
 	dto.OpenId = templateUser.OpenId
 	dto.UnionId = templateUser.UnionId
 }
-
-func convertToCrmFollowingAnalyst(dto FollowDTO) userDao.UserAnalystFollowList {
-	return userDao.UserAnalystFollowList{
-		FinancialAnalystID:   dto.AnalystId,
-		FinancialAnalystName: dto.AnalystName,
-		FollowedTime:         time.Now(),
-		Followed:             followType(dto.FollowType),
-		UserID:               dto.UserId,
-	}
-}
-
-func followType(followType string) userDao.FollowingType {
-	switch followType {
-	case "following":
-		return userDao.Following
-	case "unfollowed":
-		return userDao.Unfollowed
-	default:
-		return ""
-	}
-}

+ 2 - 6
go.mod

@@ -5,7 +5,9 @@ go 1.21
 require (
 	github.com/beego/beego/v2 v2.2.2
 	github.com/dgrijalva/jwt-go v3.2.0+incompatible
+	github.com/elastic/go-elasticsearch/v7 v7.17.10
 	github.com/go-redis/redis/v8 v8.11.5
+	github.com/google/uuid v1.6.0
 	github.com/gorilla/websocket v1.5.3
 	gorm.io/driver/mysql v1.5.7
 	gorm.io/gorm v1.25.11
@@ -16,9 +18,6 @@ require (
 	github.com/beorn7/perks v1.0.1 // indirect
 	github.com/cespare/xxhash/v2 v2.2.0 // indirect
 	github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
-	github.com/elastic/go-elasticsearch/v7 v7.17.10 // indirect
-	github.com/go-logr/logr v1.4.1 // indirect
-	github.com/go-logr/stdr v1.2.2 // indirect
 	github.com/go-sql-driver/mysql v1.8.1 // indirect
 	github.com/hashicorp/golang-lru v0.5.4 // indirect
 	github.com/jinzhu/inflection v1.0.0 // indirect
@@ -30,9 +29,6 @@ require (
 	github.com/prometheus/common v0.48.0 // indirect
 	github.com/prometheus/procfs v0.12.0 // indirect
 	github.com/shiena/ansicolor v0.0.0-20200904210342-c7312218db18 // indirect
-	go.opentelemetry.io/otel v1.24.0 // indirect
-	go.opentelemetry.io/otel/metric v1.24.0 // indirect
-	go.opentelemetry.io/otel/trace v1.24.0 // indirect
 	golang.org/x/crypto v0.23.0 // indirect
 	golang.org/x/net v0.23.0 // indirect
 	golang.org/x/sys v0.20.0 // indirect

+ 2 - 17
go.sum

@@ -13,21 +13,12 @@ github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumC
 github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
 github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
 github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
-github.com/elastic/elastic-transport-go/v8 v8.6.0 h1:Y2S/FBjx1LlCv5m6pWAF2kDJAHoSjSRSJCApolgfthA=
-github.com/elastic/elastic-transport-go/v8 v8.6.0/go.mod h1:YLHer5cj0csTzNFXoNQ8qhtGY1GTvSqPnKWKaqQE3Hk=
 github.com/elastic/go-elasticsearch/v7 v7.17.10 h1:TCQ8i4PmIJuBunvBS6bwT2ybzVFxxUhhltAs3Gyu1yo=
 github.com/elastic/go-elasticsearch/v7 v7.17.10/go.mod h1:OJ4wdbtDNk5g503kvlHLyErCgQwwzmDtaFC4XyOxXA4=
-github.com/elastic/go-elasticsearch/v8 v8.14.0 h1:1ywU8WFReLLcxE1WJqii3hTtbPUE2hc38ZK/j4mMFow=
-github.com/elastic/go-elasticsearch/v8 v8.14.0/go.mod h1:WRvnlGkSuZyp83M2U8El/LGXpCjYLrvlkSgkAH4O5I4=
 github.com/elazarl/go-bindata-assetfs v1.0.1 h1:m0kkaHRKEu7tUIUFVwhGGGYClXvyl4RE03qmvRTNfbw=
 github.com/elazarl/go-bindata-assetfs v1.0.1/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4=
 github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
 github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
-github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
-github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
-github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
-github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
-github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
 github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI=
 github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo=
 github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
@@ -35,6 +26,8 @@ github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpv
 github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
 github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
 github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
+github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
+github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
 github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
 github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
 github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc=
@@ -71,14 +64,6 @@ github.com/shiena/ansicolor v0.0.0-20200904210342-c7312218db18 h1:DAYUYH5869yV94
 github.com/shiena/ansicolor v0.0.0-20200904210342-c7312218db18/go.mod h1:nkxAfR/5quYxwPZhyDxgasBMnRtBZd0FCEpawpjMUFg=
 github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
 github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
-go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo=
-go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo=
-go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI=
-go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco=
-go.opentelemetry.io/otel/sdk v1.21.0 h1:FTt8qirL1EysG6sTQRZ5TokkU8d0ugCj8htOgThZXQ8=
-go.opentelemetry.io/otel/sdk v1.21.0/go.mod h1:Nna6Yv7PWTdgJHVRD9hIYywQBRx7pbox6nwBnZIxl/E=
-go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI=
-go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU=
 golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=
 golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
 golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs=

+ 22 - 1
models/financial_analyst/financial_analyst.go

@@ -12,7 +12,7 @@ type AnalystStatus string
 const (
 	AnalystStatusEnabled  AnalystStatus = "enabled"
 	AnalystStatusDisabled AnalystStatus = "disabled"
-	columns                             = "id,name,introduction"
+	columns                             = "id,eta_id,name,head_img_url,introduction"
 )
 
 type CrmFinancialAnalyst struct {
@@ -50,3 +50,24 @@ func GetAnalystById(id int) (analyst CrmFinancialAnalyst, err error) {
 	err = db.Select(columns).Where("id = ?", id).First(&analyst).Error
 	return
 }
+
+func GetAnalystByName(name string) (analyst CrmFinancialAnalyst, err error) {
+	db := models.Main()
+	err = db.Select(columns).Where("name = ?", name).First(&analyst).Error
+	return
+}
+
+func GetCount() (total int64) {
+	db := models.Main()
+	err := db.Model(&CrmFinancialAnalyst{}).Select("count(*) count").Scan(&total).Error
+	if err != nil {
+		return 0
+	}
+	return
+}
+
+func GetAnalystList(offset int, limit int) (analysts []CrmFinancialAnalyst, err error) {
+	db := models.Main()
+	err = db.Select(columns).Offset(offset).Limit(limit).Find(&analysts).Order("id asc").Error
+	return
+}

+ 31 - 0
models/media/media.go

@@ -10,6 +10,7 @@ import (
 
 const (
 	CommonColumns = "id,media_type,src,media_name,source_type,media_play_seconds,permission_ids,published_time"
+	DetailColumns = "id,media_type,src,media_name,source_type,media_play_seconds,permission_ids,published_time,author_id,author_name"
 )
 
 type MediaType string
@@ -52,6 +53,17 @@ func GetCountByMediaType(mediaType string) (count int64, latestId int64) {
 	return
 }
 
+func GetCountByMediaTypeByAnalystId(mediaType string, analystId int) (count int64, latestId int64) {
+	db := models.Main()
+	var ids []int
+	err := db.Model(&Media{}).Select("id").Where("media_type = ? and deleted = ? and author_id = ?", mediaType, false, analystId).Order("id desc").Scan(&ids).Error
+	if err != nil {
+		return 0, 0
+	}
+	count = int64(len(ids))
+	latestId = int64(ids[0])
+	return
+}
 func GetMediaPage(latestId int64, limit int, offset int, mediaType string) (mediaList []Media, err error) {
 	if latestId < 0 {
 		err = errors.New("非法的id参数")
@@ -83,6 +95,25 @@ func GetMediaPageByIds(latestId int64, limit int, offset int, mediaType string,
 	err = db.Select(CommonColumns).Where(" id<= ? and media_type= ? and id in ?", latestId, mediaType, mediasIds).Order("created_time desc").Limit(limit).Offset(offset).Find(&mediaList).Error
 	return
 }
+func GetMediaPageByAnalystId(latestId int64, limit int, offset int, mediaType string, analystId int) (mediaList []Media, err error) {
+	if latestId < 0 {
+		err = errors.New("非法的id参数")
+		logger.Error("非法的id参数:%d", latestId)
+		return
+	}
+	if limit <= 0 {
+		err = errors.New("非法的limit参数")
+		logger.Error("非法的limit参数:%d", limit)
+	}
+	db := models.Main()
+	err = db.Select(CommonColumns).Where(" id<= ? and media_type= ? and author_id = ?", latestId, mediaType, analystId).Order("published_time desc").Limit(limit).Offset(offset).Find(&mediaList).Error
+	return
+}
+func GetMediaById(mediaType string, mediaId int) (media Media, err error) {
+	db := models.Main()
+	err = db.Select(DetailColumns).Where("id =? and media_type=?", mediaId, mediaType).First(&media).Error
+	return
+}
 
 // 测试造数据
 func GetlIST() (media []Media) {

+ 37 - 0
models/report/report.go

@@ -22,6 +22,7 @@ const (
 
 	MaxBatchNum   = 1000
 	CommonColumns = "id,org_id,author,abstract,title,source,cover_src,published_time"
+	taskColumns   = "id,author,published_time"
 )
 
 type Report struct {
@@ -127,6 +128,19 @@ func GetTotalPageCount() (total int64) {
 	}
 	return
 }
+
+func GetTotalPageCountByAnalyst(analyst string) (total int64, latestId int64) {
+	db := models.Main()
+	err := db.Model(&Report{}).Where("author =?", analyst).Count(&total).Error
+	if err != nil {
+		return
+	}
+	err = db.Model(&Report{}).Select("Max(id)").Where("author =?", analyst).Scan(&latestId).Error
+	if err != nil {
+		return
+	}
+	return
+}
 func GetReportPage(latestId int64, limit int, offset int) (list []Report, err error) {
 	if latestId < 0 {
 		err = errors.New("非法的id参数")
@@ -159,3 +173,26 @@ func GetReportPageByOrgIds(latestId int64, limit int, offset int, orgIds []int)
 	err = db.Select(CommonColumns).Where("id<= ? and org_id in ?", latestId, orgIds).Order("published_time desc").Limit(limit).Offset(offset).Find(&list).Error
 	return
 }
+
+func GetNewReportByPublishTime(time time.Time) (list []Report) {
+	db := models.Main()
+	err := db.Select(taskColumns).Where("published_time >= ?", time).Order("published_time desc").Find(&list).Error
+	if err != nil {
+		logger.Error("查询新发布的报告列表失败:%v", err)
+	}
+	return
+}
+func GetReportPageByAnalyst(latestId int64, limit int, offset int, analyst string) (list []Report, err error) {
+	if latestId < 0 {
+		err = errors.New("非法的id参数")
+		logger.Error("非法的id参数:%d", latestId)
+		return
+	}
+	if limit <= 0 {
+		err = errors.New("非法的limit参数")
+		logger.Error("非法的limit参数:%d", limit)
+	}
+	db := models.Main()
+	err = db.Select(CommonColumns).Where("id<= ? and author = ?", latestId, analyst).Order("published_time desc").Limit(limit).Offset(offset).Find(&list).Error
+	return
+}

+ 35 - 0
models/user/meta_info.go

@@ -0,0 +1,35 @@
+package user
+
+import (
+	"time"
+)
+
+type StatusType string
+type SourceType string
+type MetaType string
+
+const (
+	UserNoticeType  MetaType = "USER_NOTICE"
+	InitMetaType    MetaType = "INIT"
+	PendingMetaType MetaType = "PENDING"
+	FinishMetaType  MetaType = "FINISH"
+	FailedMetaType  MetaType = "FAILED"
+
+	ReportSourceType SourceType = "REPORT"
+	VideoSourceType  SourceType = "VIDEO"
+	AudioSourceType  SourceType = "AUDIO"
+)
+
+// MetaInfo 表示 meta_infos 表的模型
+type MetaInfo struct {
+	Id          int        `gorm:"primaryKey;autoIncrement;column:id"`
+	Uid         int        `gorm:"column:uid"`
+	Meta        string     `gorm:"column:meta"`
+	From        string     `gorm:"column:from"`
+	To          string     `gorm:"column:to"`
+	SourceType  SourceType `gorm:"column:source_type;type:enum('REPORT','VIDEO','AUDIO')"`
+	MetaType    MetaType   `gorm:"column:meta_type;type:enum('USER_NOTICE')"`
+	Status      StatusType `gorm:"column:status;type:enum('INIT','PENDING','FINISH','FAILED')"`
+	CreatedTime time.Time
+	UpdatedTime time.Time
+}

+ 29 - 2
models/user/user_analyst_follow_list.go

@@ -11,8 +11,9 @@ import (
 type FollowingType string
 
 const (
-	Following  FollowingType = "following"
-	Unfollowed FollowingType = "unfollowed"
+	Following   FollowingType = "following"
+	Unfollowed  FollowingType = "unfollowed"
+	listColumns               = "user_id, financial_analyst_id,financial_analyst_name, followed,followed_time"
 )
 
 // UserAnalystFollowList 代表用户关注的研究员列表
@@ -27,6 +28,15 @@ type UserAnalystFollowList struct {
 	UpdatedTime          time.Time     `gorm:"type:timestamp;null;onupdate:CURRENT_TIMESTAMP"`
 }
 
+func GetPostUser(authorName string, PublishTime string) (ids []int) {
+	db := models.Main()
+	err := db.Select("user_id").Where("financial_analyst_name = ? and followed = ? and financial_analyst_name=? and followed_time <=?", authorName, Following, PublishTime).Order("followed_time desc").Find(&ids).Error
+	if err != nil {
+		return []int{}
+	}
+	return
+}
+
 func (fa UserAnalystFollowList) TableName() string {
 	return "user_analyst_follow_list"
 }
@@ -34,6 +44,23 @@ func (fa *UserAnalystFollowList) BeforeCreate(_ *gorm.DB) (err error) {
 	fa.CreatedTime = time.Now()
 	return
 }
+func GetFollowingAnalystList(userId int) (list []UserAnalystFollowList, err error) {
+	db := models.Main()
+	err = db.Select(listColumns).Where("user_id = ? and followed = ?", userId, Following).Order("followed_time desc").Find(&list).Error
+	return
+}
+func GetFollowing(userId int, analystId int) string {
+	db := models.Main()
+	var dbFollow UserAnalystFollowList
+	err := db.Model(&UserAnalystFollowList{}).Where("user_id = ? and financial_analyst_id = ?", userId, analystId).First(&dbFollow).Error
+	if err != nil {
+		if !errors.Is(err, gorm.ErrRecordNotFound) {
+			logger.Error("查询用户关注状态失败:%v", err)
+		}
+		return string(Unfollowed)
+	}
+	return string(dbFollow.Followed)
+}
 func FollowAnalyst(follow UserAnalystFollowList) (err error) {
 	if follow.Followed == "" {
 		err = errors.New("关注状态非法")

+ 64 - 11
routers/commentsRouter.go

@@ -19,6 +19,18 @@ func init() {
             Filters: nil,
             Params: nil})
 
+    beego.GlobalControllerRouter["eta_mini_ht_api/controllers/media:MediaController"] = append(beego.GlobalControllerRouter["eta_mini_ht_api/controllers/media:MediaController"],
+        beego.ControllerComments{
+            Method: "GetMedia",
+            Router: `/media`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(
+				param.New("mediaType"),
+				param.New("mediaId"),
+			),
+            Filters: nil,
+            Params: nil})
+
     beego.GlobalControllerRouter["eta_mini_ht_api/controllers/media:MediaController"] = append(beego.GlobalControllerRouter["eta_mini_ht_api/controllers/media:MediaController"],
         beego.ControllerComments{
             Method: "Search",
@@ -106,6 +118,49 @@ func init() {
             Filters: nil,
             Params: nil})
 
+    beego.GlobalControllerRouter["eta_mini_ht_api/controllers/user:AnalystController"] = append(beego.GlobalControllerRouter["eta_mini_ht_api/controllers/user:AnalystController"],
+        beego.ControllerComments{
+            Method: "AnalystDetail",
+            Router: `/analystDetail`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(
+				param.New("analystId"),
+			),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta_mini_ht_api/controllers/user:AnalystController"] = append(beego.GlobalControllerRouter["eta_mini_ht_api/controllers/user:AnalystController"],
+        beego.ControllerComments{
+            Method: "AnalystList",
+            Router: `/list`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta_mini_ht_api/controllers/user:AnalystController"] = append(beego.GlobalControllerRouter["eta_mini_ht_api/controllers/user:AnalystController"],
+        beego.ControllerComments{
+            Method: "MediaList",
+            Router: `/mediaList`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(
+				param.New("mediaType"),
+				param.New("analystId"),
+			),
+            Filters: nil,
+            Params: nil})
+
+    beego.GlobalControllerRouter["eta_mini_ht_api/controllers/user:AnalystController"] = append(beego.GlobalControllerRouter["eta_mini_ht_api/controllers/user:AnalystController"],
+        beego.ControllerComments{
+            Method: "AnalystReportList",
+            Router: `/reportList`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(
+				param.New("analystName"),
+			),
+            Filters: nil,
+            Params: nil})
+
     beego.GlobalControllerRouter["eta_mini_ht_api/controllers/user:AuthController"] = append(beego.GlobalControllerRouter["eta_mini_ht_api/controllers/user:AuthController"],
         beego.ControllerComments{
             Method: "AreaCodes",
@@ -180,17 +235,6 @@ func init() {
             Filters: nil,
             Params: nil})
 
-    beego.GlobalControllerRouter["eta_mini_ht_api/controllers/user:UserController"] = append(beego.GlobalControllerRouter["eta_mini_ht_api/controllers/user:UserController"],
-        beego.ControllerComments{
-            Method: "AnalystDetail",
-            Router: `/analystDetail`,
-            AllowHTTPMethods: []string{"get"},
-            MethodParams: param.Make(
-				param.New("analystId"),
-			),
-            Filters: nil,
-            Params: nil})
-
     beego.GlobalControllerRouter["eta_mini_ht_api/controllers/user:UserController"] = append(beego.GlobalControllerRouter["eta_mini_ht_api/controllers/user:UserController"],
         beego.ControllerComments{
             Method: "Feedback",
@@ -209,6 +253,15 @@ func init() {
             Filters: nil,
             Params: nil})
 
+    beego.GlobalControllerRouter["eta_mini_ht_api/controllers/user:UserController"] = append(beego.GlobalControllerRouter["eta_mini_ht_api/controllers/user:UserController"],
+        beego.ControllerComments{
+            Method: "FollowingAnalystList",
+            Router: `/followingAnalystList`,
+            AllowHTTPMethods: []string{"get"},
+            MethodParams: param.Make(),
+            Filters: nil,
+            Params: nil})
+
     beego.GlobalControllerRouter["eta_mini_ht_api/controllers/user:UserController"] = append(beego.GlobalControllerRouter["eta_mini_ht_api/controllers/user:UserController"],
         beego.ControllerComments{
             Method: "FollowingAnalysts",

+ 5 - 0
routers/router.go

@@ -29,6 +29,11 @@ func init() {
 				&media.MediaController{},
 			),
 		),
+		beego.NSNamespace("/analyst",
+			beego.NSInclude(
+				&user.AnalystController{},
+			),
+		),
 	)
 	beego.AddNamespace(ns)
 }

+ 53 - 0
service/analyst/analyst_service.go

@@ -0,0 +1,53 @@
+package analyst
+
+import (
+	logger "eta_mini_ht_api/common/component/log"
+	"eta_mini_ht_api/common/exception"
+	"eta_mini_ht_api/common/utils/page"
+	analystService "eta_mini_ht_api/domian/financial_analyst"
+	userService "eta_mini_ht_api/domian/user"
+	"sync"
+)
+
+type Analyst struct {
+	Id           int    `json:"id"`
+	Name         string `json:"name"`
+	HeadImgUrl   string `json:"headImgUrl"`
+	Introduction string `json:"introduction"`
+	Following    string `json:"following"`
+}
+
+func GetAnalystCount() (total int64) {
+	return analystService.GetCount()
+}
+
+func GetAnalystList(page page.Page, userId int) (analysts []Analyst, err error) {
+	List, err := analystService.GetAnalystList(page)
+	if err != nil {
+		logger.Error("查询研究员列表失败:%v", err)
+		err = exception.New(exception.GetAnalystListFailed)
+	}
+	for _, item := range List {
+		analysts = append(analysts, convertToAnalyst(item))
+	}
+	var wg sync.WaitGroup
+	for i := 0; i < len(List); i++ {
+		wg.Add(1)
+		go func(analyst *Analyst) {
+			defer wg.Done()
+			analyst.Following = userService.GetFollowing(userId, analyst.Id)
+		}(&analysts[i])
+	}
+	wg.Wait()
+	return
+}
+
+func convertToAnalyst(analyst analystService.FinancialAnalystDTO) Analyst {
+	return Analyst{
+		Id:           analyst.Id,
+		Name:         analyst.Name,
+		HeadImgUrl:   analyst.HeadImgUrl,
+		Introduction: analyst.Introduction,
+		Following:    "",
+	}
+}

+ 45 - 1
service/media/media_service.go

@@ -16,7 +16,12 @@ func GetTotalPageCount(mediaType string) (count int64, latestId int64) {
 	}
 	return mediaService.GetTotalPageCount(mediaType)
 }
-
+func GetTotalPageCountByAnalystId(mediaType string, analystId int) (total int64, latestId int64) {
+	if mediaType == "" {
+		return
+	}
+	return mediaService.GetTotalPageCountByAnalystId(mediaType, analystId)
+}
 func GetTotalPageCountByPermissionIds(mediaType string, permissionIds []int) (total int64, latestId int64, ids []int) {
 	if mediaType == "" {
 		return
@@ -31,9 +36,48 @@ func GetTotalPageCountByPermissionIds(mediaType string, permissionIds []int) (to
 func SearchMaxMediaId(mediaType string, key string) (total int64, latestId int64) {
 	return mediaService.SearchMaxMediaId(mediaType, key)
 }
+func GetMediaById(mediaType string, mediaId int) (media mediaService.MediaDTO, err error) {
+	media, err = mediaService.GetMediaById(mediaType, mediaId)
+	if err != nil {
+		err = exception.New(exception.MediaFoundFailed)
+	}
+	return
+}
+
+func GetMediaPageByAnalystId(mediaType string, pageInfo page.PageInfo, analystId int) (list []mediaService.MediaDTO, err error) {
+	list, err = mediaService.GetMediaPageByAnalystId(mediaType, pageInfo, analystId)
+	if err != nil {
+		err = exception.New(exception.GetAnalystMediaListFailed)
+		return
+	}
+	//并发获取媒体的标签
+	var wg sync.WaitGroup
+	wg.Add(len(list))
+	for i := 0; i < len(list); i++ {
+		go func(media *mediaService.MediaDTO) {
+			defer wg.Done()
+			idStr := strings.Split(media.PermissionIDs, ",")
+			var ids []int
+			ids, err = stringUtils.StringToIntSlice(idStr)
+			if err != nil {
+				logger.Error("品种名称列表转换失败:%v", err)
+			}
+			media.PermissionNames = getMediaPermissionNames(ids)
+		}(&list[i])
+	}
+	wg.Wait()
+	if err != nil {
+		err = exception.New(exception.QueryReportPageFailed)
+	}
+	return
+}
 
 func GetMediaPageByIds(mediaType string, pageInfo page.PageInfo, mediaIds []int) (list []mediaService.MediaDTO, err error) {
 	list, err = mediaService.GetMediaPageByIds(mediaType, pageInfo, mediaIds)
+	if err != nil {
+		err = exception.New(exception.GetMediaListFailed)
+		return
+	}
 	//并发获取媒体的标签
 	var wg sync.WaitGroup
 	wg.Add(len(list))

+ 6 - 2
service/report/report_service.go

@@ -143,8 +143,12 @@ func GetReportPage(pageInfo page.PageInfo, orgIds []int) (list []reportService.R
 	}
 	return
 }
-func GetReportPageByAlayyst(pageInfo page.PageInfo) (list []reportService.ReportDTO, err error) {
-	list, err = reportService.GetReportPage(pageInfo)
+
+func GetTotalPageCountByAnalyst(analyst string) (total int64, latestId int64) {
+	return reportService.GetTotalPageCountByAnalyst(analyst)
+}
+func GetReportPageByAnalyst(pageInfo page.PageInfo, analyst string) (list []reportService.ReportDTO, err error) {
+	list, err = reportService.GetReportPageByAnalyst(pageInfo, analyst)
 	//并发获取研报的标签
 	var wg sync.WaitGroup
 	wg.Add(len(list))

+ 55 - 0
service/user/user_service.go

@@ -5,6 +5,7 @@ import (
 	"eta_mini_ht_api/common/exception"
 	analystService "eta_mini_ht_api/domian/financial_analyst"
 	userService "eta_mini_ht_api/domian/user"
+	"time"
 )
 
 type User struct {
@@ -16,6 +17,7 @@ type User struct {
 
 type AnalystDetail struct {
 	AnalystName  string `json:"AnalystName"`
+	HeadImgUrl   string `json:"HeadImgUrl"`
 	Introduction string `json:"Introduction"`
 	Followed     string `json:"Followed"`
 }
@@ -36,6 +38,7 @@ func GetAnalystDetail(userId int, analystId int) (analystDetail AnalystDetail, e
 func convertToAnalystDetail(dto analystService.FinancialAnalystDTO) AnalystDetail {
 	return AnalystDetail{
 		AnalystName:  dto.Name,
+		HeadImgUrl:   dto.HeadImgUrl,
 		Introduction: dto.Introduction,
 	}
 
@@ -58,6 +61,58 @@ func FollowAnalyst(userId int, analystId int, followType string) (err error) {
 	}
 	return
 }
+func GetFollowingAnalystList(userId int) (analysts []FollowAnalystDTO, err error) {
+	dtoList, err := userService.GetFollowingAnalystList(userId)
+	if err != nil {
+		err = exception.New(exception.GetFollowingAnalystListFailed)
+	}
+	analysts, err = convertToAnalystList(dtoList)
+	if err != nil {
+		logger.Error("转换研究员列表失败:%v", err)
+		err = exception.New(exception.TransferFollowingAnalystListFailed)
+	}
+	return
+}
+
+type FollowAnalystDTO struct {
+	AnalystId    int       `json:"analystId"`
+	AnalystName  string    `json:"analystName"`
+	HeadImgUrl   string    `json:"headImgUrl"`
+	FollowedTime time.Time `json:"-"`
+	NeedNotice   bool      `json:"needNotice"`
+}
+
+func convertToAnalystList(dtoList []userService.FollowDTO) (list []FollowAnalystDTO, err error) {
+	for _, dto := range dtoList {
+		analyst := FollowAnalystDTO{
+			AnalystId:    dto.AnalystId,
+			AnalystName:  dto.AnalystName,
+			FollowedTime: dto.FollowedTime,
+			NeedNotice:   false,
+		}
+		list = append(list, analyst)
+	}
+	return
+}
+
+func FollowAnalystByName(userId int, analystName string, followType string) (err error) {
+	FinancialAnalystDTO, err := analystService.GetAnalystByName(analystName)
+	if err != nil {
+		err = exception.New(exception.AnalystNotFound)
+	}
+	followDTO := userService.FollowDTO{
+		UserId:      userId,
+		AnalystId:   FinancialAnalystDTO.Id,
+		AnalystName: FinancialAnalystDTO.Name,
+		FollowType:  followType,
+	}
+	err = userService.FollowAnalyst(followDTO)
+	if err != nil {
+		logger.Error("关注研究员失败:%v", err)
+		err = exception.New(exception.UserFollowAnalystFailed)
+	}
+	return
+}
 func FeedBack(userId int, mobile string, message string) (err error) {
 	feedback := userService.FeedbackDTO{
 		UserId:  userId,

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

@@ -7,6 +7,7 @@ import (
 	"eta_mini_ht_api/domian/report"
 	"eta_mini_ht_api/models/eta"
 	"eta_mini_ht_api/task/base"
+	"go/types"
 )
 
 var (
@@ -14,6 +15,10 @@ var (
 	cron                   = "0/5 * * * * *"
 )
 
+var (
+	reportChan types.Chan
+)
+
 // Execute Task ETA取研报的数据
 func (re *ReportTask) Execute(taskDetail *base.TaskDetail) error {
 	logger.Info(contants.TaskFormat, "同步ETA研报库开始")
@@ -37,6 +42,7 @@ func (re *ReportTask) Execute(taskDetail *base.TaskDetail) error {
 		}
 	}
 	logger.Info(contants.TaskFormat, "同步ETA研报库结束")
+
 	return nil
 }
 

+ 60 - 0
task/message/notice_task.go

@@ -0,0 +1,60 @@
+package message
+
+import (
+	logger "eta_mini_ht_api/common/component/log"
+	"eta_mini_ht_api/common/contants"
+	"eta_mini_ht_api/domian/financial_analyst"
+	"eta_mini_ht_api/models/eta"
+	"eta_mini_ht_api/task/base"
+	"fmt"
+	"github.com/google/uuid"
+	"sync"
+	"time"
+)
+
+var (
+	taskName base.TaskType = "NoticeTask"
+	cron                   = "0/5 * * * * *"
+	duration               = 5 * time.Second
+)
+
+// Execute Task ETA取研报的数据
+func (au *AuthorTask) Execute(taskDetail *base.TaskDetail) error {
+	logger.Info(contants.TaskFormat, "监听更新通知开始")
+	//报告和媒体
+	var wg sync.WaitGroup
+	wg.Add(2)
+	UUID := uuid.New()
+	uuidStr := UUID.String()
+	timeBefore := time.Now().Add(-duration)
+	fmt.Printf("监听更新通知开始:%v", timeBefore)
+	//监听报告
+	go func(uuid string) {
+		defer wg.Done()
+		//list := reportService.GetNewReportByPublishTime(timeBefore)
+		//	users := userService.GetNoticeUsersByReports(list)
+	}(uuidStr)
+	//监听媒体
+	go func(uuid string) {
+		defer wg.Done()
+	}(uuidStr)
+	wg.Wait()
+	
+	return nil
+}
+
+type AuthorTask struct {
+}
+
+func convert(author eta.ReportAuthor) financial_analyst.FinancialAnalystDTO {
+	return financial_analyst.FinancialAnalystDTO{
+		Deleted: author.IsDelete,
+		ETAId:   author.Id,
+		Name:    author.ReportAuthor,
+		Status:  author.Enable,
+	}
+}
+func init() {
+	authorTask := base.NewTask(taskName, cron, new(AuthorTask), base.PROD)
+	base.RegisterTask(&authorTask)
+}