You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

351 lines
8.6 KiB
Go

1 month ago
package article
import (
"cls/internal/domain/article"
"cls/internal/domain/free_trial"
"cls/internal/domain/purchase"
domainUser "cls/internal/domain/user"
"cls/pkg/logger"
"cls/pkg/util/page"
"errors"
"strings"
"time"
"xorm.io/builder"
)
type ArticleService struct {
repo article.ArticleRepository
userRepo domainUser.UserRepository
purchaseRepo purchase.Repository
FreeRepo free_trial.FreeTrialRepository
resp *ArticleResp
log logger.Logger
}
func NewArticleService(repo article.ArticleRepository,
userRepo domainUser.UserRepository,
purchaseRepo purchase.Repository,
FreeRepo free_trial.FreeTrialRepository,
resp *ArticleResp,
log logger.New) *ArticleService {
return &ArticleService{repo,
userRepo,
purchaseRepo,
FreeRepo,
resp,
log("cls:service:article")}
}
var class_type = map[int64]string{
20014: "狙击龙虎榜",
20015: "盘中宝",
20021: "风口研报",
20022: "公告全知道",
20023: "研选",
20025: "财联社早知道",
20026: "电报解读",
20087: "金牌纪要库",
}
var class_type_reverse = map[string]int64{
"狙击龙虎榜": 20014,
"盘中宝": 20015,
"风口研报": 20021,
"公告全知道": 20022,
"研选": 20023,
"财联社早知道": 20025,
"电报解读": 20026,
"金牌纪要库": 20087,
}
func (a *ArticleService) Find(ePhone string, page *page.Page, searchParams map[string]string) error {
conds := make([]builder.Cond, 0)
class := searchParams["search_like_class"]
if class != "" {
classCode := class_type_reverse[class]
if classCode != 0 {
conds = append(conds, builder.Eq{"type": classCode})
}
}
conds = append(conds, builder.And(builder.Gt{"ctime": time.Now().AddDate(0, 0, -2).Unix()}))
articles := make([]*article.LianV1Article, 0)
page.Content = &articles
err := a.repo.Find(page, conds)
if err != nil {
a.log.Error(err)
return err
}
user, err := a.userRepo.FindByPhone(ePhone)
if err != nil {
a.log.Error(err)
}
articleIds := make([]uint64, 0, len(articles))
for _, v := range articles {
articleIds = append(articleIds, v.Id)
}
purchaseId := make(map[uint64]struct{})
if user != nil {
purchaseData, err := a.purchaseRepo.FindArticleById(articleIds...)
if err != nil {
a.log.Error(err.Error())
}
if purchaseData != nil {
for _, v := range purchaseData {
purchaseId[v.ContentId] = struct{}{}
}
}
}
articleIds = nil
result := make([]*ArticleDto, 0, len(articles))
for _, v := range articles {
t := time.Unix(v.Ctime, 0) // 秒数和纳秒数0 表示没有纳秒部分
m, g := a.getMainGrowthBoard(v.Stocks)
_, lock := purchaseId[v.Id]
result = append(result, &ArticleDto{
EventId: v.Id,
Title: v.Title,
Class: class_type[v.Type],
ReleaseDate: t.Format("2006-01-02"),
ReleaseTime: t.Format("15:04"),
Brief: v.Brief,
MainBoard: m,
GrowthBoard: g,
Unlock: lock,
})
}
articles = nil
page.Content = &result
return nil
}
func (a *ArticleService) FindUnLock(ePhone string, page *page.Page, searchParams map[string]string) error {
user, err := a.userRepo.FindByPhone(ePhone)
if err != nil {
a.log.Error(err)
return err
}
conds := make([]builder.Cond, 0)
class := searchParams["search_like_class"]
if class != "" {
classCode := class_type_reverse[class]
if classCode != 0 {
conds = append(conds, builder.Eq{"type": classCode})
}
}
purchaseData, err := a.purchaseRepo.FindArticlesByUserId(user.Id)
if err != nil {
a.log.Error(err)
return err
}
if len(purchaseData) == 0 {
return nil
}
pId := make([]uint64, 0, len(purchaseData))
for _, v := range purchaseData {
pId = append(pId, v.ContentId)
}
conds = append(conds, builder.In("id"))
articles := make([]*article.LianV1Article, 0)
page.Content = &articles
err = a.repo.Find(page, conds)
if err != nil {
a.log.Error(err)
return err
}
result := make([]*ArticleDto, 0, len(articles))
for _, v := range articles {
t := time.Unix(v.Ctime, 0) // 秒数和纳秒数0 表示没有纳秒部分
m, g := a.getMainGrowthBoard(v.Stocks)
result = append(result, &ArticleDto{
EventId: v.Id,
Title: v.Title,
Class: class_type[v.Type],
ReleaseDate: t.Format("2006-01-02"),
ReleaseTime: t.Format("15:04"),
Brief: v.Brief,
Content: v.Content,
Stocks: v.Stocks,
MainBoard: m,
GrowthBoard: g,
Unlock: false,
})
}
articles = nil
page.Content = &result
return nil
}
func (a *ArticleService) FindFree(page *page.Page, searchParams map[string]string) error {
conds := make([]builder.Cond, 0)
class := searchParams["search_like_class"]
if class != "" {
classCode := class_type_reverse[class]
if classCode != 0 {
conds = append(conds, builder.Eq{"type": classCode})
}
}
conds = append(conds, builder.And(builder.Lt{"ctime": time.Now().AddDate(0, 0, -7).Unix()}))
page.PageSize = 20
articles := make([]*article.LianV1Article, 0)
page.Content = &articles
err := a.repo.Find(page, conds)
if err != nil {
a.log.Error(err)
return err
}
result := make([]*ArticleDto, 0, len(articles))
for _, v := range articles {
t := time.Unix(v.Ctime, 0) // 秒数和纳秒数0 表示没有纳秒部分
m, g := a.getMainGrowthBoard(v.Stocks)
result = append(result, &ArticleDto{
EventId: v.Id,
Title: v.Title,
Class: class_type[v.Type],
ReleaseDate: t.Format("2006-01-02"),
ReleaseTime: t.Format("15:04"),
Brief: v.Brief,
Stocks: v.Stocks,
Content: v.Content,
MainBoard: m,
GrowthBoard: g,
Unlock: true,
})
}
articles = nil
page.Content = &result
return nil
}
func (a *ArticleService) Detail(userPhone string, id uint64) (*ArticleDto, error) {
user, err := a.userRepo.FindByPhone(userPhone)
if err != nil {
a.log.Error(err)
return nil, err
}
p, err := a.purchaseRepo.FindByUserIdAndContent(user.Id, id, purchase.ContentTypeArticle)
if err != nil {
a.log.Error(err)
return nil, err
}
articleDto := &ArticleDto{}
if p == nil {
articleDto.Unlock = false
return articleDto, nil
}
article, err := a.repo.GetArticleById(id)
if err != nil {
a.log.Error(err)
return nil, err
}
t := time.Unix(article.Ctime, 0)
m, g := a.getMainGrowthBoard(article.Stocks)
return &ArticleDto{
EventId: article.Id,
Title: article.Title,
Class: class_type[article.Type],
ReleaseDate: t.Format("2006-01-02"),
ReleaseTime: t.Format("15:04"),
Stocks: article.Stocks,
Brief: article.Brief,
MainBoard: m,
GrowthBoard: g,
Content: article.Content,
Unlock: true,
}, nil
}
func (a *ArticleService) UnLockArticle(ePhone string, aid uint64) (*ArticleDto, error) {
user, err := a.userRepo.FindByPhone(ePhone)
if err != nil {
a.log.Error(err.Error())
return nil, err
}
if user.GiftCount-1 < 0 {
a.log.Errorf("用户【%d】赠送次数不够", user.Id)
return nil, errors.New("赠送次数用尽")
}
ar, err := a.repo.GetArticleById(aid)
if err != nil {
a.log.Error(err.Error())
return nil, err
}
err = a.userRepo.UpdateUserGiftCount(user.Id, user.GiftCount-1)
if err != nil {
a.log.Error(err.Error())
return nil, err
}
pr := &purchase.Purchase{
UserId: user.Id,
ContentId: aid,
ContentType: purchase.ContentTypeArticle,
ContentSource: purchase.ContentSourceGift,
}
err = a.purchaseRepo.Save(pr)
if err != nil {
a.log.Error(err.Error())
return nil, err
}
return &ArticleDto{
Stocks: ar.Stocks,
Content: ar.Content,
Unlock: true,
}, nil
}
func (a ArticleService) getMainGrowthBoard(stocks string) (int, int) {
if stocks == "" {
return 0, 0
}
// 将字符串分割成股票代码数组
stockList := strings.Split(stocks, ",")
mainBoardCount := 0 // 主板数量
growthBoardCount := 0 // 创业板数量
for _, stock := range stockList {
// 去除可能的空格
stock = strings.TrimSpace(stock)
// 检查股票代码长度是否合法sz/sh + 6位数字
if len(stock) < 8 {
continue
}
// 获取股票代码(去除市场前缀)
prefix := strings.ToLower(stock[0:2]) // 转换为小写
code := stock[2:]
// 检查前缀是否合法
if prefix != "sz" && prefix != "sh" {
continue
}
switch {
// 创业板: 300xxx 或 301xxx
case strings.HasPrefix(code, "300") || strings.HasPrefix(code, "301"):
growthBoardCount++
// 主板:
// 深圳主板 00xxxx
// 上海主板 60xxxx
case strings.HasPrefix(code, "000") || strings.HasPrefix(code, "001") ||
strings.HasPrefix(code, "002") || strings.HasPrefix(code, "600") ||
strings.HasPrefix(code, "601") || strings.HasPrefix(code, "603") ||
strings.HasPrefix(code, "605"):
mainBoardCount++
}
}
return mainBoardCount, growthBoardCount
}