yujialong 4 weeks ago
parent da0efc51bc
commit 1b70f00dbc
  1. 15
      src/pages/achievement/info/project.vue
  2. 2
      src/pages/achievement/list/project.vue
  3. 27
      src/pages/assessment/add/index.vue
  4. 158
      src/pages/match/manage/theoryReport.vue

@ -277,7 +277,7 @@ export default {
this.errorAnalysis = res.errorAnalysis || {}
this.max = res.highestErrorRate || {}
this.min = res.minimumErrorRate || {}
this.scores = res.getFractionalSegmentNum
this.scores = res.calculateRangeCounts
this.getChart()
this.errorChart()
} catch (e) {
@ -309,7 +309,7 @@ export default {
//
show (row) {
this.$store.commit('achievement/setRow', null)
this.$router.push(`show?reportId=${row.reportId}`)
this.$router.push(`${row.paperId ? '/match/theoryReport' : 'show'}?reportId=${row.reportId}`)
},
// ()
exportData () {
@ -347,7 +347,7 @@ export default {
mallId: this.mallId,
reportIds
}
data[this.permissions ? 'assessmentId' : 'projectId'] = this.id
data[this.permissions ? 'assessmentId' : this.paperId ? 'paperId' : 'projectId'] = this.id || this.paperId
const res = await axios.post(this.api.batchExportReportsAsZip, data, {
headers: {
token: this.token
@ -446,10 +446,7 @@ export default {
util.downloadFileDirect(`活跃度.xls`, new Blob([res.data]))
},
getChart () { // 线
const data = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
for (const i in this.scores) {
data[+(i.replace('num', '')) - 1] = this.scores[i]
}
const data = this.scores
let myChart = echarts.init(document.getElementById("chart"));
myChart.setOption({
title: { text: "实验分数分布图" },
@ -462,7 +459,7 @@ export default {
// axisLabel: {
// interval: 9,
// },
data: ["0-10", "10-20", "20-30", "30-40", "40-50", "50-60", "60-70", "70-80", "80-90", "90-100"]
data: data.map(e => e.range)
},
yAxis: {
name: this.permissions ? "人数" : '成绩报告数量',
@ -470,7 +467,7 @@ export default {
minInterval: 5,
},
series: [{
data,
data: data.map(e => e.count),
type: "line",
areaStyle: {},
label: {

@ -251,7 +251,7 @@ export default {
//
entry (row) {
this.$store.commit('achievement/setReferrer', `${this.$route.path}?${qs.stringify(this.form)}&page=${this.page}`)
this.$router.push(`project?id=${row.assessmentId || row.projectId || ''}&paperId=${row.paperId || ''}&projectName=${row.projectName}&permissions=${row.permissions || 0}&mallId=${this.form.mallId}&classId=${row.classId || ''}`)
this.$router.push(`project?id=${row.assessmentId || row.projectId || ''}&paperId=${row.paperId || ''}&projectName=${row.projectName}&permissions=${this.form.permissions}&mallId=${this.form.mallId}&classId=${row.classId || ''}`)
},
handleDelete (row) { //
this.$confirm("该项目下的所有成绩报告将会删除,是否继续?", "提示", {

@ -3,7 +3,7 @@
<el-form :disabled="isDetail">
<el-card shadow="hover" class="m-b-20">
<div class="flex-between">
<el-page-header @back="goBack" :content="isDetail ? '查看' : (form.id ? '更新' : '创建') + '教学实验'"></el-page-header>
<el-page-header @back="goBack" :content="isDetail ? '查看' : (form.id ? '更新' : '创建') + '考核'"></el-page-header>
<div>
<el-button type="primary" @click="save(0)" v-show="!isDetail">{{ form.id ? "更新" : "创建" }}</el-button>
</div>
@ -30,10 +30,10 @@
<!-- 根据发布方式判断时间的显示 -->
<el-card shadow="hover" class="m-b-20">
<div>
<p class="m-b-20">实验时间</p>
<p class="m-b-20">考核时间</p>
<!-- 手动发布显示 -->
<div class="date-inputs" v-if="form.type == 1">
实验时长
考核时长
<el-input type="number" min="0" v-model.trim="duration.day" placeholder></el-input>
<el-input type="number" min="0" v-model.trim="duration.hour" placeholder></el-input>
@ -72,7 +72,7 @@
<!-- 实训项目模块 -->
<el-card shadow="hover" class="m-b-20">
<div class="flex-between m-b-20">
<span>实训项目</span>
<span>考核项目</span>
<div style="display: inline-flex;">
<div>
<el-input placeholder="请输入项目名称" prefix-icon="el-icon-search" v-model.trim="keyword" clearable></el-input>
@ -379,7 +379,6 @@ export default {
},
getProjectData () {
const curItem = this.curriculumList.find(e => e.mallId === this.form.mallId)
console.log("🚀 ~ file: index.vue:471 ~ getProjectData ~ curItem:", curItem)
let data = {
pageNum: this.page,
pageSize: this.pageSize,
@ -419,18 +418,18 @@ export default {
let day = hour * 24;
this.form.experimentDuration = `${Math.floor(timestamp / day)}d${Math.floor(timestamp % day / hour)}h${Math.floor(timestamp % day % hour / minute)}m`;
}
if (this.form.type == 1 && this.form.experimentDuration == "0d0h0m") return util.warningMsg("请填写实验时长");
if (this.form.type == 2 && this.startTime == "0000-00-00 00:00:00") return util.warningMsg("请填写实验时间");
if (this.form.type == 1 && this.form.experimentDuration == "0d0h0m") return util.warningMsg("请填写考核时长");
if (this.form.type == 2 && this.startTime == "0000-00-00 00:00:00") return util.warningMsg("请填写考核时间");
if (this.form.type == 1) {
const { day, hour, minute } = this.duration
if (String(day).includes('.')) return util.warningMsg('实验天数请填写整数')
if (day < 0) return util.warningMsg('实验天数请勿填写负数')
if (String(hour).includes('.')) return util.warningMsg('实验小时请填写整数')
if (hour < 0) return util.warningMsg('实验小时请勿填写负数')
if (String(minute).includes('.')) return util.warningMsg('实验分钟请填写整数')
if (minute < 0) return util.warningMsg('实验分钟请勿填写负数')
if (String(day).includes('.')) return util.warningMsg('考核天数请填写整数')
if (day < 0) return util.warningMsg('考核天数请勿填写负数')
if (String(hour).includes('.')) return util.warningMsg('考核小时请填写整数')
if (hour < 0) return util.warningMsg('考核小时请勿填写负数')
if (String(minute).includes('.')) return util.warningMsg('考核分钟请填写整数')
if (minute < 0) return util.warningMsg('考核分钟请勿填写负数')
}
if (!form.uuid) return util.warningMsg("请选择实训项目");
if (!form.uuid) return util.warningMsg("请选择考核项目");
const item = this.projectData.find(e => form.uuid === e.projectId || form.uuid === e.paperId)
if (item) form[item.projectId ? 'projectId' : 'paperId'] = form.uuid
if (this.form.isSpecify == 0 && this.form.isEnableCode == 1) {

@ -64,7 +64,7 @@
<div v-else class="score-wrap">
<em>{{ info.score }}</em>
<img src="@/assets/img/point.png" alt="">
<p v-if="essayExist" class="exist">部分试题待判分成绩待定</p>
<p v-if="notReview" class="exist">部分试题待判分成绩待定</p>
</div>
</li>
<li>
@ -96,14 +96,16 @@
</el-table-column>
<el-table-column prop="userTotalScore" label="得分" align="center">
<template slot-scope="scope">
<p v-if="scope.row.questionType === 'essay'" class="text-red">待评分</p>
<p v-else-if="essayExist && !scope.row.paperId" class="text-red">{{ scope.row.userTotalScore
<p v-if="scope.row.questionType === 'essay' && scope.row.scoringStatus === '未判分'" class="text-red">待评分
</p>
<p v-else-if="notReview && !scope.row.paperId" class="text-red">{{ scope.row.userTotalScore
}}部分试题待判分成绩待定</p>
<p v-else>{{ scope.row.userTotalScore }}</p>
</template>
</el-table-column>
<el-table-column prop="scoreRatePercentage" label="得分率" align="center">
<template slot-scope="scope">{{ scope.row.questionType === 'essay' ? '-' : scope.row.scoreRatePercentage
<template slot-scope="scope">{{ scope.row.questionType === 'essay' && scope.row.scoringStatus === '未判分'
? '-' : scope.row.scoreRatePercentage
}}</template>
</el-table-column>
</el-table>
@ -127,16 +129,18 @@
<el-tag class="m-r-5" :type="ques.difficultTheme">{{ ques.difficult }}</el-tag>
<div class="stem html-parse" :id="'stem' + ques.id" v-html="ques.stem"></div>
<p>{{ ques.questionScore }}</p>
<p v-if="!ques.notScored">{{ ques.questionScore }}</p>
</div>
<div
v-if="item.questionType !== 'fill_blank' && item.questionType !== 'essay' && ques.questionAnswerVersionsList"
class="m-b-10">
<div v-for="(opt, j) in ques.questionAnswerVersionsList" :key="j" class="opt">
<img v-if="opt.optCorrect === 1" src="@/assets/img/right.svg" alt="" class="icon">
<img v-else-if="!opt.optCorrect" src="@/assets/img/wrong.svg" alt="" class="icon">
<span v-else class="icon not-ans"></span>
<template v-if="!ques.notScored">
<img v-if="opt.optCorrect === 1" src="@/assets/img/right.svg" alt="" class="icon">
<img v-else-if="!opt.optCorrect" src="@/assets/img/wrong.svg" alt="" class="icon">
<span v-else class="icon not-ans"></span>
</template>
<span>{{ numToLetter(j) }}.&nbsp;</span>
<div class="text html-parse" v-html="opt.optionText"></div>
@ -156,37 +160,46 @@
</template>
<div v-if="ques.knowledgePointList && ques.knowledgePointList.length" class="m-b-10">
<span>知识点</span>
<span class="line-label">知识点</span>
<el-tag v-for="(kp, k) in ques.knowledgePointList" :key="k" class="m-r-5" type="info">{{ kp.name
}}</el-tag>
</div>
<div class="flex m-b-10">
<span>解析</span>
<span class="line-label">解析</span>
<div
v-if="ques.questionAnswerVersionsList.length && ques.questionAnswerVersionsList[0].answerAnalysis"
v-html="ques.questionAnswerVersionsList[0].answerAnalysis" class="html-parse"></div>
<div v-else>暂无解析</div>
</div>
<div :class="['ques-info', { essay: item.questionType === 'essay' }]">
<div
:class="['ques-info', { essay: item.questionType === 'essay' && ques.scoringStatus === '未判分' && !ques.notScored }]">
<!-- 主观题 -->
<template v-if="item.questionType === 'essay'">
<div class="line">
<span class="line-label">参考答案</span>
<div v-html="ques.questionAnswerVersionsList[0].referenceAnswer" class="html-parse"></div>
<div v-if="ques.questionAnswerVersionsList[0].referenceAnswer"
v-html="ques.questionAnswerVersionsList[0].referenceAnswer" class="html-parse"></div>
<span v-else>暂无参考答案</span>
</div>
<div class="line">
<span class="line-label">考生答案</span>
<div v-if="ques.answerContent" v-html="ques.answerContent" class="html-parse"></div>
<div v-else>未作答</div>
<p v-if="!ques.richTextStatus">无需作答</p>
<div v-else-if="ques.answerContent" v-html="ques.answerContent" class="html-parse"></div>
<p v-else>未作答</p>
</div>
<div v-if="ques.attachmentUrl" class="line">
<div v-if="ques.allowAttachment" class="line">
<span class="line-label">考生上传附件</span>
<el-link class="m-r-10" type="primary" @click="preview(ques.attachmentUrl)">{{
ques.attachmentName }}</el-link>
<el-button type="primary" size="mini" round
@click="download(ques.attachmentName, ques.attachmentUrl)">下载</el-button>
<template v-if="ques.attachmentUrl">
<el-link class="m-r-10" type="primary" @click="preview(ques.attachmentUrl)">{{
ques.attachmentName }}</el-link>
<el-button type="primary" size="mini" round
@click="download(ques.attachmentName, ques.attachmentUrl)">下载</el-button>
</template>
<span v-else>未上传</span>
</div>
</template>
<!-- 客观题 -->
<template v-else>
<div class="line">正确答案{{ ques.quesAnswer }}</div>
<div class="line">
@ -195,16 +208,26 @@
<div v-else-if="ques.userAnswerFill" class="fill-answers">
<p v-for="(ans, j) in ques.userAnswerFill" :key="j" class="fill-answer">
填空{{ j + 1 }}{{ ans.studentAnswer || '未作答' }}
<img v-if="ans.correct" src="@/assets/img/right.svg" alt="" class="icon">
<img v-else src="@/assets/img/wrong.svg" alt="" class="icon">
<template v-if="!ques.notScored">
<img v-if="ans.correct" src="@/assets/img/right.svg" alt="" class="icon">
<img v-else src="@/assets/img/wrong.svg" alt="" class="icon">
</template>
</p>
</div>
<span v-else>未作答</span>
</div>
</template>
<div class="line">题目分值{{ ques.questionScore }}</div>
<div class="line">考生得分<el-input class="score-input" size="small" :value="ques.userScore"
disabled />
<div class="line">题目分值{{ ques.notScored ? '不计分' : ques.questionScore + '分' }}</div>
<div class="line">考生得分<template v-if="ques.notScored">不计分</template>
<template v-else>
<el-input class="score-input" size="small" :value="ques.userScore" disabled />
</template>
</div>
<div v-for="(coment, k) in ques.comment" :key="k" class="line">
<span class="line-label">评语{{ k + 1 }}</span>
<div v-html="coment" class="html-parse"></div>
</div>
</div>
</div>
@ -280,10 +303,15 @@ export default {
id: 4,
name: '待判分'
},
{
id: 5,
name: '不计分'
},
],
outlines: [],
paper: [],
essayExist: 0,
notReview: 0,
previewImgVisible: false,
previewImg: '',
pdfVisible: false,
@ -305,8 +333,12 @@ export default {
const { questionTypes: types, difficults } = QuesConst
const { numToLetter } = Util
let essayExist = 0
let notReview = 0
outline.map(e => {
if (e.questionType === 'essay') essayExist = 1
if (e.questionType === 'essay') {
essayExist = 1
if (e.scoringStatus === '未判分') notReview = 1
}
e.shrink = false
const type = e.questionType
e.questionTypeName = types.find(n => n.id === type).name
@ -319,10 +351,12 @@ export default {
}
}
n.notScored = n.questionScore === 0 // =0
if (n.notScored) n.userScore = '-'
const opts = n.questionAnswerVersionsList
if (type !== 'fill_blank' && type !== 'essay') { //
if (!n.userScore) n.userScore = 0
n.isCorrect = n.userScore && n.userScore === n.questionScore ? 1 : 2
this.handleIsCorrect(n)
//
let { userAnswer } = n
@ -367,14 +401,15 @@ export default {
//
let rightLen = 0
if (n.userAnswerFill) rightLen = n.userAnswerFill.filter(m => m.correct).length //
n.isCorrect = n.userScore && n.questionScore === n.userScore ? 1 : (rightLen ? 3 : 2)
n.isCorrect = n.notScored ? 5 : (n.userScore && n.questionScore === n.userScore ? 1 : (rightLen ? 3 : 2))
} else if (type === 'essay') { //
n.isCorrect = 4 //
this.handleIsCorrect(n)
}
})
})
this.essayExist = essayExist //
this.notReview = notReview //
this.paper = outline
this.outlines = [
...outline,
@ -402,6 +437,10 @@ export default {
this.loading = false
}
},
//
handleIsCorrect (n) {
n.isCorrect = n.notScored ? 5 : (n.userScore === undefined ? 4 : (n.userScore === n.questionScore ? 1 : n.userScore ? 3 : 2)) // reviewScore 0
},
scrollToSmooth (position, duration) {
let startTime = Date.now()
@ -464,10 +503,44 @@ export default {
</script>
<style lang="scss" scoped>
.wrap {
padding: 10px;
}
.text-right {
text-align: right;
}
.text-red {
color: #f00;
}
code,
kbd,
samp {
font-family: 'PingFang SC', 'Helvetica Neue', Helvetica, 'microsoft yahei', arial, STHeiTi, sans-serif;
word-wrap: break-word;
white-space: pre-wrap;
}
/deep/ pre {
white-space: pre-wrap;
/* css-3 */
white-space: -moz-pre-wrap;
/* Mozilla, since 1999 */
white-space: pre-wrap;
/* Opera 4-6 */
white-space: -o-pre-wrap;
/* Opera 7 */
word-wrap: break-word;
/* Internet Explorer 5.5+ */
word-break: break-all;
overflow: hidden;
font-size: 12px;
font-weight: 400;
font-family: 'PingFang SC', 'Helvetica Neue', Helvetica, 'microsoft yahei', arial, STHeiTi, sans-serif;
}
/deep/.report {
display: flex;
@ -582,7 +655,7 @@ export default {
}
.left {
width: 290px;
width: 320px;
margin-right: 15px;
background-color: #fff;
@ -621,7 +694,7 @@ export default {
li {
position: relative;
width: 30px;
min-width: 30px;
margin: 7px 9px;
font-size: 13px;
text-align: center;
@ -662,8 +735,15 @@ export default {
border-color: #fe9f0a;
}
.status5 .serial {
color: #fff;
background-color: #d1d1d1;
border-color: #d1d1d1;
}
.score {
height: 22px;
padding: 0 2px;
border: 1px solid #d3d3d3;
border-top: 0;
line-height: 22px;
@ -673,7 +753,7 @@ export default {
.status-filter {
display: flex;
justify-content: space-between;
padding: 10px;
padding: 10px 0;
border-top: 1px solid #e5e5e5;
li {
@ -683,6 +763,7 @@ export default {
font-size: 12px;
color: #333;
cursor: pointer;
white-space: nowrap;
border: 1px solid transparent;
&:before {
@ -726,7 +807,7 @@ export default {
}
}
&:last-child {
&:nth-child(4) {
&.active {
color: #fe9f0a;
border-color: #fe9f0a;
@ -737,6 +818,17 @@ export default {
}
}
&:last-child {
&.active {
color: #d1d1d1;
border-color: #d1d1d1;
}
&:before {
background-color: #d1d1d1;
}
}
&.active {
font-weight: 600;
}
@ -745,7 +837,7 @@ export default {
}
.right {
width: calc(100% - 305px);
width: calc(100% - 355px);
height: calc(100vh - 287px);
padding: 10px;
background-color: #fff;

Loading…
Cancel
Save