试卷发布判断重复试题等

master
yujialong 3 months ago
parent a0d8246419
commit 872a1f6514
  1. 2
      public/static/ueditorPlus/ueditor.config.js
  2. 26
      src/pages/ques/detail/index.vue
  3. 2
      src/pages/ques/list/index.vue
  4. 142
      src/pages/testPaper/detail/index.vue
  5. 16
      src/pages/testPaper/detail/manual.vue
  6. 69
      src/pages/testPaper/detail/repeatQues.vue
  7. 5
      src/pages/testPaper/list/index.vue

@ -65,7 +65,7 @@
//工具栏上的所有的功能按钮和下拉框,可以在new编辑器的实例时选择自己需要的重新定义 //工具栏上的所有的功能按钮和下拉框,可以在new编辑器的实例时选择自己需要的重新定义
// , "insertvideo" // , "insertvideo"
toolbars: [ toolbars: [
["fullscreen", "source", "|", "bold", "italic", "underline", "forecolor", "fontfamily", "fontsize", "|", "link", "unlink", "anchor", "|", "imagenone", "imageleft", "imagecenter", "imageright", "|", "justifyleft", "justifycenter", "justifyright", "justifyjustify", "|", "insertcode", "insertimage", "insertvideo", "inserttable", 'formula', "gapfilling", 'combox'] ["fullscreen", "source", "|", "bold", "italic", "underline", "rowspacingtop", "rowspacingbottom", "lineheight", "|", "customstyle", "paragraph", "forecolor", "fontfamily", "fontsize", "|", "backcolor", "insertorderedlist", "insertunorderedlist", "|", "link", "unlink", "anchor", "|", "imagenone", "imageleft", "imagecenter", "imageright", "|", "justifyleft", "justifycenter", "justifyright", "justifyjustify", "|", "insertcode", "insertimage", "insertvideo", "inserttable", 'formula', "gapfilling", 'combox']
] ]
// 公式配置 // 公式配置
, formulaConfig: { , formulaConfig: {

@ -160,8 +160,7 @@
<el-dialog title="提示" :visible.sync="repeatVisible" width="800px" :close-on-click-modal="false"> <el-dialog title="提示" :visible.sync="repeatVisible" width="800px" :close-on-click-modal="false">
<el-alert title="与当前题库中已有的试题重复(如下),是否继续保存?" type="warning" effect="dark" :closable="false"> <el-alert title="与当前题库中已有的试题重复(如下),是否继续保存?" type="warning" effect="dark" :closable="false" />
</el-alert>
<el-table class="m-t-10" :data="repeats" stripe header-align="center" row-key="id"> <el-table class="m-t-10" :data="repeats" stripe header-align="center" row-key="id">
<el-table-column type="index" width="60" label="序号" align="center"></el-table-column> <el-table-column type="index" width="60" label="序号" align="center"></el-table-column>
<el-table-column prop="name" label="题型" align="center" min-width="120"> <el-table-column prop="name" label="题型" align="center" min-width="120">
@ -647,16 +646,19 @@ export default {
}, },
// //
async saveQues () { async saveQues () {
const form = this.tempForm try {
const type = this.detailType const form = this.tempForm
// type: 1()234createNewVersion const type = this.detailType
const res = await this.$post(this.api[type === 4 ? 'createNewVersion' : type === 1 || !form.questionId ? 'addQuestion' : 'updateQuestion'], form) // type: 1()234createNewVersion
type === 4 && this.$emit('updateQues', this.tempForm, res.questionVersionId) const res = await this.$post(this.api[type === 4 ? 'createNewVersion' : type === 1 || !form.questionId ? 'addQuestion' : 'updateQuestion'], form)
type === 4 && this.$emit('updateQues', this.tempForm, res.questionVersionId)
Util.successMsg('保存成功')
this.submiting = false Util.successMsg('保存成功')
!form.questionId && this.keep ? this.init() : (this.quesVisible = false) !form.questionId && this.keep ? this.init() : (this.quesVisible = false)
this.repeatVisible = false this.repeatVisible = false
} finally {
this.submiting = false
}
}, },
// //
closeDia () { closeDia () {

@ -255,7 +255,7 @@ export default {
givenYearSort: '', givenYearSort: '',
difficultySort: '', difficultySort: '',
correctRateSort: '', correctRateSort: '',
updateTimeSort: '', updateTimeSort: 'desc',
referenceCountSort: '', referenceCountSort: '',
}, },
list: [], list: [],

@ -134,7 +134,8 @@
@update="e => updateSort(e, item)"> @update="e => updateSort(e, item)">
<div v-for="(ques, j) in item.examQuestions" :key="j" class="ques-item"> <div v-for="(ques, j) in item.examQuestions" :key="j" class="ques-item">
<el-checkbox v-model="ques.check"></el-checkbox> <el-checkbox v-model="ques.check"></el-checkbox>
<div :class="['ques-info', { disabled: !ques.status, del: ques.isDel, repeat: ques.isRepeat }]"> {{ ques.repeat }}
<div :class="['ques-info', { disabled: !ques.status, del: ques.isDel, repeat: ques.repeat }]">
<div class="top-line"> <div class="top-line">
<div class="labels"> <div class="labels">
<span class="label">{{ j + 1 }} / {{ item.examQuestions.length }}</span> <span class="label">{{ j + 1 }} / {{ item.examQuestions.length }}</span>
@ -189,25 +190,27 @@
<Manual :visible.sync="manualVisible" :questionType.sync="curType.questionType" /> <Manual :visible.sync="manualVisible" :questionType.sync="curType.questionType" />
<Auto :visible.sync="autoVisible" /> <Auto :visible.sync="autoVisible" />
<Detail :visible.sync="quesVisible" :row.sync="curRow" :detailType.sync="detailType" @updateQues="updateQues" /> <Detail :visible.sync="quesVisible" :row.sync="curRow" :detailType.sync="detailType" @updateQues="updateQues" />
<RepeatQues :visible.sync="repeatVisible" :list.sync="repeatQues" />
</div> </div>
</template> </template>
<script> <script>
import Setting from '@/setting'
import Util from '@/libs/util'
import dayjs from 'dayjs'
import Decimal from 'decimal.js'
import Draggable from 'vuedraggable' import Draggable from 'vuedraggable'
import UeditorPlus from '@/components/ueditorPlus' import UeditorPlus from '@/components/ueditorPlus'
import Breadcrumb from '@/components/breadcrumb' import Breadcrumb from '@/components/breadcrumb'
import QuesConst from '@/const/ques'
import TestPaperConst from '@/const/testPaper'
import Template from './template' import Template from './template'
import Manual from './manual' import Manual from './manual'
import Auto from './auto' import Auto from './auto'
import RepeatQues from './repeatQues'
import Detail from '@/pages/ques/detail' import Detail from '@/pages/ques/detail'
import Setting from '@/setting'
import Util from '@/libs/util'
import dayjs from 'dayjs'
import QuesConst from '@/const/ques'
import TestPaperConst from '@/const/testPaper'
import Decimal from 'decimal.js'
export default { export default {
components: { UeditorPlus, Breadcrumb, Template, Manual, Auto, Detail, Draggable }, components: { UeditorPlus, Breadcrumb, Template, Manual, Auto, RepeatQues, Detail, Draggable },
data () { data () {
return { return {
crumbs: [], crumbs: [],
@ -325,6 +328,7 @@ export default {
repeatVisible: false, repeatVisible: false,
repeatQues: [], repeatQues: [],
tempForm: {}, tempForm: {},
submiting: false,
}; };
}, },
computed: { computed: {
@ -338,60 +342,6 @@ export default {
} }
}, },
mounted () { mounted () {
function distributeScores (objects, totalScore) {
const numObjects = objects.length;
//
const baseScore = totalScore / numObjects;
const hasFraction = baseScore % 1 !== 0; //
//
for (let i = 0; i < numObjects; i++) {
objects[i].score = Math.floor(baseScore);
}
//
let fractionalPartSum = 0;
if (hasFraction) {
for (let i = 0; i < numObjects; i++) {
fractionalPartSum += baseScore % 1;
}
}
//
let remainingObjects = numObjects;
while (fractionalPartSum > 0) {
objects[--remainingObjects].score += 1;
fractionalPartSum -= 1;
}
//
if (totalScore < numObjects) {
//
const fractionalDistribution = Math.ceil(fractionalPartSum);
for (let i = 0; i < fractionalDistribution; i++) {
objects[i].score += 1;
}
}
return objects;
}
//
const objects = [
{ id: 1 },
{ id: 2 },
{ id: 3 },
{ id: 4 }
];
const totalScore = 3; //
const result = distributeScores(objects, totalScore);
console.log(result);
this.crumbs = [ this.crumbs = [
{ {
name: '试卷管理', name: '试卷管理',
@ -473,8 +423,8 @@ export default {
// //
questionTypeChange (row) { questionTypeChange (row) {
// 5 // 5
if (this.questionTypes.find(e => e.name === row.outlineName)) row.outlineName = this.questionTypes.find(e => e.id === row.questionType).name if (!row.outlineName || this.questionTypes.find(e => e.name === row.outlineName)) row.outlineName = this.questionTypes.find(e => e.id === row.questionType).name
}, },
// //
addLine (i) { addLine (i) {
@ -552,7 +502,7 @@ export default {
data.avgValueList.map((e, i) => { data.avgValueList.map((e, i) => {
// scores-1 // scores-1
if (!e.scores.includes(-1)) { if (!e.scores.includes(-1)) {
const stem = document.querySelector(`#stem` + e.questionId) const stem = document.querySelector(`#stem` + e.questionVersionId)
if (stem) { if (stem) {
const inputs = stem.querySelectorAll('.fill-input') const inputs = stem.querySelectorAll('.fill-input')
if (inputs) { if (inputs) {
@ -695,21 +645,37 @@ export default {
}, },
// //
hasRepeatQues (list) { hasRepeatQues (list) {
const result = list.filter(e => { list.forEach(e => {
if (e.questionType !== 'fill_blank' && e.questionType !== 'essay') { list.forEach(n => {
// ++ if (e.questionVersionId !== n.questionVersionId && !e.repeat) {
const opts = e.questionAnswerVersionsList // ++
// if (e.questionType !== 'fill_blank' && e.questionType !== 'essay') {
const first = opts[0].optionText //
const someOpt = opts.every(n => n.optionText === first) const opts = e.questionAnswerVersionsList
let diff = 0
return e.questionType === e.questionType && e.stem === e.stem && someOpt for (const j in opts) {
} else { // debugger
// /+ if (!n.questionAnswerVersionsList[j] || n.questionAnswerVersionsList[j].optionText !== opts[j].optionText) {
return (e.questionType === e.questionType && e.stem === e.stem) 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) {
e.repeat = true
n.repeat = true
}
}
}
})
})
const result = list.filter(e => e.repeat)
// //
if (result.length) { if (result.length) {
this.repeatVisible = true this.repeatVisible = true
@ -737,13 +703,12 @@ export default {
try { try {
await this.$post(this.api.saveExamPaper, this.tempForm) await this.$post(this.api.saveExamPaper, this.tempForm)
Util.successMsg('保存成功') Util.successMsg('保存成功')
this.submiting = false
this.back() this.back()
} catch (e) { } finally {
this.submiting = false this.submiting = false
} }
}, },
// //
async validForm (status) { async validForm (status) {
if (this.submiting) return false if (this.submiting) return false
const { isCopy } = this // const { isCopy } = this //
@ -819,11 +784,16 @@ export default {
invalid = 1 invalid = 1
break break
} }
e.examQuestions.map((n, j) => {
n.outlineName = e.outlineName
n.paperIndex = i
n.quesIndex = j
n.repeat = false
})
allQues.push(...e.examQuestions) allQues.push(...e.examQuestions)
} }
if (invalid) return false if (invalid) return false
} }
this.submiting = true this.submiting = true
form.particularYear = +(dayjs(form.particularYear).format('YYYY')) form.particularYear = +(dayjs(form.particularYear).format('YYYY'))
@ -877,8 +847,7 @@ export default {
if (isCopy) form.paperId = '' if (isCopy) form.paperId = ''
this.tempForm = form this.tempForm = form
// debugger if (this.hasRepeatQues(allQues)) return false
// if (this.hasRepeatQues(allQues)) return false
this.saveTestPaper() this.saveTestPaper()
}, },
// //
@ -982,8 +951,11 @@ export default {
} }
&.repeat { &.repeat {
border-color: #ff962a;
&:after { &:after {
content: '存在重复题'; content: '存在重复题';
background-color: #ff962a;
} }
} }
} }

@ -221,8 +221,8 @@ export default {
const el = document.createElement('div') const el = document.createElement('div')
el.innerHTML = e.stem el.innerHTML = e.stem
e.stemText = el.innerText e.stemText = el.innerText
e.check = !!this.checked.find(n => n.questionId === e.questionId) e.check = !!this.checked.find(n => n.questionVersionId === e.questionVersionId)
e.disabled = !!checked.find(n => n.questionVersionId === e.questionId) e.disabled = !!checked.find(n => n.questionVersionId === e.questionVersionId)
}) })
this.ques = data this.ques = data
} }
@ -253,7 +253,7 @@ export default {
}, },
// //
quesChange (val, item) { quesChange (val, item) {
const cur = this.checked.findIndex(e => e.questionId === item.questionId) const cur = this.checked.findIndex(e => e.questionVersionId === item.questionVersionId)
// //
if (val) { if (val) {
if (cur === -1) { if (cur === -1) {
@ -282,7 +282,7 @@ export default {
closeOnClickModal: false, closeOnClickModal: false,
}) })
checked.map(e => { checked.map(e => {
const cur = this.ques.find(n => n.questionId === e.questionId) const cur = this.ques.find(n => n.questionVersionId === e.questionVersionId)
if (cur) { if (cur) {
cur.check = false cur.check = false
} }
@ -304,9 +304,9 @@ export default {
// type: 'warning', // type: 'warning',
// closeOnClickModal: false, // closeOnClickModal: false,
// }) // })
const cur = this.ques.find(e => e.questionId === item.questionId) const cur = this.ques.find(e => e.questionVersionId === item.questionVersionId)
if (cur) cur.check = false if (cur) cur.check = false
this.checked.splice(this.checked.findIndex(e => e.questionId === item.questionId), 1) this.checked.splice(this.checked.findIndex(e => e.questionVersionId === item.questionVersionId), 1)
} catch (e) { } } catch (e) { }
}, },
// //
@ -332,14 +332,14 @@ export default {
if (!checked.length) return Util.warningMsg('请选择试题') if (!checked.length) return Util.warningMsg('请选择试题')
const { curType, curQuesIndex, curQues } = this.$parent const { curType, curQuesIndex, curQues } = this.$parent
if (this.checkedLen > +curType.questionNum) return Util.warningMsg(`目标题数为${curType.questionNum},已选题数不得大于目标题数`) if (!curQues && this.checkedLen > +curType.questionNum) return Util.warningMsg(`目标题数为${curType.questionNum},已选题数不得大于目标题数`)
try { try {
checked.map((e, i) => { checked.map((e, i) => {
this.$set(e, 'check', false) this.$set(e, 'check', false)
this.$set(e, 'sort', i + 1) this.$set(e, 'sort', i + 1)
this.$set(e, 'score', '') this.$set(e, 'score', '')
// this.$set(e, 'questionVersionId', e.questionId) // this.$set(e, 'questionVersionId', e.questionVersionId)
}) })
if (curQues) { if (curQues) {

@ -1,16 +1,20 @@
<template> <template>
<el-dialog title="提示" :visible.sync="listVisible" width="800px" :close-on-click-modal="false"> <el-dialog title="提示" :visible.sync="listVisible" width="800px" :close-on-click-modal="false" :show-close="false"
<el-alert title="以下试题在试卷中疑似出现重复,是否要继续发布!" type="warning" effect="dark" :closable="false"> @closed="closeDia">
</el-alert> <el-alert title="以下试题在试卷中疑似出现重复,是否要继续发布!" type="warning" effect="dark" :closable="false" />
<el-table class="m-t-10" :data="list" stripe header-align="center" row-key="id"> <el-table class="m-t-10" :data="data" stripe header-align="center" row-key="id">
<el-table-column prop="name" label="大题名称" align="center" width="90"></el-table-column> <el-table-column prop="outlineName" label="大题名称" align="center" width="90"></el-table-column>
<el-table-column prop="name" label="题号" align="center" width="60"></el-table-column> <el-table-column prop="serialNumber" label="题号" align="center" width="60"></el-table-column>
<el-table-column prop="stem" label="题干" align="center" min-width="120" show-overflow-tooltip></el-table-column> <el-table-column prop="stem" label="题干" align="center" min-width="120">
<template slot-scope="scope">
<div v-html="scope.row.stem"></div>
</template>
</el-table-column>
<el-table-column label="操作" align="center" width="240"> <el-table-column label="操作" align="center" width="240">
<template slot-scope="scope"> <template slot-scope="scope">
<el-button type="text">详情</el-button> <el-button type="text" @click="toQues(scope.row)">详情</el-button>
<el-button type="text">移除</el-button> <el-button type="text" @click="delQues(scope.row, scope.$index)">移除</el-button>
<el-button type="text">替换</el-button> <el-button type="text" @click="switchQues(scope.row, scope.$index)">替换</el-button>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
@ -22,15 +26,13 @@
</el-dialog> </el-dialog>
</template> </template>
<script> <script>
import Setting from '@/setting'
import Util from '@/libs/util'
import _ from 'lodash' import _ from 'lodash'
export default { export default {
props: ['visible', 'list'], props: ['visible', 'list'],
data () { data () {
return { return {
listVisible: false, listVisible: false,
// list: [], data: [],
submiting: false, submiting: false,
}; };
}, },
@ -45,32 +47,53 @@ export default {
}, },
methods: { methods: {
init () { init () {
this.data = this.list
}, },
// //
async getList () { toQues (row) {
const paper = this.$parent.form.paperOutline
this.$parent.toQues(paper[row.paperIndex], row.quesIndex, paper[row.paperIndex].examQuestions[row.quesIndex])
},
//
async delQues (row, i) {
try { try {
const res = await this.$post(this.api.examPaperTemplateList, { await this.$confirm(`确认要移除吗?`, '提示', {
pageNum: this.page, confirmButtonText: '确定',
pageSize: this.pageSize, cancelButtonText: '取消',
...this.filter type: 'warning',
closeOnClickModal: false,
}) })
this.list = res.pageList.records this.$parent.delQues(this.$parent.form.paperOutline[row.paperIndex], row.quesIndex)
this.total = res.pageList.total this.data.splice(i, 1)
} catch (e) { } } catch (e) { }
}, },
//
switchQues (row) {
const paper = this.$parent.form.paperOutline
this.$parent.showManualDia(paper[row.paperIndex], row.quesIndex, paper[row.paperIndex].examQuestions[row.quesIndex])
this.listVisible = false
},
// //
async check () { async check () {
const { list } = this
this.$parent.form.paperOutline.map(e => {
e.examQuestions.map(n => {
if (list.find(m => m.questionVersionId === n.questionVersionId)) this.$set(n, 'repeat', true)
})
})
this.$parent.submiting = false
this.listVisible = false this.listVisible = false
}, },
// //
async submit () { async submit () {
if (this.submiting) return false if (this.submiting) return false
this.submiting = true this.submiting = true
this.$parent.saveTestPaper() await this.$parent.saveTestPaper()
this.submiting = false
}, },
// //
closeDia () { closeDia () {
this.$parent.submiting = false
this.$emit('update:visible', false) this.$emit('update:visible', false)
} }
} }

@ -249,7 +249,7 @@ export default {
difficult: [], difficult: [],
professionalId: [], professionalId: [],
paperType: '', paperType: '',
updateTimeOrder: '', updateTimeOrder: 2,
crateTimeOrder: '', crateTimeOrder: '',
yearOrder: '', yearOrder: '',
keyWord: '', keyWord: '',
@ -408,6 +408,7 @@ export default {
async getList () { async getList () {
try { try {
this.listLoading = true this.listLoading = true
const type = this.$refs.typeTree
const res = await this.$post(this.api.examPaperList, { const res = await this.$post(this.api.examPaperList, {
...this.filter, ...this.filter,
isDisable: this.status === 2 ? '' : this.status, // isDisable: this.status === 2 ? '' : this.status, //
@ -418,7 +419,7 @@ export default {
pageNum: this.page, pageNum: this.page,
pageSize: this.pageSize, pageSize: this.pageSize,
libraryId: this.typeId, libraryId: this.typeId,
classificationId: this.$refs.typeTree.getCurrentKey() || '', classificationId: type ? type.getCurrentKey() || '' : '',
}) })
this.list = res.pageList.records this.list = res.pageList.records
this.total = res.pageList.total this.total = res.pageList.total

Loading…
Cancel
Save