feat(admin): 系统公告 - 支持置顶排序与管理端标识
Adapted from ddcat-ai/open-ai-canvas#339 Original commit: fcdbe2aa833f31f683f709b7f409a0534ed78e20 Refs #339 Co-authored-by: 宇熙 <101980758+yuxiwl@users.noreply.github.com>
This commit is contained in:
1 parent
d84b2b69cc
commit
bf37e45dae
8 files changed
+84
-12
No files matched your search
@@ -15,6 +15,7 @@ type CreateAnnouncementRequest struct {
|
||||
Title string `json:"title"`
|
||||
Content string `json:"content"`
|
||||
Level model.AnnouncementLevel `json:"level"`
|
||||
Pinned bool `json:"pinned"`
|
||||
}
|
||||
|
||||
type UpdateAnnouncementRequest = CreateAnnouncementRequest
|
||||
@@ -57,6 +58,7 @@ func (s *Service) CreateAnnouncement(actor *model.User, req CreateAnnouncementRe
|
||||
Title: title,
|
||||
Content: content,
|
||||
Level: level,
|
||||
Pinned: req.Pinned,
|
||||
Status: model.AnnouncementStatusActive,
|
||||
CreatedBy: actor.ID,
|
||||
PublishedAt: now,
|
||||
@@ -88,6 +90,7 @@ func (s *Service) UpdateAnnouncement(actor *model.User, id string, req UpdateAnn
|
||||
announcement.Title = title
|
||||
announcement.Content = content
|
||||
announcement.Level = level
|
||||
announcement.Pinned = req.Pinned
|
||||
announcement.Status = model.AnnouncementStatusActive
|
||||
announcement.ClosedAt = nil
|
||||
announcement.PublishedAt = now
|
||||
|
||||
@@ -2,6 +2,7 @@ package service
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"infinite-canvas/backend/internal/model"
|
||||
"infinite-canvas/backend/internal/repository"
|
||||
@@ -97,11 +98,11 @@ func TestAnnouncementUpdateRepublishesAndResetsReads(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
updated, err := svc.UpdateAnnouncement(admin, announcement.ID, UpdateAnnouncementRequest{Title: "新标题", Content: "新正文", Level: model.AnnouncementLevelWarning})
|
||||
updated, err := svc.UpdateAnnouncement(admin, announcement.ID, UpdateAnnouncementRequest{Title: "新标题", Content: "新正文", Level: model.AnnouncementLevelWarning, Pinned: true})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if updated.Status != model.AnnouncementStatusActive || updated.ClosedAt != nil || updated.Title != "新标题" || updated.Content != "新正文" || updated.Level != model.AnnouncementLevelWarning {
|
||||
if updated.Status != model.AnnouncementStatusActive || updated.ClosedAt != nil || updated.Title != "新标题" || updated.Content != "新正文" || updated.Level != model.AnnouncementLevelWarning || !updated.Pinned {
|
||||
t.Fatalf("updated announcement = %+v", updated)
|
||||
}
|
||||
feed, err := svc.UserAnnouncements(user)
|
||||
@@ -113,6 +114,51 @@ func TestAnnouncementUpdateRepublishesAndResetsReads(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestPinnedAnnouncementsAreReturnedBeforeNewerRegularAnnouncements(t *testing.T) {
|
||||
db, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
sqlDB, err := db.DB()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
sqlDB.SetMaxOpenConns(1)
|
||||
if err := db.AutoMigrate(&model.User{}, &model.Announcement{}, &model.UserAnnouncementRead{}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
svc := New(repository.New(db), t.TempDir())
|
||||
admin := &model.User{ID: "admin", Role: model.UserRoleAdmin, Status: model.UserStatusActive}
|
||||
user := &model.User{ID: "user", Role: model.UserRoleUser, Status: model.UserStatusActive}
|
||||
|
||||
pinned, err := svc.CreateAnnouncement(admin, CreateAnnouncementRequest{Title: "置顶", Content: "置顶公告", Level: model.AnnouncementLevelWarning, Pinned: true})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
regular, err := svc.CreateAnnouncement(admin, CreateAnnouncementRequest{Title: "普通", Content: "较新的普通公告", Level: model.AnnouncementLevelInfo})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := db.Model(&model.Announcement{}).Where("id = ?", pinned.ID).Update("published_at", regular.PublishedAt.Add(-time.Hour)).Error; err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
feed, err := svc.UserAnnouncements(user)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(feed.Announcements) != 2 || feed.Announcements[0].ID != pinned.ID || !feed.Announcements[0].Pinned {
|
||||
t.Fatalf("feed = %+v, want pinned announcement first", feed.Announcements)
|
||||
}
|
||||
page, err := svc.AdminAnnouncementPage(admin, AdminListQuery{Page: 1, Limit: 20})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(page.Announcements) != 2 || page.Announcements[0].ID != pinned.ID {
|
||||
t.Fatalf("admin page = %+v, want pinned announcement first", page.Announcements)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAnnouncementPublishRejectsInvalidInput(t *testing.T) {
|
||||
svc := &Service{}
|
||||
admin := &model.User{ID: "admin", Role: model.UserRoleAdmin, Status: model.UserStatusActive}
|
||||
|
||||
Reference in new issue
Block a user