package announcement import ( "context" "time" "hfb_sys/backend/internal/model" "gorm.io/gorm" ) type Repository struct { db *gorm.DB } func NewRepository(db *gorm.DB) *Repository { return &Repository{db: db} } // List 获取公告列表(前台用户) func (r *Repository) List(ctx context.Context, query AnnouncementListQuery) (*PaginatedResult, error) { var total int64 tx := r.db.WithContext(ctx).Model(&model.Announcement{}).Where("status = ?", "published") if query.Category != "" { tx = tx.Where("category = ?", query.Category) } if err := tx.Count(&total).Error; err != nil { return nil, err } offset := (query.Page - 1) * query.PageSize var rows []model.Announcement if err := tx.Order("is_pinned DESC, priority DESC, published_at DESC"). Offset(offset). Limit(query.PageSize). Find(&rows).Error; err != nil { return nil, err } items := make([]AnnouncementDTO, 0, len(rows)) for _, row := range rows { items = append(items, toAnnouncementDTO(row)) } return &PaginatedResult{ Items: items, Total: total, Page: query.Page, PageSize: query.PageSize, }, nil } // GetByID 获取公告详情 func (r *Repository) GetByID(ctx context.Context, id uint64) (*AnnouncementDTO, error) { var announcement model.Announcement db := r.db.WithContext(ctx) if err := db.Where("id = ? AND status = ?", id, "published").First(&announcement).Error; err != nil { return nil, err } // 增加查看次数 db.Model(&model.Announcement{}).Where("id = ?", id).UpdateColumn("view_count", gorm.Expr("view_count + ?", 1)) dto := toAnnouncementDTO(announcement) return &dto, nil } // AdminList 管理员获取公告列表 func (r *Repository) AdminList(ctx context.Context, query AnnouncementListQuery) (*PaginatedResult, error) { var total int64 tx := r.db.WithContext(ctx).Model(&model.Announcement{}) if query.Status != "" { tx = tx.Where("status = ?", query.Status) } if query.Category != "" { tx = tx.Where("category = ?", query.Category) } if err := tx.Count(&total).Error; err != nil { return nil, err } offset := (query.Page - 1) * query.PageSize var rows []model.Announcement if err := tx.Order("is_pinned DESC, priority DESC, id DESC"). Offset(offset). Limit(query.PageSize). Find(&rows).Error; err != nil { return nil, err } items := make([]AnnouncementDTO, 0, len(rows)) for _, row := range rows { items = append(items, toAnnouncementDTO(row)) } return &PaginatedResult{ Items: items, Total: total, Page: query.Page, PageSize: query.PageSize, }, nil } // AdminGetByID 管理员获取公告详情 func (r *Repository) AdminGetByID(ctx context.Context, id uint64) (*AnnouncementDTO, error) { var announcement model.Announcement if err := r.db.WithContext(ctx).Where("id = ?", id).First(&announcement).Error; err != nil { return nil, err } dto := toAnnouncementDTO(announcement) return &dto, nil } // Create 创建公告 func (r *Repository) Create(ctx context.Context, req CreateAnnouncementRequest, createdBy uint64) (*AnnouncementDTO, error) { announcement := model.Announcement{ Title: req.Title, Content: req.Content, Category: req.Category, Priority: req.Priority, IsPinned: req.IsPinned, IsImportant: req.IsImportant, Status: "draft", CreatedBy: &createdBy, } if err := r.db.WithContext(ctx).Create(&announcement).Error; err != nil { return nil, err } dto := toAnnouncementDTO(announcement) return &dto, nil } // Update 更新公告 func (r *Repository) Update(ctx context.Context, id uint64, req UpdateAnnouncementRequest) (*AnnouncementDTO, error) { updates := make(map[string]interface{}) if req.Title != "" { updates["title"] = req.Title } if req.Content != "" { updates["content"] = req.Content } if req.Category != "" { updates["category"] = req.Category } updates["priority"] = req.Priority updates["is_pinned"] = req.IsPinned updates["is_important"] = req.IsImportant if err := r.db.WithContext(ctx).Model(&model.Announcement{}).Where("id = ?", id).Updates(updates).Error; err != nil { return nil, err } return r.AdminGetByID(ctx, id) } // Publish 发布公告 func (r *Repository) Publish(ctx context.Context, id uint64) error { now := time.Now() return r.db.WithContext(ctx).Model(&model.Announcement{}). Where("id = ?", id). Updates(map[string]interface{}{ "status": "published", "published_at": now, }).Error } // Archive 归档公告 func (r *Repository) Archive(ctx context.Context, id uint64) error { return r.db.WithContext(ctx).Model(&model.Announcement{}). Where("id = ?", id). Update("status", "archived").Error } // Unarchive 取消归档公告,恢复为已发布状态 func (r *Repository) Unarchive(ctx context.Context, id uint64) error { now := time.Now() return r.db.WithContext(ctx).Model(&model.Announcement{}). Where("id = ?", id). Updates(map[string]interface{}{ "status": "published", "published_at": gorm.Expr("COALESCE(published_at, ?)", now), }).Error } // Delete 删除公告 func (r *Repository) Delete(ctx context.Context, id uint64) error { return r.db.WithContext(ctx).Where("id = ?", id).Delete(&model.Announcement{}).Error } func toAnnouncementDTO(a model.Announcement) AnnouncementDTO { return AnnouncementDTO{ ID: a.ID, Title: a.Title, Content: a.Content, Category: a.Category, Priority: a.Priority, IsPinned: a.IsPinned, IsImportant: a.IsImportant, ViewCount: a.ViewCount, Status: a.Status, PublishedAt: a.PublishedAt, CreatedAt: a.CreatedAt, UpdatedAt: a.UpdatedAt, } }