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