Merge branch 'master' of https://gitea.xn--7p0a.site/2312072104/dm
This commit is contained in:
commit
edba86ccea
|
@ -11,7 +11,6 @@
|
||||||
|
|
||||||
.test-analyse{
|
.test-analyse{
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 400px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.test-analyse li{
|
.test-analyse li{
|
||||||
|
|
|
@ -1,17 +1,48 @@
|
||||||
import Computer from '../../Home/img/computer.jpg'
|
import Computer from '../../Home/img/computer.jpg'
|
||||||
import React,{ useState } from 'react';
|
import React,{ useState,useEffect } from 'react';
|
||||||
import '../Analyse/AnalysePages.css'
|
import '../Analyse/AnalysePages.css'
|
||||||
import { Pie } from 'react-chartjs-2';
|
import { Pie } from 'react-chartjs-2';
|
||||||
import 'chart.js/auto';
|
import 'chart.js/auto';
|
||||||
|
import axios from 'axios';
|
||||||
|
|
||||||
|
|
||||||
// 首页 学习分析
|
// 首页 学习分析
|
||||||
function SubjectPage(){
|
function SubjectPage(){
|
||||||
|
const student_ID=localStorage.getItem('islogin')
|
||||||
//点击li弹出图像窗口
|
//点击li弹出图像窗口
|
||||||
const [SubjectModal,setSubjectModal] = useState(false);
|
const [SubjectModal,setSubjectModal] = useState(false);
|
||||||
|
|
||||||
const handleSubjectClick = () => {
|
//表视图数据
|
||||||
|
const [PieData,setPieData]=useState({})
|
||||||
|
const [PieOptions,setPieOptions]=useState({})
|
||||||
|
//题目总分
|
||||||
|
const [score,setscore]=useState()
|
||||||
|
|
||||||
|
const handleSubjectClick = (key) => {
|
||||||
setSubjectModal(!SubjectModal)
|
setSubjectModal(!SubjectModal)
|
||||||
|
|
||||||
|
//计算总分
|
||||||
|
setscore((JSON.parse(HistoryTrain[key][1][0]).length+JSON.parse(HistoryTrain[key][1][1]).length+JSON.parse(HistoryTrain[key][1][2]).length)*5+40)
|
||||||
|
|
||||||
|
setPieData({labels: ['实训题','基础题'],
|
||||||
|
datasets: [
|
||||||
|
{
|
||||||
|
label: '得分情况分布',
|
||||||
|
data: [HistoryTrain[key][0][4],HistoryTrain[key][0][5]], // 这里填写每个类型题目的数量
|
||||||
|
backgroundColor: ['#FF6384','#36A2EB'], // 颜色
|
||||||
|
hoverOffset: 2,
|
||||||
|
},
|
||||||
|
]})
|
||||||
|
|
||||||
|
setPieOptions({plugins: {
|
||||||
|
legend: {
|
||||||
|
position: 'top',
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
display: true,
|
||||||
|
text: '得分情况分布',
|
||||||
|
},
|
||||||
|
},})
|
||||||
}
|
}
|
||||||
// 处理弹窗关闭的函数
|
// 处理弹窗关闭的函数
|
||||||
const handleSubjectModalClose = () => {
|
const handleSubjectModalClose = () => {
|
||||||
|
@ -19,61 +50,52 @@ function SubjectPage(){
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// 饼图数据
|
const click=()=>{
|
||||||
const pieData = {
|
console.log(score);
|
||||||
labels: ['判断题', '填空题', '简答题','实训题'],
|
}
|
||||||
datasets: [
|
|
||||||
{
|
|
||||||
label: '题目类型分布',
|
|
||||||
data: [30, 20, 10,40], // 这里填写每个类型题目的数量
|
|
||||||
backgroundColor: ['#FF6384', '#36A2EB', '#FFCE56','#a7f7b1'], // 颜色
|
|
||||||
hoverOffset: 4,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
// 饼图配置项
|
//获取历史实训记录
|
||||||
const pieOptions = {
|
const [HistoryTrain,setHisToryTrain]=useState()
|
||||||
plugins: {
|
|
||||||
legend: {
|
|
||||||
position: 'top',
|
|
||||||
},
|
|
||||||
title: {
|
|
||||||
display: true,
|
|
||||||
text: '题目类型分布',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
|
const HistoryTrainFunc=async()=>{
|
||||||
|
try{
|
||||||
|
const HistoryTrainSrc=await axios.post('/api/student/HistoryTrain',{
|
||||||
|
student_ID
|
||||||
|
})
|
||||||
|
setHisToryTrain(HistoryTrainSrc.data['HistoryTrain'])
|
||||||
|
|
||||||
|
}catch{
|
||||||
|
alert('HistoryTrainFunc出错')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
useEffect(()=>{
|
||||||
|
HistoryTrainFunc()
|
||||||
|
},[])
|
||||||
|
|
||||||
return(
|
return(
|
||||||
<div className="body-right-analyse">
|
<div className="body-right-analyse">
|
||||||
<div className='test-analyse'>
|
{HistoryTrain&&<div className='test-analyse'>
|
||||||
{/* 内容 */}
|
{/* 内容 */}
|
||||||
<ul>
|
<ul>
|
||||||
{[{class:'课程1:达梦数据库的安装',time:"关闭时间:2024-4-16 11.46",ImgSrc:Computer},
|
{Object.keys(HistoryTrain).map((key)=>(
|
||||||
{class:'课程2:web前端开发与数据库的结合',time:"关闭时间:2024-4-16 11.46",ImgSrc:Computer},
|
<li onClick={() => handleSubjectClick(key)} key={key}>
|
||||||
{class:'课程2:web前端开发与数据库的结合',time:"关闭时间:2024-4-16 11.46",ImgSrc:Computer},
|
<img src={Computer} alt="" width='35px' height='35px'/>
|
||||||
{class:'课程2:web前端开发与数据库的结合',time:"关闭时间:2024-4-16 11.46",ImgSrc:Computer},
|
<p>
|
||||||
{class:'课程2:web前端开发与数据库的结合',time:"关闭时间:2024-4-16 11.46",ImgSrc:Computer},
|
<p className='p'>{eval(HistoryTrain[key][1][11])}</p>
|
||||||
].map((item) =>
|
<span>{HistoryTrain[key][1][5]}</span>
|
||||||
<li key={item.class} onClick={handleSubjectClick}>
|
</p>
|
||||||
<img src={item.ImgSrc} alt="" width='35px' height='35px'/>
|
</li>
|
||||||
<p>
|
))}
|
||||||
<p className='p'>{item.class}</p>
|
|
||||||
<span>{item.time}</span>
|
|
||||||
</p>
|
|
||||||
</li>
|
|
||||||
)}
|
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>}
|
||||||
|
<button onClick={click}>万能的测试按钮</button>
|
||||||
<div className='right-vertical-nav'>
|
<div className='right-vertical-nav'>
|
||||||
<p>课程</p>
|
<p>课程</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li>达梦数据库</li>
|
<li>达梦数据库</li>
|
||||||
<li className='li-deep'>数据结构</li>
|
<li className='li-deep'>数据结构</li>
|
||||||
<li>python</li>
|
<li>python</li>
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -83,16 +105,16 @@ function SubjectPage(){
|
||||||
<button className='btn-test' onClick={handleSubjectModalClose}>X</button>
|
<button className='btn-test' onClick={handleSubjectModalClose}>X</button>
|
||||||
{/* 饼图组件 */}
|
{/* 饼图组件 */}
|
||||||
<div className="pie-chart-container">
|
<div className="pie-chart-container">
|
||||||
<Pie data={pieData} options={pieOptions} />
|
<Pie data={PieData} options={PieOptions} />
|
||||||
</div>
|
</div>
|
||||||
<div className='analyse-box'>
|
{HistoryTrain&&<div className='analyse-box'>
|
||||||
{/* 图表或者文字分析 */}
|
{/* 图表或者文字分析 */}
|
||||||
<ul>
|
<ul>
|
||||||
<li>总得分:</li>
|
<li>总得分:{parseInt(PieData['datasets'][0]['data'][0])+parseInt(PieData['datasets'][0]['data'][1])}/{score}</li>
|
||||||
<li>分析:</li>
|
<li>分析:{parseInt(PieData['datasets'][0]['data'][0])>parseInt(PieData['datasets'][0]['data'][1]) ? '基础题得分略低':'实训题得分略低'}</li>
|
||||||
<li>建议:</li>
|
<li>建议:{parseInt(PieData['datasets'][0]['data'][0])>parseInt(PieData['datasets'][0]['data'][1]) ? '巩固基础,稳步提升':'加强实训,手动操作'}</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
/* 第二页(实训题)的左边导航 */
|
/* 第二页(实训题)的左边导航 */
|
||||||
.nav-left-operation1{
|
.nav-left-operation1{
|
||||||
width: 215px;
|
width: 215px;
|
||||||
height: 840px;
|
height: 100%;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
box-shadow: 2px 2px 6px #d4d4d4;
|
box-shadow: 2px 2px 6px #d4d4d4;
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,6 @@
|
||||||
}
|
}
|
||||||
.nav-left-ul1{
|
.nav-left-ul1{
|
||||||
width: 175px;
|
width: 175px;
|
||||||
height: 240px;
|
|
||||||
/* border-top: 1px solid #7f7f7f; */
|
/* border-top: 1px solid #7f7f7f; */
|
||||||
position: relative;
|
position: relative;
|
||||||
border-top: 2px solid rgb(212, 212, 212);
|
border-top: 2px solid rgb(212, 212, 212);
|
||||||
|
@ -111,4 +110,22 @@
|
||||||
.body-right1-comple tr{
|
.body-right1-comple tr{
|
||||||
background-color: rgb(110, 130, 130);
|
background-color: rgb(110, 130, 130);
|
||||||
}
|
}
|
||||||
|
.countBox{
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
.countBox div{
|
||||||
|
display: flex;
|
||||||
|
flex-wrap:wrap;
|
||||||
|
width: 200px;
|
||||||
|
}
|
||||||
|
.countBox td{
|
||||||
|
width: 40px;
|
||||||
|
height: 30px;
|
||||||
|
/* background-color: rgb(136, 243, 209); */
|
||||||
|
border: 1px solid black;
|
||||||
|
text-align: center;
|
||||||
|
margin-left: 5px;
|
||||||
|
margin-top: 5px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,13 +11,15 @@ import axios from 'axios';
|
||||||
|
|
||||||
function Operation1() {
|
function Operation1() {
|
||||||
const click=()=>{
|
const click=()=>{
|
||||||
console.log(score);
|
console.log(TrainData);
|
||||||
}
|
}
|
||||||
const clear=()=>{
|
const clear=()=>{
|
||||||
localStorage.clear('choice_answers');
|
localStorage.clear('choice_answers');
|
||||||
setchoice_answer({})
|
setchoice_answer({})
|
||||||
localStorage.clear('completion_answer')
|
localStorage.clear('completion_answer')
|
||||||
setcompletion_answer({})
|
setcompletion_answer({})
|
||||||
|
localStorage.clear('judge_answer')
|
||||||
|
setjudge_answer({})
|
||||||
}
|
}
|
||||||
|
|
||||||
const { operateID } = useParams();
|
const { operateID } = useParams();
|
||||||
|
@ -31,6 +33,7 @@ function Operation1() {
|
||||||
})
|
})
|
||||||
const returnData=TrainDataSrc.data
|
const returnData=TrainDataSrc.data
|
||||||
setTrainData(returnData)
|
setTrainData(returnData)
|
||||||
|
settime(parseInt(returnData['operateID'][4]))
|
||||||
}catch{
|
}catch{
|
||||||
alert('TrainDataFunc出错')
|
alert('TrainDataFunc出错')
|
||||||
}
|
}
|
||||||
|
@ -40,14 +43,13 @@ function Operation1() {
|
||||||
TrainDataFunc()
|
TrainDataFunc()
|
||||||
},[])
|
},[])
|
||||||
//倒计时
|
//倒计时
|
||||||
const [test_data, setTestData] = useState('');
|
|
||||||
const [countdown, setCountdown] = useState(0);
|
const [countdown, setCountdown] = useState(0);
|
||||||
|
const [time,settime]=useState()
|
||||||
// 倒计时初始化
|
// 倒计时初始化
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const examDuration = 60 * 90; // 假设考试时长为1小时
|
const examDuration = 60 * time; // 假设考试时长为1小时
|
||||||
setCountdown(examDuration);
|
setCountdown(examDuration);
|
||||||
}, []);
|
}, [time]);
|
||||||
|
|
||||||
// 倒计时更新
|
// 倒计时更新
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -155,6 +157,7 @@ function Operation1() {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<div className='nav-operation1'>
|
<div className='nav-operation1'>
|
||||||
|
@ -183,15 +186,37 @@ function Operation1() {
|
||||||
<li style={{ marginTop: isSubjectDropdownOpen ? '186px' : '0' }}>实训题</li>
|
<li style={{ marginTop: isSubjectDropdownOpen ? '186px' : '0' }}>实训题</li>
|
||||||
</Link>
|
</Link>
|
||||||
</ul>
|
</ul>
|
||||||
|
<div className='countBox'>
|
||||||
|
{TrainData&&<table>
|
||||||
|
<tr>选择题:</tr>
|
||||||
|
<div>
|
||||||
|
{Object.keys(TrainData['operateID'][0]).map((key,index)=>(
|
||||||
|
<td key={key}>{index+1}</td>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
<tr>填空题:</tr>
|
||||||
|
<div>
|
||||||
|
{Object.keys(TrainData['operateID'][1]).map((key,index)=>(
|
||||||
|
<td key={key}>{index+1}</td>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
<tr>判断题:</tr>
|
||||||
|
<div>
|
||||||
|
{Object.keys(TrainData['operateID'][2]).map((key,index)=>(
|
||||||
|
<td key={key}>{index+1}</td>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</table>}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className='body-right1'>
|
<div className='body-right1'>
|
||||||
{TrainData && (
|
{TrainData && (
|
||||||
<table className='body-right1-choice'>
|
<table className='body-right1-choice'>
|
||||||
<p>选择题:</p>
|
<p>选择题:</p>
|
||||||
<tbody>
|
<tbody>
|
||||||
{Object.keys(TrainData['operateID'][0]).map((key) => (
|
{Object.keys(TrainData['operateID'][0]).map((key,index) => (
|
||||||
<tr key={key}>
|
<tr key={key}>
|
||||||
<tr style={{fontSize:'18px'}}>{TrainData['operateID'][0][key][0][1]}</tr>
|
<tr style={{fontSize:'18px'}}>({index+1}.){TrainData['operateID'][0][key][0][1]}</tr>
|
||||||
<div className='optionBox'>
|
<div className='optionBox'>
|
||||||
<label><input type="radio" value={TrainData['operateID'][0][key][0][2]} checked={choice_answer[key] === TrainData['operateID'][0][key][0][2]} onChange={handleOptionChange} name={`group${key}`}/><span>A:{TrainData['operateID'][0][key][0][2]}</span></label>
|
<label><input type="radio" value={TrainData['operateID'][0][key][0][2]} checked={choice_answer[key] === TrainData['operateID'][0][key][0][2]} onChange={handleOptionChange} name={`group${key}`}/><span>A:{TrainData['operateID'][0][key][0][2]}</span></label>
|
||||||
<br />
|
<br />
|
||||||
|
|
|
@ -136,10 +136,17 @@ def FetchTrainTitle():
|
||||||
|
|
||||||
@app.route('/api/student/TrainData',methods=['POST'])
|
@app.route('/api/student/TrainData',methods=['POST'])
|
||||||
def TrainData():
|
def TrainData():
|
||||||
examID=request.json['operateID']
|
data=request.json
|
||||||
|
examID=data['operateID']
|
||||||
result=FetchTrainTestFunc(examID)
|
result=FetchTrainTestFunc(examID)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
@app.route('/api/student/HistoryTrain',methods=['POST'])
|
||||||
|
def HistoryTrain():
|
||||||
|
ID = request.json['student_ID']
|
||||||
|
result=HistoryTrainFunc(ID)
|
||||||
|
return jsonify({'HistoryTrain': result})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# 以下为教师功能—————————————————————————————————————————————————————————————————————
|
# 以下为教师功能—————————————————————————————————————————————————————————————————————
|
||||||
|
|
|
@ -263,10 +263,27 @@ def FetchTrainTestFunc(operateID):
|
||||||
|
|
||||||
dic={'operateID':[CHOICELIST,COMPLELIST,JUDGELIST,Train,time]}
|
dic={'operateID':[CHOICELIST,COMPLELIST,JUDGELIST,Train,time]}
|
||||||
|
|
||||||
|
|
||||||
return dic
|
return dic
|
||||||
|
|
||||||
|
# FetchTrainTestFunc('6')
|
||||||
|
|
||||||
|
def HistoryTrainFunc(ID):
|
||||||
|
dic={}
|
||||||
|
cursor=db.cursor()
|
||||||
|
cursor.execute("SELECT * FROM TRAINSCORE WHERE STUDENT_ID=? AND TF='true'",(ID))
|
||||||
|
historytrain=cursor.fetchall()
|
||||||
|
|
||||||
|
for i in historytrain:
|
||||||
|
cursor.execute("SELECT * FROM TRAINTEST WHERE ID=?", (i[2]))
|
||||||
|
dic[i[2]]=i,cursor.fetchall()[0]
|
||||||
|
|
||||||
|
|
||||||
|
return dic
|
||||||
|
|
||||||
|
# HistoryTrainFunc('20240101')
|
||||||
|
|
||||||
|
|
||||||
# FetchTrainTestFunc('3')
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue