|
|
|
@ -155,15 +155,15 @@ |
|
|
|
|
<p v-if="item.questionType !== 'fill_blank'" class="m-r-10 input-wrap"> |
|
|
|
|
(<el-input class="l-input" placeholder="请输入分值" v-model="ques.score" />分)</p> |
|
|
|
|
|
|
|
|
|
<el-popover v-else placement="bottom" width="400" trigger="click"> |
|
|
|
|
<div v-if="ques.fillScores" class="fill-scores"> |
|
|
|
|
<el-popover v-else-if="ques.fillScores" placement="bottom" width="350" trigger="click"> |
|
|
|
|
<div class="fill-scores"> |
|
|
|
|
<p class="fill-title">每空分值</p> |
|
|
|
|
<div v-for="(score, k) in ques.fillScores" :key="k" class="input-wrap"> |
|
|
|
|
<el-input class="l-input" placeholder="请输入分值" v-model="score.val" |
|
|
|
|
@change="fillScoreChange(ques)" /> |
|
|
|
|
分 填空项{{ k + 1 }} |
|
|
|
|
<span |
|
|
|
|
v-if="ques.answerData && ques.answerData.length && ques.answerData[k]"> 建议分值占比:{{ |
|
|
|
|
v-if="ques.answerData && ques.answerData.length && ques.answerData[k] && ques.answerData[k].scoreProportion != 0"> 建议分值占比:{{ |
|
|
|
|
ques.answerData[k].scoreProportion }}%</span> |
|
|
|
|
</div> |
|
|
|
|
</div> |
|
|
|
@ -171,7 +171,7 @@ |
|
|
|
|
查看每空分值<el-input class="l-input" placeholder="请输入分值" v-model="ques.score" readonly /> |
|
|
|
|
</div> |
|
|
|
|
</el-popover> |
|
|
|
|
<el-button v-if="!ques.isDel" type="text" @click="toQues(item, j, ques, 1)">编辑试题</el-button> |
|
|
|
|
<el-button v-if="!ques.isDel" type="text" @click="toQues(item, j, ques, 2)">编辑试题</el-button> |
|
|
|
|
<el-button type="text" @click="showManualDia(item, j, ques)">更换试题</el-button> |
|
|
|
|
<el-button type="text" @click="showManualDia(item, j)">添加试题</el-button> |
|
|
|
|
<el-button type="text" @click="delQues(item, j)">移除试题</el-button> |
|
|
|
@ -223,33 +223,29 @@ |
|
|
|
|
</div> |
|
|
|
|
</div> |
|
|
|
|
|
|
|
|
|
<draggable v-if="form.paperOutline && form.paperOutline.length"> |
|
|
|
|
<!-- <transition-group :key="1"> --> |
|
|
|
|
<div class="layer" id="layer" ref="layer"> |
|
|
|
|
<table class="table"> |
|
|
|
|
<thead> |
|
|
|
|
<tr> |
|
|
|
|
<th width="30%">大题</th> |
|
|
|
|
<th width="35%">已添加题数/目标题数</th> |
|
|
|
|
<th width="35%">已分配分值/目标分值</th> |
|
|
|
|
</tr> |
|
|
|
|
</thead> |
|
|
|
|
<tbody> |
|
|
|
|
<tr v-for="(item, i) in form.paperOutline" :key="i"> |
|
|
|
|
<td>第{{ arabicToChinese(i + 1) }}大题</td> |
|
|
|
|
<td>{{ item.examQuestions.length }}/{{ item.questionNum }}</td> |
|
|
|
|
<td>{{ item.examQuestions.reduce((e, j) => (e += +j.score), 0) || 0 }}/{{ item.targetScore }}</td> |
|
|
|
|
</tr> |
|
|
|
|
<tr> |
|
|
|
|
<td>总计</td> |
|
|
|
|
<td>{{ overview.alreadyQuesCount }}/{{ overview.questionCount }}</td> |
|
|
|
|
<td>{{ overview.alreadyScore }}/{{ overview.totalScore }}</td> |
|
|
|
|
</tr> |
|
|
|
|
</tbody> |
|
|
|
|
</table> |
|
|
|
|
</div> |
|
|
|
|
<!-- </transition-group> --> |
|
|
|
|
</draggable> |
|
|
|
|
<div v-if="form.paperOutline && form.paperOutline.length" class="layer" id="layer"> |
|
|
|
|
<table class="table"> |
|
|
|
|
<thead> |
|
|
|
|
<tr> |
|
|
|
|
<th width="30%">大题</th> |
|
|
|
|
<th width="35%">已添加题数/目标题数</th> |
|
|
|
|
<th width="35%">已分配分值/目标分值</th> |
|
|
|
|
</tr> |
|
|
|
|
</thead> |
|
|
|
|
<tbody> |
|
|
|
|
<tr v-for="(item, i) in form.paperOutline" :key="i"> |
|
|
|
|
<td>第{{ arabicToChinese(i + 1) }}大题</td> |
|
|
|
|
<td>{{ item.examQuestions.length }}/{{ item.questionNum }}</td> |
|
|
|
|
<td>{{ item.examQuestions.reduce((e, j) => (e += +j.score), 0) || 0 }}/{{ item.targetScore }}</td> |
|
|
|
|
</tr> |
|
|
|
|
<tr> |
|
|
|
|
<td>总计</td> |
|
|
|
|
<td>{{ overview.alreadyQuesCount }}/{{ overview.questionCount }}</td> |
|
|
|
|
<td>{{ overview.alreadyScore }}/{{ overview.totalScore }}</td> |
|
|
|
|
</tr> |
|
|
|
|
</tbody> |
|
|
|
|
</table> |
|
|
|
|
</div> |
|
|
|
|
|
|
|
|
|
<Template :visible.sync="templateVisible" /> |
|
|
|
|
<Manual :visible.sync="manualVisible" :questionType.sync="curType.questionType" /> |
|
|
|
@ -265,7 +261,6 @@ |
|
|
|
|
</template> |
|
|
|
|
<script> |
|
|
|
|
import Draggable from 'vuedraggable' |
|
|
|
|
import Sortable from 'sortablejs' |
|
|
|
|
import UeditorPlus from '@/components/ueditorPlus' |
|
|
|
|
import Breadcrumb from '@/components/breadcrumb' |
|
|
|
|
import Template from './template' |
|
|
|
@ -454,11 +449,8 @@ export default { |
|
|
|
|
name: '创建试卷' |
|
|
|
|
}, |
|
|
|
|
] |
|
|
|
|
// console.log(44, Sortable, document.querySelector('#layer')) |
|
|
|
|
// new Sortable(document.querySelector('#layer'), { |
|
|
|
|
// group: "name", |
|
|
|
|
// sort: true, |
|
|
|
|
// }) |
|
|
|
|
|
|
|
|
|
this.drag() |
|
|
|
|
this.getDetail() |
|
|
|
|
this.getType() |
|
|
|
|
this.getProfessional() |
|
|
|
@ -490,8 +482,9 @@ export default { |
|
|
|
|
if (r.particularYear) r.particularYear = r.particularYear + '' |
|
|
|
|
r.professionalId = r.professionalId ? r.professionalId.split(',').map(e => +e) : [] |
|
|
|
|
this.form = r |
|
|
|
|
this.loading = false |
|
|
|
|
} |
|
|
|
|
} finally { |
|
|
|
|
} catch (e) { |
|
|
|
|
this.loading = false |
|
|
|
|
} |
|
|
|
|
}, |
|
|
|
@ -602,7 +595,7 @@ export default { |
|
|
|
|
async fillBlankAllocation (list) { |
|
|
|
|
const param = list.map(e => { |
|
|
|
|
let { answerData } = e |
|
|
|
|
if (answerData) { |
|
|
|
|
if (answerData && e.questionAnswerVersionsList) { |
|
|
|
|
return { |
|
|
|
|
questionType: e.questionType, |
|
|
|
|
answerData: e.questionAnswerVersionsList[0].answerData, |
|
|
|
@ -659,6 +652,7 @@ export default { |
|
|
|
|
}, |
|
|
|
|
// 处理正确答案的显示 |
|
|
|
|
getCorrectAnswer (e) { |
|
|
|
|
const opts = e.questionAnswerVersionsList |
|
|
|
|
if (e.questionType === 'fill_blank') { // 填空题 |
|
|
|
|
// answerData里存了该填空题所有填空项的正确答案及分值占比,对象转化为字符串存起来了 |
|
|
|
|
let data = e.answerData |
|
|
|
@ -671,10 +665,10 @@ export default { |
|
|
|
|
} |
|
|
|
|
return '' |
|
|
|
|
} else if (e.questionType === 'essay') { // 问答题取参考答案 |
|
|
|
|
return e.questionAnswerVersionsList[0].referenceAnswer || '暂无' |
|
|
|
|
if (opts) return opts[0].referenceAnswer || '暂无' |
|
|
|
|
} else { |
|
|
|
|
if (e.questionAnswerVersionsList) { |
|
|
|
|
const correct = e.questionAnswerVersionsList.filter(e => e.answerIsCorrect) |
|
|
|
|
if (opts) { |
|
|
|
|
const correct = opts.filter(e => e.answerIsCorrect) |
|
|
|
|
return correct ? (e.questionType === 'judgement' ? correct[0].optionText : correct.map(e => Util.numToLetter(e.optionNumber - 1)).join('')) : '' // 单选多选显示ABC选项,判断题显示选项内容 |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -742,10 +736,12 @@ export default { |
|
|
|
|
this.addQuesVisible = false |
|
|
|
|
}, |
|
|
|
|
// 编辑试题完成后把新的试题信息带过来 |
|
|
|
|
updateQues (ques, id) { |
|
|
|
|
updateQues (ques) { |
|
|
|
|
ques.questionAnswerVersionsList = ques.questionAnswerVersions |
|
|
|
|
delete ques.questionAnswerVersions |
|
|
|
|
ques.score = '' |
|
|
|
|
this.curType.examQuestions[this.curQuesIndex] = Object.assign(this.curRow, ques) |
|
|
|
|
this.handleQuesInfo(this.curType.examQuestions[this.curQuesIndex]) |
|
|
|
|
this.calcDifficult() |
|
|
|
|
}, |
|
|
|
|
|
|
|
|
@ -814,46 +810,39 @@ export default { |
|
|
|
|
}, |
|
|
|
|
// 检查重复试题 |
|
|
|
|
hasRepeatQues (list) { |
|
|
|
|
const result = [] |
|
|
|
|
list.forEach(e => { |
|
|
|
|
list.forEach(n => { |
|
|
|
|
if (e.questionVersionId !== n.questionVersionId && !e.repeat) { |
|
|
|
|
// 选择和判断题则判断题型+题干+选项内容 |
|
|
|
|
let diff = 0 |
|
|
|
|
// 选择和判断题则判断题型+题干+选项内容;填空/问答:题干+题型一样即重复 |
|
|
|
|
if (e.questionType !== 'fill_blank' && e.questionType !== 'essay') { |
|
|
|
|
// 判断每个选项的内容是否相同 |
|
|
|
|
const opts = e.questionAnswerVersionsList |
|
|
|
|
if (opts) { |
|
|
|
|
let diff = 0 |
|
|
|
|
for (const j in opts) { |
|
|
|
|
// debugger |
|
|
|
|
if (!n.questionAnswerVersionsList || !n.questionAnswerVersionsList[j] || n.questionAnswerVersionsList[j].optionText !== opts[j].optionText) { |
|
|
|
|
diff = 1 |
|
|
|
|
break |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (e.questionType === n.questionType && e.stem === n.stem && !diff) { |
|
|
|
|
e.repeat = true |
|
|
|
|
n.repeat = true |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
// 填空/问答:题干+题型一样即重复 |
|
|
|
|
if (e.questionType === n.questionType && e.stem === n.stem) { |
|
|
|
|
} |
|
|
|
|
if (e.questionType === n.questionType && e.stem === n.stem && !diff) { |
|
|
|
|
const i = result.findIndex(m => m.questionVersionId === e.questionVersionId || m.questionVersionId === n.questionVersionId) |
|
|
|
|
if (!e.repeat) { |
|
|
|
|
i === -1 ? result.push(e) : result.splice(i, 0, e) |
|
|
|
|
e.repeat = true |
|
|
|
|
} |
|
|
|
|
if (!n.repeat) { |
|
|
|
|
i === -1 ? result.push(n) : result.splice(i, 0, n) |
|
|
|
|
n.repeat = true |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
}) |
|
|
|
|
}) |
|
|
|
|
const result = list.filter(e => e.repeat) |
|
|
|
|
// 如果有重复的试题,则弹框显示这些试题 |
|
|
|
|
if (result.length) { |
|
|
|
|
this.repeatVisible = true |
|
|
|
|
this.repeatQues = result |
|
|
|
|
return true |
|
|
|
|
} |
|
|
|
|
return false |
|
|
|
|
return result |
|
|
|
|
}, |
|
|
|
|
// 提交 |
|
|
|
|
submit (status) { |
|
|
|
@ -889,6 +878,7 @@ export default { |
|
|
|
|
async validForm (status) { |
|
|
|
|
if (this.submiting) return false |
|
|
|
|
const { isCopy, overview } = this // 复制 |
|
|
|
|
const { getUuid } = Util |
|
|
|
|
const form = _.cloneDeep(this.form) |
|
|
|
|
const paper = form.paperOutline |
|
|
|
|
const allQues = [] |
|
|
|
@ -897,6 +887,8 @@ export default { |
|
|
|
|
if (status) { |
|
|
|
|
if (isNaN(form.suggestTime) || form.suggestTime < 1 || form.suggestTime % 1) return Util.warningMsg('估计用时请输入正整数') |
|
|
|
|
let invalid = 0 |
|
|
|
|
|
|
|
|
|
loop1: |
|
|
|
|
for (const i in paper) { |
|
|
|
|
const e = paper[i] |
|
|
|
|
const chineseNum = this.arabicToChinese(+i + 1) |
|
|
|
@ -931,14 +923,21 @@ export default { |
|
|
|
|
// 填空题需要拿每个小空的分数计算 |
|
|
|
|
if (e.questionType === 'fill_blank') { |
|
|
|
|
let totalScore = 0 |
|
|
|
|
e.examQuestions.map(n => { |
|
|
|
|
|
|
|
|
|
for (const j in e.examQuestions) { |
|
|
|
|
const n = e.examQuestions[j] |
|
|
|
|
const { fillScores } = n |
|
|
|
|
if (fillScores) { |
|
|
|
|
for (const e of fillScores) { |
|
|
|
|
if (e.val === '' || e.val === undefined || e.val === null) { |
|
|
|
|
Util.warningMsg(`第${chineseNum}大题的第${this.arabicToChinese(+j + 1)}小题填空分数未填写完成,请重新修改`) |
|
|
|
|
invalid = 1 |
|
|
|
|
break loop1 |
|
|
|
|
} |
|
|
|
|
totalScore = Decimal(totalScore).add(e.val || 0).toNumber() |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
}) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (+e.targetScore !== totalScore) { |
|
|
|
|
Util.warningMsg(`第${chineseNum}大题的小题总分跟目标分值不一致,请重新修改`) |
|
|
|
@ -959,6 +958,7 @@ export default { |
|
|
|
|
break |
|
|
|
|
} |
|
|
|
|
e.examQuestions.map((n, j) => { |
|
|
|
|
e.uuid = getUuid() |
|
|
|
|
n.outlineName = e.outlineName |
|
|
|
|
n.paperIndex = i |
|
|
|
|
n.quesIndex = j |
|
|
|
@ -1014,7 +1014,15 @@ export default { |
|
|
|
|
if (isCopy) form.paperId = '' |
|
|
|
|
this.tempForm = form |
|
|
|
|
|
|
|
|
|
if (this.hasRepeatQues(allQues)) return false |
|
|
|
|
|
|
|
|
|
// 如果有重复的试题,则弹框显示这些试题 |
|
|
|
|
const repeats = this.hasRepeatQues(allQues) |
|
|
|
|
if (repeats.length) { |
|
|
|
|
this.repeatVisible = true |
|
|
|
|
this.repeatQues = repeats |
|
|
|
|
return false |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
this.saveTestPaper() |
|
|
|
|
}, |
|
|
|
|
// 预览 |
|
|
|
@ -1024,7 +1032,35 @@ export default { |
|
|
|
|
// 返回 |
|
|
|
|
back () { |
|
|
|
|
this.$router.back() |
|
|
|
|
} |
|
|
|
|
}, |
|
|
|
|
// 拖拽面板 |
|
|
|
|
drag () { |
|
|
|
|
const el = document.querySelector('#layer') |
|
|
|
|
if (el) { |
|
|
|
|
const drag = e => { |
|
|
|
|
e.stopPropagation && e.stopPropagation() |
|
|
|
|
e.preventDefault && e.preventDefault() |
|
|
|
|
e.cancelBubble = true |
|
|
|
|
e.returnValue = false |
|
|
|
|
let x = e.clientX - el.offsetLeft |
|
|
|
|
let y = e.clientY - el.offsetTop |
|
|
|
|
let left = 0 |
|
|
|
|
let top = 0 |
|
|
|
|
|
|
|
|
|
document.onmousemove = function (eve) { |
|
|
|
|
left = eve.clientX - x |
|
|
|
|
top = eve.clientY - y |
|
|
|
|
el.style.left = left + 'px' |
|
|
|
|
el.style.top = top + 'px' |
|
|
|
|
} |
|
|
|
|
document.onmouseup = e => { |
|
|
|
|
document.onmousemove = null |
|
|
|
|
document.onmouseup = null |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
el.onmousedown = drag |
|
|
|
|
} |
|
|
|
|
}, |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
</script> |
|
|
|
@ -1270,6 +1306,7 @@ export default { |
|
|
|
|
background-color: #fff; |
|
|
|
|
box-shadow: 0 0 7px rgba(235, 235, 235, .8); |
|
|
|
|
overflow: auto; |
|
|
|
|
cursor: move; |
|
|
|
|
|
|
|
|
|
.table { |
|
|
|
|
text-align: center; |
|
|
|
|