parent
0288826ad1
commit
1e1aa85a21
7 changed files with 619 additions and 135 deletions
@ -0,0 +1,154 @@ |
|||||||
|
import React, { useEffect, useState } from 'react'; |
||||||
|
import { Table, Button } from 'antd'; |
||||||
|
import { withRouter, RouteComponentProps } from 'react-router-dom'; |
||||||
|
import { getDetail } from "api/exam-online/index"; |
||||||
|
import ESBreadcrumbComponent from "./ESBreadcrumbComponent"; |
||||||
|
|
||||||
|
// 定义考试参与情况数据类型,移除 serialNumber 字段
|
||||||
|
type ExamParticipationItem = { |
||||||
|
key: string; |
||||||
|
name: string; |
||||||
|
phoneNumber: string; |
||||||
|
score: number; |
||||||
|
wrongQuestionIds: string; |
||||||
|
}; |
||||||
|
|
||||||
|
// 定义考试答题情况数据类型,移除 serialNumber 字段
|
||||||
|
type ExamAnswerItem = { |
||||||
|
key: string; |
||||||
|
questionNumber: string; |
||||||
|
wrongPeopleCount: number; |
||||||
|
wrongPeopleRatio: string; |
||||||
|
}; |
||||||
|
|
||||||
|
// 定义 API 返回的数据类型
|
||||||
|
type DetailResponse = { |
||||||
|
examParticipation: ExamParticipationItem[]; |
||||||
|
examAnswer: ExamAnswerItem[]; |
||||||
|
}; |
||||||
|
|
||||||
|
// 考试参与情况表格列定义
|
||||||
|
const examParticipationColumns: Array<{ |
||||||
|
title: string; |
||||||
|
dataIndex?: keyof ExamParticipationItem; |
||||||
|
key: string; |
||||||
|
render?: (text: any, record: ExamParticipationItem, index: number) => React.ReactNode; |
||||||
|
}> = [ |
||||||
|
{ |
||||||
|
title: '序号', |
||||||
|
key: 'serialNumber', |
||||||
|
render: (_, __, index) => index + 1 |
||||||
|
}, |
||||||
|
{ |
||||||
|
title: '姓名', |
||||||
|
dataIndex: 'name', |
||||||
|
key: 'name', |
||||||
|
}, |
||||||
|
{ |
||||||
|
title: '手机号', |
||||||
|
dataIndex: 'phoneNumber', |
||||||
|
key: 'phoneNumber', |
||||||
|
}, |
||||||
|
{ |
||||||
|
title: '成绩', |
||||||
|
dataIndex: 'score', |
||||||
|
key: 'score', |
||||||
|
}, |
||||||
|
{ |
||||||
|
title: '错题编号', |
||||||
|
dataIndex: 'wrongQuestionIds', |
||||||
|
key: 'wrongQuestionIds', |
||||||
|
render: (wrongQuestionIds)=>{ |
||||||
|
if(!wrongQuestionIds) { |
||||||
|
return "-"; |
||||||
|
}else{ |
||||||
|
return wrongQuestionIds; |
||||||
|
} |
||||||
|
} |
||||||
|
}, |
||||||
|
]; |
||||||
|
|
||||||
|
// 考试答题情况表格列定义
|
||||||
|
const examAnswerColumns: Array<{ |
||||||
|
title: string; |
||||||
|
dataIndex?: keyof ExamAnswerItem; |
||||||
|
key: string; |
||||||
|
render?: (text: any, record: ExamAnswerItem, index: number) => React.ReactNode; |
||||||
|
}> = [ |
||||||
|
{ |
||||||
|
title: '序号', |
||||||
|
key: 'serialNumber', |
||||||
|
render: (_, __, index) => index + 1 |
||||||
|
}, |
||||||
|
{ |
||||||
|
title: '题目号', |
||||||
|
dataIndex: 'questionNumber', |
||||||
|
key: 'questionNumber', |
||||||
|
}, |
||||||
|
{ |
||||||
|
title: '错题人数', |
||||||
|
dataIndex: 'wrongPeopleCount', |
||||||
|
key: 'wrongPeopleCount', |
||||||
|
}, |
||||||
|
{ |
||||||
|
title: '错题人数占比', |
||||||
|
dataIndex: 'wrongPeopleRatio', |
||||||
|
key: 'wrongPeopleRatio', |
||||||
|
render: (wrongPeopleRatio)=>{ |
||||||
|
return wrongPeopleRatio+'%' |
||||||
|
} |
||||||
|
}, |
||||||
|
]; |
||||||
|
|
||||||
|
const ExamStatisticsPage: React.FC<RouteComponentProps> = ({ history }) => { |
||||||
|
const [examParticipationData, setExamParticipationData] = useState<ExamParticipationItem[]>([]); |
||||||
|
const [examAnswerData, setExamAnswerData] = useState<ExamAnswerItem[]>([]); |
||||||
|
|
||||||
|
useEffect(() => { |
||||||
|
const fetchData = async () => { |
||||||
|
try { |
||||||
|
const examId = sessionStorage.getItem('examId'); |
||||||
|
sessionStorage.removeItem('examId'); |
||||||
|
// 调用 getDetail 方法进行初始化检索
|
||||||
|
const response = await getDetail(examId); |
||||||
|
// 从 AxiosResponse 中提取 data 部分
|
||||||
|
const data = response as DetailResponse; |
||||||
|
// 假设返回的数据结构包含 examParticipation 和 examAnswer 两个字段
|
||||||
|
setExamParticipationData(data.examParticipation); |
||||||
|
setExamAnswerData(data.examAnswer); |
||||||
|
} catch (error) { |
||||||
|
console.error('数据加载失败:', error); |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
fetchData(); |
||||||
|
}, []); |
||||||
|
|
||||||
|
return ( |
||||||
|
<div style={{ padding: 20 }}> |
||||||
|
<ESBreadcrumbComponent currentText="答题情况" /> |
||||||
|
{/* 考试参与情况部分 */} |
||||||
|
<h2>考试参与情况</h2> |
||||||
|
<Table |
||||||
|
columns={examParticipationColumns} |
||||||
|
dataSource={examParticipationData} |
||||||
|
pagination={false} |
||||||
|
/> |
||||||
|
|
||||||
|
{/* 考试答题情况部分 */} |
||||||
|
<h2 style={{ marginTop: 20 }}>考试答题情况</h2> |
||||||
|
<Table |
||||||
|
columns={examAnswerColumns} |
||||||
|
dataSource={examAnswerData} |
||||||
|
pagination={false} |
||||||
|
/> |
||||||
|
|
||||||
|
{/* 返回按钮 */} |
||||||
|
<div style={{ marginTop: 20, textAlign: 'right' }}> |
||||||
|
<Button onClick={() => history.push('/exam-schedule')}>返回</Button> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
); |
||||||
|
}; |
||||||
|
|
||||||
|
export default withRouter(ExamStatisticsPage); |
@ -0,0 +1,34 @@ |
|||||||
|
import React, { Component } from "react"; |
||||||
|
import ExamDetailPage from "./compoents/ExamDetailPage"; |
||||||
|
interface States { |
||||||
|
resData: any |
||||||
|
visible: boolean |
||||||
|
title: string |
||||||
|
current: any |
||||||
|
} |
||||||
|
|
||||||
|
class ExamDetail extends Component<any, States> { |
||||||
|
constructor(props: any) { |
||||||
|
super(props); |
||||||
|
this.state = { |
||||||
|
resData: undefined, |
||||||
|
visible: false, |
||||||
|
title: '', |
||||||
|
current: {} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
componentDidMount() { |
||||||
|
// this.getList()
|
||||||
|
} |
||||||
|
|
||||||
|
render() { |
||||||
|
return ( |
||||||
|
<div className="container"> |
||||||
|
<ExamDetailPage/> |
||||||
|
</div> |
||||||
|
) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
export default ExamDetail; |
@ -1,34 +1,107 @@ |
|||||||
import React, { Component } from "react"; |
import React, { Component } from 'react'; |
||||||
import ExamEditPage from "./compoents/ExamEditPage"; |
import ExamEditPage from "./compoents/ExamEditPage"; |
||||||
|
import { withRouter, RouteComponentProps } from 'react-router-dom'; |
||||||
|
import { getExamDataById } from "api/exam-online/index"; |
||||||
|
import { ExamBasicInfo } from './compoents/ExamEditPage'; |
||||||
|
import moment, { Moment } from 'moment'; |
||||||
|
|
||||||
|
// 定义 Params 类型
|
||||||
|
interface Params { |
||||||
|
examId: string; |
||||||
|
} |
||||||
|
|
||||||
|
// 定义 location.state 的类型
|
||||||
|
interface LocationState { |
||||||
|
data?: number; |
||||||
|
} |
||||||
|
|
||||||
|
// 定义状态类型,使用 ExamBasicInfo 接口
|
||||||
interface States { |
interface States { |
||||||
resData: any |
initialFormData: ExamBasicInfo; |
||||||
visible: boolean |
isLoading: boolean; |
||||||
title: string |
} |
||||||
current: any |
|
||||||
|
// 扩展 RouteComponentProps 以包含自定义的 location.state 类型
|
||||||
|
interface CustomRouteComponentProps extends RouteComponentProps<Params> { |
||||||
|
location: { |
||||||
|
state: LocationState; |
||||||
|
pathname: string; |
||||||
|
search: string; |
||||||
|
hash: string; |
||||||
|
}; |
||||||
} |
} |
||||||
|
|
||||||
class ExamEdit extends Component<any, States> { |
class ExamEdit extends Component<CustomRouteComponentProps, States> { |
||||||
constructor(props: any) { |
constructor(props: CustomRouteComponentProps) { |
||||||
super(props); |
super(props); |
||||||
this.state = { |
this.state = { |
||||||
resData: undefined, |
initialFormData: { |
||||||
visible: false, |
examId: '', |
||||||
title: '', |
examName: '', |
||||||
current: {} |
regulatedIndustry: '', |
||||||
|
paperId: '', |
||||||
|
examScore: '', |
||||||
|
examDuration: '', |
||||||
|
examRegion: '', |
||||||
|
validFrom: null, |
||||||
|
validTo: null, |
||||||
|
remark: '' |
||||||
|
}, |
||||||
|
isLoading: true |
||||||
|
}; |
||||||
} |
} |
||||||
|
|
||||||
|
async componentDidMount() { |
||||||
|
|
||||||
|
// 尝试从 sessionStorage 中获取 examId
|
||||||
|
const storedExamId = sessionStorage.getItem('examId'); |
||||||
|
const examId = storedExamId; |
||||||
|
if(storedExamId){ |
||||||
|
sessionStorage.removeItem('examId'); |
||||||
} |
} |
||||||
|
|
||||||
componentDidMount() { |
try { |
||||||
// this.getList()
|
const response = await getExamDataById(examId); |
||||||
|
const newInitFormData: ExamBasicInfo = { |
||||||
|
examId: response.data.examId, |
||||||
|
examName: response.data.examName, |
||||||
|
regulatedIndustry: response.data.regulatedIndustry, |
||||||
|
paperId: response.data.paperId, |
||||||
|
examScore: response.data.examScore, |
||||||
|
examDuration: response.data.examDuration, |
||||||
|
examRegion: response.data.examRegion, |
||||||
|
validFrom: response.data.validFrom ? moment(response.data.validFrom) : null, |
||||||
|
validTo: response.data.validTo ? moment(response.data.validTo) : null, |
||||||
|
remark: response.data.remark |
||||||
|
}; |
||||||
|
|
||||||
|
console.log('Received examId:', examId); |
||||||
|
|
||||||
|
this.setState({ |
||||||
|
initialFormData: newInitFormData, |
||||||
|
isLoading: false |
||||||
|
}); |
||||||
|
} catch (error) { |
||||||
|
console.error('获取考试数据失败:', error); |
||||||
|
this.setState({ |
||||||
|
isLoading: false |
||||||
|
}); |
||||||
|
} |
||||||
} |
} |
||||||
|
|
||||||
render() { |
render() { |
||||||
|
const { isLoading, initialFormData } = this.state; |
||||||
|
|
||||||
|
if (isLoading) { |
||||||
|
return <div>加载中...</div>; |
||||||
|
} |
||||||
|
|
||||||
return ( |
return ( |
||||||
<div className="container"> |
<div className="container"> |
||||||
<ExamEditPage isEdit={true}/> |
<ExamEditPage isEdit={true} initialFormData={initialFormData} /> |
||||||
</div> |
</div> |
||||||
) |
); |
||||||
} |
} |
||||||
} |
} |
||||||
|
|
||||||
export default ExamEdit; |
export default withRouter(ExamEdit); |
Loading…
Reference in new issue