Files
ai_english/serve/api/handlers/user_handler.go

296 lines
8.1 KiB
Go
Raw Permalink Normal View History

2025-11-17 13:39:05 +08:00
package handlers
import (
"net/http"
"strconv"
"github.com/gin-gonic/gin"
"github.com/go-playground/validator/v10"
"github.com/Nanqipro/YunQue-Tech-Projects/ai_english_learning/serve/internal/common"
"github.com/Nanqipro/YunQue-Tech-Projects/ai_english_learning/serve/internal/services"
"github.com/Nanqipro/YunQue-Tech-Projects/ai_english_learning/serve/internal/utils"
)
// UserHandler 用户处理器
type UserHandler struct {
userService *services.UserService
validator *validator.Validate
}
// NewUserHandler 创建用户处理器实例
func NewUserHandler(userService *services.UserService) *UserHandler {
return &UserHandler{
userService: userService,
validator: validator.New(),
}
}
// UpdateUserRequest 更新用户信息请求结构
type UpdateUserRequest struct {
Username string `json:"username" validate:"omitempty,min=3,max=20"`
Email string `json:"email" validate:"omitempty,email"`
Nickname string `json:"nickname" validate:"omitempty,min=1,max=50"`
Avatar string `json:"avatar" validate:"omitempty,url"`
Timezone string `json:"timezone" validate:"omitempty"`
Language string `json:"language" validate:"omitempty"`
}
// UpdateUserPreferencesRequest 更新用户偏好设置请求结构
type UpdateUserPreferencesRequest struct {
DailyGoal int `json:"daily_goal" validate:"omitempty,min=1,max=1000"`
WeeklyGoal int `json:"weekly_goal" validate:"omitempty,min=1,max=7000"`
ReminderEnabled bool `json:"reminder_enabled"`
DifficultyLevel string `json:"difficulty_level" validate:"omitempty,oneof=beginner intermediate advanced"`
LearningMode string `json:"learning_mode" validate:"omitempty,oneof=casual intensive exam"`
}
// UserStatsResponse 用户学习统计响应结构
type UserStatsResponse struct {
TotalWords int `json:"total_words"`
LearnedWords int `json:"learned_words"`
MasteredWords int `json:"mastered_words"`
StudyDays int `json:"study_days"`
ConsecutiveDays int `json:"consecutive_days"`
TotalStudyTime int `json:"total_study_time"` // 分钟
}
// GetUserProfile 获取用户信息
func (h *UserHandler) GetUserProfile(c *gin.Context) {
userID, exists := utils.GetUserIDFromContext(c)
if !exists {
common.BadRequestResponse(c, "请先登录")
return
}
user, err := h.userService.GetUserByID(userID)
if err != nil {
if businessErr, ok := err.(*common.BusinessError); ok {
common.ErrorResponse(c, http.StatusBadRequest, businessErr.Message)
return
}
common.InternalServerErrorResponse(c, "获取用户信息失败")
return
}
// 获取用户偏好设置
preferences, err := h.userService.GetUserPreferences(userID)
if err != nil {
// 偏好设置获取失败不影响用户信息返回,记录日志即可
preferences = nil
}
// 构造响应数据
response := map[string]interface{}{
"id": user.ID,
"username": user.Username,
"email": user.Email,
"nickname": user.Nickname,
"avatar": user.Avatar,
"timezone": user.Timezone,
"language": user.Language,
"status": user.Status,
"created_at": user.CreatedAt,
"updated_at": user.UpdatedAt,
}
if preferences != nil {
response["preferences"] = map[string]interface{}{
"daily_goal": preferences.DailyGoal,
"weekly_goal": preferences.WeeklyGoal,
"reminder_enabled": preferences.ReminderEnabled,
"difficulty_level": preferences.DifficultyLevel,
"learning_mode": preferences.LearningMode,
}
}
common.SuccessResponse(c, response)
}
// UpdateUserProfile 更新用户信息
func (h *UserHandler) UpdateUserProfile(c *gin.Context) {
userID, exists := utils.GetUserIDFromContext(c)
if !exists {
common.BadRequestResponse(c, "请先登录")
return
}
var req UpdateUserRequest
if err := c.ShouldBindJSON(&req); err != nil {
common.ValidationErrorResponse(c, err)
return
}
// 验证请求参数
if err := h.validator.Struct(&req); err != nil {
common.ValidationErrorResponse(c, err)
return
}
// 构造更新数据
updates := make(map[string]interface{})
if req.Username != "" {
updates["username"] = req.Username
}
if req.Email != "" {
updates["email"] = req.Email
}
if req.Nickname != "" {
updates["nickname"] = req.Nickname
}
if req.Avatar != "" {
updates["avatar"] = req.Avatar
}
if req.Timezone != "" {
updates["timezone"] = req.Timezone
}
if req.Language != "" {
updates["language"] = req.Language
}
if len(updates) == 0 {
common.BadRequestResponse(c, "没有需要更新的字段")
return
}
// 更新用户信息
user, err := h.userService.UpdateUser(userID, updates)
if err != nil {
if businessErr, ok := err.(*common.BusinessError); ok {
common.ErrorResponse(c, http.StatusBadRequest, businessErr.Message)
return
}
common.InternalServerErrorResponse(c, "更新用户信息失败")
return
}
common.SuccessResponse(c, user)
}
// UpdateUserPreferences 更新用户偏好设置
func (h *UserHandler) UpdateUserPreferences(c *gin.Context) {
userID, exists := utils.GetUserIDFromContext(c)
if !exists {
common.BadRequestResponse(c, "请先登录")
return
}
var req UpdateUserPreferencesRequest
if err := c.ShouldBindJSON(&req); err != nil {
common.ValidationErrorResponse(c, err)
return
}
// 验证请求参数
if err := h.validator.Struct(&req); err != nil {
common.ValidationErrorResponse(c, err)
return
}
// 构造更新数据
updates := make(map[string]interface{})
if req.DailyGoal > 0 {
updates["daily_goal"] = req.DailyGoal
}
if req.WeeklyGoal > 0 {
updates["weekly_goal"] = req.WeeklyGoal
}
updates["reminder_enabled"] = req.ReminderEnabled
if req.DifficultyLevel != "" {
updates["difficulty_level"] = req.DifficultyLevel
}
if req.LearningMode != "" {
updates["learning_mode"] = req.LearningMode
}
// 更新用户偏好设置
preferences, err := h.userService.UpdateUserPreferences(userID, updates)
if err != nil {
if businessErr, ok := err.(*common.BusinessError); ok {
common.ErrorResponse(c, http.StatusBadRequest, businessErr.Message)
return
}
common.InternalServerErrorResponse(c, "更新偏好设置失败")
return
}
common.SuccessResponse(c, preferences)
}
// GetUserStats 获取用户学习统计
func (h *UserHandler) GetUserStats(c *gin.Context) {
userID, exists := utils.GetUserIDFromContext(c)
if !exists {
common.BadRequestResponse(c, "请先登录")
return
}
// 获取时间范围参数
timeRange := c.DefaultQuery("time_range", "all") // all, week, month, year
// 这里需要实现具体的统计逻辑,暂时返回模拟数据
// TODO: 实现真实的统计查询使用userID和timeRange参数
_ = userID // 避免未使用变量错误
_ = timeRange // 避免未使用变量错误
stats := &UserStatsResponse{
TotalWords: 1000,
LearnedWords: 750,
MasteredWords: 500,
StudyDays: 30,
ConsecutiveDays: 7,
TotalStudyTime: 1800, // 30小时
}
common.SuccessResponse(c, stats)
}
// GetUserLearningProgress 获取用户学习进度
func (h *UserHandler) GetUserLearningProgress(c *gin.Context) {
userID, exists := utils.GetUserIDFromContext(c)
if !exists {
common.BadRequestResponse(c, "请先登录")
return
}
// 获取分页参数
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
limit, _ := strconv.Atoi(c.DefaultQuery("limit", "20"))
if page < 1 {
page = 1
}
if limit < 1 || limit > 100 {
limit = 20
}
// 获取过滤参数
masteryLevel := c.Query("mastery_level")
categoryID := c.Query("category_id")
// 调用词汇服务获取用户的学习进度
progressList, total, err := h.userService.GetUserLearningProgress(utils.Int64ToString(userID), page, limit)
if err != nil {
common.InternalServerErrorResponse(c, "获取学习进度失败")
return
}
totalPages := int64(0)
if limit > 0 {
totalPages = (total + int64(limit) - 1) / int64(limit)
}
response := map[string]interface{}{
"progress": progressList,
"pagination": map[string]interface{}{
"page": page,
"limit": limit,
"total": total,
"total_page": totalPages,
},
"filters": map[string]interface{}{
"mastery_level": masteryLevel,
"category_id": categoryID,
},
}
common.SuccessResponse(c, response)
}