Files
wx_service/internal/marketing/repository/template_repo.go
T
nepiedg ac49e1458c feat(marketing): 新增营销图管理模块
- 新增 marketing 模块:model/repository/service/handler 四层架构
- 数据模型:marketing_categories、marketing_templates、marketing_user_downloads
- 小程序端接口:分类列表、模板列表/详情、下载记录、广告回调
- 管理后台接口:分类/模板 CRUD、下载统计(X-Admin-Token 鉴权)
- 路由注册:接入现有 AuthMiddleware,新增 AdminTokenMiddleware
- Web 管理后台:单页面 Vue3 + Element Plus(分类管理、模板管理、数据概览)

Closes #37, #38, #39, #40

Made-with: Cursor
2026-03-06 07:36:05 +00:00

121 lines
3.0 KiB
Go

package repository
import (
"errors"
"fmt"
"gorm.io/gorm"
"wx_service/internal/marketing/model"
)
var ErrTemplateNotFound = errors.New("marketing template not found")
type TemplateRepository struct {
db *gorm.DB
}
func NewTemplateRepository(db *gorm.DB) *TemplateRepository {
return &TemplateRepository{db: db}
}
func (r *TemplateRepository) Create(tpl *model.MarketingTemplate) error {
if err := r.db.Create(tpl).Error; err != nil {
return fmt.Errorf("create marketing template: %w", err)
}
return nil
}
func (r *TemplateRepository) Update(tpl *model.MarketingTemplate) error {
tx := r.db.Model(tpl).Updates(map[string]interface{}{
"category_id": tpl.CategoryID,
"title": tpl.Title,
"image_url": tpl.ImageURL,
"thumbnail_url": tpl.ThumbnailURL,
"width": tpl.Width,
"height": tpl.Height,
"sort_order": tpl.SortOrder,
"status": tpl.Status,
})
if tx.Error != nil {
return fmt.Errorf("update marketing template: %w", tx.Error)
}
if tx.RowsAffected == 0 {
return ErrTemplateNotFound
}
return nil
}
func (r *TemplateRepository) Delete(id uint) error {
tx := r.db.Delete(&model.MarketingTemplate{}, id)
if tx.Error != nil {
return fmt.Errorf("delete marketing template: %w", tx.Error)
}
if tx.RowsAffected == 0 {
return ErrTemplateNotFound
}
return nil
}
func (r *TemplateRepository) FindByID(id uint) (*model.MarketingTemplate, error) {
var tpl model.MarketingTemplate
err := r.db.Preload("Category").First(&tpl, id).Error
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, ErrTemplateNotFound
}
return nil, fmt.Errorf("find marketing template: %w", err)
}
return &tpl, nil
}
type TemplateListParams struct {
CategoryID uint
OnlyEnabled bool
Page int
PageSize int
}
func (r *TemplateRepository) FindList(params TemplateListParams) ([]model.MarketingTemplate, int64, error) {
if params.Page <= 0 {
params.Page = 1
}
if params.PageSize <= 0 {
params.PageSize = 20
}
if params.PageSize > 100 {
params.PageSize = 100
}
query := r.db.Model(&model.MarketingTemplate{})
if params.CategoryID > 0 {
query = query.Where("category_id = ?", params.CategoryID)
}
if params.OnlyEnabled {
query = query.Where("status = ?", 1)
}
query = query.Order("sort_order DESC, id DESC")
var total int64
if err := query.Count(&total).Error; err != nil {
return nil, 0, fmt.Errorf("count marketing templates: %w", err)
}
var templates []model.MarketingTemplate
offset := (params.Page - 1) * params.PageSize
if err := query.Preload("Category").Offset(offset).Limit(params.PageSize).Find(&templates).Error; err != nil {
return nil, 0, fmt.Errorf("list marketing templates: %w", err)
}
return templates, total, nil
}
func (r *TemplateRepository) IncrementDownloadCount(id uint) error {
tx := r.db.Model(&model.MarketingTemplate{}).Where("id = ?", id).
UpdateColumn("download_count", gorm.Expr("download_count + 1"))
if tx.Error != nil {
return fmt.Errorf("increment download count: %w", tx.Error)
}
return nil
}