package services import ( "errors" "fmt" "github.com/PuerkitoBio/goquery" "hongze/hongze_clpt/models" "hongze/hongze_clpt/utils" "html" "regexp" "sort" "strconv" "strings" "time" "unicode/utf8" ) func FixArticleImgUrl(body string) (contentSub string, err error) { r := strings.NewReader(string(body)) doc, err := goquery.NewDocumentFromReader(r) if err != nil { fmt.Println(err) } doc.Find("img").Each(func(i int, s *goquery.Selection) { src, _ := s.Attr("src") if i == 0 && src != "" { contentSub = src } }) return } // GetReportContentTextSubByarticle 解析文章内容 func GetReportContentTextSubByarticle(content, abstract string, articleId int) (contentSub string, err error) { var lenabstract int //如果不是研选就这么展示 if articleId < utils.SummaryArticleId { abstract = html.UnescapeString(abstract) doc, errdoc := goquery.NewDocumentFromReader(strings.NewReader(abstract)) if errdoc != nil { err = errdoc return } docabstract := doc.Text() lenabstract = utf8.RuneCountInString(docabstract) if lenabstract >= 20 { contentSub = docabstract return } else { contentSub, err = GetReportContentTextSub(content) } } else { contentSub, err = GetReportContentTextSub(content) } return } func GetReportContentTextSub(content string) (contentSub string, err error) { content = html.UnescapeString(content) doc, errdoc := goquery.NewDocumentFromReader(strings.NewReader(content)) if errdoc != nil { err = errdoc return } docText := doc.Text() bodyRune := []rune(docText) bodyRuneLen := len(bodyRune) body := string(bodyRune[:bodyRuneLen]) contentSub = body contentSub = strings.Replace(body, "Powered by Froala Editor", "", -1) contentSub = strings.Replace(body, "PoweredbyFroalaEditor", "", -1) contentSub = strings.Replace(body, " ", "", -1) return } func GetReportContentTextArticleBody(content string) (contentSub string) { contentSub = html.UnescapeString(content) contentSub = strings.Replace(contentSub, "
Powered by Froala Editor
", "", -1) contentSub = strings.Replace(contentSub, "pre", "div", -1) return } // HandleArticleCategoryImg 预处理文章的封面图片 func HandleArticleCategoryImg(list []*models.ArticleListResp, user *models.WxUserItem) (items []*models.ArticleListResp, err error) { //研选的五张图片 detailResearch, e := models.GetConfigByCode("category_research_img_url") if e != nil { err = errors.New("获取研选的五张图片失败" + e.Error()) return } researchList := strings.Split(detailResearch.ConfigValue, "{|}") //对应分类的所图片 detailCategoryUrl, err := models.GetConfigByCode("category_map_img_url") if err != nil { err = errors.New("获取对应分类的所图片失败" + err.Error()) return } categoryUrlList := strings.Split(detailCategoryUrl.ConfigValue, "{|}") mapCategoryUrl := make(map[string]string) var categoryId string var imgUrlChart string for _, v := range categoryUrlList { vslice := strings.Split(v, "_") categoryId = vslice[0] imgUrlChart = vslice[len(vslice)-1] mapCategoryUrl[categoryId] = imgUrlChart } mapChartPerssion := make(map[string]string) reportMappingList, err := models.GetReportMappingStrategyAll() if err != nil { err = errors.New("GetReportMappingStrategyAll err" + err.Error()) return } for _, v := range reportMappingList { mapChartPerssion[strconv.Itoa(v.CategoryId)] = v.ChartPermissionName } for k, v := range list { if list[k].Annotation == "" { imgurl, _ := FixArticleImgUrl(html.UnescapeString(list[k].Body)) if imgurl != "" { list[k].BodyImg = imgurl } } item := list[k] //如果文章一开始的内容是图片,优先展示第一张图片 //newBody, _ := GetReportContentTextSubByarticle(item.Body, item.Annotation, item.ArticleId) list[k].Resource = item.Resource list[k].Annotation = ArticleAnnotation(item) list[k].Body = "" list[k].Abstract, _ = GetReportContentTextSub(v.Abstract) list[k].PublishDate = utils.StrTimeToTime(item.PublishDate).Format(utils.FormatDate) //时间字符串格式转时间格式 list[k].ChartPermissionName = mapChartPerssion[v.CategoryId] //如果是研选系列的任意取五张图片的中的一张 if v.CategoryId == "0" || v.ArticleId >= utils.SummaryArticleId { knum := v.ArticleId % 5 list[k].ImgUrlPc = researchList[knum] } else { list[k].ImgUrlPc = mapCategoryUrl[v.CategoryId] } if list[k].ArticleId < utils.SummaryArticleId { list[k].HttpUrl = utils.StrategyPlatform + strconv.Itoa(v.ArticleId) list[k].IsNeedJump = true } list[k].Source = 1 //添加行业默认图片 if v.ImgUrlPc == "" { if v.ChartPermissionName == utils.YI_YAO_NAME { list[k].ImgUrlPc = utils.YI_YAO_OTHER_IMG } else if v.ChartPermissionName == utils.XIAO_FEI_NAME { list[k].ImgUrlPc = utils.XIAO_FEI_OTHER_IMG } else if v.ChartPermissionName == utils.KE_JI_NAME { list[k].ImgUrlPc = utils.KE_JI_OTHER_IMG } else if v.ChartPermissionName == utils.ZHI_ZAO_NAME { list[k].ImgUrlPc = utils.ZHI_ZAO_OTHER_IMG } } if v.ArticleTypeId > 0 { list[k].IsResearch = true } } articleIds := make([]int, 0) var articleIdsSpecialArr []int // 研选专栏ID for _, v := range list { if v.IsSpecial == 0 { articleIds = append(articleIds, v.ArticleId) } else { articleIdsSpecialArr = append(articleIdsSpecialArr, v.ArticleId) } } // 报告关联产业信息 industryMap := make(map[int][]*models.IndustrialManagementIdInt, 0) if len(articleIds) > 0 { var industryCond string var industryPars []interface{} industryCond += ` AND mg.article_id IN (` + utils.GetOrmInReplace(len(articleIds)) + `)` industryPars = append(industryPars, articleIds) industryList, e := models.GetIndustrialListByarticleId(industryPars, industryCond) if e != nil { err = errors.New("GetIndustrialListByarticleId" + e.Error()) return } for i := range industryList { v := industryList[i] industryMap[v.ArticleId] = append(industryMap[v.ArticleId], &models.IndustrialManagementIdInt{ ArticleId: v.ArticleId, IndustrialManagementId: v.IndustrialManagementId, IndustryName: v.IndustryName, ChartPermissionId: v.ChartPermissionId, }) } } //// 处理文章收藏字段 //mapCollect, e := GetUserAticleCollectMap(user) //if e != nil { // err = errors.New("GetUserAticleCollectMap" + e.Error()) // return //} //var articleIds []int //for _, v := range list { // articleIds = append(articleIds, v.ArticleId) //} articleMapPv := GetArticleHistoryByArticleId(articleIds) //文章Pv articleCollectMap, _ := GetCygxArticleCollectMap(user.UserId) //用户收藏的文章 articleCollectNumMap, _ := GetCygxArticleCollectNumMapByArtcileIds(articleIds) //文章收藏的数量 articleCollectYanxuanSpecialMap, _ := GetYanxuanSpecialCollectMap(user.UserId) //用户收藏的研选专栏 yanxuanSpecialPv := GetYanxuanSpecialRecordByYanxuanSpecialId(articleIdsSpecialArr) //研选专栏Pv for k, v := range list { if len(industryMap[v.ArticleId]) > 0 { list[k].List = industryMap[v.ArticleId] } else { list[k].List = make([]*models.IndustrialManagementIdInt, 0) } //if _, ok := mapCollect[v.ArticleId]; ok { // list[k].IsCollect = true //} if v.IsSpecial == 0 { list[k].Pv = articleMapPv[v.ArticleId] list[k].IsCollect = articleCollectMap[v.ArticleId] list[k].CollectNum = articleCollectNumMap[v.ArticleId] } else { v.IsCollect = articleCollectYanxuanSpecialMap[v.ArticleId] v.Pv = yanxuanSpecialPv[v.ArticleId] } } if len(list) == 0 { list = make([]*models.ArticleListResp, 0) } items = list return } // HandleArticleStock 处理报告关联的个股标签 func HandleArticleStock(stock string) (items []*models.ComapnyNameResp) { sliceSubjects := strings.Split(stock, "/") if len(sliceSubjects) > 0 { for _, vSubject := range sliceSubjects { sliceKuohao := strings.Split(vSubject, "(") //过滤括号 sliceXiahuaxian := strings.Split(sliceKuohao[0], "-") //过滤下划线 subject := sliceXiahuaxian[0] items = append(items, &models.ComapnyNameResp{ComapnyName: subject}) } } return } // 弘则报告发布日期在三个月以内的 func GetArticNewLabelWhithActivity3Month() (labelMap map[int]bool, err error) { var condition string var pars []interface{} condition += ` AND publish_date <= ? AND article_id < ? ` pars = append(pars, time.Now().AddDate(0, -3, 0), utils.SummaryArticleId) articleList, e := models.GetArticleList(condition, pars) if e != nil { err = errors.New("GetArticleList, Err: " + e.Error()) return } var articleIds []int for _, v := range articleList { articleIds = append(articleIds, v.ArticleId) } if len(articleIds) == 0 { return } pars = make([]interface{}, 0) condition = ` AND article_id IN (` + utils.GetOrmInReplace(len(articleIds)) + `)` pars = append(pars, articleIds) industrialList, e := models.GetIndustrialArticleGroupManagementList(condition, pars) if e != nil { err = errors.New("GetIndustrialArticleGroupManagementList, Err: " + e.Error()) return } labelMap = make(map[int]bool, 0) var industrialIds []int for _, v := range industrialList { industrialIds = append(industrialIds, v.IndustrialManagementId) } // 获取活动关联的产业 var groupCond string var groupPars []interface{} groupCond += ` AND b.industrial_management_id IN (` + utils.GetOrmInReplace(len(industrialIds)) + `) AND b.source = 1 ` groupPars = append(groupPars, industrialIds) groups, e := models.GetActivityIndustryRelationList(groupCond, groupPars) if e != nil { err = errors.New("获取活动产业关联列表失败, Err: " + e.Error()) return } for _, v := range groups { labelMap[v.ActivityId] = true } return } // GetSpecialArticleDetailUserPower 处理用户查看专项调研文章详情的权限 func GetSpecialArticleDetailUserPower(user *models.WxUserItem, articleInfo *models.ArticleDetail) (havePower bool, err error) { userType, _, e := GetUserType(user.CompanyId) if e != nil { err = errors.New("GetSpecialUserType, Err: " + e.Error()) return } // 永续客户、大套餐客户可以查看行业升级套餐客户 权限 if userType == 1 || userType == 2 { havePower = true return } permissionStr, e := GetCompanyPermissionUpgrade(user.CompanyId) if e != nil { err = errors.New("GetCompanyPermissionUpgrade, Err: " + e.Error()) return } reportMapDetail, e := models.GetdetailByCategoryIdPush(articleInfo.CategoryId) if e != nil { err = errors.New("GetdetailByCategoryIdPush, Err: " + e.Error()) return } if reportMapDetail == nil { err = errors.New("GetdetailByCategoryIdP,获取详情失败, Err: ") return } //如果没有对应的升级权限,则返回 if !strings.Contains(permissionStr, reportMapDetail.ChartPermissionName) { return } else { havePower = true } return } //处理核心观点的展示规则 //func ArticleAnnotation(item *models.ArticleListResp) (annotation string) { // if item.Annotation != "" { // annotation = strings.Replace(item.Annotation, "Froala Editor
", "", -1) return } // 处理核心观点的展示规则 func ArticleAnnotation(item *models.ArticleListResp) (annotation string) { if item.ArticleId >= utils.SummaryArticleId { item.Annotation = YxArticleAnnotation(item) } if item.Annotation != "" { annotation = strings.Replace(item.Annotation, "" + annotationHtml + "
" annotation = annotationHtml } } return } // 处理核心观点的展示规则 func AnnotationHtml(bodyText string) (annotation string) { if bodyText == "" { return } annotation = bodyText annotation = html.UnescapeString(annotation) doc, _ := goquery.NewDocumentFromReader(strings.NewReader(annotation)) docText := doc.Text() mapDoc := make(map[int]string) var mapSort []int p := doc.Find("p") p.Each(func(tk int, pd *goquery.Selection) { pdText := pd.Text() pdText = strings.Replace(pdText, " ", "", -1) if pdText != "" { textLen := strings.Index(docText, pdText) if textLen >= 0 { mapDoc[(strings.Index(docText, pdText))] = pdText mapSort = append(mapSort, textLen) } } }) li := doc.Find("li") li.Each(func(tk int, li *goquery.Selection) { liText := li.Text() liText = strings.Replace(liText, " ", "", -1) if liText != "" { textLen := strings.Index(docText, liText) mapDoc[(strings.Index(docText, liText))] = strconv.Itoa(tk+1) + "." + liText mapSort = append(mapSort, textLen) } }) ul := doc.Find("ul") ul.Each(func(tk int, ul *goquery.Selection) { ulText := ul.Text() ulText = strings.Replace(ulText, " ", "", -1) if ulText != "" { textLen := strings.Index(docText, ulText) mapDoc[(strings.Index(docText, ulText))] = ulText mapSort = append(mapSort, textLen) } }) if len(mapSort) == 0 { return } else { //排序 sort.Ints(mapSort) var annotationHtml string for _, vSort := range mapSort { for k, v := range mapDoc { if k == vSort && v != "" { annotationHtml += v + "" + annotationHtml + "
" annotation = annotationHtml } return } // 处理产品内测展示规则 func ProductInteriorHtml(bodyText string) (annotation string) { if bodyText == "" { return } sliceBody := strings.Split(bodyText, "") annotation, _ = GetReportContentTextSub(sliceBody[0]) return } // 解析研选内容中的核心观点 func YxArticleAnnotation(article *models.ArticleListResp) (annotation string) { //如果不规范,就获取内容主体 if strings.Count(article.Body, "")
re, _ := regexp.Compile("
0 {
sliceId := strings.Split(reportLink, "id=")
if len(sliceId) > 1 {
reportLink = sliceId[1]
sliceMd5Id := strings.Split(reportLink, "&")
artMd5 = sliceMd5Id[0]
}
if artMd5 != "" {
detail, errArt := models.GetArticleDetailByIdMd5(artMd5)
if errArt != nil && errArt.Error() != utils.ErrNoRow() {
err = errArt
return
}
if detail != nil {
articleId = detail.ArticleId
}
}
} else {
//处理活动的
linkList := strings.Split(reportLink, "/")
if linkList[len(linkList)-1] != "" {
linkArticleId, _ := strconv.Atoi(linkList[len(linkList)-1])
if linkArticleId > 0 {
articleInfo, errArt := models.GetArticleDetailById(linkArticleId)
if errArt != nil && errArt.Error() != utils.ErrNoRow() {
err = errArt
return
}
if articleInfo != nil {
articleId = articleInfo.ArticleId
}
}
}
}
return
}
// GetArticleStockMap 获取个股标签所对应的文章ID
func GetArticleStockMap() (mapResp map[string]int, err error) {
defer func() {
if err != nil {
go utils.SendAlarmMsg("获取个股标签所对应的文章ID失败"+err.Error(), 2)
}
}()
list, err := models.GetArticleStock()
if err != nil && err.Error() != utils.ErrNoRow() {
return
}
mapResp = make(map[string]int, 0)
if len(list) > 0 {
//一对一精准匹配
for _, v := range list {
sliceSubjects := strings.Split(v.Stock, "/")
if len(sliceSubjects) > 0 {
for _, vSubject := range sliceSubjects {
sliceKuohao := strings.Split(vSubject, "(") //过滤括号
sliceXiahuaxian := strings.Split(sliceKuohao[0], "-") //过滤下划线
subject := sliceXiahuaxian[0]
mapResp[subject] = v.ArticleId
}
}
}
}
return
}
// 用户报告操作行为,模板消息推送
func ArticleUserRemind(user *models.WxUserItem, articleDetail *models.ArticleDetail, source int) (err error) {
defer func() {
if err != nil {
go utils.SendAlarmMsg("用户报告操作行为,模板消息推送 ,err"+err.Error(), 2)
}
}()
countUser, err := models.GetUserRemind(user.UserId)
if err != nil {
return err
}
if countUser == 0 {
return err
}
var sourceMsg string
if source == 1 {
sourceMsg = "阅读报告"
} else {
sourceMsg = "收藏报告"
}
//获取销售手机号
sellerItemQy, err := models.GetSellerByCompanyIdCheckFicc(user.CompanyId, 2)
if err != nil && err.Error() != utils.ErrNoRow() {
return err
}
if sellerItemQy != nil {
articleId := articleDetail.ArticleId
sllerAndShareMobileArr, e := GetCompanySellerAndShareMobileByRai(user.CompanyId) //获取所属销售以及对应销售的手机号
if e != nil {
err = errors.New("GetCompanySellerAndShareMobileByRai, Err: " + e.Error())
return
}
sllerAndShareMobiles := strings.Join(sllerAndShareMobileArr, ",")
openIdList, e := models.GetWxOpenIdByMobileList(sllerAndShareMobiles)
if e != nil {
err = errors.New("GetWxOpenIdByMobileList, Err: " + e.Error())
return err
}
var keyword1 string
var keyword2 string
keyword1 = articleDetail.Title
keyword2 = fmt.Sprint("互动:", sourceMsg, ",", user.RealName, "--", user.CompanyName)
SendWxMsgWithArticleUserRemind(keyword1, keyword2, openIdList, articleId)
if articleDetail.ArticleTypeId > 0 {
// 类目模版买方研选
openIdListMfyx, e := models.GetMfyxWxOpenIdByMobileList(sellerItemQy.Mobile)
if e != nil {
err = errors.New("GetMfyxWxOpenIdByMobileList, Err: " + e.Error())
return err
}
var redirectUrl string
keyword1 = utils.TruncateActivityNameString(user.RealName + "-" + user.CompanyName)
keyword2 = fmt.Sprint("互动提醒:", sourceMsg)
keyword3 := utils.TruncateActivityNameString(articleDetail.Title)
keyword4 := time.Now().Format(utils.FormatDateTimeMinute2)
redirectUrl = utils.WX_MSG_PATH_YX_ARTICLE_DETAIL + strconv.Itoa(articleId)
SendWxCategoryMsgWithActivityUserRemind(keyword1, keyword2, keyword3, keyword4, redirectUrl, openIdListMfyx, articleId)
}
}
return
}
// GetAiQianYanArtilceList 获取AI前沿几篇文章
func GetAiQianYanArtilceList(startSize, pageSize int) (items []*models.HomeArticle, total int, err error) {
defer func() {
if err != nil {
go utils.SendAlarmMsg("获取AI前沿几篇文章失败"+err.Error(), 2)
}
}()
var condition string
var pars []interface{}
condition += ` AND title LIKE '%AI前沿%' AND publish_status = 1 ORDER BY publish_date DESC `
articleList, e := models.GetCygxCygxArticleList(condition, pars, startSize, pageSize)
if e != nil {
err = errors.New("GetCygxCygxArticleList, Err: " + e.Error())
return
}
total, e = models.GetCygxArticleCount(condition, pars)
if e != nil {
err = errors.New("GetCygxArticleCount, Err: " + e.Error())
return
}
for _, v := range articleList {
item := new(models.HomeArticle)
item.ArticleId = v.ArticleId
item.Title = v.Title
item.Abstract = v.Abstract
item.Annotation = v.Annotation
item.PublishDate = v.PublishDate
item.CategoryId = strconv.Itoa(v.CategoryId)
item.Body = v.Body
items = append(items, item)
}
return
}
// GetYxArticleIdMap 获取研选文章ID
func GetYxArticleIdMap(articleIds []int) (mapResp map[int]bool) {
var err error
defer func() {
if err != nil {
go utils.SendAlarmMsg("获取研选文章ID失败,GetYxArticleIdMap"+err.Error(), 2)
}
}()
var condition string
var pars []interface{}
condition = ` AND article_type_id > 0 `
if len(articleIds) > 0 {
condition += ` AND article_id IN (` + utils.GetOrmInReplace(len(articleIds)) + `)`
pars = append(pars, articleIds)
}
articleList, e := models.GetArticleList(condition, pars)
if e != nil {
err = errors.New("GetArticleList, Err: " + e.Error())
return
}
mapResp = make(map[int]bool, 0)
for _, v := range articleList {
mapResp[v.ArticleId] = true
}
return
}
// 获取报告分享图片
func GetArticleShareImg(articleId int) (shareImg string) {
var err error
defer func() {
if err != nil {
fmt.Println(err)
go utils.SendAlarmMsg(fmt.Sprint("获取活动分享封面图片失败 GetArticleShareImg Err:", err.Error(), "活动ID:", articleId), 2)
}
}()
imgDetail, e := models.CygxCygxArticleDataDetail(articleId)
if e != nil && e.Error() != utils.ErrNoRow() {
err = errors.New("CygxCygxArticleDataDetail, Err: " + e.Error())
return
}
if imgDetail != nil {
shareImg = imgDetail.Cover
} else {
shareImg = utils.YANXUAN_ARTICLE_SHARE_IMG
}
return
}