🎨 优化文章和讲师接口
This commit is contained in:
@@ -10,6 +10,7 @@ type TeacherVip struct {
|
|||||||
Avatar string `json:"avatar" gorm:"comment:讲师头像"`
|
Avatar string `json:"avatar" gorm:"comment:讲师头像"`
|
||||||
Price float64 `json:"price" gorm:"comment:VIP价格(单位为分)"`
|
Price float64 `json:"price" gorm:"comment:VIP价格(单位为分)"`
|
||||||
Desc string `json:"desc" gorm:"comment:VIP描述;type:longtext"`
|
Desc string `json:"desc" gorm:"comment:VIP描述;type:longtext"`
|
||||||
|
CategoryId uint `json:"category_id" gorm:"comment:分类ID;"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (TeacherVip) TableName() string {
|
func (TeacherVip) TableName() string {
|
||||||
|
@@ -31,6 +31,7 @@ type ArticleVo struct {
|
|||||||
TeacherAvatar string `json:"teacherAvatar" gorm:"comment:讲师头像"`
|
TeacherAvatar string `json:"teacherAvatar" gorm:"comment:讲师头像"`
|
||||||
IsFree int `json:"isFree" gorm:"comment:是否免费;default:0"` // 是否免费 0-否 1-是
|
IsFree int `json:"isFree" gorm:"comment:是否免费;default:0"` // 是否免费 0-否 1-是
|
||||||
IsBuy int `json:"isBuy" gorm:"comment:是否购买;default:0"` // 是否购买 0-否 1-是
|
IsBuy int `json:"isBuy" gorm:"comment:是否购买;default:0"` // 是否购买 0-否 1-是
|
||||||
|
CategoryId uint `json:"categoryId" gorm:"comment:分类ID"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ArticleTeacherVo struct {
|
type ArticleTeacherVo struct {
|
||||||
|
@@ -10,7 +10,7 @@ type VipRouter struct{}
|
|||||||
// InitVipRouter 初始化会员路由
|
// InitVipRouter 初始化会员路由
|
||||||
func (s *VipRouter) InitVipRouter(Router *gin.RouterGroup, PublicRouter *gin.RouterGroup) {
|
func (s *VipRouter) InitVipRouter(Router *gin.RouterGroup, PublicRouter *gin.RouterGroup) {
|
||||||
vipRouter := Router.Group("vip").Use(middleware.OperationRecord())
|
vipRouter := Router.Group("vip").Use(middleware.OperationRecord())
|
||||||
vipNoAuthRouter := PublicRouter.Group("vip").Use(middleware.OperationRecord())
|
vipNoAuthRouter := PublicRouter.Group("vip")
|
||||||
{
|
{
|
||||||
vipRouter.POST("", vipApi.Create) // 获取用户列表
|
vipRouter.POST("", vipApi.Create) // 获取用户列表
|
||||||
vipRouter.DELETE("", vipApi.Delete) // 更新用户余额
|
vipRouter.DELETE("", vipApi.Delete) // 更新用户余额
|
||||||
|
@@ -250,14 +250,34 @@ func (u *AppUserService) GetTeacherList(p common.PageInfo) (list []vo.TeacherInf
|
|||||||
return nil, 0, err
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取每个教师的粉丝数
|
// 批量查询所有教师的粉丝数
|
||||||
for i := range list {
|
var teacherIDs []uint
|
||||||
followCount, err := u.GetTeacherFansCount(list[i].ID)
|
for _, t := range list {
|
||||||
|
teacherIDs = append(teacherIDs, t.ID)
|
||||||
|
}
|
||||||
|
type FansCount struct {
|
||||||
|
TeacherId uint
|
||||||
|
Count int64
|
||||||
|
}
|
||||||
|
var fansCounts []FansCount
|
||||||
|
if len(teacherIDs) > 0 {
|
||||||
|
err = global.GVA_DB.Model(&app.Follow{}).
|
||||||
|
Select("teacher_id, count(*) as count").
|
||||||
|
Where("teacher_id IN ?", teacherIDs).
|
||||||
|
Group("teacher_id").
|
||||||
|
Scan(&fansCounts).Error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
global.GVA_LOG.Error("查询教师粉丝数失败", zap.Error(err))
|
global.GVA_LOG.Error("批量查询教师粉丝数失败", zap.Error(err))
|
||||||
return nil, 0, err
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
list[i].Follow = followCount
|
}
|
||||||
|
// 映射粉丝数
|
||||||
|
fansMap := make(map[uint]int64)
|
||||||
|
for _, fc := range fansCounts {
|
||||||
|
fansMap[fc.TeacherId] = fc.Count
|
||||||
|
}
|
||||||
|
for i := range list {
|
||||||
|
list[i].Follow = fansMap[list[i].ID]
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
|
@@ -64,11 +64,8 @@ func (s ArticleService) APPGetArticleList(pageInfo request.GetList) (list []vo.A
|
|||||||
offset := pageInfo.PageSize * (pageInfo.Page - 1)
|
offset := pageInfo.PageSize * (pageInfo.Page - 1)
|
||||||
|
|
||||||
db := global.GVA_DB.Model(&article.Article{}).Where("status = 1") // 只查询已发布的文章
|
db := global.GVA_DB.Model(&article.Article{}).Where("status = 1") // 只查询已发布的文章
|
||||||
err = db.Count(&total).Error
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// 优化:先构建所有筛选条件再查询总数和数据
|
||||||
if pageInfo.Title != "" {
|
if pageInfo.Title != "" {
|
||||||
db = db.Where("title LIKE ?", "%"+pageInfo.Title+"%")
|
db = db.Where("title LIKE ?", "%"+pageInfo.Title+"%")
|
||||||
}
|
}
|
||||||
@@ -78,14 +75,41 @@ func (s ArticleService) APPGetArticleList(pageInfo request.GetList) (list []vo.A
|
|||||||
if pageInfo.TeacherId != 0 {
|
if pageInfo.TeacherId != 0 {
|
||||||
db = db.Where("teacher_id = ?", pageInfo.TeacherId)
|
db = db.Where("teacher_id = ?", pageInfo.TeacherId)
|
||||||
}
|
}
|
||||||
|
|
||||||
if pageInfo.Keyword != "" {
|
if pageInfo.Keyword != "" {
|
||||||
db = db.Where("title LIKE ? OR article.desc LIKE ? OR teacher_name LIKE ?", "%"+pageInfo.Keyword+"%", "%"+pageInfo.Keyword+"%", "%"+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
|
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 {
|
for i, a := range list {
|
||||||
global.GVA_DB.Table("app_user").Select("avatar").Where("id = ?", a.TeacherId).Scan(&list[i].TeacherAvatar)
|
list[i].TeacherAvatar = avatars[a.TeacherId]
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
@@ -113,9 +137,37 @@ func (s ArticleService) APPGetArticle(id string, userId int) (article *vo.Articl
|
|||||||
|
|
||||||
// 如果count = 0 或者 TeacherId 不等于 userId,表示用户没有购买过该文章
|
// 如果count = 0 或者 TeacherId 不等于 userId,表示用户没有购买过该文章
|
||||||
if count == 0 && article.TeacherId != userId {
|
if count == 0 && article.TeacherId != userId {
|
||||||
// 用户没有购买过,隐藏Content
|
|
||||||
article.Content = ""
|
// 判断用户是否已经包月该讲师和是否是讲师本人
|
||||||
article.IsBuy = 0 // 设置为未购买
|
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 // 设置为未购买
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user