import React, { useEffect, useState } from 'react' import { useNavigate } from 'react-router-dom' import { Card, Tabs, List, Tag, Typography, Space, Divider, Button, Spin, message, Input, } from 'antd' import { BookOutlined, CheckCircleOutlined, CloseCircleOutlined, EditOutlined, FileTextOutlined, UnorderedListOutlined, SearchOutlined, ArrowLeftOutlined, } from '@ant-design/icons' import * as questionApi from '../api/question' import type { Question } from '../types/question' import styles from './QuestionList.module.less' const { Title, Text, Paragraph } = Typography // 题型配置 const questionTypeConfig: Record = { 'multiple-choice': { label: '选择题', icon: , color: '#1677ff' }, 'multiple-selection': { label: '多选题', icon: , color: '#52c41a' }, 'true-false': { label: '判断题', icon: , color: '#fa8c16' }, 'fill-in-blank': { label: '填空题', icon: , color: '#722ed1' }, 'short-answer': { label: '简答题', icon: , color: '#eb2f96' }, } const QuestionList: React.FC = () => { const navigate = useNavigate() const [loading, setLoading] = useState(false) const [questions, setQuestions] = useState([]) const [filteredQuestions, setFilteredQuestions] = useState([]) const [selectedType, setSelectedType] = useState('all') const [searchKeyword, setSearchKeyword] = useState('') // 加载题目列表 const loadQuestions = async () => { setLoading(true) try { const res = await questionApi.getQuestions({}) if (res.success && res.data) { setQuestions(res.data) setFilteredQuestions(res.data) } } catch (error) { message.error('加载题目列表失败') console.error('加载题目失败:', error) } finally { setLoading(false) } } useEffect(() => { loadQuestions() }, []) // 筛选题目 useEffect(() => { let filtered = questions // 按题型筛选 if (selectedType !== 'all') { filtered = filtered.filter(q => q.type === selectedType) } // 按关键词搜索 if (searchKeyword.trim()) { const keyword = searchKeyword.trim().toLowerCase() filtered = filtered.filter(q => q.content.toLowerCase().includes(keyword) || q.question_id.toLowerCase().includes(keyword) ) } setFilteredQuestions(filtered) }, [selectedType, searchKeyword, questions]) // 渲染填空题内容,将****替换为下划线 const renderFillInBlankContent = (content: string): React.ReactNode => { // 将 **** 替换为下划线样式 const parts = content.split('****') return ( <> {parts.map((part, index) => ( {part} {index < parts.length - 1 && ( ______ )} ))} ) } // 格式化答案显示 const formatAnswer = (question: Question): string => { const { type, answer, options } = question switch (type) { case 'true-false': return answer === true ? '正确' : '错误' case 'multiple-choice': const option = options?.find(opt => opt.key === answer) return option ? `${answer}. ${option.value}` : String(answer) case 'multiple-selection': if (Array.isArray(answer)) { return answer.map(key => { const opt = options?.find(o => o.key === key) return opt ? `${key}. ${opt.value}` : key }).join('; ') } return String(answer) case 'fill-in-blank': if (Array.isArray(answer)) { return answer.map((a, i) => `空${i + 1}: ${a}`).join('; ') } return String(answer) case 'short-answer': return String(answer) default: return String(answer) } } // 渲染选项 const renderOptions = (question: Question) => { // 判断题不显示选项 if (question.type === 'true-false') { return null } if (!question.options || question.options.length === 0) { return null } return (
{question.options.map(opt => (
{opt.key} {opt.value}
))}
) } return (
{/* 头部 */}
<BookOutlined /> 题目列表
{/* 筛选栏 */} } value={searchKeyword} onChange={e => setSearchKeyword(e.target.value)} allowClear size="large" className={styles.searchInput} /> {/* 题型选项卡 */} 全部题型 ), }, ...Object.entries(questionTypeConfig).map(([type, config]) => ({ key: type, label: ( {config.icon} {config.label} ), })), ]} /> 共 {filteredQuestions.length} 道题目 {/* 题目列表 */} { const typeConfig = questionTypeConfig[question.type] return ( {/* 题目头部 */}
{typeConfig?.icon} {typeConfig?.label || question.type} #{question.question_id} 第 {index + 1} 题
{/* 题目内容 */}
{question.type === 'fill-in-blank' ? renderFillInBlankContent(question.content) : question.content }
{/* 选项 */} {renderOptions(question)} {/* 答案 */}
正确答案: {formatAnswer(question)}
) }} locale={{ emptyText: '暂无题目' }} />
) } export default QuestionList