Files
wx_service/internal/admin/service/mini_program_service.go
T

266 lines
7.0 KiB
Go

package service
import (
"context"
"errors"
"strings"
"time"
expirymodel "wx_service/internal/expiry"
membershipmodel "wx_service/internal/membership/model"
"wx_service/internal/model"
rmmodel "wx_service/internal/remove_watermark/model"
"gorm.io/gorm"
)
type ListMiniProgramsQuery struct {
Page int
PageSize int
Keyword string
}
type MiniProgramItem struct {
ID uint `json:"id"`
Name string `json:"name"`
AppID string `json:"app_id"`
Description string `json:"description"`
UserCount int64 `json:"user_count"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
AppSecretSet bool `json:"app_secret_set"`
}
type ListMiniProgramsResult struct {
List []MiniProgramItem `json:"list"`
Total int64 `json:"total"`
Page int `json:"page"`
PageSize int `json:"page_size"`
}
func (s *Service) ListMiniPrograms(ctx context.Context, query ListMiniProgramsQuery) (*ListMiniProgramsResult, error) {
if query.Page < 1 {
query.Page = 1
}
if query.PageSize < 1 {
query.PageSize = 20
}
if query.PageSize > 100 {
query.PageSize = 100
}
query.Keyword = strings.TrimSpace(query.Keyword)
dbQuery := s.db.WithContext(ctx).Model(&model.MiniProgram{})
if query.Keyword != "" {
keywordLike := "%" + query.Keyword + "%"
dbQuery = dbQuery.Where("name LIKE ? OR app_id LIKE ?", keywordLike, keywordLike)
}
var total int64
if err := dbQuery.Count(&total).Error; err != nil {
return nil, err
}
var miniPrograms []model.MiniProgram
if total > 0 {
if err := dbQuery.Order("id DESC").
Limit(query.PageSize).
Offset((query.Page - 1) * query.PageSize).
Find(&miniPrograms).Error; err != nil {
return nil, err
}
}
ids := make([]uint, 0, len(miniPrograms))
for _, item := range miniPrograms {
ids = append(ids, item.ID)
}
userCountMap, err := s.groupCountByMiniProgramID(ctx, &model.User{}, ids, "")
if err != nil {
return nil, err
}
result := make([]MiniProgramItem, 0, len(miniPrograms))
for _, item := range miniPrograms {
result = append(result, MiniProgramItem{
ID: item.ID,
Name: item.Name,
AppID: item.AppID,
Description: item.Description,
UserCount: userCountMap[item.ID],
CreatedAt: item.CreatedAt,
UpdatedAt: item.UpdatedAt,
AppSecretSet: item.AppSecret != "",
})
}
return &ListMiniProgramsResult{
List: result,
Total: total,
Page: query.Page,
PageSize: query.PageSize,
}, nil
}
func (s *Service) GetMiniProgram(ctx context.Context, id uint) (*MiniProgramItem, error) {
var miniProgram model.MiniProgram
if err := s.db.WithContext(ctx).Where("id = ?", id).First(&miniProgram).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, ErrMiniProgramNotFound
}
return nil, err
}
var userCount int64
if err := s.db.WithContext(ctx).Model(&model.User{}).Where("mini_program_id = ?", id).Count(&userCount).Error; err != nil {
return nil, err
}
return &MiniProgramItem{
ID: miniProgram.ID,
Name: miniProgram.Name,
AppID: miniProgram.AppID,
Description: miniProgram.Description,
UserCount: userCount,
CreatedAt: miniProgram.CreatedAt,
UpdatedAt: miniProgram.UpdatedAt,
AppSecretSet: miniProgram.AppSecret != "",
}, nil
}
type CreateMiniProgramInput struct {
Name string
AppID string
AppSecret string
Description string
}
func (s *Service) CreateMiniProgram(ctx context.Context, input CreateMiniProgramInput) (*MiniProgramItem, error) {
input.Name = strings.TrimSpace(input.Name)
input.AppID = strings.TrimSpace(input.AppID)
input.AppSecret = strings.TrimSpace(input.AppSecret)
input.Description = strings.TrimSpace(input.Description)
if input.Name == "" || input.AppID == "" || input.AppSecret == "" {
return nil, ErrInvalidInput
}
item := &model.MiniProgram{
Name: input.Name,
AppID: input.AppID,
AppSecret: input.AppSecret,
Description: input.Description,
}
if err := s.db.WithContext(ctx).Create(item).Error; err != nil {
if isDuplicateError(err) {
return nil, ErrMiniProgramAppIDUsed
}
return nil, err
}
return s.GetMiniProgram(ctx, item.ID)
}
type UpdateMiniProgramInput struct {
Name string
AppID string
AppSecret *string
Description string
}
func (s *Service) UpdateMiniProgram(ctx context.Context, id uint, input UpdateMiniProgramInput) (*MiniProgramItem, error) {
input.Name = strings.TrimSpace(input.Name)
input.AppID = strings.TrimSpace(input.AppID)
input.Description = strings.TrimSpace(input.Description)
if input.Name == "" || input.AppID == "" {
return nil, ErrInvalidInput
}
var item model.MiniProgram
if err := s.db.WithContext(ctx).Where("id = ?", id).First(&item).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, ErrMiniProgramNotFound
}
return nil, err
}
updateData := map[string]interface{}{
"name": input.Name,
"app_id": input.AppID,
"description": input.Description,
}
if input.AppSecret != nil {
trimmedSecret := strings.TrimSpace(*input.AppSecret)
if trimmedSecret != "" {
updateData["app_secret"] = trimmedSecret
}
}
if err := s.db.WithContext(ctx).Model(&item).Updates(updateData).Error; err != nil {
if isDuplicateError(err) {
return nil, ErrMiniProgramAppIDUsed
}
return nil, err
}
return s.GetMiniProgram(ctx, id)
}
func (s *Service) DeleteMiniProgram(ctx context.Context, id uint) error {
var item model.MiniProgram
if err := s.db.WithContext(ctx).Where("id = ?", id).First(&item).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return ErrMiniProgramNotFound
}
return err
}
var userCount int64
if err := s.db.WithContext(ctx).Model(&model.User{}).Where("mini_program_id = ?", id).Count(&userCount).Error; err != nil {
return err
}
if userCount > 0 {
return ErrMiniProgramHasUsers
}
return s.db.WithContext(ctx).Delete(&item).Error
}
type MiniProgramDetailStats struct {
UserCount int64 `json:"user_count"`
DataCount int64 `json:"data_count"`
}
func (s *Service) GetMiniProgramStats(ctx context.Context, id uint) (*MiniProgramDetailStats, error) {
var exists int64
if err := s.db.WithContext(ctx).Model(&model.MiniProgram{}).Where("id = ?", id).Count(&exists).Error; err != nil {
return nil, err
}
if exists == 0 {
return nil, ErrMiniProgramNotFound
}
userCounts, err := s.groupCountByMiniProgramID(ctx, &model.User{}, []uint{id}, "")
if err != nil {
return nil, err
}
expiryCounts, err := s.groupCountByMiniProgramID(ctx, &expirymodel.ExpiryItem{}, []uint{id}, "")
if err != nil {
return nil, err
}
videoCounts, err := s.groupCountByMiniProgramID(ctx, &rmmodel.VideoParseLog{}, []uint{id}, "")
if err != nil {
return nil, err
}
redeemCounts, err := s.groupCountByMiniProgramID(ctx, &membershipmodel.MembershipRedemption{}, []uint{id}, "")
if err != nil {
return nil, err
}
dataCount := expiryCounts[id] + videoCounts[id] + redeemCounts[id]
return &MiniProgramDetailStats{
UserCount: userCounts[id],
DataCount: dataCount,
}, nil
}