package user import ( "errors" "eta/eta_mini_ht_api/common/component/cache" logger "eta/eta_mini_ht_api/common/component/log" "eta/eta_mini_ht_api/common/exception" "eta/eta_mini_ht_api/common/utils/page" "eta/eta_mini_ht_api/controllers" permissionService "eta/eta_mini_ht_api/domian/config" reportDomian "eta/eta_mini_ht_api/domian/report" chartService "eta/eta_mini_ht_api/service/media" "eta/eta_mini_ht_api/service/report" "eta/eta_mini_ht_api/service/user" userService "eta/eta_mini_ht_api/service/user" "gorm.io/gorm" "sync" ) // BookMarkController Operations about bookmark type BookMarkController struct { controllers.ListController redis *cache.RedisCache } const ( Chart = "chart" Report = "report" ) func (bk *BookMarkController) Prepare() { bk.ListController.Prepare() bk.redis = cache.GetInstance() } type BookMarkReq struct { SourceType string `json:"sourceType"` SourceId int `json:"sourceId"` ChartImage string `json:"chartImage"` ChartInfoId int `json:"chartInfoId"` ChartName string `json:"chartName"` UniqueCode string `json:"uniqueCode"` } // BookMark 收藏 // @Summary 收藏 // @Description 收藏 // @Success 200 {object} controllers.BaseResponse // @router /bookMark [post] func (bk *BookMarkController) BookMark() { controllers.Wrap(&bk.BaseController, func() (result *controllers.WrapData, err error) { result = bk.InitWrapData("收藏失败") bookMark := new(BookMarkReq) bk.GetPostParams(bookMark) var userInfo user.User userInfo = bk.Data["user"].(user.User) if bookMark.SourceType == "" { bk.FailedResult("收藏失败", result) err = exception.New(exception.IllegalSourceType) return } if bookMark.SourceId == 0 { bk.FailedResult("收藏失败", result) err = exception.New(exception.IllegalSourceId) return } err = userService.BookMark(userInfo.Id, bookMark.SourceId, bookMark.SourceType) if err != nil { err = exception.NewWithException(exception.FeedBackError, err.Error()) bk.FailedResult("收藏失败", result) return } //将图表加入es if bookMark.SourceType == Chart { chartService.AddChartToEs(chartService.ChartInfo{ ChartImage: bookMark.ChartImage, ChartInfoId: bookMark.ChartInfoId, ChartName: bookMark.ChartName, UniqueCode: bookMark.UniqueCode, }) } bk.SuccessResult("收藏成功", nil, result) return }) } // UnBookMark 取消收藏 // @Summary 取消收藏 // @Description 取消收藏 // @Success 200 {object} controllers.BaseResponse // @router /unBookMark [post] func (bk *BookMarkController) UnBookMark() { controllers.Wrap(&bk.BaseController, func() (result *controllers.WrapData, err error) { result = bk.InitWrapData("取消收藏失败") bookMark := new(BookMarkReq) bk.GetPostParams(bookMark) var userInfo user.User userInfo = bk.Data["user"].(user.User) if bookMark.SourceType == "" { bk.FailedResult("取消收藏失败", result) err = exception.New(exception.IllegalSourceType) return } if bookMark.SourceId == 0 { bk.FailedResult("取消收藏失败", result) err = exception.New(exception.IllegalSourceId) return } err = userService.UnBookMark(userInfo.Id, bookMark.SourceId, bookMark.SourceType) if err != nil { err = exception.NewWithException(exception.FeedBackError, err.Error()) bk.FailedResult("取消收藏失败", result) return } bk.SuccessResult("收藏成功", nil, result) return }) } type CheckBookMarkResp struct { IsBookMarked bool `json:"isBookMarked"` } // CheckBookMark 取消收藏 // @Summary 取消收藏 // @Description 取消收藏 // @Success 200 {object} controllers.BaseResponse // @router /checkBookMark [post] func (bk *BookMarkController) CheckBookMark() { controllers.Wrap(&bk.BaseController, func() (result *controllers.WrapData, err error) { result = bk.InitWrapData("取消收藏失败") bookMark := new(BookMarkReq) bk.GetPostParams(bookMark) var userInfo user.User userInfo = bk.Data["user"].(user.User) if bookMark.SourceType == "" { bk.FailedResult("获取是否收藏失败", result) err = exception.New(exception.IllegalSourceType) return } if bookMark.SourceId == 0 { bk.FailedResult("获取是否收藏失败", result) err = exception.New(exception.IllegalSourceId) return } isBookMarked, err := userService.CheckBookMarkStatus(userInfo.Id, bookMark.SourceId, bookMark.SourceType) if err != nil { err = exception.NewWithException(exception.FeedBackError, err.Error()) bk.FailedResult("获取是否收藏失败", result) return } bk.SuccessResult("获取是否收藏成功", &CheckBookMarkResp{ IsBookMarked: isBookMarked, }, result) return }) } // BookMarkSearch 搜索收藏列表 // @Description 搜索报告列表 // @Success 200 {object} // @router /bookMarkSearch [get] func (bk *BookMarkController) BookMarkSearch(key string) { controllers.Wrap(&bk.BaseController, func() (result *controllers.WrapData, err error) { result = bk.InitWrapData("分页搜索报告列表失败") if key == "" { err = exception.New(exception.SearchKeyEmptyError) bk.FailedResult("分页搜索报告列表失败", result) return } userInfo := bk.Data["user"].(user.User) pageRes := page.Page{ Current: bk.PageInfo.Current, PageSize: bk.PageInfo.PageSize, } //获取当前可以被搜索的报告原始ID //先要限制查询的id范围 var reportIds []int var mappingRiskLevel string var userRiskStatus string pageRes.Total, pageRes.LatestId, reportIds, _, mappingRiskLevel, userRiskStatus, err = report.RangeSearch(key, true, userInfo.Id) if err != nil { logger.Error("获取报告原始ID列表失败:%v", err) bk.FailedResult("分页搜索报告列表失败", result) return } if len(reportIds) == 0 { reports := new(page.PageResult) reports.Data = []reportDomian.ReportDTO{} reports.Page = pageRes logger.Info("没有可以查询的报告列表") bk.SuccessResult("分页搜索报告列表成功", reports, result) return } if bk.PageInfo.LatestId == 0 { //pageRes.Total, pageRes.LatestId = report.SearchMaxReportId(key) bk.PageInfo.LatestId = pageRes.LatestId bk.PageInfo.Total = pageRes.Total } else { pageRes.LatestId = bk.PageInfo.LatestId pageRes.Total = bk.PageInfo.Total } pageRes.TotalPage = page.TotalPages(pageRes.Total, pageRes.PageSize) list := make([]reportDomian.ReportDTO, 0) if pageRes.LatestId > 0 { list, err = report.SearchReportList(key, reportIds, bk.PageInfo, true, userInfo.Id, mappingRiskLevel, userRiskStatus) if err != nil { bk.FailedResult("分页搜索报告列表失败", result) return } } reports := new(page.PageResult) reports.Data = list reports.Page = pageRes bk.SuccessResult("分页搜索报告列表成功", reports, result) return }) } type BookMarkListReq struct { SourceType string `json:"source_type"` } // SearchBookMark 获取收藏列表 // @Description 获取收藏列表 // @Success 200 {object} // @router /searchBookMark [get] func (bk *BookMarkController) SearchBookMark(sourceType string, key string) { controllers.Wrap(&bk.BaseController, func() (result *controllers.WrapData, err error) { result = bk.InitWrapData("分页搜索收藏列表失败") pageRes := page.Page{ Current: bk.PageInfo.Current, PageSize: bk.PageInfo.PageSize, } if sourceType == "" || (sourceType != Report && sourceType != Chart) { err = exception.New(exception.IllegalSourceType) bk.FailedResult("分页搜索收藏列表失败", result) return } userInfo := bk.Data["user"].(user.User) var sourceIds []int pageRes.Total, sourceIds, err = user.GetTotalBookMarkPageBySourceType(userInfo.Id, sourceType) //隐藏品种信息未设置风险等级的报告 if sourceType == Report { pageRes.Total, sourceIds, err = report.FilterReportIds(sourceIds) } if pageRes.Total == 0 { bookMarks := new(page.PageResult) bookMarks.Data = []interface{}{} bookMarks.Page = pageRes bk.SuccessResult("分页搜索收藏列表列表成功", bookMarks, result) return } pageRes.Total = bk.PageInfo.Total pageRes.TotalPage = page.TotalPages(pageRes.Total, pageRes.PageSize) var bookMarkList []userService.BookMarkInterface switch sourceType { case Report: reportList, reportErr := report.SearchReportBookMark(key, sourceIds, bk.PageInfo, true, userInfo.Id) if reportErr != nil { logger.Error("搜索研报列表失败%v", err) err = exception.NewWithException(exception.GetBookMarkListFailed, reportErr.Error()) bk.FailedResult("分页搜索收藏列表失败", result) return } for _, reportInfo := range reportList { bookMarkList = append(bookMarkList, ConvertToBookMarkReport(reportInfo)) } case Chart: chartList, chartErr := chartService.SearchChartList(key, sourceIds, bk.PageInfo) if chartErr != nil { logger.Error("搜索研报列表失败%v", err) err = exception.NewWithException(exception.GetBookMarkListFailed, chartErr.Error()) bk.FailedResult("分页搜索收藏列表失败", result) return } for _, chart := range chartList { bookMarkList = append(bookMarkList, ConvertToBookMarkChart(chart)) } default: err = exception.NewWithException(exception.GetBookMarkListFailed, "不支持的收藏类型") bk.FailedResult("分页搜索收藏列表失败", result) return } //bookMarkList, err = user.SearchBookMark(key, sourceType, sourceIds, bk.PageInfo, userInfo.Id) bookMarks := new(page.PageResult) bookMarks.Data = bookMarkList bookMarks.Page = pageRes bk.SuccessResult("分页搜索收藏列表成功", bookMarks, result) return }) } func ConvertToBookMarkChart(chart chartService.ChartInfo) userService.BookMarkChart { return userService.BookMarkChart{ ChartName: chart.ChartName, ChartImage: chart.ChartImage, UniqueCode: chart.UniqueCode, ChartInfoId: chart.ChartInfoId, } } func ConvertToBookMarkReport(report reportDomian.ReportDTO) userService.BookMarkReport { return userService.BookMarkReport{ Abstract: report.Abstract, Author: report.Author, AuthorInfo: report.AuthorInfo, ClassifyId: report.ClassifyId, CoverSrc: report.CoverSrc, CoverUrl: report.CoverUrl, Detail: report.Detail, Highlight: report.Highlight, IsFree: report.IsFree, IsPackage: report.IsPackage, IsSubscribe: report.IsSubscribe, Login: report.Login, OrgId: report.OrgId, PdfUrl: report.PdfUrl, PermissionNames: report.PermissionNames, Permissions: report.Permissions, PlateName: report.PlateName, Price: report.Price, ProductId: report.ProductId, PublishedTime: report.PublishedTime, ReportID: report.ReportID, RiskLevel: report.RiskLevel, RiskLevelStatus: report.RiskLevelStatus, Score: report.Score, SecondPermission: report.SecondPermission, Show: report.Show, Source: report.Source, SubscribeStatus: report.SubscribeStatus, Title: report.Title, Type: report.Type, } } // BookMarkList 获取收藏列表 // @Description 获取收藏列表 // @Success 200 {object} // @router /bookMarkList [get] func (bk *BookMarkController) BookMarkList(sourceType string) { controllers.Wrap(&bk.BaseController, func() (result *controllers.WrapData, err error) { result = bk.InitWrapData("分页查询收藏列表失败") pageRes := page.Page{ Current: bk.PageInfo.Current, PageSize: bk.PageInfo.PageSize, } if sourceType == "" || (sourceType != Report && sourceType != Chart) { err = exception.New(exception.IllegalSourceType) bk.FailedResult("分页查询收藏列表失败", result) return } userInfo := bk.Data["user"].(user.User) var sourceIds []int pageRes.Total, sourceIds, err = user.GetTotalBookMarkPageBySourceType(userInfo.Id, sourceType) //隐藏品种信息未设置风险等级的报告 if sourceType == Report { pageRes.Total, sourceIds, err = report.FilterReportIds(sourceIds) } if pageRes.Total == 0 { bookMarks := new(page.PageResult) bookMarks.Data = []interface{}{} bookMarks.Page = pageRes bk.SuccessResult("分页查询收藏列表成功", bookMarks, result) return } pageRes.Total = bk.PageInfo.Total pageRes.TotalPage = page.TotalPages(pageRes.Total, pageRes.PageSize) switch sourceType { case Report: var list []userService.BookMarkReport list, err = getReportList(bk.PageInfo, userInfo.Id, sourceIds) if err != nil { err = exception.NewWithException(exception.GetBookMarkListFailed, err.Error()) bk.FailedResult("分页查询收藏列表失败", result) return } bookMarks := new(page.PageResult) bookMarks.Data = list bookMarks.Page = pageRes bk.SuccessResult("分页查询收藏列表成功", bookMarks, result) return case Chart: var list []userService.BookMarkChart list, err = getChartList(bk.PageInfo, userInfo.Id) if err != nil { err = exception.NewWithException(exception.GetBookMarkListFailed, err.Error()) bk.FailedResult("分页查询收藏列表失败", result) return } bookMarks := new(page.PageResult) bookMarks.Data = list bookMarks.Page = pageRes bk.SuccessResult("分页查询收藏列表成功", bookMarks, result) return default: err = exception.New(exception.IllegalSourceType) bk.FailedResult("分页查询收藏列表失败", result) return } }) } func getReportList(info page.PageInfo, templateUserId int, sourceIds []int) (list []userService.BookMarkReport, err error) { sourceIds, err = userService.GetBookMarkPageRangeBySourceType(templateUserId, info, Report, sourceIds) if err != nil { return } userProfile, userErr := user.GetUserProfile(templateUserId) if userErr != nil { if errors.Is(userErr, gorm.ErrRecordNotFound) { err = exception.New(exception.TemplateUserNotFound) } else { err = exception.New(exception.TemplateUserFoundFailed) } logger.Error("获取临时客户信息失败:%v", err) return } var mappingRiskLevel, userRiskStatus string userRiskStatus = userProfile.RiskLevelStatus if userProfile.RiskLevel != "" { var mapping permissionService.CustomerProductRiskMappingDTO mapping, err = permissionService.GetRiskMappingByCustomerRiskLevel(userProfile.RiskLevel) if err != nil { logger.Error("查询产品风险等级映射失败:%v", err) return } mappingRiskLevel = mapping.ProductRiskLevel } reports, err := report.GetReportListById(templateUserId, sourceIds, mappingRiskLevel, userRiskStatus) if err != nil { return nil, err } list = make([]userService.BookMarkReport, len(sourceIds)) // 并发获取数据 for index, sourceId := range sourceIds { for _, reportDTO := range reports { if reportDTO.ReportID == sourceId { reportInfo := ConvertToBookMarkReport(reportDTO) list[index] = reportInfo } } } return } func getChartList(info page.PageInfo, templateUserId int) (list []userService.BookMarkChart, err error) { sourceIds, err := userService.GetBookMarkPageBySourceType(templateUserId, info, Chart) if err != nil { return } // 创建一个切片来存储结果,长度与 sourceIds 相同 list = make([]userService.BookMarkChart, len(sourceIds)) // 使用 WaitGroup 来等待所有 goroutine 完成 var wg sync.WaitGroup wg.Add(len(sourceIds)) // 使用 Mutex 来保护对 list 的写操作 var mu sync.Mutex // 并发获取数据 for index, sourceId := range sourceIds { go func(index int, id int) { defer wg.Done() var data chartService.ChartInfo data, err = chartService.GetChartById(id) chartInfo := ConvertToBookMarkChart(data) if err != nil { logger.Error("获取数据失败: %v", err) } // 使用 Mutex 保护对 list 的写操作 mu.Lock() list[index] = chartInfo mu.Unlock() }(index, sourceId) } // 等待所有 goroutine 完成 wg.Wait() return }