Files
gongxue-base/apps/taro/src/pages/student/review/index.tsx

103 lines
4.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { useEffect, useState } from 'react';
import Taro, { useRouter } from '@tarojs/taro';
import { Button, Text, View } from '@tarojs/components';
import {
loadFavoriteQuestions,
loadWrongQuestionReviewPlan,
resolveWrongQuestion,
type QuestionItem,
type WrongQuestionReviewItem,
} from '@/services/learning';
import '../student.css';
type ReviewMode = 'wrong' | 'favorite';
function questionIdOf(item: QuestionItem | WrongQuestionReviewItem) {
return 'questionId' in item && item.questionId ? item.questionId : (item as QuestionItem).id;
}
export default function StudentReviewPage() {
const router = useRouter();
const initialMode = router.params?.type === 'favorite' ? 'favorite' : 'wrong';
const [mode, setMode] = useState<ReviewMode>(initialMode);
const [wrongItems, setWrongItems] = useState<WrongQuestionReviewItem[]>([]);
const [favoriteItems, setFavoriteItems] = useState<QuestionItem[]>([]);
const [error, setError] = useState('');
function reload(nextMode = mode) {
setError('');
if (nextMode === 'wrong') {
loadWrongQuestionReviewPlan(30)
.then(payload => setWrongItems(payload.items || []))
.catch(nextError => setError(nextError instanceof Error ? nextError.message : '错题加载失败'));
return;
}
loadFavoriteQuestions(50)
.then(payload => setFavoriteItems(payload.items || []))
.catch(nextError => setError(nextError instanceof Error ? nextError.message : '收藏加载失败'));
}
useEffect(() => {
reload(mode);
}, [mode]);
function startReview() {
const reviewMode = mode === 'wrong' ? 'wrong_review' : 'favorite_review';
Taro.navigateTo({ url: `/pages/student/practice/index?mode=${reviewMode}&questionLimit=30` });
}
async function markResolved(questionId: string) {
try {
await resolveWrongQuestion(questionId);
Taro.showToast({ title: '已移出错题', icon: 'success' });
reload('wrong');
} catch (nextError) {
setError(nextError instanceof Error ? nextError.message : '移出错题失败');
}
}
const items = mode === 'wrong' ? wrongItems : favoriteItems;
return (
<View className='student-page review-page'>
<View className='student-topbar'>
<View className='student-title-block'>
<Text className='student-kicker'>Review</Text>
<Text className='student-title'>{mode === 'wrong' ? '错题本' : '收藏夹'}</Text>
<Text className='student-subtitle'>/</Text>
</View>
<Button className='secondary-button' onClick={() => Taro.navigateBack()}></Button>
</View>
<View className='toolbar wrap'>
<Button className={`pill-button ${mode === 'wrong' ? 'active' : ''}`} onClick={() => setMode('wrong')}></Button>
<Button className={`pill-button ${mode === 'favorite' ? 'active' : ''}`} onClick={() => setMode('favorite')}></Button>
<Button className='primary-button' onClick={startReview}></Button>
</View>
<View className='section-block'>
<Text className='section-heading'>{mode === 'wrong' ? '建议复习' : '收藏题目'}</Text>
<View className='list-stack'>
{items.map(item => {
const questionId = questionIdOf(item);
return (
<View className='list-row' key={questionId}>
<Text className='row-main'>{item.content || '未提供题干'}</Text>
<Text className='row-meta'>{item.typeLabel || item.type || '题目'}{mode === 'wrong' ? ` · 错 ${String((item as WrongQuestionReviewItem).wrongCount || 0)}` : ''}</Text>
{mode === 'wrong' ? (
<View className='toolbar'>
<Button className='secondary-button' onClick={() => markResolved(questionId)}></Button>
</View>
) : null}
</View>
);
})}
</View>
{!items.length ? <View className='empty-state'>{mode === 'wrong' ? '暂无待复习错题。' : '暂无收藏题目。'}</View> : null}
</View>
{error ? <Text className='error-text'>{error}</Text> : null}
</View>
);
}