diff --git a/packages/examination/src/api/exam-online/index.tsx b/packages/examination/src/api/exam-online/index.tsx
index dd9682c..60fcad8 100644
--- a/packages/examination/src/api/exam-online/index.tsx
+++ b/packages/examination/src/api/exam-online/index.tsx
@@ -108,4 +108,37 @@ export const getExamDetailAnalysisPageList = async (obj:any) => {
export const getPaperAnalysisData = async () => {
const response = await axios.get('/ex/exam-statistics/getPaperAnalysisData');
return response.data;
+};
+
+export const getExamPaperAnalysisPageList = async (obj:any) => {
+ const response = await axios.get('/ex/exam-statistics/getExamPaperAnalysisPageList',{
+ params:obj
+ });
+ return response.data;
+};
+
+// api.ts
+// 模拟获取试卷名称的接口
+export const getPaperName = async (id:string|null) => {
+ const response = await axios.get('/ex/exam-statistics/getPaperName',{
+ params: {id:id}
+ });
+ return response.data;
+};
+
+// 模拟获取题目准确率数据的接口
+export const getQuestionAccuracyData = async (id:string|null) => {
+ const response = await axios.get('/ex/exam-statistics/getQuestionAccuracyData',{
+ params: {id:id}
+ });
+ return response.data;
+};
+
+// 模拟获取题目准确率数据的接口
+export const getQuestions = async (id:string|null) => {
+ // 这里可以替换为实际的 API 请求
+ const response = await axios.get('/ex/exam-statistics/getQuestions',{
+ params: {id:id}
+ });
+ return response.data;
};
\ No newline at end of file
diff --git a/packages/examination/src/components/contentMain/index.js b/packages/examination/src/components/contentMain/index.js
index b0ce1b9..98f6d0f 100644
--- a/packages/examination/src/components/contentMain/index.js
+++ b/packages/examination/src/components/contentMain/index.js
@@ -35,6 +35,7 @@ import ExamPaperList from 'views/examPaper/examPaperList';
import ExamDetailAnalysis from "../../views/exam-online/exam-detail-analysis";
import ExamPaperAnalysis from "../../views/exam-online/exam-paper-analysis";
import ExamPaperAdd from 'views/examPaper/examPaperAdd';
+import ExamPaperAnalysisDetail from "../../views/exam-online/exam_paper_analysis_detail";
class ContentMain extends Component {
@@ -60,6 +61,7 @@ class ContentMain extends Component {
+
diff --git a/packages/examination/src/views/exam-online/compoents/ExamDetailAnalysisPage.tsx b/packages/examination/src/views/exam-online/compoents/ExamDetailAnalysisPage.tsx
index 5ab1621..c9c05eb 100644
--- a/packages/examination/src/views/exam-online/compoents/ExamDetailAnalysisPage.tsx
+++ b/packages/examination/src/views/exam-online/compoents/ExamDetailAnalysisPage.tsx
@@ -3,6 +3,7 @@ import { Row, Col, Input, Select, Button, Table, Space, Cascader, Modal } from '
import ReactECharts from 'echarts-for-react';
import {getExamDetailAnalysisPageList, getIndustryList, getScoreDistribution} from 'api/exam-online/index';
import { convertToCascaderData } from "./ExamEditPage";
+import ESBreadcrumbComponent from "./ESBreadcrumbComponent";
const { Option } = Select;
@@ -166,6 +167,7 @@ const ExamDetailAnalysisPage: React.FC = () => {
return (
+
{/* 检索条件行 */}
diff --git a/packages/examination/src/views/exam-online/compoents/ExamPaperAnalysisDetailPage.tsx b/packages/examination/src/views/exam-online/compoents/ExamPaperAnalysisDetailPage.tsx
new file mode 100644
index 0000000..252bceb
--- /dev/null
+++ b/packages/examination/src/views/exam-online/compoents/ExamPaperAnalysisDetailPage.tsx
@@ -0,0 +1,144 @@
+import React, { useState, useEffect } from 'react';
+import {Row, Col, Typography, Button} from 'antd';
+import ReactECharts from 'echarts-for-react';
+import QuestionComponent from './QuestionComponent';
+import { getPaperName, getQuestionAccuracyData, getQuestions } from 'api/exam-online/index';
+import { withRouter, RouteComponentProps } from 'react-router-dom'; // 引入 withRouter 和 RouteComponentProps
+import { SingleQuestionProps } from './QuestionComponent';
+import ESBreadcrumbComponent from "./ESBreadcrumbComponent";
+
+const { Title } = Typography;
+
+// 接口返回的数据结构,包含准确率和数量(这里数量每个都是 1)
+interface QuestionAccuracyItem {
+ accuracy: number;
+ count: number;
+}
+
+interface PaperData {
+ paperName: string;
+ questionAccuracyData: QuestionAccuracyItem[];
+}
+
+const ExamPaperAnalysisDetailPage: React.FC = ({history}) => {
+ const [paperData, setPaperData] = useState(null);
+ const [tableData, setTableData] = useState([]);
+
+ useEffect(() => {
+ const fetchData = async () => {
+ try {
+ const id = sessionStorage.getItem("paperId");
+ sessionStorage.removeItem("paperId");
+ const paperName = await getPaperName(id);
+ const questionAccuracyData = await getQuestionAccuracyData(id);
+ setPaperData({ paperName, questionAccuracyData });
+ const questions = await getQuestions(id);
+ setTableData(questions);
+ } catch (error) {
+ console.error('数据获取失败:', error);
+ }
+ };
+
+ fetchData();
+ }, []);
+ const handleGoBack = () => {
+ history.push("/exam-paper-analysis");
+ };
+
+
+ const getBarChartOption = (data: QuestionAccuracyItem[]) => {
+ // 初始化每个区间的题目数量
+ const countGroupedData = [0, 0, 0, 0];
+ let totalCount = 0;
+
+ // 统计每个区间的题目数量和总数量
+ data.forEach(item => {
+ if (item.accuracy < 0.1) {
+ countGroupedData[0] += item.count;
+ } else if (item.accuracy >= 0.1 && item.accuracy < 0.6) {
+ countGroupedData[1] += item.count;
+ } else if (item.accuracy >= 0.6 && item.accuracy < 0.8) {
+ countGroupedData[2] += item.count;
+ } else if (item.accuracy >= 0.8) {
+ countGroupedData[3] += item.count;
+ }
+ totalCount += item.count;
+ });
+
+ // 计算每个区间的百分比
+ const groupedData = countGroupedData.map(count => totalCount > 0 ? count / totalCount : 0);
+
+ return {
+ tooltip: {
+ trigger: 'axis',
+ axisPointer: {
+ type: 'shadow',
+ },
+ // 修改 formatter 函数,将数值转换为百分比形式
+ formatter: (params: any) => {
+ const xAxisValue = params[0].name;
+ const yAxisValue = (params[0].value * 100).toFixed(2) + '%';
+ return `${xAxisValue}
试题数量占比: ${yAxisValue}`;
+ },
+ },
+ xAxis: {
+ type: 'category',
+ data: ['<10%', '10%-60%', '60%-80%', '80%-100%'],
+ },
+ yAxis: {
+ type: 'value',
+ min: 0,
+ max: 1,
+ interval: 0.2,
+ axisLabel: {
+ formatter: (value: number) => `${value * 100}%`,
+ },
+ name: '试题数量占比',
+ nameLocation: 'top',
+ nameRotate: 0, // 让名称水平显示
+ nameGap: 0, // 调整名称与坐标轴的间距
+ nameTextStyle: {
+ padding: [0, 40, 100, 0] // 给名称上方增加一些内边距,使其更靠上
+ }
+ },
+ series: [
+ {
+ data: groupedData,
+ type: 'bar',
+ },
+ ],
+ };
+ };
+
+ return (
+
+
+ {paperData && (
+ <>
+ {/* 第一行:试卷名称 */}
+
+
+ 试卷名称:{paperData.paperName}
+
+
+
+ {/* 第二行:QuestionComponent 标签 */}
+
+
+
+
+
+ {/* 第三行:柱状图 */}
+
+
+ 准确率分析
+
+
+
+ >
+ )}
+
+ );
+};
+
+export default withRouter(ExamPaperAnalysisDetailPage);
\ No newline at end of file
diff --git a/packages/examination/src/views/exam-online/compoents/ExamPaperAnalysisPage.tsx b/packages/examination/src/views/exam-online/compoents/ExamPaperAnalysisPage.tsx
index 31e9fc2..f128141 100644
--- a/packages/examination/src/views/exam-online/compoents/ExamPaperAnalysisPage.tsx
+++ b/packages/examination/src/views/exam-online/compoents/ExamPaperAnalysisPage.tsx
@@ -1,11 +1,17 @@
import React, { useState, useEffect } from 'react';
import { Row, Col, Input, Select, Button, Table, Space } from 'antd';
-import { getIndustryList, getPaperAnalysisData } from 'api/exam-online/index'; // 假设的接口导入
+import { withRouter, RouteComponentProps } from 'react-router-dom'; // 引入 withRouter 和 RouteComponentProps
+import {
+ getExamPaperAnalysisPageList,
+ getIndustryList,
+ getPaperAnalysisData, getScoreDistribution
+} from 'api/exam-online/index';
+import ESBreadcrumbComponent from "./ESBreadcrumbComponent"; // 假设的接口导入
const { Option } = Select;
// 定义表格数据项的类型
-type PaperAnalysisDataItem = {
+export type PaperAnalysisDataItem = {
key: string;
paperId: string;
paperName: string;
@@ -15,38 +21,15 @@ type PaperAnalysisDataItem = {
accuracyRate: string;
};
-// 模拟数据
-const mockData: PaperAnalysisDataItem[] = [
- {
- key: '1',
- paperId: 'paper1',
- paperName: '试卷1',
- industry: '行业1',
- useCount: 20,
- participantCount: 100,
- accuracyRate: '80%',
- },
- {
- key: '2',
- paperId: 'paper2',
- paperName: '试卷2',
- industry: '行业2',
- useCount: 30,
- participantCount: 150,
- accuracyRate: '90%',
- },
- // 可以添加更多模拟数据
-];
-
-const ExamPaperAnalysisPage: React.FC = () => {
+const ExamPaperAnalysisPage: React.FC = ({history}) => {
const [paperName, setPaperName] = useState('');
const [industry, setIndustry] = useState('');
const [industryOptions, setIndustryOptions] = useState<{ value: string; label: string }[]>([]);
- const [tableData, setTableData] = useState(mockData);
+ const [tableData, setTableData] = useState([]);
const [pagination, setPagination] = useState({
current: 1,
pageSize: 10,
- total: mockData.length,
+ total: tableData.length,
});
const [totalCount, setTotalCount] = useState(0);
const [usedCount, setUsedCount] = useState(0);
@@ -72,27 +55,42 @@ const ExamPaperAnalysisPage: React.FC = () => {
const handleReset = () => {
setPaperName('');
setIndustry('');
- setTableData(mockData);
+ setTableData(tableData);
setPagination({
...pagination,
current: 1,
});
};
+ const handleShowScoreDistribution = async (paperId: string) => {
+ try {
+ // const response = await getScoreDistribution(paperId);
+ sessionStorage.setItem("paperId",paperId)
+ history.push("/exam_paper_analysis_detail");
+ } catch (error) {
+ console.error('获取成绩分布数据失败:', error);
+ }
+ };
+
const handleSearch = () => {
- // 这里可以添加实际的筛选逻辑
- const filteredData = mockData.filter((item) => {
- return (
- item.paperName.includes(paperName) &&
- (industry === '' || item.industry === industry)
- );
- });
- setTableData(filteredData);
- setPagination({
- ...pagination,
- current: 1,
- total: filteredData.length,
- });
+ const param = {
+ paperName:paperName,
+ industry:industry,
+ }
+ const fetchData = async () => {
+ try {
+ const resultData = await getExamPaperAnalysisPageList(param)
+ setTableData(resultData);
+ setPagination({
+ ...pagination,
+ current: 1,
+ total: resultData.length,
+ });
+ } catch (error) {
+ console.error('数据获取失败:', error);
+ }
+ };
+ fetchData();
};
const handleTableChange = (newPagination: any) => {
@@ -124,21 +122,24 @@ const ExamPaperAnalysisPage: React.FC = () => {
{
title: '准确率',
dataIndex: 'accuracyRate',
+ render: (text:any, record: PaperAnalysisDataItem) =>{
+ if(record.accuracyRate){
+ return record.accuracyRate+"%";
+ }else{
+ return "";
+ }
+ }
},
{
title: '查看',
dataIndex: 'view',
- render: (text:any, record: PaperAnalysisDataItem) => 详情,
- },
- {
- title: 'paperId',
- dataIndex: 'paperId',
- visible: false, // 隐藏列
+ render: (text:any, record: PaperAnalysisDataItem) => {handleShowScoreDistribution(record.paperId)}}>题目正确率分析,
},
];
return (
+
{/* 检索条件行 */}
@@ -211,4 +212,4 @@ const ExamPaperAnalysisPage: React.FC = () => {
);
};
-export default ExamPaperAnalysisPage;
\ No newline at end of file
+export default withRouter(ExamPaperAnalysisPage);
\ No newline at end of file
diff --git a/packages/examination/src/views/exam-online/compoents/QuestionComponent.tsx b/packages/examination/src/views/exam-online/compoents/QuestionComponent.tsx
new file mode 100644
index 0000000..a92ddc9
--- /dev/null
+++ b/packages/examination/src/views/exam-online/compoents/QuestionComponent.tsx
@@ -0,0 +1,76 @@
+import React from 'react';
+
+// 定义单条题目的 props 类型
+export interface SingleQuestionProps {
+ question_types: number; // 题目类型,1 为单选,2 为多选
+ question_content: string; // 题干
+ answer: string; // 答案
+ options: string; // 答题选项
+ question_number: number; // 题目编号
+ accuracyRate: number; // 准确率
+}
+
+// 定义组件接收的参数类型,为单条题目 props 的数组
+interface QuestionProps {
+ questions: SingleQuestionProps[];
+ style?: React.CSSProperties; // 用于外部传入样式,控制组件范围大小
+}
+
+const QuestionComponent: React.FC = ({ questions, style }) => {
+ return (
+
+
试题详情
+ {questions.map((question, index) => {
+ const { question_types, question_content, answer, options, question_number, accuracyRate } = question;
+
+ // 处理 answer 为空的情况
+ const answerArray = answer ? answer.split(',') : [];
+ // 处理 options 为空的情况
+ const optionArray = options ? options.split(',') : [];
+
+ // 根据题目类型判断是单选还是多选
+ const isSingleChoice = question_types === 1;
+
+ // 生成选项字母列表(A, B, C...)
+ const optionLetters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
+
+ return (
+
+ );
+ })}
+
+ );
+};
+
+export default QuestionComponent;
\ No newline at end of file
diff --git a/packages/examination/src/views/exam-online/exam_paper_analysis_detail.tsx b/packages/examination/src/views/exam-online/exam_paper_analysis_detail.tsx
new file mode 100644
index 0000000..a046c85
--- /dev/null
+++ b/packages/examination/src/views/exam-online/exam_paper_analysis_detail.tsx
@@ -0,0 +1,57 @@
+import React from 'react';
+import QuestionComponent from './compoents/QuestionComponent';
+import ExamPaperAnalysisDetailPage from "./compoents/ExamPaperAnalysisDetailPage";
+
+const ExamPaperAnalysisDetail: React.FC = () => {
+ const questions = [
+ {
+ question_types: 1,
+ question_content: '一天有多少小时?',
+ answer: 'B',
+ options: 'A:12小时,B:24小时,C:36小时',
+ question_number: 1,
+ accuracyRate: '90%'
+ },
+ {
+ question_types: 2,
+ question_content: '以下哪些是水果?',
+ answer: 'A,C',
+ options: 'A:苹果,B:黄瓜,C:香蕉',
+ question_number: 2,
+ accuracyRate: '80%'
+ },
+ {
+ question_types: 2,
+ question_content: '以下哪些是水果?',
+ answer: 'A,C',
+ options: 'A:苹果,B:黄瓜,C:香蕉',
+ question_number: 2,
+ accuracyRate: '80%'
+ },
+ {
+ question_types: 2,
+ question_content: '以下哪些是水果?',
+ answer: 'A,C',
+ options: 'A:苹果,B:黄瓜,C:香蕉',
+ question_number: 2,
+ accuracyRate: '80%'
+ },
+ {
+ question_types: 2,
+ question_content: '以下哪些是水果?',
+ answer: 'A,C',
+ options: 'A:苹果,B:黄瓜,C:香蕉',
+ question_number: 2,
+ accuracyRate: '80%'
+ }
+ ];
+
+ return (
+
+
+
+ );
+};
+
+export default ExamPaperAnalysisDetail;
\ No newline at end of file