2022年5月29日从svn移到git

This commit is contained in:
daihh
2022-05-29 18:56:34 +08:00
commit b050613020
488 changed files with 68444 additions and 0 deletions

View File

@@ -0,0 +1,549 @@
<template>
<div class="exam-index">
<div v-if="has" class="test-div">
<div v-if="!testStart">
<div>
<div class="test-info" v-if="content.contentName!=''">名称:{{content.contentName}}</div>
<div class="test-info">
<span >考试时长{{info.testDuration}}分钟</span>
<span style="margin-left: 20px;">及格线{{info.passLine}}</span>
<span v-if="records.length>0" style="margin-left: 20px;font-size: 18px;">您的考试成绩{{examScore}}</span>
</div>
</div>
<!-- 预览用显示试题 -->
<div v-if="showTest">
<div style="margin: 10px 0;">考试试题:</div>
<div v-for="(item,index) in viewTest" :key="index">
<div class="test-info">{{index +1}}.{{getTypeName(item.type)}}{{item.content}}</div>
<div class="test-info" style="padding-left: 20px;">
<div v-if="item.type==101 || item.type==103">
<el-radio-group v-model="item.userAnswer" size="medium">
<el-radio v-for="(opt,optIdx) in item.options" :key="optIdx" :label="opt.id">{{toLetter(optIdx+1)}}.{{opt.content}}</el-radio>
</el-radio-group>
</div>
<div v-if="item.type==102">
<el-checkbox v-for="(it,indcc) in item.options" :key="indcc" v-model="it.isCheck" :label="it.id">{{toLetter(indcc+1)}}.{{it.content}}</el-checkbox>
</div>
</div>
</div>
</div>
<!--开始考试button-->
<div v-if="showSubmit" style="text-align: center; margin-bottom: 15px">
<el-button type="primary" @click="startTest()">开始考试</el-button>
</div>
<!--考试记录-->
<div v-if="showRecord">
<el-table :data="records" style="width: 100%" border>
<el-table-column prop="lastTime" label="完成时间" align="center" ></el-table-column>
<el-table-column prop="testDuration" label="用时" align="center">
<template slot-scope="scope">{{formatSeconds(scope.row.testDuration)}}</template>
</el-table-column>
<el-table-column prop="score" label="成绩" align="center"></el-table-column>
<el-table-column label="操作" width="100" align="center">
<template slot-scope="scope">
<el-button @click="showExamAnswer(scope.row)" type="text" >查看试卷</el-button>
</template>
</el-table-column>
</el-table>
</div>
</div>
<div v-else>
<!--考试部分-->
<div>
<div style="display: flex;justify-content: space-between;padding: 10px 0px;">
<div style="font-size: 18px;">{{curIndex+1}} / {{total}}</div>
<div style="font-size: 20px;"><span style="font-size: 40upx;" :class="{'redText':timerValue<5}">{{timerValue}}</span> 分钟</div>
</div>
<div class="qitem">
<div class="qitem-info">{{getTypeName(curItem.type)}}{{curItem.content}}</div>
<div v-for="(opt,optIdx) in curItem.options" :key="optIdx">
<div class="qitem-opts">
<div class="qitem-opt" :class="{check:opt.checked}" @click="chooseOption(opt)">
{{toLetter(optIdx+1)}}.{{opt.content}}
<i class="el-icon-check" v-if="opt.checked" name="checkbox-mark" color="#00aa00"></i>
</div>
</div>
</div>
</div>
<div style="text-align: center; margin-bottom: 15px">
<el-button :disabled="curIndex==0" type="primary" @click="prevSub()">上一题</el-button>
<el-button type="success" icon="el-icon-check" @click="present()"> </el-button>
<el-button :disabled="curIndex>=(total-1)" type="primary" @click="nextSub()">下一题</el-button>
</div>
</div>
</div>
</div>
<div v-else style="text-align: center;padding-top: 20px;color: red;">此课程无考试内容</div>
<el-dialog :visible.sync="detailShow" title="查询答卷详细信息" width="800px" custom-class="g-dialog">
<div style="text-align: left;" class="upaper">
<!--答卷信息-->
<div v-for="(ditem,didx) in detailItems" :key="didx" class="upaper-item">
<div class="upaper-item-q">{{didx +1}}.{{getTypeName(ditem.type)}}{{ditem.content}}</div>
<div class="upaper-item-opts" style="padding-left: 20px;">
<div v-for="(opt,optIdx) in ditem.options" :key="optIdx" class="upaper-item-opt" :class="{'upaper-item-opt-user':ditem.userOptIdxs.indexOf(optIdx)>-1}">
<div>
<div>{{toLetter(optIdx+1)}}, {{opt.content}}</div>
</div>
<div>
<span v-if="ditem.userOptIdxs.indexOf(optIdx)>-1 && ditem.correctOptIdxs.indexOf(optIdx)>-1" style="color: #00aa00;font-size: 25px; "></span>
<span v-if="ditem.userOptIdxs.indexOf(optIdx)>-1 && ditem.correctOptIdxs.indexOf(optIdx)==-1" style="color: #ff0000;font-size: 25px; ">×</span>
</div>
</div>
</div>
<div class="upaper-item-answer" style="display: flex;">
<div class="upaper-item-answer-cell">
<span v-if="ditem.result" style="color: #00aa00; ">回答正确</span>
<span v-else style="color: #ff0000; ">回答错误</span>
</div>
<div class="upaper-item-answer-cell">
<span class="response-tit">正确答案</span>
<span v-for="op in ditem.correctOptIdxs" :key="op">{{toLetter(op+1)}}</span>
</div>
<div class="upaper-item-answer-cell">
<span class="response-tit">我的答案</span>
<span v-for="op in ditem.userOptIdxs" :key="op">{{toLetter(op+1)}}</span>
</div>
</div>
</div>
</div>
<span slot="footer" class="dialog-footer">
<el-button type="primary" @click="detailShow = false"> </el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import apiStudy from '@/api/modules/courseStudy.js';
import apiCourse from '@/api/modules/course.js';
import {formatDate,formatSeconds} from '@/utils/datetime.js';
import {testType,correctJudgment,numberToLetter} from '@/utils/tools.js';
export default {
props:{
studyId: {
type: String,
},
showRecord:{
type:Boolean,
default:true
},
showSubmit:{
type:Boolean,
default:true
},
content: {
type: Object,
default:()=>{}
},
showTest:{
type:Boolean,
default:false
}
},
data() {
return {
viewTest:[],
correctJudgment:correctJudgment,
toLetter:numberToLetter,
formatSeconds:formatSeconds,
examScore:0,//考试得分
show:0,
getTypeName:testType,
has:true,
startTime:null,//开始考试的时间,可以去掉
testStart: false,//是否开始考试
info:{},//考试信息
paper:[],//试卷信息
studyItemId:'',
total:0,//总试题的数量
curIndex:0,//当前视频的索引
curItem:{},//当前试题
timer:null,//用于计算倒计时控制
lastScore:0,//最终得分,用于考试试卷记录
timerValue:0,//当前倒计时的值
noAnswers:[], //有未答完的试题
records:[] ,//考试记录
allowSubmit:true,//是否允许考试,尝试次数达到后不能再考试,暂时未使用
detailShow:false,
detailItems:[]
};
},
mounted() {
this.loadExamInfo();
},
watch:{
content(newVal){
this.loadExamInfo();
}
},
methods: {
changeTimer(){
if(this.timerValue==0){
window.clearInterval(this.timer);
//系统自动提交
this.confirmStop();
}else{
this.timerValue--;
}
},
loadExamInfo(){
apiCourse.getExam(this.content.id).then(res=>{
if(res.status==200){
this.info=res.result;
if(this.showTest) {
let paper= JSON.parse(this.info.paperContent);
paper.items.forEach(item=>{
//console.log(item);
if(item.type==101){
item.userAnswer='';
}else if(item.type==102){
item.userAnswer=[];
}else{
item.userAnswer=''
}
item.options.forEach(opt=>{
opt.checked=false;
})
});
this.total=paper.items.length;
this.paper =paper;
//console.log(this.paper);
this.viewTest =paper.items;
}
if(!this.showTest && this.showRecord){
this.loadStudyItemId();
this.loadRecord();
}
}else if(res.status==404){
//没有找到考试信息
}else{
this.$message.error(res.message);
}
})
},
loadStudyItemId(){
//获取studyItemId;
apiStudy.getStudyContentItem(this.studyId,this.info.contentId).then(rs=>{
if(rs.status==200){
this.examScore=rs.result.score;
this.studyItemId=rs.result.id;
}
})
},
loadRecord(){
if(this.records.length==0){
let params={
studyId:this.studyId,
contentId:this.content.id
}
apiStudy.myExamList2(params).then(examRs=>{
if(examRs.status==200){
this.records=examRs.result;
let len=examRs.result.length;
if(this.info.times>len){
this.allowSubmit=true;
}else{
this.allowSubmit=false;
}
}
})
}
},
startTest(){
let paper= JSON.parse(this.info.paperContent);
paper.items.forEach(item=>{
//console.log(item);
if(item.type==101){
item.userAnswer='';
}else if(item.type==102){
item.userAnswer=[];
}else{
item.userAnswer=''
}
item.options.forEach(opt=>{
opt.checked=false;
})
});
this.total=paper.items.length;
this.paper =paper;
//console.log(this.paper);
this.curItem=paper.items[this.curIndex];
this.startTime=new Date();//记录开始时间
this.timerValue=this.info.testDuration;
this.timer=setInterval(this.changeTimer,60000);
this.testStart=true;
},
chooseOption(opt){
if(this.curItem.type==101 || this.curItem.type==103){
this.curItem.options.forEach(op=>{
op.checked=false;
})
opt.checked=true;
}else{
if(opt.checked){
opt.checked=false;
}else{
opt.checked=true;
}
}
},
confirmStop(){
this.$alert('考试时间已到,点击确定提交试卷', '提示', {
confirmButtonText: '确定',
showClose:false,
callback: action => {
this.submitTest();
}
});
},
prevSub(){ //上一题
if(this.curIndex==0){
return;
}
this.curIndex--;
if(this.curIndex>-1){
this.curItem=this.paper.items[this.curIndex];
}
},
nextSub() { //下一题
if(this.curIndex>=(this.total-1)){
return;
}
this.curIndex++;
this.curItem=this.paper.items[this.curIndex];
},
present(){ //提交前处理
let $this=this;
let score=this.countTest();
if(this.noAnswers.length>0){
this.$confirm('还有未答试题,您确定要提交吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
showClose:false,
type: 'warning'
}).then(() => {
this.submitTest()
}).catch(()=>{
})
}else{
this.submitTest()
}
},
countTest(){ //计算考试的分数
//console.log(this.paper.items);
let totalScore=0;
this.paper.items.forEach(item => {
totalScore+=item.score;//加到总分中
if(item.type != 102){
item.userAnswer='';
item.options.forEach(opt => {
if(opt.checked){
item.userAnswer=opt.id;
}
});
}else{
item.userAnswer=[];
item.options.forEach(opt => {
if(opt.checked){
item.userAnswer.push(opt.id);
}
});
}
});
let scoreNum = 0;//用户得分
let noAnswers=[];//是否都已答
this.paper.items.forEach((item,idx) => {
if(item.type != 102){
if(item.userAnswer==''){
noAnswers.push(idx+1);
}
item.options.forEach(it => {
if(it.answer && item.userAnswer == it.id) {
scoreNum+=item.score
}
})
}else{
if(item.userAnswer.length==0){
noAnswers.push(idx+1);
}
let allRight = true;
item.options.forEach(it =>{
if(it.answer && item.userAnswer.indexOf(it.id)==-1) {
allRight=false;
}
});
if(allRight){
scoreNum+=item.score;
}
}
})
this.noAnswers=noAnswers;
if(scoreNum === null)scoreNum=0;
this.lastScore=scoreNum;
//转化成百分制显示
if(this.info.percentScore){
this.lastScore=parseInt(scoreNum*100/totalScore);
}
return this.lastScore;
},
submitTest(){ //提交处理
let now=new Date();
let testScore=this.countTest();
let postData={
studyId:this.studyId,//
studyItemId:this.studyItemId,//前面已经给了
courseId:this.content.courseId,
contentId:this.content.id,
testId:this.info.id,
testName:''+this.content.contentName,//应该是课程的名称 + 内容的名称
testDuration:0,
arrange:this.info.arrange,
passLine:this.info.passLine,
randomMode:this.info.randomMode,
score:this.lastScore,//分数需要计算,在检查是否填写完整性时就可以计算出分数
paperJson:JSON.stringify(this.paper),//原来是对象,这里要也要对象
//startTime:formatDate(this.startTime),//此时间需要格式化,格式化时间可以放在util中
//endTime:formatDate(now),
}
//计划考试的时长
var dateDiff = now.getTime() - this.startTime.getTime();//时间差的毫秒数
var minutes=Math.floor(dateDiff/(1000))//计算相差秒数分钟记录的太大经常为0
postData.testDuration=minutes;
apiStudy.saveExam(postData).then(res=>{
if(res.status == 200) {
this.records.push(res.result);
this.content.status=9;//表已学习完,判断上级的章是否已完成
this.studyItemId=res.result.studyItemId;//第一次保存时是没有的,所以这里要赋值
this.$alert('您本次考试得分:'+this.lastScore, '考试成绩', {
confirmButtonText: '确定',
callback: action => {
this.testStart = false;
}
});
this.testStart = false;
this.$emit('submit',this.lastScore);//考试提交回调处理
} else {
this.$message.error(res.message);
}
})
},
showExamAnswer(item){
//显示试卷的答卷信息
this.detailShow=true;
apiStudy.myExamPaper(item.id).then(rs=>{
if(rs.status==200){
let items=JSON.parse(rs.result.paper).items
items.forEach((item)=>{
item.correctOptIdxs=[];
item.userOptIdxs=[];
item.result=true;
//对答案进行判断
item.options.forEach((opt,idx)=>{
//填充正确答案
if(opt.answer){
item.correctOptIdxs.push(idx);
}
if(item.type!=102){ //单选或判断
if(opt.id==item.userAnswer){
item.userOptIdxs.push(idx);
}
}else{ //多选
if(item.userAnswer.indexOf(opt.id)>-1){
item.userOptIdxs.push(idx);
}
}
});
//判断答案是否正确
if(item.correctOptIdxs.toString()==item.userOptIdxs.toString()){
item.result=true;
}else{
item.result=false;
}
});
this.detailItems=items;
}
});
},
}
}
</script>
<style scoped lang="scss">
.qitem {
padding: 10px 20px;
.qitem-info {
font-size: 1.2em;
padding: 10px 0px;
}
.qitem-opts {
padding: 5px 0px;
.qitem-opt {
cursor: pointer;
display: flex;
margin-bottom: 10px;
padding: 10px 15px;
background-color: #FFFFFF;
border-radius: 6px;
}
.check{
color:#00aa00;
}
}
}
.upaper{
text-align: left;
.upaper-item{
border-bottom: 1px solid #dadada;
padding: 10px;
.upaper-item-q{
padding: 8px 0px;
}
.upaper-item-opts{
padding: 8px 0px;
line-height: 20px;
.upaper-item-opt{
min-height: 50px;
border-radius: 4px;
display: flex;
background-color: #FFFFFF;
justify-content: space-between;
padding: 10px 20px;
}
.upaper-item-opt-user{
background-color: #fff3e5;
}
}
.upaper-item-answer{
display: flex;
.upaper-item-answer-cell{
margin-right: 20px;
}
}
}
}
.test-div {
border: 1px solid #dadada;
min-height: 500px;
padding: 20px;
font-size: 14px;
text-align: left;
.test-info {
text-align: left;
margin-bottom: 10px;
}
}
</style>