第一版完成
This commit is contained in:
355
internal/service/news.go
Normal file
355
internal/service/news.go
Normal file
@@ -0,0 +1,355 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"cms-api/internal/dao"
|
||||
"cms-api/internal/model"
|
||||
"strings"
|
||||
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
)
|
||||
|
||||
type sNews struct{}
|
||||
|
||||
func News() *sNews {
|
||||
return &sNews{}
|
||||
}
|
||||
|
||||
// GetById 根据ID获取新闻信息
|
||||
func (s *sNews) GetById(ctx context.Context, id int) (*model.News, error) {
|
||||
news, err := dao.News.GetById(ctx, id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if news != nil {
|
||||
// 增加浏览次数
|
||||
go func() {
|
||||
dao.News.IncrementViewCount(context.Background(), id)
|
||||
}()
|
||||
}
|
||||
return news, nil
|
||||
}
|
||||
|
||||
// GetBySlug 根据URL别名获取新闻
|
||||
func (s *sNews) GetBySlug(ctx context.Context, slug string) (*model.News, error) {
|
||||
news, err := dao.News.GetBySlug(ctx, slug)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if news != nil {
|
||||
// 增加浏览次数
|
||||
go func() {
|
||||
dao.News.IncrementViewCount(context.Background(), news.Id)
|
||||
}()
|
||||
}
|
||||
return news, nil
|
||||
}
|
||||
|
||||
// List 获取新闻列表
|
||||
func (s *sNews) List(ctx context.Context, req *model.NewsListRequest) (*model.PageResponse, error) {
|
||||
var (
|
||||
page = req.Page
|
||||
pageSize = req.PageSize
|
||||
)
|
||||
|
||||
if page <= 0 {
|
||||
page = 1
|
||||
}
|
||||
if pageSize <= 0 {
|
||||
pageSize = 10
|
||||
}
|
||||
|
||||
// 设置分页参数
|
||||
req.Page = page
|
||||
req.PageSize = pageSize
|
||||
|
||||
// 获取列表
|
||||
newsList, total, err := dao.News.List(ctx, req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &model.PageResponse{
|
||||
List: newsList,
|
||||
Total: total,
|
||||
Page: page,
|
||||
PageSize: pageSize,
|
||||
TotalPages: (total + pageSize - 1) / pageSize,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Create 创建新闻
|
||||
func (s *sNews) Create(ctx context.Context, req *model.CreateNewsRequest) error {
|
||||
// 检查URL别名是否存在
|
||||
if req.Slug != "" {
|
||||
existNews, err := dao.News.GetBySlug(ctx, req.Slug)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if existNews != nil {
|
||||
return gerror.New("URL别名已存在")
|
||||
}
|
||||
} else {
|
||||
// 如果没有提供slug,则根据标题生成
|
||||
req.Slug = s.generateSlug(req.Title)
|
||||
}
|
||||
|
||||
// 创建新闻
|
||||
news := &model.News{
|
||||
Title: req.Title,
|
||||
Slug: req.Slug,
|
||||
Summary: req.Summary,
|
||||
Content: req.Content,
|
||||
CoverImage: req.CoverImage,
|
||||
Category: req.Category,
|
||||
Source: req.Source,
|
||||
Author: req.Author,
|
||||
IsPublished: req.IsPublished,
|
||||
IsFeatured: req.IsFeatured,
|
||||
IsTop: req.IsTop,
|
||||
CreatedAt: gtime.Now(),
|
||||
UpdatedAt: gtime.Now(),
|
||||
}
|
||||
|
||||
if req.IsPublished == 1 {
|
||||
news.PublishedAt = gtime.Now()
|
||||
}
|
||||
|
||||
_, err := dao.News.Create(ctx, news)
|
||||
return err
|
||||
}
|
||||
|
||||
// Update 更新新闻
|
||||
func (s *sNews) Update(ctx context.Context, id int, req *model.UpdateNewsRequest) error {
|
||||
// 检查新闻是否存在
|
||||
news, err := s.GetById(ctx, id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if news == nil {
|
||||
return gerror.New("新闻不存在")
|
||||
}
|
||||
|
||||
// 检查URL别名是否被其他新闻使用
|
||||
if req.Slug != "" && req.Slug != news.Slug {
|
||||
existNews, err := dao.News.GetBySlug(ctx, req.Slug)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if existNews != nil && existNews.Id != id {
|
||||
return gerror.New("URL别名已被使用")
|
||||
}
|
||||
}
|
||||
|
||||
// 更新新闻
|
||||
updateData := g.Map{
|
||||
"title": req.Title,
|
||||
"slug": req.Slug,
|
||||
"summary": req.Summary,
|
||||
"content": req.Content,
|
||||
"cover_image": req.CoverImage,
|
||||
"category": req.Category,
|
||||
"source": req.Source,
|
||||
"author": req.Author,
|
||||
"is_published": req.IsPublished,
|
||||
"is_featured": req.IsFeatured,
|
||||
"is_top": req.IsTop,
|
||||
"updated_at": gtime.Now(),
|
||||
}
|
||||
|
||||
// 如果从草稿变为发布状态,设置发布时间
|
||||
if req.IsPublished == 1 && news.IsPublished == 0 {
|
||||
updateData["published_at"] = gtime.Now()
|
||||
}
|
||||
|
||||
return dao.News.Update(ctx, id, updateData)
|
||||
}
|
||||
|
||||
// Delete 删除新闻
|
||||
func (s *sNews) Delete(ctx context.Context, id int) error {
|
||||
// 检查新闻是否存在
|
||||
news, err := s.GetById(ctx, id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if news == nil {
|
||||
return gerror.New("新闻不存在")
|
||||
}
|
||||
|
||||
return dao.News.Delete(ctx, id)
|
||||
}
|
||||
|
||||
// UpdateStatus 更新新闻状态
|
||||
func (s *sNews) UpdateStatus(ctx context.Context, id int, isPublished int) error {
|
||||
// 检查新闻是否存在
|
||||
news, err := s.GetById(ctx, id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if news == nil {
|
||||
return gerror.New("新闻不存在")
|
||||
}
|
||||
|
||||
updateData := g.Map{
|
||||
"is_published": isPublished,
|
||||
"updated_at": gtime.Now(),
|
||||
}
|
||||
|
||||
// 如果是发布状态,设置发布时间
|
||||
if isPublished == 1 && news.IsPublished == 0 {
|
||||
updateData["published_at"] = gtime.Now()
|
||||
}
|
||||
|
||||
return dao.News.Update(ctx, id, updateData)
|
||||
}
|
||||
|
||||
// SetFeatured 设置推荐状态
|
||||
func (s *sNews) SetFeatured(ctx context.Context, id int, isFeatured int) error {
|
||||
// 检查新闻是否存在
|
||||
news, err := s.GetById(ctx, id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if news == nil {
|
||||
return gerror.New("新闻不存在")
|
||||
}
|
||||
|
||||
return dao.News.Update(ctx, id, g.Map{
|
||||
"is_featured": isFeatured,
|
||||
"updated_at": gtime.Now(),
|
||||
})
|
||||
}
|
||||
|
||||
// SetTop 设置置顶状态
|
||||
func (s *sNews) SetTop(ctx context.Context, id int, isTop int) error {
|
||||
// 检查新闻是否存在
|
||||
news, err := s.GetById(ctx, id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if news == nil {
|
||||
return gerror.New("新闻不存在")
|
||||
}
|
||||
|
||||
return dao.News.Update(ctx, id, g.Map{
|
||||
"is_top": isTop,
|
||||
"updated_at": gtime.Now(),
|
||||
})
|
||||
}
|
||||
|
||||
// GetStats 获取新闻统计信息
|
||||
func (s *sNews) GetStats(ctx context.Context) (map[string]interface{}, error) {
|
||||
// 获取总新闻数
|
||||
totalCount, err := dao.News.GetCount(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 获取已发布新闻数
|
||||
publishedCount, err := dao.News.GetPublishedCount(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 获取草稿数
|
||||
draftCount := totalCount - publishedCount
|
||||
|
||||
// 获取推荐新闻数
|
||||
featuredCount, err := dao.News.GetFeaturedCount(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 获取各分类新闻数
|
||||
companyNewsCount, err := dao.News.GetCountByCategory(ctx, "company_news")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
industryNewsCount, err := dao.News.GetCountByCategory(ctx, "industry_news")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return map[string]interface{}{
|
||||
"total_count": totalCount,
|
||||
"published_count": publishedCount,
|
||||
"draft_count": draftCount,
|
||||
"featured_count": featuredCount,
|
||||
"company_news_count": companyNewsCount,
|
||||
"industry_news_count": industryNewsCount,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GetFeatured 获取推荐新闻
|
||||
func (s *sNews) GetFeatured(ctx context.Context, limit int) ([]*model.News, error) {
|
||||
if limit <= 0 {
|
||||
limit = 5
|
||||
}
|
||||
return dao.News.GetFeatured(ctx, limit)
|
||||
}
|
||||
|
||||
// GetLatest 获取最新新闻
|
||||
func (s *sNews) GetLatest(ctx context.Context, limit int) ([]*model.News, error) {
|
||||
if limit <= 0 {
|
||||
limit = 10
|
||||
}
|
||||
return dao.News.GetLatest(ctx, limit)
|
||||
}
|
||||
|
||||
// GetByCategory 根据分类获取新闻
|
||||
func (s *sNews) GetByCategory(ctx context.Context, category string, page, pageSize int) (*model.PageResponse, error) {
|
||||
if page <= 0 {
|
||||
page = 1
|
||||
}
|
||||
if pageSize <= 0 {
|
||||
pageSize = 10
|
||||
}
|
||||
|
||||
newsList, total, err := dao.News.GetByCategory(ctx, category, page, pageSize)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &model.PageResponse{
|
||||
List: newsList,
|
||||
Total: total,
|
||||
Page: page,
|
||||
PageSize: pageSize,
|
||||
TotalPages: (total + pageSize - 1) / pageSize,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// generateSlug 生成URL别名
|
||||
func (s *sNews) generateSlug(title string) string {
|
||||
// 简单的slug生成逻辑
|
||||
slug := strings.ToLower(title)
|
||||
slug = strings.ReplaceAll(slug, " ", "-")
|
||||
slug = strings.ReplaceAll(slug, " ", "-") // 全角空格
|
||||
return slug
|
||||
}
|
||||
|
||||
// Search 搜索新闻
|
||||
func (s *sNews) Search(ctx context.Context, keyword string, page, pageSize int) (*model.PageResponse, error) {
|
||||
if page <= 0 {
|
||||
page = 1
|
||||
}
|
||||
if pageSize <= 0 {
|
||||
pageSize = 10
|
||||
}
|
||||
|
||||
newsList, total, err := dao.News.Search(ctx, keyword, page, pageSize)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &model.PageResponse{
|
||||
List: newsList,
|
||||
Total: total,
|
||||
Page: page,
|
||||
PageSize: pageSize,
|
||||
TotalPages: (total + pageSize - 1) / pageSize,
|
||||
}, nil
|
||||
}
|
||||
Reference in New Issue
Block a user