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.

369 lines
9.2 KiB
Go

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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"
"fmt"
"strings"
"time"
"xorm.io/builder"
)
type ArticleService struct {
repo article.ArticleRepository
userRepo domainUser.UserRepository
purchaseRepo purchase.Repository
userAggregateRepo domainUser.UserAggregateRepository
FreeRepo free_trial.FreeTrialRepository
log logger.Logger
}
func NewArticleService(repo article.ArticleRepository,
userRepo domainUser.UserRepository,
purchaseRepo purchase.Repository,
userAggregateRepo domainUser.UserAggregateRepository,
FreeRepo free_trial.FreeTrialRepository,
log logger.New) *ArticleService {
return &ArticleService{repo,
userRepo,
purchaseRepo,
userAggregateRepo,
FreeRepo,
log("cls:service:article")}
}
var class_type = map[uint64]string{
20014: "狙击龙虎榜",
20015: "盘中宝",
20021: "风口研报",
20022: "公告全知道",
20023: "研选",
20025: "财联社早知道",
20026: "电报解读",
20087: "金牌纪要库",
}
var class_type_reverse = map[string]uint64{
"狙击龙虎榜": 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
}
purchaseId := make(map[uint64]struct{})
if ePhone != "" {
user, err := a.userRepo.FindByPhone(ePhone)
if err != nil {
a.log.Error(err)
}
columnData, err := a.purchaseRepo.FindColumnsByUserId(user.Id)
columnMap := make(map[uint64]struct{})
if len(columnData) != 0 {
for _, v := range columnData {
columnMap[v.ContentId] = struct{}{}
}
}
articleIds := make([]uint64, 0, len(articles))
for _, v := range articles {
_, has := columnMap[v.Type]
if has {
purchaseId[v.Id] = struct{}{}
} else {
articleIds = append(articleIds, v.Id)
}
}
purchaseData, err := a.purchaseRepo.FindArticleById(user.Id, articleIds...)
articleIds = nil
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]
ad := &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,
}
if lock {
ad.Stocks = v.Stocks
ad.Content = v.Content
}
result = append(result, ad)
}
purchaseId = nil
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_eq_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", pId))
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: true,
})
}
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) {
// 1. 获取用户聚合根
userAggregate, err := a.userAggregateRepo.GetUserAggregate(ePhone)
if err != nil {
return nil, fmt.Errorf("获取用户信息失败: %w", err)
}
u := userAggregate.GetUser()
if u.GiftCount < 1 {
a.log.Errorf("用户【%d】免费次数不够", u.Id)
return nil, errors.New("没有次数了")
}
// 2. 获取文章
article, err := a.repo.GetArticleById(aid)
if err != nil {
return nil, fmt.Errorf("获取文章信息失败: %w", err)
}
// 3. 执行领域逻辑
if err := userAggregate.UnlockArticle(aid); err != nil {
return nil, fmt.Errorf("解锁文章失败: %w", err)
}
// 4. 保存聚合根状态
if err := a.userAggregateRepo.SaveUserAggregate(userAggregate); err != nil {
return nil, fmt.Errorf("保存用户状态失败: %w", err)
}
// 5. 返回结果
return &ArticleDto{
Stocks: article.Stocks,
Content: article.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
}