diff --git a/.artifacts/playwright/new-quiz-page-2025-12-28T15-59-55-535Z.png b/.artifacts/playwright/new-quiz-page-2025-12-28T15-59-55-535Z.png new file mode 100644 index 0000000..acfab91 Binary files /dev/null and b/.artifacts/playwright/new-quiz-page-2025-12-28T15-59-55-535Z.png differ diff --git a/data/survey.db b/data/survey.db index 862b58d..f96dae6 100644 Binary files a/data/survey.db and b/data/survey.db differ diff --git a/src/pages/QuizPage.tsx b/src/pages/QuizPage.tsx index ea58535..d00af86 100644 --- a/src/pages/QuizPage.tsx +++ b/src/pages/QuizPage.tsx @@ -1,13 +1,15 @@ import { useState, useEffect, useMemo, useRef, type TouchEventHandler } from 'react'; -import { Card, Button, Radio, Checkbox, Input, message, Progress, Modal } from 'antd'; +import { Card, Button, Modal, message } from 'antd'; import { useNavigate, useLocation } from 'react-router-dom'; import { useUser, useQuiz } from '../contexts'; import { quizAPI } from '../services/api'; import { questionTypeMap } from '../utils/validation'; import { detectHorizontalSwipe } from '../utils/swipe'; import { UserLayout } from '../layouts/UserLayout'; - -const { TextArea } = Input; +import { QuizHeader } from './quiz/components/QuizHeader'; +import { QuizProgress } from './quiz/components/QuizProgress'; +import { OptionList } from './quiz/components/OptionList'; +import { QuizFooter } from './quiz/components/QuizFooter'; interface Question { id: string; @@ -216,24 +218,13 @@ const QuizPage = () => { }, 1000); }; - const formatTime = (seconds: number) => { - const minutes = Math.floor(seconds / 60); - const remainingSeconds = seconds % 60; - return `${minutes}:${remainingSeconds.toString().padStart(2, '0')}`; - }; - const getTagColor = (type: string) => { switch (type) { - case 'single': - return 'bg-blue-100 text-blue-800'; - case 'multiple': - return 'bg-purple-100 text-purple-800'; - case 'judgment': - return 'bg-orange-100 text-orange-800'; - case 'text': - return 'bg-green-100 text-green-800'; - default: - return 'bg-gray-100 text-gray-800'; + case 'single': return 'bg-orange-100 text-orange-800 border-orange-200'; + case 'multiple': return 'bg-blue-100 text-blue-800 border-blue-200'; + case 'judgment': return 'bg-purple-100 text-purple-800 border-purple-200'; + case 'text': return 'bg-green-100 text-green-800 border-green-200'; + default: return 'bg-gray-100 text-gray-800 border-gray-200'; } }; @@ -322,7 +313,6 @@ const QuizPage = () => { setSubmitting(true); if (!forceSubmit) { - // 检查是否所有题目都已回答 const unansweredQuestions = questions.filter(q => !answers[q.id]); if (unansweredQuestions.length > 0) { message.warning(`还有 ${unansweredQuestions.length} 道题未作答`); @@ -330,7 +320,6 @@ const QuizPage = () => { } } - // 准备答案数据 const answersData = questions.map(question => { const isCorrect = checkAnswer(question, answers[question.id]); return { @@ -387,72 +376,6 @@ const QuizPage = () => { } }; - const renderQuestion = (question: Question) => { - const currentAnswer = answers[question.id]; - - switch (question.type) { - case 'single': - return ( - handleAnswerChange(question.id, e.target.value)} - className="w-full" - > - {question.options?.map((option, index) => ( - - {String.fromCharCode(65 + index)}. {option} - - ))} - - ); - - case 'multiple': - return ( - handleAnswerChange(question.id, checkedValues)} - className="w-full" - > - {question.options?.map((option, index) => ( - - {String.fromCharCode(65 + index)}. {option} - - ))} - - ); - - case 'judgment': - return ( - handleAnswerChange(question.id, e.target.value)} - className="w-full" - > - - 正确 - - - 错误 - - - ); - - case 'text': - return ( -