From b1551e6deb5b9d868d2633b0f1e89abecc368371 Mon Sep 17 00:00:00 2001 From: yanlongqi Date: Tue, 2 Dec 2025 00:31:33 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=AF=8F=E6=97=A5=E4=B8=80?= =?UTF-8?q?=E7=BB=83=E6=8E=92=E8=A1=8C=E6=A6=9C=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 修复 daily_exam_service.go 中的类型转换错误 - 在首页添加每日一练排行榜组件 - 显示今日每日一练的考试成绩和用时排行 - 当今日尚未生成每日一练时显示友好提示 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- internal/services/daily_exam_service.go | 4 +- web/src/pages/Home.tsx | 118 ++++++++++++++++++++++++ 2 files changed, 120 insertions(+), 2 deletions(-) diff --git a/internal/services/daily_exam_service.go b/internal/services/daily_exam_service.go index 6bb3a00..15d30bd 100644 --- a/internal/services/daily_exam_service.go +++ b/internal/services/daily_exam_service.go @@ -75,7 +75,7 @@ func (s *DailyExamService) GenerateDailyExam() error { } exam := models.Exam{ - UserID: firstUser.ID, // 使用第一个用户作为创建者 + UserID: uint(firstUser.ID), // 使用第一个用户作为创建者 Title: title, TotalScore: int(totalScore), Duration: 60, @@ -92,7 +92,7 @@ func (s *DailyExamService) GenerateDailyExam() error { log.Printf("成功创建每日一练试卷: ID=%d, Title=%s", exam.ID, exam.Title) // 6. 分享给所有用户 - if err := s.shareToAllUsers(exam.ID, firstUser.ID); err != nil { + if err := s.shareToAllUsers(exam.ID, uint(firstUser.ID)); err != nil { log.Printf("分享试卷失败: %v", err) // 不返回错误,因为试卷已创建成功 } diff --git a/web/src/pages/Home.tsx b/web/src/pages/Home.tsx index 2b542e7..ae50f8d 100644 --- a/web/src/pages/Home.tsx +++ b/web/src/pages/Home.tsx @@ -24,6 +24,7 @@ import { CrownOutlined, } from '@ant-design/icons' import * as questionApi from '../api/question' +import * as examApi from '../api/exam' import { fetchWithAuth } from '../utils/request' import type { Statistics } from '../types/question' import styles from './Home.module.less' @@ -110,6 +111,23 @@ const Home: React.FC = () => { const [rankingType, setRankingType] = useState<'daily' | 'total'>('daily') // 排行榜类型:每日或总榜 const [sliderPosition, setSliderPosition] = useState<'left' | 'right'>('left') // 滑块位置 + // 每日一练排行榜状态 + const [dailyExamRanking, setDailyExamRanking] = useState<{ + exam_id?: number + exam_title?: string + rankings: Array<{ + user_id: number + username: string + nickname: string + avatar: string + score: number + time_spent: number + rank: number + }> + total: number + }>({ rankings: [], total: 0 }) + const [dailyExamLoading, setDailyExamLoading] = useState(false) + // 答题设置状态 const [autoNext, setAutoNext] = useState(() => { const saved = localStorage.getItem('autoNextEnabled') @@ -183,6 +201,23 @@ const Home: React.FC = () => { setSliderPosition(type === 'daily' ? 'left' : 'right') } + // 加载每日一练排行榜 + const loadDailyExamRanking = async () => { + setDailyExamLoading(true) + try { + const res = await examApi.getDailyExamRanking() + if (res.success && res.data) { + setDailyExamRanking(res.data) + } + } catch (error) { + console.error('加载每日一练排行榜失败:', error) + // 如果失败,设置为空数据(可能是今日尚未生成) + setDailyExamRanking({ rankings: [], total: 0 }) + } finally { + setDailyExamLoading(false) + } + } + // 加载用户信息 useEffect(() => { const token = localStorage.getItem('token') @@ -206,6 +241,7 @@ const Home: React.FC = () => { useEffect(() => { loadStatistics() loadCurrentRanking() + loadDailyExamRanking() }, [rankingType]) // 动态加载聊天插件(仅在首页加载) @@ -823,6 +859,88 @@ const Home: React.FC = () => { )} + {/* 每日一练排行榜 */} +
+ + <CrownOutlined style={{ color: '#fa8c16' }} /> 每日一练排行榜 + + {dailyExamLoading ? ( + + ) : dailyExamRanking.rankings.length === 0 ? ( + +
+ +
今日每日一练尚未生成
+
请等待系统每天凌晨1点自动生成
+
+
+ ) : ( + + {dailyExamRanking.exam_title && ( +
+ + {dailyExamRanking.exam_title} +
+ )} +
+ {dailyExamRanking.rankings.map((user, index) => ( +
+
+ {index < 3 ? ( +
+ {index === 0 && } + {index === 1 && } + {index === 2 && } +
+ ) : ( +
{index + 1}
+ )} + } + className={styles.rankAvatar} + /> +
+
{user.nickname}
+
@{user.username}
+
+
+
+
+
= 80 ? '#52c41a' : user.score >= 60 ? '#faad14' : '#ff4d4f', + fontSize: 18, + fontWeight: 'bold' + }}> + {user.score} +
+
得分
+
+
+
+
+ {Math.floor(user.time_spent / 60)}' + {user.time_spent % 60 < 10 ? '0' : ''}{user.time_spent % 60}" +
+
用时
+
+
+
+ ))} +
+
+ )} +
+ {/* 用户类型补充模态框 */}