feat: add announcement data models
Add announcement and read-tracking models with active/unread query helpers for the operations announcement system.
This commit is contained in:
parent
1de1cdb14f
commit
6a409b7724
92
model/announcement.go
Normal file
92
model/announcement.go
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"gorm.io/gorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Announcement struct {
|
||||||
|
Id int `json:"id" gorm:"primaryKey;autoIncrement"`
|
||||||
|
Title string `json:"title" gorm:"type:varchar(255);not null"`
|
||||||
|
Content string `json:"content" gorm:"type:text;not null"`
|
||||||
|
ContentHtml string `json:"content_html" gorm:"type:text"`
|
||||||
|
Status string `json:"status" gorm:"type:varchar(16);not null;default:'draft';index"`
|
||||||
|
NotifyMode string `json:"notify_mode" gorm:"type:varchar(16);not null;default:'silent'"`
|
||||||
|
JsonRules string `json:"json_rules" gorm:"type:text"`
|
||||||
|
StartsAt *time.Time `json:"starts_at" gorm:"index"`
|
||||||
|
EndsAt *time.Time `json:"ends_at" gorm:"index"`
|
||||||
|
CreatedBy int `json:"created_by" gorm:"not null;default:0"`
|
||||||
|
CreatedAt time.Time `json:"created_at"`
|
||||||
|
UpdatedAt time.Time `json:"updated_at"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (Announcement) TableName() string {
|
||||||
|
return "announcements"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Announcement) Insert() error {
|
||||||
|
return DB.Create(a).Error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Announcement) Update() error {
|
||||||
|
return DB.Save(a).Error
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetAnnouncementByID(id int) (*Announcement, error) {
|
||||||
|
var announcement Announcement
|
||||||
|
err := DB.First(&announcement, "id = ?", id).Error
|
||||||
|
return &announcement, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetAnnouncements(page int, pageSize int, status string) ([]Announcement, int64, error) {
|
||||||
|
var announcements []Announcement
|
||||||
|
var total int64
|
||||||
|
query := DB.Model(&Announcement{})
|
||||||
|
if status != "" {
|
||||||
|
query = query.Where("status = ?", status)
|
||||||
|
}
|
||||||
|
if err := query.Count(&total).Error; err != nil {
|
||||||
|
return nil, 0, err
|
||||||
|
}
|
||||||
|
if page < 1 {
|
||||||
|
page = 1
|
||||||
|
}
|
||||||
|
if pageSize < 1 {
|
||||||
|
pageSize = 20
|
||||||
|
}
|
||||||
|
err := query.Order("id DESC").Offset((page - 1) * pageSize).Limit(pageSize).Find(&announcements).Error
|
||||||
|
return announcements, total, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetActiveAnnouncements() ([]Announcement, error) {
|
||||||
|
var announcements []Announcement
|
||||||
|
err := activeAnnouncementQuery().
|
||||||
|
Order("id DESC").
|
||||||
|
Find(&announcements).Error
|
||||||
|
return announcements, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetUnreadAnnouncements(userId int) ([]Announcement, error) {
|
||||||
|
var announcements []Announcement
|
||||||
|
readSubQuery := DB.Model(&AnnouncementRead{}).
|
||||||
|
Select("announcement_id").
|
||||||
|
Where("user_id = ?", userId)
|
||||||
|
err := activeAnnouncementQuery().
|
||||||
|
Where("id NOT IN (?)", readSubQuery).
|
||||||
|
Order("id DESC").
|
||||||
|
Find(&announcements).Error
|
||||||
|
return announcements, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func DeleteAnnouncementByID(id int) error {
|
||||||
|
return DB.Delete(&Announcement{}, id).Error
|
||||||
|
}
|
||||||
|
|
||||||
|
func activeAnnouncementQuery() *gorm.DB {
|
||||||
|
now := time.Now()
|
||||||
|
return DB.Model(&Announcement{}).
|
||||||
|
Where("status = ?", "active").
|
||||||
|
Where("(starts_at IS NULL OR starts_at <= ?)", now).
|
||||||
|
Where("(ends_at IS NULL OR ends_at >= ?)", now)
|
||||||
|
}
|
||||||
33
model/announcement_read.go
Normal file
33
model/announcement_read.go
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
type AnnouncementRead struct {
|
||||||
|
Id int `json:"id" gorm:"primaryKey;autoIncrement"`
|
||||||
|
AnnouncementId int `json:"announcement_id" gorm:"not null;index:idx_announcement_read_user,unique"`
|
||||||
|
UserId int `json:"user_id" gorm:"not null;index:idx_announcement_read_user,unique"`
|
||||||
|
ReadAt time.Time `json:"read_at" gorm:"not null"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (AnnouncementRead) TableName() string {
|
||||||
|
return "announcement_reads"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *AnnouncementRead) Insert() error {
|
||||||
|
return DB.Create(r).Error
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsAnnouncementRead(announcementId int, userId int) (bool, error) {
|
||||||
|
var count int64
|
||||||
|
err := DB.Model(&AnnouncementRead{}).
|
||||||
|
Where("announcement_id = ? AND user_id = ?", announcementId, userId).
|
||||||
|
Count(&count).Error
|
||||||
|
return count > 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
type AnnouncementReadStatus struct {
|
||||||
|
UserId int `json:"user_id"`
|
||||||
|
Username string `json:"username"`
|
||||||
|
ReadAt *time.Time `json:"read_at"`
|
||||||
|
IsRead bool `json:"is_read"`
|
||||||
|
}
|
||||||
@ -283,6 +283,8 @@ func migrateDB() error {
|
|||||||
&PerfMetric{},
|
&PerfMetric{},
|
||||||
&PromoCode{},
|
&PromoCode{},
|
||||||
&PromoCodeUsage{},
|
&PromoCodeUsage{},
|
||||||
|
&Announcement{},
|
||||||
|
&AnnouncementRead{},
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -334,6 +336,8 @@ func migrateDBFast() error {
|
|||||||
{&PerfMetric{}, "PerfMetric"},
|
{&PerfMetric{}, "PerfMetric"},
|
||||||
{&PromoCode{}, "PromoCode"},
|
{&PromoCode{}, "PromoCode"},
|
||||||
{&PromoCodeUsage{}, "PromoCodeUsage"},
|
{&PromoCodeUsage{}, "PromoCodeUsage"},
|
||||||
|
{&Announcement{}, "Announcement"},
|
||||||
|
{&AnnouncementRead{}, "AnnouncementRead"},
|
||||||
}
|
}
|
||||||
// 动态计算migration数量,确保errChan缓冲区足够大
|
// 动态计算migration数量,确保errChan缓冲区足够大
|
||||||
errChan := make(chan error, len(migrations))
|
errChan := make(chan error, len(migrations))
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user