319 lines
7.8 KiB
Go
319 lines
7.8 KiB
Go
|
|
package service
|
|||
|
|
|
|||
|
|
import (
|
|||
|
|
"dianshang/internal/model"
|
|||
|
|
"dianshang/internal/repository"
|
|||
|
|
"errors"
|
|||
|
|
"fmt"
|
|||
|
|
"time"
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
// BannerService 轮播图服务
|
|||
|
|
type BannerService struct {
|
|||
|
|
bannerRepo *repository.BannerRepository
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// NewBannerService 创建轮播图服务
|
|||
|
|
func NewBannerService(bannerRepo *repository.BannerRepository) *BannerService {
|
|||
|
|
return &BannerService{
|
|||
|
|
bannerRepo: bannerRepo,
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// GetActiveBanners 获取有效的轮播图
|
|||
|
|
func (s *BannerService) GetActiveBanners() ([]model.Banner, error) {
|
|||
|
|
return s.bannerRepo.GetActiveBannersWithTimeRange()
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// GetBannerList 获取轮播图列表(分页)
|
|||
|
|
func (s *BannerService) GetBannerList(page, pageSize int, status *int) ([]model.Banner, int64, error) {
|
|||
|
|
if page <= 0 {
|
|||
|
|
page = 1
|
|||
|
|
}
|
|||
|
|
if pageSize <= 0 || pageSize > 100 {
|
|||
|
|
pageSize = 10
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return s.bannerRepo.GetBannerList(page, pageSize, status)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// GetBannerByID 根据ID获取轮播图
|
|||
|
|
func (s *BannerService) GetBannerByID(id uint) (*model.Banner, error) {
|
|||
|
|
if id == 0 {
|
|||
|
|
return nil, errors.New("轮播图ID不能为空")
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return s.bannerRepo.GetBannerByID(id)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// CreateBanner 创建轮播图
|
|||
|
|
func (s *BannerService) CreateBanner(banner *model.Banner) error {
|
|||
|
|
// 验证必填字段
|
|||
|
|
if err := s.validateBanner(banner); err != nil {
|
|||
|
|
return err
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 如果没有设置排序值,自动设置为最大值+10
|
|||
|
|
if banner.Sort == 0 {
|
|||
|
|
maxSort, err := s.bannerRepo.GetMaxSort()
|
|||
|
|
if err != nil {
|
|||
|
|
return fmt.Errorf("获取最大排序值失败: %v", err)
|
|||
|
|
}
|
|||
|
|
banner.Sort = maxSort + 10
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 设置默认状态
|
|||
|
|
if banner.Status == 0 {
|
|||
|
|
banner.Status = 1
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return s.bannerRepo.CreateBanner(banner)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// UpdateBanner 更新轮播图
|
|||
|
|
func (s *BannerService) UpdateBanner(id uint, banner *model.Banner) error {
|
|||
|
|
if id == 0 {
|
|||
|
|
return errors.New("轮播图ID不能为空")
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 检查轮播图是否存在
|
|||
|
|
exists, err := s.bannerRepo.CheckBannerExists(id)
|
|||
|
|
if err != nil {
|
|||
|
|
return fmt.Errorf("检查轮播图是否存在失败: %v", err)
|
|||
|
|
}
|
|||
|
|
if !exists {
|
|||
|
|
return errors.New("轮播图不存在")
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 验证必填字段
|
|||
|
|
if err := s.validateBanner(banner); err != nil {
|
|||
|
|
return err
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
banner.ID = id
|
|||
|
|
return s.bannerRepo.UpdateBanner(banner)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// DeleteBanner 删除轮播图
|
|||
|
|
func (s *BannerService) DeleteBanner(id uint) error {
|
|||
|
|
if id == 0 {
|
|||
|
|
return errors.New("轮播图ID不能为空")
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 检查轮播图是否存在
|
|||
|
|
exists, err := s.bannerRepo.CheckBannerExists(id)
|
|||
|
|
if err != nil {
|
|||
|
|
return fmt.Errorf("检查轮播图是否存在失败: %v", err)
|
|||
|
|
}
|
|||
|
|
if !exists {
|
|||
|
|
return errors.New("轮播图不存在")
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return s.bannerRepo.DeleteBanner(id)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// BatchDeleteBanners 批量删除轮播图
|
|||
|
|
func (s *BannerService) BatchDeleteBanners(ids []uint) error {
|
|||
|
|
if len(ids) == 0 {
|
|||
|
|
return errors.New("轮播图ID列表不能为空")
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return s.bannerRepo.BatchDeleteBanners(ids)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// UpdateBannerStatus 更新轮播图状态
|
|||
|
|
func (s *BannerService) UpdateBannerStatus(id uint, status int) error {
|
|||
|
|
if id == 0 {
|
|||
|
|
return errors.New("轮播图ID不能为空")
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if status < 0 || status > 1 {
|
|||
|
|
return errors.New("状态值无效,只能是0或1")
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 检查轮播图是否存在
|
|||
|
|
exists, err := s.bannerRepo.CheckBannerExists(id)
|
|||
|
|
if err != nil {
|
|||
|
|
return fmt.Errorf("检查轮播图是否存在失败: %v", err)
|
|||
|
|
}
|
|||
|
|
if !exists {
|
|||
|
|
return errors.New("轮播图不存在")
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return s.bannerRepo.UpdateBannerStatus(id, status)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// BatchUpdateBannerStatus 批量更新轮播图状态
|
|||
|
|
func (s *BannerService) BatchUpdateBannerStatus(ids []uint, status int) error {
|
|||
|
|
if len(ids) == 0 {
|
|||
|
|
return errors.New("轮播图ID列表不能为空")
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if status < 0 || status > 1 {
|
|||
|
|
return errors.New("状态值无效,只能是0或1")
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return s.bannerRepo.BatchUpdateBannerStatus(ids, status)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// UpdateBannerSort 更新轮播图排序
|
|||
|
|
func (s *BannerService) UpdateBannerSort(id uint, sort int) error {
|
|||
|
|
if id == 0 {
|
|||
|
|
return errors.New("轮播图ID不能为空")
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if sort < 0 {
|
|||
|
|
return errors.New("排序值不能为负数")
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 检查轮播图是否存在
|
|||
|
|
exists, err := s.bannerRepo.CheckBannerExists(id)
|
|||
|
|
if err != nil {
|
|||
|
|
return fmt.Errorf("检查轮播图是否存在失败: %v", err)
|
|||
|
|
}
|
|||
|
|
if !exists {
|
|||
|
|
return errors.New("轮播图不存在")
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return s.bannerRepo.UpdateBannerSort(id, sort)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// BatchUpdateBannerSort 批量更新轮播图排序
|
|||
|
|
func (s *BannerService) BatchUpdateBannerSort(sortData []map[string]interface{}) error {
|
|||
|
|
if len(sortData) == 0 {
|
|||
|
|
return errors.New("排序数据不能为空")
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 验证排序数据
|
|||
|
|
for _, data := range sortData {
|
|||
|
|
id, ok := data["id"]
|
|||
|
|
if !ok {
|
|||
|
|
return errors.New("排序数据中缺少ID字段")
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
sort, ok := data["sort"]
|
|||
|
|
if !ok {
|
|||
|
|
return errors.New("排序数据中缺少sort字段")
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 类型检查
|
|||
|
|
if _, ok := id.(uint); !ok {
|
|||
|
|
if idFloat, ok := id.(float64); ok {
|
|||
|
|
data["id"] = uint(idFloat)
|
|||
|
|
} else {
|
|||
|
|
return errors.New("ID字段类型错误")
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if _, ok := sort.(int); !ok {
|
|||
|
|
if sortFloat, ok := sort.(float64); ok {
|
|||
|
|
data["sort"] = int(sortFloat)
|
|||
|
|
} else {
|
|||
|
|
return errors.New("sort字段类型错误")
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return s.bannerRepo.BatchUpdateBannerSort(sortData)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// GetBannersByDateRange 根据日期范围获取轮播图
|
|||
|
|
func (s *BannerService) GetBannersByDateRange(startDate, endDate time.Time) ([]model.Banner, error) {
|
|||
|
|
if startDate.After(endDate) {
|
|||
|
|
return nil, errors.New("开始日期不能晚于结束日期")
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return s.bannerRepo.GetBannersByDateRange(startDate, endDate)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// GetBannersByStatus 根据状态获取轮播图
|
|||
|
|
func (s *BannerService) GetBannersByStatus(status int) ([]model.Banner, error) {
|
|||
|
|
if status < 0 || status > 1 {
|
|||
|
|
return nil, errors.New("状态值无效,只能是0或1")
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return s.bannerRepo.GetBannersByStatus(status)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// GetBannerStatistics 获取轮播图统计信息
|
|||
|
|
func (s *BannerService) GetBannerStatistics() (map[string]interface{}, error) {
|
|||
|
|
// 获取总数
|
|||
|
|
total, err := s.bannerRepo.GetBannerCount()
|
|||
|
|
if err != nil {
|
|||
|
|
return nil, fmt.Errorf("获取轮播图总数失败: %v", err)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 获取启用数量
|
|||
|
|
activeCount, err := s.bannerRepo.GetBannerCountByStatus(1)
|
|||
|
|
if err != nil {
|
|||
|
|
return nil, fmt.Errorf("获取启用轮播图数量失败: %v", err)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 获取禁用数量
|
|||
|
|
inactiveCount, err := s.bannerRepo.GetBannerCountByStatus(0)
|
|||
|
|
if err != nil {
|
|||
|
|
return nil, fmt.Errorf("获取禁用轮播图数量失败: %v", err)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 获取过期轮播图
|
|||
|
|
expiredBanners, err := s.bannerRepo.GetExpiredBanners()
|
|||
|
|
if err != nil {
|
|||
|
|
return nil, fmt.Errorf("获取过期轮播图失败: %v", err)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return map[string]interface{}{
|
|||
|
|
"total": total,
|
|||
|
|
"active": activeCount,
|
|||
|
|
"inactive": inactiveCount,
|
|||
|
|
"expired": len(expiredBanners),
|
|||
|
|
"expired_list": expiredBanners,
|
|||
|
|
}, nil
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// CleanExpiredBanners 清理过期轮播图
|
|||
|
|
func (s *BannerService) CleanExpiredBanners() error {
|
|||
|
|
expiredBanners, err := s.bannerRepo.GetExpiredBanners()
|
|||
|
|
if err != nil {
|
|||
|
|
return fmt.Errorf("获取过期轮播图失败: %v", err)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if len(expiredBanners) == 0 {
|
|||
|
|
return nil
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 将过期轮播图状态设置为禁用
|
|||
|
|
var ids []uint
|
|||
|
|
for _, banner := range expiredBanners {
|
|||
|
|
ids = append(ids, banner.ID)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return s.bannerRepo.BatchUpdateBannerStatus(ids, 0)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// validateBanner 验证轮播图数据
|
|||
|
|
func (s *BannerService) validateBanner(banner *model.Banner) error {
|
|||
|
|
if banner.Title == "" {
|
|||
|
|
return errors.New("轮播图标题不能为空")
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if banner.Image == "" {
|
|||
|
|
return errors.New("轮播图图片不能为空")
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if banner.LinkType < 1 || banner.LinkType > 4 {
|
|||
|
|
return errors.New("链接类型无效,只能是1-4")
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if banner.Sort < 0 {
|
|||
|
|
return errors.New("排序值不能为负数")
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 验证时间范围
|
|||
|
|
if banner.StartTime != nil && banner.EndTime != nil {
|
|||
|
|
if banner.StartTime.After(*banner.EndTime) {
|
|||
|
|
return errors.New("开始时间不能晚于结束时间")
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return nil
|
|||
|
|
}
|