Files
2025-07-29 12:45:07 +08:00

355 lines
7.8 KiB
Go
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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 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
}