forked from FLY123-coder/123
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathQuestionRenderer.tsx
More file actions
148 lines (135 loc) · 4.06 KB
/
Copy pathQuestionRenderer.tsx
File metadata and controls
148 lines (135 loc) · 4.06 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
import React from 'react';
import type { Question } from '@/types';
import { QuestionType } from '@/types';
import {
SingleChoiceQuestion,
MultipleChoiceQuestion,
FillBlankQuestion,
ShortAnswerQuestion,
CodeOutputQuestion,
CodeWritingQuestion,
} from './questions';
import { useAttachMultipleChoiceHotkeys } from './questions/MultipleChoiceQuestion';
interface Props {
question: Question;
onAnswerChange: (questionId: string, answer: unknown) => void;
disabled?: boolean;
showCorrectAnswer?: boolean;
questionNumber?: number;
}
/**
* 题目渲染器组件
* 根据题目类型动态渲染对应的题目组件
*/
export const QuestionRenderer: React.FC<Props> = ({
question,
onAnswerChange,
disabled = false,
showCorrectAnswer = false,
questionNumber,
}) => {
const handleAnswerChange = (answer: unknown) => {
onAnswerChange(question.id, answer);
};
const renderQuestion = () => {
switch (question.type) {
case QuestionType.SINGLE_CHOICE:
return (
<SingleChoiceQuestion
question={question}
onAnswerChange={handleAnswerChange}
disabled={disabled}
showCorrectAnswer={showCorrectAnswer}
/>
);
case QuestionType.MULTIPLE_CHOICE:
// 挂载多选题热键(1-9 选择/取消,Enter 下一题)
useAttachMultipleChoiceHotkeys(
question as unknown as import('@/types').MultipleChoiceQuestion,
disabled,
(ans: number[]) => handleAnswerChange(ans),
);
return (
<MultipleChoiceQuestion
question={question}
onAnswerChange={handleAnswerChange}
disabled={disabled}
showCorrectAnswer={showCorrectAnswer}
/>
);
case QuestionType.FILL_BLANK:
return (
<FillBlankQuestion
question={question}
onAnswerChange={handleAnswerChange}
disabled={disabled}
showCorrectAnswer={showCorrectAnswer}
/>
);
case QuestionType.SHORT_ANSWER:
return (
<ShortAnswerQuestion
question={question}
onAnswerChange={handleAnswerChange}
disabled={disabled}
showCorrectAnswer={showCorrectAnswer}
/>
);
case QuestionType.CODE_OUTPUT:
return (
<CodeOutputQuestion
question={question}
onAnswerChange={handleAnswerChange}
disabled={disabled}
showCorrectAnswer={showCorrectAnswer}
/>
);
case QuestionType.CODE_WRITING:
return (
<CodeWritingQuestion
question={question}
onAnswerChange={handleAnswerChange}
disabled={disabled}
showCorrectAnswer={showCorrectAnswer}
/>
);
default:
return (
<div className='p-4 bg-red-50 border border-red-200 rounded-lg'>
<p className='text-red-800'>
未知题目类型: {(question as { type: string }).type}
</p>
</div>
);
}
};
return (
<div className='bg-white rounded-lg border border-gray-200 p-6 shadow-sm'>
{questionNumber && (
<div className='flex items-center gap-2 mb-4'>
<span className='bg-blue-100 text-blue-800 px-3 py-1 rounded-full text-sm font-medium'>
第 {questionNumber} 题
</span>
<span className='text-gray-500 text-sm'>
{getQuestionTypeLabel(question.type)}
</span>
</div>
)}
{renderQuestion()}
</div>
);
};
/**
* 获取题目类型的中文标签
*/
function getQuestionTypeLabel(type: QuestionType): string {
const labels: Record<QuestionType, string> = {
[QuestionType.SINGLE_CHOICE]: '单选题',
[QuestionType.MULTIPLE_CHOICE]: '多选题',
[QuestionType.FILL_BLANK]: '填空题',
[QuestionType.SHORT_ANSWER]: '简答题',
[QuestionType.CODE_OUTPUT]: '代码输出题',
[QuestionType.CODE_WRITING]: '代码编写题',
};
return labels[type] || '未知题型';
}