package handlers import ( "ankao/internal/database" "ankao/internal/models" "net/http" "github.com/gin-gonic/gin" ) // GetAllUsersWithStats 获取所有用户及其答题统计(仅管理员可访问) func GetAllUsersWithStats(c *gin.Context) { db := database.GetDB() // 查询所有用户及其答题统计 var userStats []models.UserStats // SQL查询:联合查询用户表和答题记录表 query := ` SELECT u.id as user_id, u.username, u.nickname, u.avatar, u.user_type, COALESCE(COUNT(ar.id), 0) as total_answers, COALESCE(SUM(CASE WHEN ar.is_correct = true THEN 1 ELSE 0 END), 0) as correct_count, COALESCE(SUM(CASE WHEN ar.is_correct = false THEN 1 ELSE 0 END), 0) as wrong_count, CASE WHEN COUNT(ar.id) > 0 THEN ROUND(CAST(CAST(SUM(CASE WHEN ar.is_correct = true THEN 1 ELSE 0 END) AS FLOAT) / COUNT(ar.id) * 100 AS NUMERIC), 2) ELSE 0 END as accuracy, u.created_at, MAX(ar.answered_at) as last_answer_at FROM users u LEFT JOIN user_answer_records ar ON u.id = ar.user_id AND ar.deleted_at IS NULL WHERE u.deleted_at IS NULL GROUP BY u.id, u.username, u.nickname, u.avatar, u.user_type, u.created_at ORDER BY total_answers DESC, accuracy DESC ` if err := db.Raw(query).Scan(&userStats).Error; err != nil { c.JSON(http.StatusInternalServerError, gin.H{ "success": false, "message": "获取用户统计数据失败", "error": err.Error(), }) return } c.JSON(http.StatusOK, gin.H{ "success": true, "data": userStats, }) } // GetUserDetailStats 获取指定用户的详细统计信息 func GetUserDetailStats(c *gin.Context) { userID := c.Param("id") db := database.GetDB() // 查询用户基本信息 var user models.User if err := db.First(&user, userID).Error; err != nil { c.JSON(http.StatusNotFound, gin.H{ "success": false, "message": "用户不存在", }) return } // 查询用户答题统计 var stats models.UserStats query := ` SELECT u.id as user_id, u.username, u.nickname, u.avatar, u.user_type, COALESCE(COUNT(ar.id), 0) as total_answers, COALESCE(SUM(CASE WHEN ar.is_correct = true THEN 1 ELSE 0 END), 0) as correct_count, COALESCE(SUM(CASE WHEN ar.is_correct = false THEN 1 ELSE 0 END), 0) as wrong_count, CASE WHEN COUNT(ar.id) > 0 THEN ROUND(CAST(CAST(SUM(CASE WHEN ar.is_correct = true THEN 1 ELSE 0 END) AS FLOAT) / COUNT(ar.id) * 100 AS NUMERIC), 2) ELSE 0 END as accuracy, u.created_at, MAX(ar.answered_at) as last_answer_at FROM users u LEFT JOIN user_answer_records ar ON u.id = ar.user_id AND ar.deleted_at IS NULL WHERE u.id = ? AND u.deleted_at IS NULL GROUP BY u.id, u.username, u.nickname, u.avatar, u.user_type, u.created_at ` if err := db.Raw(query, userID).Scan(&stats).Error; err != nil { c.JSON(http.StatusInternalServerError, gin.H{ "success": false, "message": "获取用户统计数据失败", "error": err.Error(), }) return } // 查询按题型分类的统计 var typeStats []struct { QuestionType string `json:"question_type"` QuestionTypeName string `json:"question_type_name"` TotalAnswers int `json:"total_answers"` CorrectCount int `json:"correct_count"` Accuracy float64 `json:"accuracy"` } typeQuery := ` SELECT pq.type as question_type, pq.type_name as question_type_name, COUNT(ar.id) as total_answers, SUM(CASE WHEN ar.is_correct = true THEN 1 ELSE 0 END) as correct_count, CASE WHEN COUNT(ar.id) > 0 THEN ROUND(CAST(CAST(SUM(CASE WHEN ar.is_correct = true THEN 1 ELSE 0 END) AS FLOAT) / COUNT(ar.id) * 100 AS NUMERIC), 2) ELSE 0 END as accuracy FROM user_answer_records ar JOIN practice_questions pq ON ar.question_id = pq.id WHERE ar.user_id = ? AND ar.deleted_at IS NULL GROUP BY pq.type, pq.type_name ORDER BY total_answers DESC ` db.Raw(typeQuery, userID).Scan(&typeStats) c.JSON(http.StatusOK, gin.H{ "success": true, "data": gin.H{ "user_info": stats, "type_stats": typeStats, }, }) }