- 后端新增 /api/ranking/daily 接口,支持获取今日用户刷题排行 - 排行榜按今日刷题数量和正确率进行排序 - 前端首页展示今日排行榜,显示前10名用户 - 前三名使用金银铜渐变色王冠徽章标识 - 正确率根据分数显示不同颜色(绿色≥80%、黄色≥60%、红色<60%) - 完整支持移动端、平板端、PC端响应式布局 - 优化排行榜标题与上方内容的间距 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
83 lines
2.0 KiB
Go
83 lines
2.0 KiB
Go
package handlers
|
|
|
|
import (
|
|
"ankao/internal/database"
|
|
"ankao/internal/models"
|
|
"net/http"
|
|
"strconv"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
)
|
|
|
|
// HomeHandler 首页处理器
|
|
func HomeHandler(c *gin.Context) {
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"message": "欢迎使用AnKao Web服务",
|
|
"version": "1.0.0",
|
|
})
|
|
}
|
|
|
|
// HealthCheckHandler 健康检查处理器
|
|
func HealthCheckHandler(c *gin.Context) {
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"status": "healthy",
|
|
})
|
|
}
|
|
|
|
// GetDailyRanking 获取今日排行榜
|
|
func GetDailyRanking(c *gin.Context) {
|
|
db := database.GetDB()
|
|
|
|
// 获取查询参数
|
|
limitStr := c.DefaultQuery("limit", "10")
|
|
limit, err := strconv.Atoi(limitStr)
|
|
if err != nil || limit <= 0 || limit > 100 {
|
|
limit = 10
|
|
}
|
|
|
|
// 查询今日排行榜(按答题数量和正确率排序)
|
|
var rankings []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
|
|
AND DATE(ar.answered_at) = CURRENT_DATE
|
|
WHERE u.deleted_at IS NULL
|
|
GROUP BY u.id, u.username, u.nickname, u.avatar, u.user_type, u.created_at
|
|
HAVING COUNT(ar.id) > 0
|
|
ORDER BY total_answers DESC, accuracy DESC, correct_count DESC
|
|
LIMIT ?
|
|
`
|
|
|
|
if err := db.Raw(query, limit).Scan(&rankings).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": rankings,
|
|
})
|
|
}
|