You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1106 lines
32 KiB
1106 lines
32 KiB
<template> |
|
<div class="wrap"> |
|
<div class="top"> |
|
<p class="paper-name">{{ paperName }}</p> |
|
|
|
<div class="actions"> |
|
<el-button v-if="showPrev" class="btn" @click="switchRecord(0)">上一个</el-button> |
|
<el-button v-if="showNext" class="btn" @click="switchRecord(1)">下一个</el-button> |
|
<el-button v-if="!readonly" class="btn" @click="saveAll">一键保存分数</el-button> |
|
<img class="exit" src="@/assets/images/exit.svg" alt="" @click="close"> |
|
</div> |
|
</div> |
|
|
|
<div class="report" v-loading="loading"> |
|
<div class="left"> |
|
<h6 class="title">答题卡</h6> |
|
<ul v-if="hasManualScoreType" class="review-type"> |
|
<li v-for="(item, i) in reviews" :key="i" :class="{ active: curReview === item.id }" |
|
@click="reviewClick(item)"> |
|
{{ item.name }}</li> |
|
</ul> |
|
<div v-if="paper" class="type-wrap"> |
|
<template v-for="(item, i) in paper"> |
|
<div |
|
v-if="item.userAnswerList.length && (!sheetStatus || item.userAnswerList.some(e => e.isCorrect === sheetStatus))" |
|
:key="i" class="type"> |
|
<h6 class="stem">{{ arabicToChinese(i + 1) }}、{{ item.outlineName }}(本题共{{ item.questionNum }}小题,共{{ |
|
item.targetScore }}分)</h6> |
|
<ul class="serials"> |
|
<template v-for="(ques, j) in item.userAnswerList"> |
|
<li v-if="!sheetStatus || sheetStatus === ques.isCorrect" :key="j" :class="'status' + ques.isCorrect" |
|
@click="scrollToQues(ques, item)"> |
|
<p :class="['serial', { answered: ques.answered, partAnswer: ques.partAnswer }]">{{ |
|
ques.serialNumber }}</p> |
|
<p class="score">{{ ques.originUserScore }}</p> |
|
</li> |
|
</template> |
|
</ul> |
|
</div> |
|
</template> |
|
</div> |
|
<ul class="status-filter"> |
|
<li v-for="(item, i) in statusList" :key="i" :class="{ active: sheetStatus === item.id }" |
|
@click="filterStatus(item.id)">{{ item.name }}</li> |
|
</ul> |
|
</div> |
|
<div :class="['middle', { none: !paper || !paper.length }]" id="middle"> |
|
<ul v-if="paper && paper.length" class="ques-wrap"> |
|
<li v-for="(item, i) in paper" :key="i"> |
|
<div class="outline"> |
|
{{ arabicToChinese(i + 1) }}、{{ item.outlineName }}(本题共{{ item.questionNum }}小题,共{{ |
|
item.targetScore }}分) |
|
<img :class="['shrink', { active: item.shrink }]" src="@/assets/images/shrink.svg" alt="" |
|
@click="item.shrink = !item.shrink"> |
|
</div> |
|
<div :class="['ques', { hide: item.shrink }]"> |
|
<div v-for="(ques, j) in item.userAnswerList" :key="j" class="item" :id="'ques' + ques.id"> |
|
<div class="stem-wrap"> |
|
<div class="labels"> |
|
<span class="label">{{ ques.serialNumber }} / {{ item.questionNum }}</span> |
|
<span class="label">{{ item.questionTypeName }}</span> |
|
</div> |
|
<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> |
|
</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/images/right.svg" alt="" class="icon"> |
|
<img v-else-if="!opt.optCorrect" src="@/assets/images/wrong.svg" alt="" class="icon"> |
|
<span v-else class="icon not-ans"></span> |
|
|
|
<span>{{ numToLetter(j) }}. </span> |
|
<div class="text html-parse" v-html="opt.optionText"></div> |
|
</div> |
|
</div> |
|
<template v-if="item.questionType === 'essay'"> |
|
<div v-if="ques.stemAttachment" class="m-b-10"> |
|
<el-link class="m-r-10" type="primary" @click="preview(ques.stemAttachment)">{{ ques.fileName || |
|
ques.stemAttachment }}</el-link> |
|
<el-button type="primary" size="mini" round |
|
@click="download(ques.fileName || ques.stemAttachment, ques.stemAttachment)">下载</el-button> |
|
</div> |
|
<div v-if="ques.uploadInstructions" class="line m-b-10"> |
|
<span class="line-label">考生上传附件说明:</span> |
|
<div v-html="ques.uploadInstructions" class="html-parse"></div> |
|
</div> |
|
</template> |
|
|
|
<div v-if="ques.knowledgePointList && ques.knowledgePointList.length" class="m-b-10"> |
|
<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 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' && ques.reviewScore === '' }]"> |
|
<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> |
|
<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> |
|
</div> |
|
<div v-if="ques.attachmentUrl" 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> |
|
</div> |
|
</template> |
|
<template v-else> |
|
<div class="line">正确答案:{{ ques.quesAnswer }}</div> |
|
<div class="line"> |
|
<span class="line-label">考生答案:</span> |
|
<p v-if="item.questionType !== 'fill_blank'">{{ ques.userAnswerStr }}</p> |
|
<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 :src="require('@/assets/images/' + (ans.correct ? 'right' : 'wrong') + '.svg')" alt="" |
|
class="icon" @click="fillAnswerSwitch(ans, j, ques)"> |
|
</p> |
|
</div> |
|
</div> |
|
</template> |
|
|
|
<div class="line">题目分值:{{ ques.questionScore }}分</div> |
|
<div class="line"> |
|
考生得分:<el-input class="score-input hide-spin" type="number" placeholder="请输入分数" size="small" |
|
:disabled="item.questionType === 'fill_blank' || readonly" v-model.number="ques.reviewScore" /> |
|
<span class="m-r-10">分</span> |
|
<span v-if="item.questionType === 'fill_blank'">(如需修改填空题的得分请直接修改考生答案的对错)</span> |
|
|
|
<el-button v-if="ques.originUserScore !== ques.reviewScore && !readonly" class="m-l-10" |
|
type="primary" size="mini" @click="saveScore(ques)">保存分数</el-button> |
|
<el-popover v-if="!readonly" class="m-l-20" placement="bottom" width="400" trigger="click"> |
|
<el-input type="textarea" :rows="3" :autosize="{ minRows: 3 }" resize="none" placeholder="请输入" |
|
v-model="ques.newComments" /> |
|
<div class="m-t-10 text-right"> |
|
<el-button type="primary" size="mini" @click="saveComment(ques)">保存</el-button> |
|
</div> |
|
<div slot="reference"> |
|
<el-button type="primary" size="mini">评语</el-button> |
|
</div> |
|
</el-popover> |
|
</div> |
|
<div v-if="ques.comments" class="line"> |
|
<span class="line-label">评语:</span> |
|
<div> |
|
<span>{{ ques.commentSetTime }}</span> |
|
<i v-if="!readonly" class="el-icon-delete-solid del-comment" @click="delComment(ques)"></i> |
|
|
|
<div class="comment" v-html="ques.comments"></div> |
|
</div> |
|
</div> |
|
</div> |
|
</div> |
|
</div> |
|
</li> |
|
</ul> |
|
<div v-else class="empty"> |
|
<img class="icon" src="@/assets/images/empty.svg" alt=""> |
|
<p>暂无数据</p> |
|
</div> |
|
</div> |
|
<div class="right"> |
|
<h6>基本信息</h6> |
|
<div class="lines"> |
|
<template v-if="showUserInfo"> |
|
<p>考生所在院校:{{ info.realSchool }}</p> |
|
<p>团队名称:{{ info.teamName }}</p> |
|
<!-- <p>考生班级:{{ info.className }}</p> --> |
|
<p>考生姓名:{{ info.userName }}</p> |
|
<p>考生学号:{{ info.workNumber }}</p> |
|
</template> |
|
<p>答卷ID:{{ info.reportId }}</p> |
|
<p>提交时间:{{ info.submitTime }}</p> |
|
<p>用时:{{ info.timeSum }}min</p> |
|
</div> |
|
</div> |
|
</div> |
|
|
|
<el-dialog title="图片预览" :visible.sync="previewImgVisible" width="800px" :close-on-click-modal="false"> |
|
<el-image style="max-width: 100px; max-height: 100px" :src="previewImg" :preview-src-list="[previewImg]"> |
|
</el-image> |
|
</el-dialog> |
|
<PdfDia :key="pdfVisible" :visible.sync="pdfVisible" :src.sync="pdfSrc" /> |
|
</div> |
|
</template> |
|
|
|
<script> |
|
import PdfDia from '@/components/pdf' |
|
import QuesConst from '@/const/ques' |
|
import Util from '@/libs/util' |
|
import _ from 'lodash' |
|
import Decimal from 'decimal.js' |
|
export default { |
|
components: { |
|
PdfDia |
|
}, |
|
data () { |
|
return { |
|
numToLetter: Util.numToLetter, |
|
arabicToChinese: Util.arabicToChinese, |
|
reportId: this.$route.query.id, |
|
competitionId: this.$route.query.c, |
|
stageId: this.$route.query.s, |
|
showUserInfo: +this.$route.query.u, // 是否展示学生信息 |
|
hasManualScoreType: +this.$route.query.m, // 是否有主观题 |
|
readonly: !!(+this.$route.query.r), // 仅查看 |
|
curIndex: 0, |
|
paperName: '', |
|
outline: [], |
|
editing: false, |
|
loading: false, |
|
curReview: +this.$route.query.m ? 0 : '', |
|
reviews: [ |
|
{ |
|
id: '', |
|
name: '全部' |
|
}, |
|
{ |
|
id: 0, |
|
name: '待评阅' |
|
}, |
|
{ |
|
id: 1, |
|
name: '已评阅' |
|
}, |
|
], |
|
sheetStatus: '', |
|
statusList: [ |
|
{ |
|
id: 1, |
|
name: '正确' |
|
}, |
|
{ |
|
id: 2, |
|
name: '错误' |
|
}, |
|
{ |
|
id: 3, |
|
name: '部分正确' |
|
}, |
|
{ |
|
id: 4, |
|
name: '待判分' |
|
}, |
|
], |
|
info: {}, |
|
paper: [], |
|
showNext: true, |
|
showPrev: true, |
|
page: 1, |
|
recordTotal: 0, |
|
previewImgVisible: false, |
|
previewImg: '', |
|
pdfVisible: false, |
|
pdfSrc: '', |
|
submiting: false, |
|
savePromise: null, |
|
}; |
|
}, |
|
mounted () { |
|
this.switchRecord(0, 1) |
|
this.getData(1) |
|
}, |
|
methods: { |
|
async getData (init) { |
|
this.loading = true |
|
try { |
|
const { userAnswers: outline, entryInformation: info } = await this.$get(`${this.api.reviewTheDetailsReport}?reportId=${this.reportId}&status=${this.curReview}`) |
|
this.info = info |
|
|
|
// 处理试题信息 |
|
const { questionTypes: types, difficults } = QuesConst |
|
const { numToLetter } = Util |
|
const paper = [] |
|
outline.map(e => { |
|
if (e.userAnswerList && e.userAnswerList.length) { |
|
e.shrink = false |
|
const type = e.questionType |
|
e.questionTypeName = types.find(n => n.id === type).name |
|
e.userAnswerList.map(n => { |
|
if (n.difficulty) { |
|
const curDiff = difficults.find(m => m.id === n.difficulty) |
|
if (curDiff) { |
|
n.difficult = curDiff.name |
|
n.difficultTheme = curDiff.theme |
|
} |
|
} |
|
|
|
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 |
|
|
|
// 用户选择结果 |
|
let { userAnswer } = n |
|
if (userAnswer) { |
|
userAnswer = JSON.parse(userAnswer) |
|
n.userAnswerStr = userAnswer.length ? (type === 'judgement' ? opts[+userAnswer[0] - 1].optionText : userAnswer.map(m => numToLetter(+m - 1)).join('')) : '未作答' |
|
} else { |
|
userAnswer = [] |
|
} |
|
|
|
const quesAnswer = [] |
|
opts && opts.map((m, j) => { |
|
const selected = userAnswer.includes(m.optionNumber) |
|
m.optCorrect = m.answerIsCorrect ? 1 : (selected ? 0 : -1) // 用户选择的结果跟正确答案是否匹配(1正确,0错误,-1未选择) |
|
m.answerIsCorrect && quesAnswer.push(type === 'judgement' ? m.optionText : numToLetter(j)) |
|
}) |
|
n.quesAnswer = quesAnswer.join('') |
|
|
|
} else if (type === 'fill_blank') { // 填空题 |
|
// 学生做的填空题答案及分数 |
|
let { jsonText } = n |
|
if (jsonText) { |
|
n.userAnswerFill = JSON.parse(jsonText) |
|
} |
|
|
|
// 正确答案 |
|
if (opts && opts.length) { |
|
let { answerData } = opts[0] |
|
if (answerData) { |
|
answerData = JSON.parse(answerData) |
|
let quesAnswer = '' |
|
answerData.map((m, j) => { |
|
if (m.fills) { |
|
quesAnswer += `填空${j + 1}:${m.fills.map(n => n.val).join(' ||| ')};` |
|
} |
|
}) |
|
n.quesAnswer = quesAnswer |
|
} |
|
} |
|
|
|
if (!n.userScore) n.userScore = 0 |
|
// 填空题需要区分部分正确还是正确、错误 |
|
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) |
|
} else if (type === 'essay') { // 简答题 |
|
if (!n.userScore) n.userScore = '' |
|
if (isNaN(n.reviewScore)) n.reviewScore = '' |
|
this.handleIsCorrect(n) |
|
} |
|
n.originUserScore = n.reviewScore |
|
n.newComments = n.comments || '' |
|
}) |
|
paper.push(e) |
|
} |
|
}) |
|
// 初始化的时候,如果没有待评阅的试题,则查询已评阅 |
|
if (!paper.length && init) { |
|
this.curReview = 1 |
|
this.getData() |
|
return false |
|
} |
|
this.paper = paper |
|
|
|
this.loading = false |
|
} catch (e) { |
|
this.loading = false |
|
} |
|
}, |
|
// 判断试题的对错 |
|
handleIsCorrect (n) { |
|
n.isCorrect = n.reviewScore === '' ? 4 : (n.reviewScore === n.questionScore ? 1 : n.reviewScore ? 3 : 2) // 简答题没有reviewScore则显示待判分, 有则判断是否跟题目分数相同,完全相同是正确,小于则部分正确,0则错误 |
|
}, |
|
scrollToSmooth (position, duration) { |
|
let startTime = Date.now() |
|
|
|
function scroll () { |
|
let now = Date.now() |
|
let progress = Math.min(1, (now - startTime) / duration) |
|
document.querySelector('#middle').scrollTo(0, position * progress) |
|
|
|
if (progress < 1) { |
|
window.requestAnimationFrame(scroll) |
|
} |
|
} |
|
|
|
window.requestAnimationFrame(scroll) |
|
}, |
|
// 答题卡题目点击滚动 |
|
scrollToQues (e, item) { |
|
item.shrink = false |
|
const el = document.querySelector('#ques' + e.id) |
|
this.$nextTick(() => { |
|
el && this.scrollToSmooth(el.offsetTop - document.querySelector('#middle').offsetTop, 200) |
|
}) |
|
}, |
|
// 左侧评阅切换 |
|
reviewClick (item) { |
|
this.curReview = item.id |
|
this.getData() |
|
}, |
|
// 答题卡筛选 |
|
filterStatus (e) { |
|
this.sheetStatus = this.sheetStatus === e ? '' : e |
|
}, |
|
// 预览附件 |
|
preview (url) { |
|
const ext = url.split('.').pop() |
|
if (Util.isDoc(ext)) { |
|
window.open('https://view.officeapps.live.com/op/view.aspx?src=' + url) |
|
} else if (Util.isImg(ext)) { |
|
this.previewImgVisible = true |
|
this.previewImg = url |
|
} else if (ext === 'pdf') { |
|
this.pdfVisible = true |
|
this.pdfSrc = url |
|
} |
|
}, |
|
// 下载附件 |
|
download (name, url) { |
|
Util.downloadFile(name, url) |
|
}, |
|
// 保存分数 |
|
async saveScore (ques) { |
|
if (ques.reviewScore === '') return Util.warningMsg('请输入考生得分!') |
|
if (ques.questionScore < ques.reviewScore) return Util.warningMsg('考生得分不得大于题目分值!') |
|
|
|
await this.$post(this.api.reviewPaper, [{ |
|
assignmentDetailId: ques.assignmentDetailId, |
|
reviewScore: ques.reviewScore, |
|
}]) |
|
ques.originUserScore = ques.reviewScore |
|
this.handleIsCorrect(ques) |
|
Util.successMsg('保存成功') |
|
}, |
|
// 填空题的小空对错点击回调 |
|
async fillAnswerSwitch (ans, j, ques) { |
|
ans.correct = !ans.correct |
|
ans.status = ans.correct ? '正确' : '错误' |
|
ques.userAnswerFill[j] = ans |
|
ques.jsonText = JSON.stringify(ques.userAnswerFill) |
|
ques.reviewScore = Decimal(ques.reviewScore)[ans.correct ? 'add' : 'sub'](Decimal(ans.score)).toNumber() |
|
await this.$post(this.api.reviewPaper, [{ |
|
assignmentDetailId: ques.assignmentDetailId, |
|
reviewScore: ques.reviewScore, |
|
jsonText: ques.jsonText |
|
}]) |
|
ques.originUserScore = ques.reviewScore |
|
this.handleIsCorrect(ques) |
|
Util.successMsg('保存成功') |
|
}, |
|
// 保存评语 |
|
async saveComment (ques) { |
|
const res = await this.$post(this.api.setComments, { |
|
assignmentDetailId: ques.assignmentDetailId, |
|
comments: ques.newComments, |
|
}) |
|
this.$set(ques, 'commentSetTime', res.commentSetTime) |
|
this.$set(ques, 'comments', ques.newComments) |
|
Util.successMsg('保存成功') |
|
}, |
|
// 删除评语 |
|
async delComment (ques) { |
|
await this.$confirm(`确定要删除该评语吗?`, '提示', { |
|
confirmButtonText: '确定', |
|
cancelButtonText: '取消', |
|
type: 'warning', |
|
}) |
|
await this.$post(`${this.api.deleteComments}?assignmentDetailId=${ques.assignmentDetailId}`) |
|
ques.comments = '' |
|
Util.successMsg('删除成功') |
|
}, |
|
|
|
// 判断是否需要弹框提示保存分数 |
|
async handleLeave (type, cb) { |
|
if (this.readonly) { |
|
cb() |
|
} else { |
|
const { paper } = this |
|
let invalid = 0 |
|
for (const e of paper) { |
|
if (e.userAnswerList.some(n => n.originUserScore !== n.reviewScore)) { |
|
invalid = 1 |
|
break |
|
} |
|
} |
|
|
|
let notReview = 0 |
|
// 判断是否还有未评阅的试题 |
|
if (this.curReview) { |
|
// 如果当前是已评阅的切换,则查询待评阅的试题是否还有试题,有则算还未评阅完 |
|
const { userAnswers: outline } = await this.$get(`${this.api.reviewTheDetailsReport}?reportId=${this.reportId}&status=0`) |
|
for (const e of outline) { |
|
if (e.userAnswerList.length) { |
|
notReview = 1 |
|
break |
|
} |
|
} |
|
} else { |
|
for (const e of paper) { |
|
if (e.userAnswerList.some(n => n.reviewScore === '')) { |
|
notReview = 1 |
|
break |
|
} |
|
} |
|
} |
|
|
|
if (invalid) { |
|
try { |
|
await this.$confirm(`还有未保存的分数,${notReview ? '并且还有试题未评阅,' : ''}是否保存并继续?`, '提示', { |
|
confirmButtonText: '确定', |
|
cancelButtonText: '取消', |
|
type: 'warning', |
|
closeOnClickModal: false, |
|
}) |
|
await this.saveAll() |
|
this.savePromise.then(() => { |
|
cb() |
|
}) |
|
} catch (e) { } |
|
} else { |
|
if (notReview) { |
|
await this.$confirm(`还有试题未评阅,确定要${!type ? '前往上一个' : type === 1 ? '前往下一个' : '退出'}吗?`, '提示', { |
|
confirmButtonText: '确定', |
|
cancelButtonText: '取消', |
|
type: 'warning', |
|
closeOnClickModal: false, |
|
}) |
|
cb() |
|
} else { |
|
cb() |
|
} |
|
} |
|
} |
|
}, |
|
// 查询上一个下一个id |
|
async queryRecord (isNext, init) { |
|
const res = await this.$post(this.api.getTheLabReportIdUpAndDown, { |
|
competitionId: this.competitionId, |
|
stageId: this.stageId, |
|
currentReportId: this.reportId |
|
}) |
|
this.showNext = !init && !isNext && res.previousReportId ? true : (init ? !!res.nextReportId : !!res.nextNextReportId) |
|
this.showPrev = !init && isNext && res.nextReportId ? true : (init ? !!res.previousReportId : !!res.previousPreviousReportId) |
|
|
|
if (!init) { |
|
const id = res[isNext ? 'nextReportId' : 'previousReportId'] |
|
if (id) { |
|
this.reportId = id |
|
this.$router.push(`/theoryReview?id=${id}&u=${this.showUserInfo}&m=${this.hasManualScoreType}&c=${this.competitionId}&s=${this.stageId}&r=${this.readonly ? 1 : 0}`) |
|
this.getData() |
|
} |
|
} |
|
}, |
|
// 下一个、上一个 |
|
async switchRecord (isNext, init) { |
|
if (init) { |
|
this.queryRecord(isNext, init) |
|
} else { |
|
this.handleLeave(isNext, async () => { |
|
this.queryRecord(isNext, init) |
|
}) |
|
} |
|
}, |
|
// 一键保存分数 |
|
async saveAll () { |
|
if (this.submiting) return false |
|
try { |
|
this.submiting = true |
|
const { paper } = this |
|
const params = [] |
|
let invalid = 0 |
|
|
|
loop1: for (const e of paper) { |
|
for (const i in e.userAnswerList) { |
|
const n = e.userAnswerList[i] |
|
if (n.questionScore < n.reviewScore) { |
|
Util.warningMsg(`${e.outlineName}的第${+i + 1}小题的考生得分不得大于题目分值!`) |
|
invalid = 1 |
|
break loop1 |
|
} else { |
|
n.originUserScore !== n.reviewScore && params.push({ |
|
assignmentDetailId: n.assignmentDetailId, |
|
reviewScore: n.reviewScore, |
|
}) |
|
} |
|
} |
|
} |
|
if (invalid) return false |
|
|
|
if (params.length) { |
|
this.savePromise = new Promise(async (resolve, reject) => { |
|
await this.$post(this.api.reviewPaper, params) |
|
for (const e of paper) { |
|
for (const n of e.userAnswerList) { |
|
n.originUserScore = n.reviewScore |
|
this.handleIsCorrect(n) |
|
} |
|
} |
|
Util.successMsg('保存成功') |
|
resolve() |
|
}) |
|
} |
|
} finally { |
|
this.submiting = false |
|
} |
|
}, |
|
close () { |
|
this.handleLeave(2, window.close) |
|
}, |
|
} |
|
}; |
|
</script> |
|
|
|
<style lang="scss" scoped> |
|
.top { |
|
display: flex; |
|
justify-content: space-between; |
|
align-items: center; |
|
padding: 10px 20px; |
|
color: #fff; |
|
background-color: $main-color; |
|
|
|
.item { |
|
display: inline-flex; |
|
align-items: center; |
|
} |
|
|
|
.paper-name { |
|
font-size: 18px; |
|
font-weight: 600; |
|
} |
|
|
|
.submit { |
|
width: 106px; |
|
font-size: 15px; |
|
} |
|
|
|
.exit { |
|
margin-left: 20px; |
|
cursor: pointer; |
|
|
|
&:hover { |
|
opacity: .9; |
|
} |
|
} |
|
} |
|
|
|
/deep/.report { |
|
display: flex; |
|
height: 100%; |
|
|
|
.left { |
|
width: 290px; |
|
padding: 0 10px; |
|
background-color: #fff; |
|
|
|
.title { |
|
padding: 10px 0; |
|
font-size: 16px; |
|
text-align: center; |
|
color: #333; |
|
} |
|
|
|
.progress { |
|
padding: 10px; |
|
color: #5a5a5a; |
|
background-color: #d4e9ff; |
|
} |
|
|
|
.review-type { |
|
display: flex; |
|
margin-bottom: 20px; |
|
|
|
li { |
|
width: 33.33%; |
|
font-size: 15px; |
|
color: #333; |
|
text-align: center; |
|
line-height: 1.8; |
|
border: 1px solid #ccc; |
|
cursor: pointer; |
|
|
|
&:nth-child(2) { |
|
border-left: 0; |
|
border-right: 0; |
|
} |
|
|
|
&.active { |
|
color: #fff; |
|
background-color: $main-color; |
|
} |
|
} |
|
|
|
&+.type-wrap { |
|
height: calc(100vh - 185px); |
|
} |
|
} |
|
|
|
.type-wrap { |
|
height: calc(100vh - 137px); |
|
padding: 10px 0; |
|
overflow: auto; |
|
|
|
.type { |
|
margin-bottom: 20px; |
|
} |
|
|
|
.stem { |
|
font-size: 15px; |
|
color: #333; |
|
} |
|
} |
|
|
|
.serials { |
|
display: flex; |
|
flex-wrap: wrap; |
|
margin-top: 5px; |
|
|
|
li { |
|
position: relative; |
|
min-width: 30px; |
|
margin: 7px 9px; |
|
font-size: 13px; |
|
text-align: center; |
|
cursor: pointer; |
|
|
|
&:hover { |
|
opacity: .9; |
|
} |
|
} |
|
|
|
.serial { |
|
color: #505050; |
|
line-height: 30px; |
|
border: 1px solid #d3d3d3; |
|
border-bottom: 1px solid transparent; |
|
} |
|
|
|
.status1 .serial { |
|
color: #fff; |
|
background-color: #2abd8c; |
|
border-color: #2abd8c; |
|
} |
|
|
|
.status2 .serial { |
|
color: #fff; |
|
background-color: #e75050; |
|
border-color: #e75050; |
|
} |
|
|
|
.status3 .serial { |
|
color: #2abd8c; |
|
border-color: #2abd8c; |
|
} |
|
|
|
.status4 .serial { |
|
color: #fff; |
|
background-color: #fe9f0a; |
|
border-color: #fe9f0a; |
|
} |
|
|
|
.score { |
|
height: 22px; |
|
padding: 0 2px; |
|
border: 1px solid #d3d3d3; |
|
border-top: 0; |
|
line-height: 22px; |
|
} |
|
} |
|
|
|
.status-filter { |
|
display: flex; |
|
justify-content: space-between; |
|
padding: 10px; |
|
border-top: 1px solid #e5e5e5; |
|
|
|
li { |
|
display: inline-flex; |
|
align-items: center; |
|
padding: 0 3px; |
|
font-size: 12px; |
|
color: #333; |
|
cursor: pointer; |
|
border: 1px solid transparent; |
|
|
|
&:before { |
|
content: ''; |
|
width: 13px; |
|
height: 13px; |
|
margin-right: 5px; |
|
border: 1px solid transparent; |
|
} |
|
|
|
&:first-child { |
|
&.active { |
|
color: #2abd8c; |
|
border-color: #2abd8c; |
|
} |
|
|
|
&:before { |
|
background-color: #2abd8c; |
|
} |
|
} |
|
|
|
&:nth-child(2) { |
|
&.active { |
|
color: #e75050; |
|
border-color: #e75050; |
|
} |
|
|
|
&:before { |
|
background-color: #e75050; |
|
} |
|
} |
|
|
|
&:nth-child(3) { |
|
&.active { |
|
color: #2abd8c; |
|
border-color: #2abd8c; |
|
} |
|
|
|
&:before { |
|
border-color: #2abd8c; |
|
} |
|
} |
|
|
|
&:last-child { |
|
&.active { |
|
color: #fe9f0a; |
|
border-color: #fe9f0a; |
|
} |
|
|
|
&:before { |
|
background-color: #fe9f0a; |
|
} |
|
} |
|
|
|
&.active { |
|
font-weight: 600; |
|
} |
|
} |
|
} |
|
} |
|
|
|
.middle { |
|
width: calc(100% - 520px); |
|
height: calc(100vh - 54px); |
|
padding: 10px; |
|
margin: 0 15px; |
|
background-color: #fff; |
|
overflow: auto; |
|
outline: none; |
|
|
|
&.none { |
|
display: flex; |
|
justify-content: center; |
|
align-items: center; |
|
} |
|
|
|
&>li { |
|
margin-bottom: 15px; |
|
} |
|
|
|
.outline { |
|
display: flex; |
|
justify-content: space-between; |
|
align-items: center; |
|
padding: 10px 15px; |
|
font-size: 15px; |
|
font-weight: 600; |
|
color: #333; |
|
background-color: #e8f0ff; |
|
} |
|
|
|
.shrink { |
|
cursor: pointer; |
|
transition: .5s; |
|
|
|
&.active { |
|
transform: rotate(180deg); |
|
} |
|
} |
|
|
|
.ques { |
|
padding: 15px; |
|
margin-bottom: 15px; |
|
transition: all 1.5s; |
|
overflow: hidden; |
|
|
|
&.hide { |
|
display: none; |
|
} |
|
} |
|
|
|
img { |
|
max-width: 100%; |
|
} |
|
|
|
.item:not(:last-child) { |
|
padding-bottom: 15px; |
|
margin-bottom: 15px; |
|
border-bottom: 1px dashed #e1e1e1; |
|
} |
|
|
|
.stem-wrap { |
|
display: flex; |
|
align-items: baseline; |
|
margin-bottom: 10px; |
|
} |
|
|
|
|
|
.tag { |
|
margin-left: 10px; |
|
cursor: pointer; |
|
|
|
&:hover { |
|
opacity: .9; |
|
} |
|
} |
|
|
|
.labels { |
|
display: inline-flex; |
|
align-items: center; |
|
} |
|
|
|
.label { |
|
padding: 3px 5px; |
|
margin-right: 10px; |
|
font-size: 12px; |
|
line-height: 1; |
|
color: $main-color; |
|
white-space: nowrap; |
|
border: 1px solid; |
|
border-radius: 2px; |
|
} |
|
|
|
.stem { |
|
max-width: calc(100% - 216px); |
|
} |
|
|
|
.ques-info { |
|
position: relative; |
|
padding: 10px; |
|
background-color: #f3f3f3; |
|
overflow: hidden; |
|
|
|
&.essay { |
|
&:after { |
|
content: '待 判 分'; |
|
position: absolute; |
|
top: 17px; |
|
right: -33px; |
|
padding: 5px 36px; |
|
font-size: 14px; |
|
color: #fff; |
|
background-color: #fe9f0a; |
|
transform: rotate(45deg); |
|
opacity: .7; |
|
} |
|
} |
|
} |
|
|
|
.line { |
|
display: flex; |
|
align-items: baseline; |
|
margin-bottom: 8px; |
|
font-size: 13px; |
|
color: #333; |
|
|
|
&:last-child { |
|
margin-bottom: 0; |
|
} |
|
|
|
img { |
|
max-width: 100%; |
|
} |
|
} |
|
|
|
.del-comment { |
|
margin-left: 10px; |
|
font-size: 16px; |
|
color: $main-color; |
|
cursor: pointer; |
|
} |
|
|
|
.comment { |
|
margin-top: 5px; |
|
font-size: 16px; |
|
} |
|
|
|
.line-label { |
|
white-space: nowrap; |
|
} |
|
|
|
.fill-answers { |
|
display: inline-flex; |
|
align-items: center; |
|
} |
|
|
|
.fill-answer { |
|
display: inline-flex; |
|
align-items: center; |
|
margin-right: 10px; |
|
|
|
.icon { |
|
margin-left: 7px; |
|
cursor: pointer; |
|
|
|
&:hover { |
|
opacity: .8; |
|
} |
|
} |
|
} |
|
|
|
.score-input { |
|
width: 100px; |
|
margin-right: 5px; |
|
} |
|
|
|
.fill-input { |
|
width: 100px; |
|
height: 28px; |
|
padding: 0 15px; |
|
margin: 0 10px; |
|
font-size: 13px; |
|
line-height: 28px; |
|
color: #606266; |
|
border: 1px solid #DCDEE0; |
|
border-radius: 2px; |
|
|
|
&:focus { |
|
outline: none; |
|
} |
|
} |
|
|
|
.opt { |
|
display: flex; |
|
flex-wrap: wrap; |
|
align-items: flex-start; |
|
padding-left: 10px; |
|
margin-bottom: 5px; |
|
font-size: 14px; |
|
color: #707070; |
|
line-height: 1.6; |
|
|
|
&>.icon { |
|
margin-right: 12px; |
|
} |
|
|
|
.not-ans { |
|
width: 18px; |
|
height: 18px; |
|
border: 1px solid #ccc; |
|
border-radius: 50%; |
|
} |
|
|
|
.text { |
|
max-width: calc(100% - 55px); |
|
} |
|
} |
|
} |
|
|
|
.right { |
|
width: 200px; |
|
padding: 20px; |
|
background-color: #fff; |
|
|
|
h6 { |
|
font-size: 16px; |
|
} |
|
|
|
.lines { |
|
font-size: 14px; |
|
color: #333; |
|
|
|
&>p { |
|
margin: 10px 0; |
|
} |
|
} |
|
} |
|
|
|
.ques-wrap { |
|
&>li { |
|
margin-bottom: 15px; |
|
} |
|
} |
|
} |
|
|
|
|
|
@media (max-width: 1430px) { |
|
.wrap { |
|
padding: 12px 100px 20px; |
|
} |
|
} |
|
</style> |