|
|
|
|
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
|
|
|
|
|
}
|