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 }