整合三个排行榜为单一可切换的排行榜界面

- 合并每日一练排行榜、今日排行榜、总排行榜到一个界面
- 添加三个可点击切换的标签页
- 优化滑块动画,支持三个位置(左、中、右)
- 统一加载状态显示
- 保持各排行榜原有的数据展示和样式
This commit is contained in:
燕陇琪 2025-12-02 00:40:09 +08:00
parent fa2964e144
commit 4f7dfae855

View File

@ -108,8 +108,8 @@ const Home: React.FC = () => {
const [dailyRanking, setDailyRanking] = useState<questionApi.UserStats[]>([])
const [totalRanking, setTotalRanking] = useState<questionApi.UserStats[]>([])
const [rankingLoading, setRankingLoading] = useState(false)
const [rankingType, setRankingType] = useState<'daily' | 'total'>('daily') // 排行榜类型:每日或总榜
const [sliderPosition, setSliderPosition] = useState<'left' | 'right'>('left') // 滑块位置
const [rankingType, setRankingType] = useState<'daily-exam' | 'daily' | 'total'>('daily-exam') // 排行榜类型:每日一练、每日或总榜
const [sliderPosition, setSliderPosition] = useState<'left' | 'center' | 'right'>('left') // 滑块位置
// 每日一练排行榜状态
const [dailyExamRanking, setDailyExamRanking] = useState<{
@ -188,7 +188,9 @@ const Home: React.FC = () => {
// 加载当前选中的排行榜数据
const loadCurrentRanking = async () => {
if (rankingType === 'daily') {
if (rankingType === 'daily-exam') {
await loadDailyExamRanking()
} else if (rankingType === 'daily') {
await loadDailyRanking()
} else {
await loadTotalRanking()
@ -196,9 +198,15 @@ const Home: React.FC = () => {
}
// 切换排行榜类型
const switchRankingType = (type: 'daily' | 'total') => {
const switchRankingType = (type: 'daily-exam' | 'daily' | 'total') => {
setRankingType(type)
setSliderPosition(type === 'daily' ? 'left' : 'right')
if (type === 'daily-exam') {
setSliderPosition('left')
} else if (type === 'daily') {
setSliderPosition('center')
} else {
setSliderPosition('right')
}
}
// 加载每日一练排行榜
@ -241,7 +249,6 @@ const Home: React.FC = () => {
useEffect(() => {
loadStatistics()
loadCurrentRanking()
loadDailyExamRanking()
}, [rankingType])
// 动态加载聊天插件(仅在首页加载)
@ -724,14 +731,42 @@ const Home: React.FC = () => {
</Row>
</div>
{/* 每日一练排行榜 */}
{/* 排行榜 */}
<div className={styles.rankingSection}>
<Title level={4} className={styles.sectionTitle}>
<CrownOutlined style={{ color: '#fa8c16' }} />
<TrophyOutlined />
</Title>
{dailyExamLoading ? (
<div className={styles.rankingSwitch}>
<div
className={`${styles.rankingSwitchButton} ${rankingType === 'daily-exam' ? styles.active : ''}`}
onClick={() => switchRankingType('daily-exam')}
>
</div>
<div
className={`${styles.rankingSwitchButton} ${rankingType === 'daily' ? styles.active : ''}`}
onClick={() => switchRankingType('daily')}
>
</div>
<div
className={`${styles.rankingSwitchButton} ${rankingType === 'total' ? styles.active : ''}`}
onClick={() => switchRankingType('total')}
>
</div>
<div
className={styles.rankingSwitchSlider}
style={{
width: 'calc(33.33% - 4px)',
left: sliderPosition === 'left' ? '4px' : sliderPosition === 'center' ? 'calc(33.33% + 0px)' : 'calc(66.66% - 4px)',
}}
/>
</div>
{(rankingLoading || dailyExamLoading) ? (
<Card className={styles.rankingCard} loading={true} />
) : dailyExamRanking.rankings.length === 0 ? (
) : rankingType === 'daily-exam' ? (
dailyExamRanking.rankings.length === 0 ? (
<Card className={styles.rankingCard}>
<div style={{ textAlign: 'center', padding: '40px 20px', color: '#8c8c8c' }}>
<CrownOutlined style={{ fontSize: 48, marginBottom: 16, opacity: 0.3, color: '#fa8c16' }} />
@ -803,37 +838,7 @@ const Home: React.FC = () => {
))}
</div>
</Card>
)}
</div>
{/* 排行榜 */}
<div className={styles.rankingSection}>
<Title level={4} className={styles.sectionTitle}>
<TrophyOutlined />
</Title>
<div className={styles.rankingSwitch}>
<div
className={`${styles.rankingSwitchButton} ${rankingType === 'daily' ? styles.active : ''}`}
onClick={() => switchRankingType('daily')}
>
</div>
<div
className={`${styles.rankingSwitchButton} ${rankingType === 'total' ? styles.active : ''}`}
onClick={() => switchRankingType('total')}
>
</div>
<div
className={styles.rankingSwitchSlider}
style={{
width: 'calc(50% - 4px)',
left: sliderPosition === 'left' ? '4px' : 'calc(50% + 0px)',
}}
/>
</div>
{rankingLoading ? (
<Card className={styles.rankingCard} loading={true} />
)
) : rankingType === 'daily' ? (
dailyRanking.length === 0 ? (
<Card className={styles.rankingCard}>