feat(marketing): user profile update, ad placement management, logo limits

- Add PUT /auth/profile endpoint for nickname and avatar updates
- Add ad_placements table and CRUD admin API for managing ad units
- Add GET /marketing/ad-config public API for mini-program to fetch ad config
- Reduce logo limit from 10 to 3 per user, add 2MB file size validation

Made-with: Cursor
This commit is contained in:
nepiedg
2026-04-04 04:02:06 +08:00
parent b4170b4863
commit 1c0aeb152a
11 changed files with 347 additions and 7 deletions
@@ -0,0 +1,76 @@
package repository
import (
"errors"
"fmt"
"gorm.io/gorm"
"wx_service/internal/marketing/model"
)
var ErrAdPlacementNotFound = errors.New("ad placement not found")
type AdPlacementRepository struct {
db *gorm.DB
}
func NewAdPlacementRepository(db *gorm.DB) *AdPlacementRepository {
return &AdPlacementRepository{db: db}
}
func (r *AdPlacementRepository) Create(p *model.AdPlacement) error {
if err := r.db.Create(p).Error; err != nil {
return fmt.Errorf("create ad placement: %w", err)
}
return nil
}
func (r *AdPlacementRepository) Update(p *model.AdPlacement) error {
if err := r.db.Save(p).Error; err != nil {
return fmt.Errorf("update ad placement: %w", err)
}
return nil
}
func (r *AdPlacementRepository) Delete(id uint) error {
tx := r.db.Delete(&model.AdPlacement{}, id)
if tx.Error != nil {
return fmt.Errorf("delete ad placement: %w", tx.Error)
}
if tx.RowsAffected == 0 {
return ErrAdPlacementNotFound
}
return nil
}
func (r *AdPlacementRepository) FindByID(id uint) (*model.AdPlacement, error) {
var p model.AdPlacement
err := r.db.First(&p, id).Error
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, ErrAdPlacementNotFound
}
return nil, fmt.Errorf("find ad placement: %w", err)
}
return &p, nil
}
func (r *AdPlacementRepository) ListAll() ([]model.AdPlacement, error) {
var list []model.AdPlacement
err := r.db.Order("id DESC").Find(&list).Error
return list, err
}
func (r *AdPlacementRepository) FindByMiniProgramAndType(miniProgramID uint, adType string) (*model.AdPlacement, error) {
var p model.AdPlacement
err := r.db.Where("mini_program_id = ? AND ad_type = ? AND status = 1", miniProgramID, adType).
First(&p).Error
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, ErrAdPlacementNotFound
}
return nil, fmt.Errorf("find ad placement by type: %w", err)
}
return &p, nil
}