([]) // 填空题答案数组
// 统计弹窗
const [statsVisible, setStatsVisible] = useState(false)
@@ -58,6 +61,7 @@ const QuestionPage: React.FC = () => {
if (res.success && res.data) {
setCurrentQuestion(res.data)
setSelectedAnswer(res.data.type === 'multiple' ? [] : '')
+ setFillAnswers([])
setShowResult(false)
setAnswerResult(null)
}
@@ -79,6 +83,7 @@ const QuestionPage: React.FC = () => {
setCurrentQuestion(res.data[0])
setCurrentIndex(0)
setSelectedAnswer(res.data[0].type === 'multiple' ? [] : '')
+ setFillAnswers([])
setShowResult(false)
setAnswerResult(null)
}
@@ -107,12 +112,24 @@ const QuestionPage: React.FC = () => {
if (!currentQuestion) return
// 检查是否选择了答案
- if (
- (currentQuestion.type === 'multiple' && (selectedAnswer as string[]).length === 0) ||
- (currentQuestion.type !== 'multiple' && !selectedAnswer)
- ) {
- Toast.show('请选择或填写答案')
- return
+ if (currentQuestion.type === 'multiple') {
+ // 多选题:检查数组长度
+ if ((selectedAnswer as string[]).length === 0) {
+ Toast.show('请选择答案')
+ return
+ }
+ } else if (currentQuestion.type === 'fill') {
+ // 填空题:检查所有填空是否都已填写
+ if (fillAnswers.length === 0 || fillAnswers.some(a => !a || a.trim() === '')) {
+ Toast.show('请填写所有空格')
+ return
+ }
+ } else {
+ // 单选题、判断题、简答题:检查是否有值
+ if (!selectedAnswer || (typeof selectedAnswer === 'string' && selectedAnswer.trim() === '')) {
+ Toast.show('请填写答案')
+ return
+ }
}
setLoading(true)
@@ -146,6 +163,7 @@ const QuestionPage: React.FC = () => {
setCurrentIndex(nextIndex)
setCurrentQuestion(allQuestions[nextIndex])
setSelectedAnswer(allQuestions[nextIndex].type === 'multiple' ? [] : '')
+ setFillAnswers([])
setShowResult(false)
setAnswerResult(null)
} else {
@@ -158,6 +176,7 @@ const QuestionPage: React.FC = () => {
setCurrentQuestion(question)
setCurrentIndex(index)
setSelectedAnswer(question.type === 'multiple' ? [] : '')
+ setFillAnswers([])
setShowResult(false)
setAnswerResult(null)
setListVisible(false)
@@ -188,9 +207,19 @@ const QuestionPage: React.FC = () => {
// 初始化
useEffect(() => {
- loadRandomQuestion()
- loadQuestions()
- }, [])
+ // 从URL参数获取题型
+ const typeParam = searchParams.get('type')
+ const categoryParam = searchParams.get('category')
+
+ if (typeParam || categoryParam) {
+ // 如果有筛选参数,加载筛选后的题目列表
+ loadQuestions(typeParam || undefined, categoryParam || undefined)
+ } else {
+ // 否则加载随机题目
+ loadRandomQuestion()
+ loadQuestions()
+ }
+ }, [searchParams])
// 获取题型名称
const getTypeName = (type: string) => {
@@ -199,22 +228,78 @@ const QuestionPage: React.FC = () => {
multiple: '多选题',
fill: '填空题',
judge: '判断题',
+ short: '简答题',
}
return typeMap[type] || type
}
+ // 渲染填空题内容(将****替换为输入框)
+ const renderFillContent = () => {
+ if (!currentQuestion) return null
+
+ const content = currentQuestion.content
+ const parts = content.split('****')
+
+ // 如果没有****,说明不是填空题格式
+ if (parts.length === 1) {
+ return {content}
+ }
+
+ // 初始化填空答案数组
+ if (fillAnswers.length === 0) {
+ setFillAnswers(new Array(parts.length - 1).fill(''))
+ }
+
+ return (
+
+ {parts.map((part, index) => (
+
+ {part}
+ {index < parts.length - 1 && (
+ {
+ const newAnswers = [...fillAnswers]
+ newAnswers[index] = val
+ setFillAnswers(newAnswers)
+ setSelectedAnswer(newAnswers)
+ }}
+ disabled={showResult}
+ style={{
+ display: 'inline-block',
+ width: '120px',
+ margin: '0 8px',
+ borderBottom: '2px solid #1677ff',
+ borderRadius: 0,
+ }}
+ />
+ )}
+
+ ))}
+
+ )
+ }
+
// 渲染题目选项
const renderOptions = () => {
if (!currentQuestion) return null
+ // 填空题:使用特殊渲染(在题目内容中嵌入输入框)
if (currentQuestion.type === 'fill') {
+ return null // 填空题的输入框已在题目内容中渲染
+ }
+
+ // 简答题:使用大文本框
+ if (currentQuestion.type === 'short') {
return (
setSelectedAnswer(val)}
disabled={showResult}
- style={{ marginTop: 20 }}
+ style={{ marginTop: 20, minHeight: 100 }}
/>
)
}
@@ -289,7 +374,10 @@ const QuestionPage: React.FC = () => {
第 {currentQuestion.id} 题
- {currentQuestion.content}
+ {/* 填空题使用特殊渲染 */}
+ {currentQuestion.type === 'fill' ? renderFillContent() : (
+ {currentQuestion.content}
+ )}
{renderOptions()}
@@ -437,6 +525,7 @@ const QuestionPage: React.FC = () => {
{ label: '多选题', value: 'multiple' },
{ label: '填空题', value: 'fill' },
{ label: '判断题', value: 'judge' },
+ { label: '简答题', value: 'short' },
]}
value={[filterType]}
onChange={(arr) => setFilterType(arr[0] || '')}
diff --git a/web/src/types/question.ts b/web/src/types/question.ts
index 4f51be5..a6a65f4 100644
--- a/web/src/types/question.ts
+++ b/web/src/types/question.ts
@@ -1,5 +1,5 @@
// 题目类型
-export type QuestionType = 'single' | 'multiple' | 'fill' | 'judge'
+export type QuestionType = 'single' | 'multiple' | 'fill' | 'judge' | 'short'
// 选项
export interface Option {