Files
lckt-server/service/article/article.go
2025-09-17 12:09:18 +08:00

313 lines
9.2 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package article
import (
"fmt"
"git.echol.cn/loser/lckt/global"
"git.echol.cn/loser/lckt/model/app"
"git.echol.cn/loser/lckt/model/article"
"git.echol.cn/loser/lckt/model/article/request"
"git.echol.cn/loser/lckt/model/article/vo"
"git.echol.cn/loser/lckt/model/user"
"go.uber.org/zap"
"strings"
"time"
)
type ArticleService struct{}
func (ArticleService) CreateArticle(req article.Article) (err error) {
err = global.GVA_DB.Create(&req).Error
return
}
func (ArticleService) DeleteArticle(ids request.DeleteIds) (err error) {
err = global.GVA_DB.Delete(&article.Article{}, "id in ?", ids.Ids).Error
return
}
func (ArticleService) UpdateArticle(req article.Article) (err error) {
err = global.GVA_DB.Model(&article.Article{}).Where("id = ?", req.ID).Updates(&req).Error
return
}
func (ArticleService) GetArticle(id string) (article article.Article, err error) {
err = global.GVA_DB.Where("id = ?", id).First(&article).Error
return
}
func (ArticleService) GetArticleList(pageInfo request.GetList) (list []article.Article, total int64, err error) {
limit := pageInfo.PageSize
offset := pageInfo.PageSize * (pageInfo.Page - 1)
// 创建db
db := global.GVA_DB.Model(&article.Article{})
if pageInfo.Title != "" {
db = db.Where("title LIKE ?", "%"+pageInfo.Title+"%")
}
if pageInfo.CategoryId != 0 {
db = db.Where("category_id = ?", pageInfo.CategoryId)
}
if pageInfo.TeacherId != 0 {
db = db.Where("teacher_id = ?", pageInfo.TeacherId)
}
err = db.Count(&total).Error
if err != nil {
return
}
err = db.Limit(limit).Offset(offset).Order("created_at desc").Find(&list).Error
return
}
func (s ArticleService) APPGetArticleList(pageInfo request.GetList) (list []vo.ArticleListVo, total int64, err error) {
limit := pageInfo.PageSize
offset := pageInfo.PageSize * (pageInfo.Page - 1)
db := global.GVA_DB.Model(&article.Article{}).Where("status = 1") // 只查询已发布的文章
// 优化:先构建所有筛选条件再查询总数和数据
if pageInfo.Title != "" {
db = db.Where("title LIKE ?", "%"+pageInfo.Title+"%")
}
if pageInfo.CategoryId != 0 {
db = db.Where("category_id = ?", pageInfo.CategoryId)
}
if pageInfo.TeacherId != 0 {
db = db.Where("teacher_id = ?", pageInfo.TeacherId)
}
if pageInfo.Keyword != "" {
db = db.Where("title LIKE ? OR article.desc LIKE ? OR teacher_name LIKE ?", "%"+pageInfo.Keyword+"%", "%"+pageInfo.Keyword+"%", "%"+pageInfo.Keyword+"%")
}
// 先查总数
err = db.Count(&total).Error
if err != nil {
return
}
// 批量查出teacher_id
err = db.Limit(limit).Offset(offset).Omit("teacher_avatar").Order("created_at desc").Find(&list).Error
if err != nil {
return
}
// 优化批量查询讲师头像避免N+1查询
teacherIds := make([]int, 0, len(list))
for _, a := range list {
teacherIds = append(teacherIds, a.TeacherId)
}
avatars := make(map[int]string)
if len(teacherIds) > 0 {
type avatarResult struct {
ID int
Avatar string
}
var results []avatarResult
global.GVA_DB.Table("app_user").Select("id, avatar").Where("id IN ?", teacherIds).Find(&results)
for _, r := range results {
avatars[r.ID] = r.Avatar
}
}
for i, a := range list {
list[i].TeacherAvatar = avatars[a.TeacherId]
}
return
}
func (s ArticleService) APPGetArticle(id string, userId int) (article *vo.ArticleVo, err error) {
err = global.GVA_DB.Table("article").Where("id = ?", id).First(&article).Error
if err != nil {
global.GVA_LOG.Error("获取文章失败", zap.Error(err))
return
}
article.IsBuy = 1
global.GVA_DB.Table("app_user").Select("avatar").Where("id = ?", article.TeacherId).Scan(&article.TeacherAvatar)
// 判断是否免费
if article.IsFree == 0 {
// 如果不是免费文章,判断用户是否购买过
var count int64
err = global.GVA_DB.Model(&app.Order{}).Where("article_id = ? AND user_id = ? AND status = 2", id, userId).Count(&count).Error
if err != nil {
global.GVA_LOG.Error("查询用户购买记录失败", zap.Error(err))
return nil, err
}
// 如果count = 0 或者 TeacherId 不等于 userId表示用户没有购买过该文章
if count == 0 && article.TeacherId != userId {
// 判断用户是否已经包月该讲师和是否是讲师本人
if userId != 0 && userId != article.TeacherId {
var userTeacherVip []app.UserTeacherVip
err = global.GVA_DB.Model(&app.UserTeacherVip{}).Where("teacher_id = ? AND user_id = ? AND is_expire = 1", article.TeacherId, userId).Find(&userTeacherVip).Count(&count).Error
if err != nil {
global.GVA_LOG.Error("查询用户包月记录失败", zap.Error(err))
return nil, err
}
for _, vip := range userTeacherVip {
// 获取包月的信息 判断文章是否在包月范围内
var teacherVipInfo app.TeacherVip
err = global.GVA_DB.Model(&app.TeacherVip{}).Where("id = ?", vip.TeacherVipId).First(&teacherVipInfo).Error
if err != nil {
global.GVA_LOG.Error("查询讲师包月信息失败", zap.Error(err))
return nil, err
}
// 用户包月了,判断文章是否在包月范围内
if count != 0 {
if teacherVipInfo.CategoryId == article.CategoryId {
return
}
}
}
// 用户没有购买过隐藏Content
article.Content = ""
article.IsBuy = 0 // 设置为未购买
}
}
}
return
}
// AppPush app端推送文章
func (s ArticleService) AppPush(req article.Article) (err error) {
req.Status = 2 // 默认状态为待审核
if req.ID != 0 {
err = global.GVA_DB.Model(&article.Article{}).Where("id = ?", req.ID).Updates(&req).Error
} else {
err = global.GVA_DB.Create(&req).Error
}
if err != nil {
global.GVA_LOG.Error("推送文章失败", zap.Error(err))
return err
}
return nil
}
func (s ArticleService) GetMyArticleList(req request.GetList) (list []article.Article, total int64, err error) {
limit := req.PageSize
offset := req.PageSize * (req.Page - 1)
db := global.GVA_DB.Model(&article.Article{}).Where("teacher_id = ?", req.TeacherId)
if req.Title != "" {
db = db.Where("title LIKE ?", "%"+req.Title+"%")
}
if req.CategoryId != 0 {
db = db.Where("category_id = ?", req.CategoryId)
}
if req.Status != 0 {
db = db.Where("status = ?", req.Status)
}
err = db.Count(&total).Error
if err != nil {
return nil, 0, err
}
err = db.Limit(limit).Offset(offset).Find(&list).Error
return list, total, err
}
func (s ArticleService) GetBuyList(p request.GetList) (articles []article.Article, total int64, err error) {
buyIds := make([]int, 0)
// 获取用户购买的文章ID列表
err = global.GVA_DB.Model(&app.Order{}).Where("user_id = ? AND status = 2", p.UserId).Select("article_id").Find(&buyIds).Error
if err != nil {
global.GVA_LOG.Error("查询用户购买记录失败", zap.Error(err))
return nil, 0, err
}
if len(buyIds) == 0 {
// 如果没有购买记录,直接返回空列表
return []article.Article{}, 0, nil
}
db := global.GVA_DB.Model(&article.Article{}).Where("id IN ?", buyIds)
if p.Title != "" {
db = db.Where("title LIKE ?", "%"+p.Title+"%")
}
err = db.Count(&total).Error
if err != nil {
global.GVA_LOG.Error("查询购买文章总数失败", zap.Error(err))
return nil, 0, err
}
err = db.Limit(p.PageSize).Offset(p.PageSize * (p.Page - 1)).Find(&articles).Error
if err != nil {
global.GVA_LOG.Error("查询购买文章列表失败", zap.Error(err))
return nil, 0, err
}
return articles, total, nil
}
func (s ArticleService) AppDelete(id string) error {
err := global.GVA_DB.Delete(&article.Article{}, "id = ?", id).Error
if err != nil {
global.GVA_LOG.Error("删除文章失败", zap.Error(err))
return err
}
return nil
}
func (s ArticleService) BulkUpload(p request.BulkUpload) (err error) {
var articles []article.Article
var failedFiles []string
for _, a := range p.Files {
teacher := user.User{}
if dbErr := global.GVA_DB.Model(&teacher).Where("nick_name = ?", getTeacherName(a)).First(&teacher).Error; dbErr != nil {
global.GVA_LOG.Error("获取讲师信息失败", zap.Error(dbErr))
failedFiles = append(failedFiles, a)
continue
}
content := "<p><img src=" + a + " alt=\"" + a + "\" data-href=\"\" style=\"width: 100%;height: auto;\"/></p>"
// 将 p.PublishTime转为time.time类型
loc, _ := time.LoadLocation("Asia/Shanghai")
publishTime, _ := time.ParseInLocation("2006-01-02 15:04:05", p.PublishTime, loc)
articles = append(articles, article.Article{
Title: teacher.NickName + "--" + p.Title,
Desc: p.Desc,
CategoryId: p.CategoryId,
TeacherId: int(teacher.ID),
TeacherName: teacher.NickName,
CoverImg: teacher.Avatar,
Content: content,
IsFree: p.IsFree,
Price: int64(p.Price),
PublishTime: &publishTime,
})
}
if len(articles) > 0 {
if dbErr := global.GVA_DB.Create(&articles).Error; dbErr != nil {
global.GVA_LOG.Error("批量上传文章失败", zap.Error(dbErr))
return dbErr
}
}
if len(failedFiles) > 0 {
global.GVA_LOG.Error("部分文件上传失败", zap.Strings("failedFiles", failedFiles))
return fmt.Errorf("部分文件上传失败: %v", failedFiles)
}
return nil
}
func getTeacherName(url string) string {
lastSlash := strings.LastIndex(url, "/")
underscore := strings.Index(url[lastSlash+1:], "_")
if lastSlash == -1 || underscore == -1 {
return ""
}
return url[lastSlash+1 : lastSlash+1+underscore]
}