package storage import ( "context" "encoding/json" "fmt" "goalfymax-admin/internal/models" "time" "gorm.io/gorm" ) // MessagePushStorage 消息推送存储接口 type MessagePushStorage interface { Create(ctx context.Context, log *models.MessagePushLog) error List(ctx context.Context, req *models.MessagePushListRequest) ([]models.MessagePushLog, int64, error) GetByID(ctx context.Context, id int64) (*models.MessagePushLog, error) UpdateStatus(ctx context.Context, id int64, status int, successCount, failCount int, errorMessage string) error SearchUsers(ctx context.Context, keyword string, limit int) ([]models.UserSearchItem, error) } type messagePushStorage struct { db *gorm.DB } // NewMessagePushStorage 创建消息推送存储实例 func NewMessagePushStorage() MessagePushStorage { return &messagePushStorage{db: DB} } // Create 创建推送记录 func (s *messagePushStorage) Create(ctx context.Context, log *models.MessagePushLog) error { if err := s.db.WithContext(ctx).Create(log).Error; err != nil { return fmt.Errorf("创建推送记录失败: %w", err) } return nil } // List 获取推送记录列表 func (s *messagePushStorage) List(ctx context.Context, req *models.MessagePushListRequest) ([]models.MessagePushLog, int64, error) { var logs []models.MessagePushLog var total int64 query := s.db.WithContext(ctx).Model(&models.MessagePushLog{}) if req.Status != nil { query = query.Where("status = ?", *req.Status) } if req.SenderID != nil { query = query.Where("sender_id = ?", *req.SenderID) } if req.StartTime != "" { query = query.Where("created_at >= ?", req.StartTime) } if req.EndTime != "" { query = query.Where("created_at <= ?", req.EndTime) } if err := query.Count(&total).Error; err != nil { return nil, 0, fmt.Errorf("查询总数失败: %w", err) } if req.Page > 0 && req.PageSize > 0 { offset := (req.Page - 1) * req.PageSize query = query.Offset(offset).Limit(req.PageSize) } if err := query.Order("created_at DESC").Find(&logs).Error; err != nil { return nil, 0, fmt.Errorf("查询推送记录失败: %w", err) } return logs, total, nil } // GetByID 根据ID获取推送记录 func (s *messagePushStorage) GetByID(ctx context.Context, id int64) (*models.MessagePushLog, error) { var log models.MessagePushLog if err := s.db.WithContext(ctx).First(&log, id).Error; err != nil { if err == gorm.ErrRecordNotFound { return nil, fmt.Errorf("推送记录不存在") } return nil, fmt.Errorf("获取推送记录失败: %w", err) } return &log, nil } // UpdateStatus 更新推送状态 func (s *messagePushStorage) UpdateStatus(ctx context.Context, id int64, status int, successCount, failCount int, errorMessage string) error { updates := map[string]interface{}{ "status": status, "success_count": successCount, "fail_count": failCount, } if errorMessage != "" { updates["error_message"] = errorMessage } if status == 2 || status == 3 { // 发送成功或失败时更新发送时间 now := time.Now() updates["sent_at"] = &now } if err := s.db.WithContext(ctx).Model(&models.MessagePushLog{}).Where("id = ?", id).Updates(updates).Error; err != nil { return fmt.Errorf("更新推送状态失败: %w", err) } return nil } // SearchUsers 搜索用户 func (s *messagePushStorage) SearchUsers(ctx context.Context, keyword string, limit int) ([]models.UserSearchItem, error) { var users []models.UserSearchItem // 从admin_goalfymax_users表搜索用户 query := s.db.WithContext(ctx).Table("admin_goalfymax_users"). Select("user_id as id, username, email"). Where("deleted_at IS NULL") // 排除已删除的用户 // 如果有关键词,添加搜索条件 if keyword != "" { query = query.Where("username LIKE ? OR email LIKE ?", "%"+keyword+"%", "%"+keyword+"%") } query = query.Limit(limit) // 添加调试日志 fmt.Printf("🔍 [SearchUsers] 搜索关键词: %s, 限制: %d\n", keyword, limit) if err := query.Find(&users).Error; err != nil { fmt.Printf("❌ [SearchUsers] 查询失败: %v\n", err) return nil, fmt.Errorf("搜索用户失败: %w", err) } fmt.Printf("✅ [SearchUsers] 找到 %d 个用户\n", len(users)) return users, nil } // ParseTargetUsers 解析目标用户JSON func ParseTargetUsers(targetUsersJSON string) ([]int, error) { var userIDs []int if err := json.Unmarshal([]byte(targetUsersJSON), &userIDs); err != nil { return nil, fmt.Errorf("解析目标用户失败: %w", err) } return userIDs, nil } // SerializeTargetUsers 序列化目标用户为JSON func SerializeTargetUsers(userIDs []int) (string, error) { jsonData, err := json.Marshal(userIDs) if err != nil { return "", fmt.Errorf("序列化目标用户失败: %w", err) } return string(jsonData), nil }