package product import ( logger "eta/eta_mini_ht_api/common/component/log" "eta/eta_mini_ht_api/common/exception" "eta/eta_mini_ht_api/common/utils/page" permissionService "eta/eta_mini_ht_api/domian/config" mediaDomain "eta/eta_mini_ht_api/domian/media" merchantService "eta/eta_mini_ht_api/domian/merchant" orderDomain "eta/eta_mini_ht_api/domian/order" reportDomain "eta/eta_mini_ht_api/domian/report" "eta/eta_mini_ht_api/domian/user" "eta/eta_mini_ht_api/models/config" "eta/eta_mini_ht_api/models/image" "eta/eta_mini_ht_api/models/media" merchantDao "eta/eta_mini_ht_api/models/merchant" configService "eta/eta_mini_ht_api/service/config" mediaService "eta/eta_mini_ht_api/service/media" reportService "eta/eta_mini_ht_api/service/report" userService "eta/eta_mini_ht_api/service/user" "fmt" "sort" "sync" "sync/atomic" "time" ) type ProductDTO struct { Id int `json:"id"` Title string `json:"title"` SourceTitle string `json:"sourceTitle"` Abstract string `json:"abstract"` Src string `json:"src"` PermissionNames []string `json:"permissionNames"` PermissionIds []int `json:"-"` Description string `json:"description"` Price string `json:"price"` CoverSrc int `json:"coverSrc"` CoverUrl string `json:"coverUrl"` RiskLevel string `json:"riskLevel"` Type string `json:"type"` BeginDate string `json:"beginDate"` EndDate string `json:"endDate"` SourceId int `json:"sourceId"` IsSubscribe bool `json:"isSubscribe"` ReportId int `json:"reportId"` MediaId int `json:"mediaId"` } func GetProductRiskLevel(product merchantService.MerchantProductDTO) (riskLevel, sourceTitle, sourceAbsract, coverSrc, sourceSrc string, permissionNames []string, permissionIds []int, err error) { switch product.Type { case "package": permissionRisk, permissionErr := config.PermissionsByPermissionId(product.SourceId) permissionNames = []string{permissionRisk.Name} permissionIds = []int{product.SourceId} if permissionErr != nil { logger.Error("获取权限信息失败[permissionId:%d]", product.SourceId) } else { riskLevel = permissionRisk.RiskLevel } coverSrc = product.CoverUrl case "audio", "video": mediaInfo, mediaErr := media.GetMediaById(product.Type, product.SourceId) sourceTitle, coverSrc, sourceSrc = mediaInfo.MediaName, mediaInfo.CoverSrc, mediaInfo.Src if mediaErr != nil { logger.Error("获取媒体信息失败[mediaType:%s,mediaId:%d]", product.Type, product.SourceId) } permissionIds, mediaErr = media.GetMediaPermissionMappingByMedia(product.Type, product.SourceId) if mediaErr != nil { logger.Error("获取媒体权限失败[mediaType:%s,mediaId:%d]", product.Type, product.SourceId) } else { permissions, permissionErr := permissionService.GetPermissionListByIds(permissionIds) if permissionErr != nil { logger.Error("获取权限信息失败[permissionIds:%v]", permissionIds) } permissionNames = mediaService.GetMediaPermissionNames(permissionIds) riskNum := configService.GetHighestRiskLevel(permissions) riskLevel = fmt.Sprintf("R%d", riskNum) } case "report": report, reportErr := reportDomain.GetReportById(product.SourceId, 0) var coverSrcId int sourceAbsract, sourceTitle, coverSrcId = report.Abstract, report.Title, report.CoverSrc if coverSrcId > 0 { var imageSrc string imageSrc, coverSrcErr := image.GetImageSrc(coverSrcId) if coverSrcErr != nil { logger.Error("获取图片资源失败:%v,资源ID:%d", err, coverSrcId) } else { coverSrc = imageSrc } } if reportErr != nil { logger.Error("获取研报信息失败[reportId:%d]", product.SourceId) } else { switch report.Source { case reportDomain.SourceHT: permission, permissionErr := configService.GetPermissionByName(report.PlateName) if permissionErr != nil { logger.Error("获取板块权限失败[plateName:%s]", report.PlateName) } else { riskLevel = permission.RiskLevel permissionIds = []int{permission.PermissionId} } case reportDomain.SourceETA: permissions, permissionErr := configService.GetSecondPermissionsByClassifyId(report.ClassifyId) if permissionErr != nil { logger.Error("获取板块权限失败[plateName:%s]", report.PlateName) } else { riskNum := configService.GetHighestRiskLevel(permissions) for _, permission := range permissions { permissionIds = append(permissionIds, permission.PermissionId) } riskLevel = fmt.Sprintf("R%d", riskNum) } } _, permissionNames = reportService.GetReportPermissionNames(report.OrgId, report.Source) } default: logger.Warn("不支持的产品类型[%s]", product.Type) } return } func GetProductInfoById(productId int) (product ProductDTO, err error) { merchantProduct, err := merchantService.GetMerchantProductById(productId) if err != nil { err = exception.NewWithException(exception.ProductInfoError, err.Error()) return } product = convertToProductDTO(merchantProduct) product.RiskLevel, product.SourceTitle, product.Abstract, product.CoverUrl, product.Src, product.PermissionNames, _, err = GetProductRiskLevel(merchantProduct) if err != nil { logger.Error("获取风险等级失败[productId:%d]", productId) } return } func convertToProductDTO(product merchantService.MerchantProductDTO) (productDTO ProductDTO) { beginDate := time.Now() endDate := beginDate.Add(time.Duration(product.ValidDays) * 24 * time.Hour) productDTO = ProductDTO{ Id: product.Id, Title: product.Title, Description: product.Description, Price: product.Price, RiskLevel: product.RiskLevel, CoverSrc: product.CoverSrc, CoverUrl: product.CoverUrl, Type: product.Type, BeginDate: beginDate.Format(time.DateOnly), EndDate: endDate.Format(time.DateOnly), SourceId: product.SourceId, } if product.CoverUrl == "" && product.CoverSrc > 0 { imageSrc, err := image.GetImageSrc(product.CoverSrc) if err != nil { logger.Error("获取图片地址失败:%v,资源Id:%d", err, product.CoverSrc) } else { productDTO.CoverUrl = imageSrc } } return } // OpenProduct 开通产品 func OpenProduct(productOrder orderDomain.ProductOrderDTO) (err error) { product, err := merchantService.GetMerchantProductById(productOrder.ProductID) if err != nil { logger.Error("获取产品信息失败:%v", err) return } return merchantService.OpenProduct(productOrder.TemplateUserID, productOrder.OrderID, product) } // CloseProduct 退款关闭套餐 func CloseProduct(productOrder orderDomain.ProductOrderDTO) (err error) { product, err := merchantService.GetMerchantProductById(productOrder.ProductID) if err != nil { logger.Error("获取产品信息失败:%v", err) return } return merchantService.CloseProduct(productOrder.TemplateUserID, productOrder.OrderID, product) } // 过期产品 func GetRelatePackage(info ProductDTO) (prodList []ProductDTO, err error) { switch info.Type { case "audio", "video": permissionIds, permissionErr := media.GetMediaPermissionMappingByMedia(info.Type, info.SourceId) if permissionErr != nil { logger.Error("获取媒体品种信息失败:%v", err) return } merchantProduct, pdErr := merchantService.GetProductListBySourceIds(permissionIds, "package") if pdErr != nil { return } for _, product := range merchantProduct { if !product.Deleted && product.SaleStatus == "on_sale" { prodList = append(prodList, convertToProductDTO(product)) } } return case "report": reportInfo, reportErr := reportDomain.GetReportById(info.SourceId, 0) if reportErr != nil { logger.Error("获取报告信息失败:%v", err) return } permissions := reportDomain.GetReportSecondPermissionsById(reportInfo.OrgId, reportInfo.Source) var permissionIds []int if len(permissions) > 0 { for _, permission := range permissions { permissionIds = append(permissionIds, permission.PermissionId) } permissionIds = append(permissionIds, permissions[0].PermissionId) } merchantProduct, pdErr := merchantService.GetProductListBySourceIds(permissionIds, "package") if pdErr != nil { return } for _, product := range merchantProduct { prodList = append(prodList, convertToProductDTO(product)) } return default: err = exception.New(exception.ProductTypeError) return } } func GetProductListByProductType(productType string, permissionIds []int, templateUserId int) (total, latestId int64, productIds []int) { filterPermissionIds, riskLevel, _, err := userService.GetRiskLevelPermissionList(permissionIds, true, templateUserId) if err != nil { return } var dtoList []*ProductDTO productList, err := merchantService.GetProductListByProductType(productType) var wg sync.WaitGroup wg.Add(len(productList)) for i := 0; i < len(productList); i++ { go func(merchantProduct merchantService.MerchantProductDTO) { defer wg.Done() product := convertToProductDTO(merchantProduct) product.RiskLevel, product.SourceTitle, product.Abstract, product.CoverUrl, product.Src, product.PermissionNames, product.PermissionIds, err = GetProductRiskLevel(merchantProduct) if !compare(product.RiskLevel, riskLevel) { return } match := false for _, pdPermissionId := range product.PermissionIds { for _, permissionId := range filterPermissionIds { if pdPermissionId == permissionId { match = true break } } } if !match { return } dtoList = append(dtoList, &product) }(productList[i]) } wg.Wait() total = int64(len(dtoList)) var maxId int for i := 0; i < len(dtoList); i++ { productIds = append(productIds, dtoList[i].Id) if dtoList[i].Id > maxId { maxId = dtoList[i].Id } } latestId = int64(maxId) return } func compare(riskLevel, MatchRiskLevel string) bool { pRiskNum, riskErr := configService.ParseRiskLevel(riskLevel) if riskErr != nil { return false } riskLevelNum, riskErr := configService.ParseRiskLevel(MatchRiskLevel) if riskErr != nil { return false } if pRiskNum <= riskLevelNum { return true } return false } func ProductList(productIds []int, templateUserId int, info page.PageInfo) (dtoList []ProductDTO, err error) { var merchantProductList []merchantService.MerchantProductDTO merchantProductList, err = merchantService.GetProductPageByProductType(productIds, info) for _, product := range merchantProductList { productDTO := convertToProductDTO(product) productDTO.RiskLevel, productDTO.SourceTitle, productDTO.Abstract, productDTO.CoverUrl, productDTO.Src, productDTO.PermissionNames, _, err = GetProductRiskLevel(product) dtoList = append(dtoList, productDTO) } var wg sync.WaitGroup wg.Add(len(dtoList)) for i := 0; i < len(dtoList); i++ { go func(productDTO *ProductDTO) { defer wg.Done() productDTO.IsSubscribe = isSubscribeSignal(productDTO.Id, templateUserId) }(&dtoList[i]) } wg.Wait() return } func RangeProductList() (productIdMap map[string][]int, err error) { return merchantService.GetProductByProductType() } func ProductSearch(key string, templateUserId int, pageInfo page.PageInfo) (list []ProductDTO, err error) { var merchantProductList []merchantService.MerchantProductDTO var sourceIds []int var maxId int for _, product := range merchantProductList { if product.SourceId > maxId { maxId = product.SourceId } sourceIds = append(sourceIds, product.SourceId) } //reportList, err := reportDomain.SearchReportList(key, sourceIds, 1, len(sourceIds), int64(maxId)) //mediaList, err := mediaDomain.SearchMediaList(key) for _, product := range merchantProductList { productDTO := convertToProductDTO(product) list = append(list, productDTO) } return } func convertReportToSearchDTO(report reportDomain.ReportDTO) (dto reportDomain.ProductSearchDTO) { return reportDomain.ProductSearchDTO{ HighLight: report.Highlight[0], SourceId: report.ReportID, SourceType: "report", Score: report.Score, } } func convertMediaToSearchDTO(media mediaDomain.MediaDTO) (dto reportDomain.ProductSearchDTO) { return reportDomain.ProductSearchDTO{ HighLight: media.Highlight[0], SourceId: media.MediaId, SourceType: media.MediaType, Score: media.Score, } } func SearchRelateProduct(key string, productIdMap map[string][]int) (list []reportDomain.ProductSearchDTO, err error) { var wg sync.WaitGroup wg.Add(2) go func() { defer wg.Done() docIds := productIdMap["report"] reports, reportErr := reportService.SearchReportProduct(key, docIds) if reportErr != nil { logger.Error("搜索相关报告失败:%v,key:%s", reportErr, key) return } for _, report := range reports { list = append(list, convertReportToSearchDTO(report)) } }() go func() { defer wg.Done() docIds := append(productIdMap["audio"], productIdMap["video"]...) medias, mediaErr := mediaService.SearchMediaProduct(key, docIds) if mediaErr != nil { logger.Error("搜索相关媒体失败:%v,key:%s", mediaErr, key) return } for _, mediaInfo := range medias { list = append(list, convertMediaToSearchDTO(mediaInfo)) } }() wg.Wait() sort.Slice(list, func(i, j int) bool { return list[i].Score > list[j].Score }) return } func LatestId() (latestId int64) { return merchantService.LatestId() } func CountSearchPackageList(list []reportDomain.ProductSearchDTO) (total, latestId int64, permissionTotalMap map[int]*atomic.Int32) { productIdMap := make(map[string][]int, len(list)) permissionTotalMap = make(map[int]*atomic.Int32) for _, product := range list { ids := productIdMap[product.SourceType] ids = append(ids, product.SourceId) productIdMap[product.SourceType] = ids } var wg sync.WaitGroup wg.Add(len(productIdMap)) for key, ids := range productIdMap { go func(k string, ids []int) { defer wg.Done() var permissionMap map[int]int switch k { case "report": permissionMap = reportService.CountPermissionWeight(ids) case "audio", "video": permissionMap = mediaService.CountPermissionWeight(ids) } for permissionId, weight := range permissionMap { if permissionTotalMap[permissionId] == nil { permissionTotalMap[permissionId] = new(atomic.Int32) } permissionTotalMap[permissionId].Add(int32(weight)) } }(key, ids) } wg.Wait() total = int64(len(permissionTotalMap)) latestId = merchantService.LatestId() return } func ProductListBySort(isSignal bool, list []reportDomain.ProductSearchDTO, weightMap map[int]*atomic.Int32, templateUserId int, info page.PageInfo) (resultList []ProductDTO, err error) { var pdDTOS []merchantService.MerchantProductDTO pdDTOS, err = merchantService.ProductListBySort(isSignal, list, weightMap, info) var wg sync.WaitGroup wg.Add(len(pdDTOS)) for _, pd := range pdDTOS { go func(pd merchantService.MerchantProductDTO) { defer wg.Done() productDTO := convertToProductDTO(pd) productDTO.RiskLevel, productDTO.SourceTitle, productDTO.Abstract, productDTO.CoverUrl, productDTO.Src, productDTO.PermissionNames, _, err = GetProductRiskLevel(pd) productDTO.IsSubscribe = isSubscribeSignal(pd.Id, templateUserId) resultList = append(resultList, productDTO) }(pd) } wg.Wait() return } func isSubscribeSignal(productId int, templateUserId int) (isSubscribe bool) { subscribeList, subErr := user.GetUserSubscribe([]int{productId}, templateUserId) if subErr != nil { logger.Error("获取用户订阅状态失败:%v", subErr) return false } else { if len(subscribeList) == 0 { logger.Error("用户未订阅单品,productId:%v", productId) return false } else { return subscribeList[0].Status == merchantDao.SubscribeValid } } }