yujialong 3 months ago
parent 0a07ceed91
commit b15d416d74
  1. 2
      public/static/ueditorPlus/plugins/gapfilling/gapfilling.js
  2. 12
      src/const/ques.js
  3. 356
      src/pages/ques/detail/index.vue
  4. 3
      src/pages/testPaper/detail/auto.vue
  5. 423
      src/pages/testPaper/detail/index.vue
  6. 30
      src/pages/testPaper/detail/manual.vue

@ -2,7 +2,7 @@
UE.registerUI('gapfilling', function (editor, uiName) { UE.registerUI('gapfilling', function (editor, uiName) {
editor.registerCommand(uiName, { editor.registerCommand(uiName, {
execCommand: function (cmdName, value) { execCommand: function (cmdName, value) {
editor.execCommand('insertHtml', `<span class="gapfilling-span" data-id="${Math.random() * 100000}">______</span>`) editor.execCommand('insertHtml', `<span class="gapfilling-span" data-id="${Date.now()}">______</span>`)
} }
}) })

@ -3,22 +3,26 @@ export default {
{ {
id: 'basic', id: 'basic',
name: '基础', name: '基础',
coefficient: 0.2 // 难度系数,试卷里计算试卷难度专用 coefficient: 0.2, // 难度系数,试卷里计算试卷难度专用
theme: 'success',
}, },
{ {
id: 'easy', id: 'easy',
name: '普通', name: '普通',
coefficient: 0.4 coefficient: 0.4,
theme: '',
}, },
{ {
id: 'medium', id: 'medium',
name: '较难', name: '较难',
coefficient: 0.6 coefficient: 0.6,
theme: 'warning',
}, },
{ {
id: 'hard', id: 'hard',
name: '难', name: '难',
coefficient: 0.8 coefficient: 0.8,
theme: 'danger',
}, },
], ],
questionTypes: [ questionTypes: [

@ -2,184 +2,188 @@
<div class="page h-full"> <div class="page h-full">
<Breadcrumb v-if="!paperType" :data="crumbs" /> <Breadcrumb v-if="!paperType" :data="crumbs" />
<p class="page-name mb">试题</p> <p class="page-name mb">试题</p>
<el-form :model="form" :rules="rules" :class="['input-form model', { paper: paperType }]" ref="form" <div v-loading="loading">
label-width="110px" :disabled="detailType === 2"> <el-form :model="form" :rules="rules" :class="['input-form model', { paper: paperType }]" ref="form"
<div class="item-line"> label-width="110px" :disabled="detailType === 2">
<template v-if="paperType === 1"> <div class="item-line">
<el-form-item prop="questionBankTypeId" label="题库分类"> <template v-if="paperType === 1">
<el-cascader placeholder="请选择题库分类" v-model="form.questionBankTypeId" :options="questionBankTypes" <el-form-item prop="questionBankTypeId" label="题库分类">
:props="{ value: 'id', label: 'name', checkStrictly: true }" clearable <el-cascader placeholder="请选择题库分类" v-model="form.questionBankTypeId" :options="questionBankTypes"
@change="getQuesBank"></el-cascader> :props="{ value: 'id', label: 'name', checkStrictly: true }" clearable
</el-form-item> @change="getQuesBank"></el-cascader>
<el-form-item prop="questionBankId" label="题库"> </el-form-item>
<el-select v-model="form.questionBankId" filterable placeholder="请选择题库" @change="getKnowledge"> <el-form-item prop="questionBankId" label="题库">
<el-option v-for="(item, i) in questionBanks" :key="i" :label="item.questionBankName" <el-select v-model="form.questionBankId" filterable placeholder="请选择题库" @change="getKnowledge">
:value="item.id"></el-option> <el-option v-for="(item, i) in questionBanks" :key="i" :label="item.questionBankName"
:value="item.id"></el-option>
</el-select>
</el-form-item>
</template>
<template v-else>
<el-form-item label="题库分类">
<el-input v-model="questionBankCategory" disabled />
</el-form-item>
<el-form-item label="题库">
<el-input v-model="questionBankName" disabled />
</el-form-item>
</template>
</div>
<div class="item-line">
<el-form-item prop="specialtyIds" label="所属专业">
<el-select v-model="form.specialtyIds" clearable multiple filterable placeholder="请选择所属专业">
<el-option v-for="(item, i) in professionals" :key="i" :label="item.professionalName"
:value="item.professionalId"></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
</template> <el-form-item prop="knowledgePointIds" label="所属知识点">
<template v-else> <el-cascader placeholder="请选择所属知识点" v-model="form.knowledgePointIds" :options="knowledges"
<el-form-item label="题库分类"> :props="{ value: 'id', label: 'name', multiple: true, checkStrictly: true }" :show-all-levels="false"
<el-input v-model="questionBankCategory" disabled /> filterable clearable></el-cascader>
</el-form-item> </el-form-item>
<el-form-item label="题库"> </div>
<el-input v-model="questionBankName" disabled /> <div class="item-line">
<el-form-item prop="givenYear" label="年份">
<el-date-picker v-model="form.givenYear" type="year" placeholder="请选择年份" format="yyyy" value-format="yyyy">
</el-date-picker>
</el-form-item> </el-form-item>
</template> <el-form-item prop="difficulty" label="难度">
</div> <el-select v-model="form.difficulty" clearable placeholder="请选择试卷难度">
<div class="item-line"> <el-option v-for="(item, i) in difficults" :key="i" :label="item.name" :value="item.id"></el-option>
<el-form-item prop="specialtyIds" label="所属专业"> </el-select>
<el-select v-model="form.specialtyIds" clearable multiple filterable placeholder="请选择所属专业"> </el-form-item>
<el-option v-for="(item, i) in professionals" :key="i" :label="item.professionalName" </div>
:value="item.professionalId"></el-option> <el-form-item prop="questionType" label="题型">
</el-select> <el-radio-group v-model="form.questionType" @change="questionTypeChange">
</el-form-item> <el-radio v-for="(item, i) in questionTypes" :key="i" :label="item.id">{{ item.name }}</el-radio>
<el-form-item prop="knowledgePointIds" label="所属知识点"> </el-radio-group>
<el-cascader placeholder="请选择所属知识点" v-model="form.knowledgePointIds" :options="knowledges"
:props="{ value: 'id', label: 'name', multiple: true, checkStrictly: true }" :show-all-levels="false"
filterable clearable></el-cascader>
</el-form-item>
</div>
<div class="item-line">
<el-form-item prop="givenYear" label="年份">
<el-date-picker v-model="form.givenYear" type="year" placeholder="请选择年份" format="yyyy" value-format="yyyy">
</el-date-picker>
</el-form-item>
<el-form-item prop="difficulty" label="难度">
<el-select v-model="form.difficulty" clearable placeholder="请选择试卷难度">
<el-option v-for="(item, i) in difficults" :key="i" :label="item.name" :value="item.id"></el-option>
</el-select>
</el-form-item> </el-form-item>
</div> <el-form-item class="is-required" prop="stem" label="题干">
<el-form-item prop="questionType" label="题型"> <UeditorPlus ref="stem" :config="editorConfig" @ready="stemReady" v-model="form.stem" />
<el-radio-group v-model="form.questionType" @change="questionTypeChange">
<el-radio v-for="(item, i) in questionTypes" :key="i" :label="item.id">{{ item.name }}</el-radio> <Upload v-if="form.questionType === 'essay'" class="m-t-10"
</el-radio-group> accept=".csv,.xlsx,.xls,.docx,.doc,.pdf,.jpg,.png,.zip,.rar,.7z" :max-size="50" :file-list="uploadList"
</el-form-item> :on-remove="handleRemove" @onSuccess="uploadSuccess">
<el-form-item class="is-required" prop="stem" label="题干"> <div slot="trigger">
<UeditorPlus ref="stem" :config="editorConfig" @ready="stemReady" v-model="form.stem" /> <el-button type="primary">上传题干文件</el-button>
<Upload v-if="form.questionType === 'essay'" class="m-t-10"
accept=".csv,.xlsx,.xls,.docx,.doc,.pdf,.jpg,.png,.zip,.rar,.7z" :max-size="50" :file-list="uploadList"
:on-remove="handleRemove" @onSuccess="uploadSuccess">
<div slot="trigger">
<el-button type="primary">上传题干文件</el-button>
</div>
<template slot="tip">
<p>支持.csv.xlsx .docx .pdf .jpg .zip 等常见文件格式上传文件大小不能超过50MB</p>
</template>
</Upload>
</el-form-item>
<!-- 单选多选判断特有 -->
<el-form-item v-if="form.questionType !== 'fill_blank' && form.questionType !== 'essay'"
prop="questionAnswerVersions" label="正确答案">
<div class="opts">
<div v-for="(item, i) in form.questionAnswerVersions" :key="i" class="opt">
<el-checkbox v-if="form.questionType === 'multiple_choice'" class="correct-check"
v-model="item.answerIsCorrect" :true-label="1">选项{{ numToLetter(i) }}</el-checkbox>
<el-radio v-else v-model="item.answerIsCorrect" :true-label="1" :label="1" @change="correctChange(i)">选项{{
numToLetter(i)
}}</el-radio>
<div v-if="!item.focus" class="opt-input" @click="optFocus(item)">
<div v-if="item.optionText" v-html="item.optionText"></div>
<p v-else class="default">请输入</p>
</div> </div>
<UeditorPlus v-else class="opt-editor" :ref="'opt' + item.optionNumber" :config="editorConfig" <template slot="tip">
v-model="item.optionText" @ready="editor => optReady(editor, item)" /> <p>支持.csv.xlsx .docx .pdf .jpg .zip 等常见文件格式上传文件大小不能超过50MB</p>
<template v-if="form.questionType !== 'judgement'">
<i class="icon el-icon-circle-plus-outline m-t-8" @click="addOpt(i)"></i>
<i v-if="form.questionAnswerVersions.length > 2" class="icon el-icon-remove-outline m-t-8"
@click="delOpt(i)"></i>
</template> </template>
</div> </Upload>
</div> </el-form-item>
</el-form-item>
<!-- 填空题特有 -->
<template v-if="form.questionType === 'fill_blank'">
<el-form-item label="正确答案" required>
<div class="opts fill-blanks">
<div v-for="(item, i) in fillBlanks" :key="i" class="opt j-between">
<div class="fills">
<span>填空{{ i + 1 }}</span>
<div v-if="item.fills" class="fill-items">
<div v-for="(fill, j) in item.fills" :key="j" class="fill-item">
<el-input type="textarea" autosize resize="none" placeholder="请输入" v-model="fill.val" />
<span v-if="j !== item.fills.length - 1" class="m-r-8"></span>
<i v-if="j" class="action-icon el-icon-remove-outline" @click="item.fills.splice(j, 1)"></i>
</div>
</div>
<el-button class="add-fill" type="primary" size="small" @click="addFill(item)">新增答案</el-button> <!-- 单选多选判断特有 -->
</div> <el-form-item v-if="form.questionType !== 'fill_blank' && form.questionType !== 'essay'"
<div class="score-wrap"> prop="questionAnswerVersions" label="正确答案">
<span>分值占比</span> <div class="opts">
<el-input class="score" placeholder="请输入" size="small" v-model="item.scoreProportion" /> <div v-for="(item, i) in form.questionAnswerVersions" :key="i" class="opt">
<span>%</span> <el-checkbox v-if="form.questionType === 'multiple_choice'" class="correct-check"
v-model="item.answerIsCorrect" :true-label="1">选项{{ numToLetter(i) }}</el-checkbox>
<el-radio v-else v-model="item.answerIsCorrect" :true-label="1" :label="1" @change="correctChange(i)">选项{{
numToLetter(i)
}}</el-radio>
<div v-if="!item.focus" class="opt-input" @click="optFocus(item)">
<div v-if="item.optionText" v-html="item.optionText"></div>
<p v-else class="default">请输入</p>
</div> </div>
<UeditorPlus v-else class="opt-editor" :ref="'opt' + item.optionNumber" :config="editorConfig"
v-model="item.optionText" @ready="editor => optReady(editor, item)" />
<template v-if="form.questionType !== 'judgement'">
<i class="icon el-icon-circle-plus-outline m-t-8" @click="addOpt(i)"></i>
<i v-if="form.questionAnswerVersions.length > 2" class="icon el-icon-remove-outline m-t-8"
@click="delOpt(i)"></i>
</template>
</div> </div>
</div> </div>
</el-form-item> </el-form-item>
<el-form-item label="判分标准" class="is-required">
<el-select :value="form.questionAnswerVersions[0].gradingStandard" placeholder="请选择判分标准" disabled> <!-- 填空题特有 -->
<el-option label="完全一致" value="exact_match"></el-option> <template v-if="form.questionType === 'fill_blank'">
</el-select> <el-form-item label="正确答案" required>
</el-form-item> <div class="opts fill-blanks">
<el-form-item label="判分规则"> <div v-for="(item, i) in fillBlanks" :key="i" class="opt j-between">
<div> <div class="fills">
<el-switch disabled active-text="判分时忽略答案中的字母大小写"></el-switch> <span>填空{{ i + 1 }}</span>
</div> <div v-if="item.fills" class="fill-items">
<div> <div v-for="(fill, j) in item.fills" :key="j" class="fill-item">
<el-switch disabled active-text="判分时忽略答案中的空格"></el-switch> <el-input type="textarea" autosize resize="none" placeholder="请输入" v-model="fill.val" />
</div> <span v-if="j !== item.fills.length - 1" class="m-r-8"></span>
<div> <i v-if="j" class="action-icon el-icon-remove-outline" @click="item.fills.splice(j, 1)"></i>
<el-switch disabled active-text="允许学生每个填空的答案与正确答案的顺序不一致"></el-switch> </div>
</div> </div>
<div>
<el-switch disabled active-text="判分时允许数值相等"></el-switch> <el-button class="add-fill" type="primary" size="small" @click="addFill(item)">新增答案</el-button>
</div> </div>
</el-form-item> <div class="score-wrap">
</template> <span>分值占比</span>
<el-input class="score" placeholder="请输入" size="small" v-model="item.scoreProportion" />
<!-- 问答题特有 --> <span>%</span>
<template v-if="form.questionType === 'essay'"> </div>
<el-form-item prop="allowAttachment" label="支持学生上传附件" label-width="140px"> </div>
<el-radio-group v-model="form.allowAttachment"> </div>
<el-radio :label="0"></el-radio> </el-form-item>
<el-radio :label="1"></el-radio> <el-form-item label="判分标准" class="is-required">
</el-radio-group> <el-select :value="form.questionAnswerVersions[0].gradingStandard" placeholder="请选择判分标准" disabled>
</el-form-item> <el-option label="完全一致" value="exact_match"></el-option>
<el-form-item v-if="form.allowAttachment" prop="uploadInstructions" label="上传要求说明"> </el-select>
<UeditorPlus ref="uploadInstructions" :config="editorConfig" @ready="uploadInstructionsReady" </el-form-item>
v-model="form.uploadInstructions" /> <el-form-item label="判分规则">
</el-form-item> <div>
<el-form-item label="判分标准" class="is-required"> <el-switch disabled active-text="判分时忽略答案中的字母大小写"></el-switch>
<el-select :value="form.questionAnswerVersions[0].gradingStandard" placeholder="请选择判分标准" disabled> </div>
<el-option label="人工判分" value="manual"></el-option> <div>
</el-select> <el-switch disabled active-text="判分时忽略答案中的空格"></el-switch>
</el-form-item> </div>
<el-form-item prop="referenceAnswer" label="参考答案"> <div>
<UeditorPlus ref="referenceAnswer" :config="editorConfig" @ready="referenceAnswerReady" <el-switch disabled active-text="允许学生每个填空的答案与正确答案的顺序不一致"></el-switch>
v-model="form.questionAnswerVersions[0].referenceAnswer" /> </div>
<div>
<el-switch disabled active-text="判分时允许数值相等"></el-switch>
</div>
</el-form-item>
</template>
<!-- 问答题特有 -->
<template v-if="form.questionType === 'essay'">
<el-form-item prop="allowAttachment" label="支持学生上传附件" label-width="140px">
<el-radio-group v-model="form.allowAttachment">
<el-radio :label="0"></el-radio>
<el-radio :label="1"></el-radio>
</el-radio-group>
</el-form-item>
<el-form-item v-if="form.allowAttachment" prop="uploadInstructions" label="上传要求说明">
<UeditorPlus ref="uploadInstructions" :config="editorConfig" @ready="uploadInstructionsReady"
v-model="form.uploadInstructions" />
</el-form-item>
<el-form-item label="判分标准" class="is-required">
<el-select :value="form.questionAnswerVersions[0].gradingStandard" placeholder="请选择判分标准" disabled>
<el-option label="人工判分" value="manual"></el-option>
</el-select>
</el-form-item>
<el-form-item prop="referenceAnswer" label="参考答案">
<UeditorPlus ref="referenceAnswer" :config="editorConfig" @ready="referenceAnswerReady"
v-model="form.questionAnswerVersions[0].referenceAnswer" />
</el-form-item>
</template>
<el-form-item prop="answerAnalysis" label="解析">
<UeditorPlus ref="answerAnalysis" :config="editorConfig" @ready="answerAnalysisReady"
v-model="answerAnalysis" />
</el-form-item> </el-form-item>
</template> </el-form>
<div class="btns">
<el-form-item prop="answerAnalysis" label="解析"> <template v-if="detailType !== 2">
<UeditorPlus ref="answerAnalysis" :config="editorConfig" @ready="answerAnalysisReady" <el-button v-if="detailType === 1" type="primary" :loading="submiting && keep === 0"
v-model="answerAnalysis" /> @click="submit(1)">保存</el-button>
</el-form-item> <template v-else>
</el-form> <el-button type="primary" :loading="submiting && keep === 0" @click="submit(0)">保存</el-button>
<div v-if="detailType !== 2" class="btns"> <el-button type="primary" :loading="submiting && keep === 1" @click="submit(1)">{{ questionId ? '保存并同步更新相似题'
<el-button v-if="detailType === 1" type="primary" :loading="submiting && keep === 0" :
@click="submit(1)">保存</el-button> '保存并继续新增' }}</el-button>
<template v-else> </template>
<el-button type="primary" :loading="submiting && keep === 0" @click="submit(0)">保存</el-button> </template>
<el-button type="primary" :loading="submiting && keep === 1" @click="submit(1)">{{ questionId ? '保存并同步更新相似题' <el-button @click="back">{{ detailType !== 2 ? '取消' : '返回' }}</el-button>
: </div>
'保存并继续新增' }}</el-button>
</template>
<el-button @click="back">取消</el-button>
</div> </div>
<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">
@ -216,6 +220,7 @@ import Oss from '@/components/upload/upload.js'
import dayjs from 'dayjs' import dayjs from 'dayjs'
import _ from 'lodash' import _ from 'lodash'
import Const from '@/const/ques' import Const from '@/const/ques'
import Decimal from 'decimal.js'
export default { export default {
props: ['paperType', 'curQues'], // props: ['paperType', 'curQues'], //
components: { Breadcrumb, UeditorPlus, Upload }, components: { Breadcrumb, UeditorPlus, Upload },
@ -229,6 +234,7 @@ export default {
questionBankCategory: this.$route.query.questionBankCategory, questionBankCategory: this.$route.query.questionBankCategory,
detailType: +this.$route.query.detailType, detailType: +this.$route.query.detailType,
numToLetter: Util.numToLetter, numToLetter: Util.numToLetter,
loading: false,
questionBankTypes: [], questionBankTypes: [],
questionBanks: [], questionBanks: [],
professionals: [], professionals: [],
@ -328,6 +334,7 @@ export default {
} else if (this.curQues) { } else if (this.curQues) {
this.questionId = this.curQues.questionId this.questionId = this.curQues.questionId
this.version = this.curQues.version this.version = this.curQues.version
if (this.paperType === 3) this.detailType = 2
} }
this.editorConfig = this.paperType ? { this.editorConfig = this.paperType ? {
@ -342,6 +349,7 @@ export default {
methods: { methods: {
// //
init (v) { init (v) {
this.loading = true
this.form = _.cloneDeep(this.originForm) this.form = _.cloneDeep(this.originForm)
const type = this.detailType const type = this.detailType
@ -419,16 +427,19 @@ export default {
}] }]
} }
// //
if (this.paperType === 2) { if (this.paperType > 1) {
this.questionBankName = r.questionBankName this.questionBankName = r.questionBankName
console.log("🚀 ~ getKnowledge ~ id:", this.form)
// this.questionBankCategory = r.questionBankCategory // this.questionBankCategory = r.questionBankCategory
this.$nextTick(() => { this.$nextTick(() => {
this.getKnowledge() this.getKnowledge()
}) })
} }
} else {
this.loading = false
} }
} catch (e) { } } finally {
this.loading = false
}
}, },
// //
async getKnowledge () { async getKnowledge () {
@ -595,9 +606,10 @@ export default {
let gapfillingItems = content.match(spanRegex) let gapfillingItems = content.match(spanRegex)
if (gapfillingItems !== null) { if (gapfillingItems !== null) {
gapfillingItems.forEach(function (span, index) { gapfillingItems.forEach(function (span, index) {
const pairRegex = /<span class="gapfilling-span" (.*?)">(.*?)______(.*?)<\/span>/ let pairRegex = /<span class="gapfilling-span" data-id="(.*?)">(.*?)______(.*?)<\/span>/
if (span.includes('data-id')) pairRegex = /<span class="gapfilling-span" (.*?)">(.*?)______(.*?)<\/span>/
pairRegex.test(span) pairRegex.test(span)
newFormItem.push({ fills: [{ val: '' }], uuid: RegExp.$1, scoreProportion: '0' }) newFormItem.push({ fills: [{ val: '' }], uuid: RegExp.$1, scoreProportion: '' })
}) })
newFormItem.forEach(e => { newFormItem.forEach(e => {
@ -650,13 +662,17 @@ export default {
if (invalid) return false if (invalid) return false
if (!opt.find(e => e.answerIsCorrect)) return Util.warningMsg('请设置正确答案') if (!opt.find(e => e.answerIsCorrect)) return Util.warningMsg('请设置正确答案')
} else if (form.questionType === 'fill_blank') { } else if (form.questionType === 'fill_blank') {
let scorePro = 0
for (const e of blanks) { for (const e of blanks) {
if (e.fills.every(n => !n.val)) { if (e.fills.every(n => !n.val)) {
Util.warningMsg('请输入填空项正确答案') Util.warningMsg('请输入填空项正确答案')
invalid = 1 invalid = 1
break break
} }
const pro = e.scoreProportion
if (pro && !isNaN(pro)) scorePro = Decimal(scorePro).add(pro || 0).toNumber()
} }
if (scorePro && scorePro !== 100) return Util.warningMsg('分值占比不满100,请重新调整')
} }
this.submiting = true this.submiting = true

@ -578,7 +578,8 @@ export default {
res.list[i].questions.map((e, i) => { res.list[i].questions.map((e, i) => {
// e.questionVersionId = e.id // e.questionVersionId = e.id
e.serialNumber = i + 1 e.serialNumber = i + 1
this.$parent.handleFillScore(e) e.originSort = i + 1
this.$parent.handleQuesInfo(e)
}) })
this.$parent.form.paperOutline[i].examQuestions = res.list[i].questions this.$parent.form.paperOutline[i].examQuestions = res.list[i].questions
}) })

@ -1,209 +1,219 @@
<template> <template>
<div class="page"> <div class="page">
<Breadcrumb :data="crumbs" /> <Breadcrumb :data="crumbs" />
<el-form :model="form" :rules="rules" class="input-form model" ref="form" label-width="140px"> <div v-loading="loading">
<p class="page-name mb">试卷基础信息</p> <el-form :model="form" :rules="rules" class="input-form model" ref="form" label-width="140px">
<el-form-item prop="name" label="试卷名称"> <p class="page-name mb">试卷基础信息</p>
<el-input style="width: 940px" placeholder="请输入试卷名称" v-model="form.name" clearable maxlength="100" /> <el-form-item prop="name" label="试卷名称">
</el-form-item> <el-input style="width: 940px" placeholder="请输入试卷名称" v-model="form.name" clearable maxlength="100" />
<div class="item-line">
<el-form-item prop="particularYear" label="年份">
<el-date-picker v-model="form.particularYear" type="year" placeholder="请选择年份" format="yyyy"
value-format="yyyy">
</el-date-picker>
</el-form-item> </el-form-item>
<el-form-item prop="classificationId" label="所属试卷分类"> <div class="item-line">
<el-cascader filterable placeholder="请选择所属试卷分类" :options="types" v-model="form.classificationId" <el-form-item prop="particularYear" label="年份">
:props="cascaderProps" style="width: 100%"> <el-date-picker v-model="form.particularYear" type="year" placeholder="请选择年份" format="yyyy"
</el-cascader> value-format="yyyy">
</el-form-item> </el-date-picker>
</div> </el-form-item>
<div class="item-line"> <el-form-item prop="classificationId" label="所属试卷分类">
<el-form-item prop="paperType" label="建议用途"> <el-cascader filterable placeholder="请选择所属试卷分类" :options="types" v-model="form.classificationId"
<el-select v-model="form.paperType" clearable placeholder="请选择建议用途"> :props="cascaderProps" style="width: 100%">
<el-option v-for="(item, i) in paperTypes" :key="i" :label="item.name" :value="item.id"></el-option> </el-cascader>
</el-select> </el-form-item>
</el-form-item> </div>
<el-form-item prop="suggestTime" label="估计用时"> <div class="item-line">
<el-input placeholder="请输入估计用时" v-model.number="form.suggestTime"> <el-form-item prop="paperType" label="建议用途">
<template slot="append">分钟</template> <el-select v-model="form.paperType" clearable placeholder="请选择建议用途">
</el-input> <el-option v-for="(item, i) in paperTypes" :key="i" :label="item.name" :value="item.id"></el-option>
</el-form-item> </el-select>
</div> </el-form-item>
<div class="item-line"> <el-form-item prop="suggestTime" label="估计用时">
<el-form-item prop="professionals" label="所属专业"> <el-input placeholder="请输入估计用时" v-model.number="form.suggestTime">
<el-select v-model="form.professionalId" filterable multiple clearable placeholder="请选择所属专业"> <template slot="append">分钟</template>
<el-option v-for="(item, i) in professionals" :key="i" :label="item.professionalName" </el-input>
:value="item.professionalId" filter></el-option> </el-form-item>
</el-select> </div>
</el-form-item> <div class="item-line">
<el-form-item prop="difficult" label="试卷难度"> <el-form-item prop="professionals" label="所属专业">
<el-select v-model="form.difficult" clearable placeholder="系统自动评估,也可手动选择" <el-select v-model="form.professionalId" filterable multiple clearable placeholder="请选择所属专业">
@change="val => difficultSelected = !!val"> <el-option v-for="(item, i) in professionals" :key="i" :label="item.professionalName"
<el-option v-for="(item, i) in difficults" :key="i" :label="item.name" :value="item.id"></el-option> :value="item.professionalId" filter></el-option>
</el-select> </el-select>
<el-tooltip placement="top"> </el-form-item>
<div class="diff-text" slot="content"> <el-form-item prop="difficult" label="试卷难度">
<p>基础题难度系数0.2</p> <el-select v-model="form.difficult" clearable placeholder="系统自动评估,也可手动选择"
<p>普通题难度系数0.4</p> @change="val => difficultSelected = !!val">
<p>较难题难度系数0.6</p> <el-option v-for="(item, i) in difficults" :key="i" :label="item.name" :value="item.id"></el-option>
<p>困难题难度系数0.8</p> </el-select>
<p>1<span class="em">题型难度系数</span>=对应题型所有试题的难度系数之和/总试题数</p> <el-tooltip placement="top">
<p>2<span class="em">试卷总难度系数</span>=所有试题的难度系数之和/总试题数</p> <div class="diff-text" slot="content">
<p>3<span class="em">难度系数评价</span></p> <p>基础题难度系数0.2</p>
<div class="coe"> <p>普通题难度系数0.4</p>
<p>简单系数 &lt;=0.3</p> <p>较难题难度系数0.6</p>
<p>普通0.3&lt;系数&lt;=0.4</p> <p>困难题难度系数0.8</p>
<p>较难0.4&lt;系数&lt;0.5</p> <p>1<span class="em">题型难度系数</span>=对应题型所有试题的难度系数之和/总试题数</p>
<p>困难:系数&gt;=0.5</p> <p>2<span class="em">试卷总难度系数</span>=所有试题的难度系数之和/总试题数</p>
<p>3<span class="em">难度系数评价</span></p>
<div class="coe">
<p>简单系数 &lt;=0.3</p>
<p>普通0.3&lt;系数&lt;=0.4</p>
<p>较难0.4&lt;系数&lt;0.5</p>
<p>困难:系数&gt;=0.5</p>
</div>
</div> </div>
</div> <i class="el-icon-question m-l-10" style="font-size: 16px;color: #8f8f8f;cursor: pointer;"></i>
<i class="el-icon-question m-l-10" style="font-size: 16px;color: #8f8f8f;cursor: pointer;"></i> </el-tooltip>
</el-tooltip> </el-form-item>
</div>
<el-form-item prop="remarks" label="试卷说明">
<UeditorPlus ref="remarks" @ready="remarksReady" />
</el-form-item> </el-form-item>
</div>
<el-form-item prop="remarks" label="试卷说明">
<UeditorPlus ref="remarks" @ready="remarksReady" />
</el-form-item>
<div class="line"></div> <div class="line"></div>
<p class="page-name mb">试卷大纲</p> <p class="page-name mb">试卷大纲</p>
<div class="relative text-center m-b-40"> <div class="relative text-center m-b-40">
<p class="fs-16">{{ templateName }}</p> <p class="fs-16">{{ templateName }}</p>
<el-button class="tem-btn" type="primary" size="small" @click="showTemplate">选择大纲模板</el-button> <el-button class="tem-btn" type="primary" size="small" @click="showTemplate">选择大纲模板</el-button>
</div> </div>
<el-table :data="form.paperOutline" stripe header-align="center" row-key="id"> <el-table :data="form.paperOutline" 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 label="大题" align="center" min-width="120"> <el-table-column label="大题" align="center" min-width="120">
<template slot-scope="scope">{{ arabicToChinese(scope.$index + 1) }}大题</template> <template slot-scope="scope">{{ arabicToChinese(scope.$index + 1) }}大题</template>
</el-table-column> </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">
<template slot-scope="scope"> <template slot-scope="scope">
<el-select v-model="scope.row.questionType" placeholder="请选择题型" @change="questionTypeChange(scope.row)"> <el-select v-model="scope.row.questionType" placeholder="请选择题型" @change="questionTypeChange(scope.row)">
<el-option v-for="(item, i) in questionTypes" :key="i" :label="item.name" :value="item.id"></el-option> <el-option v-for="(item, i) in questionTypes" :key="i" :label="item.name" :value="item.id"></el-option>
</el-select> </el-select>
</template> </template>
</el-table-column> </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">
<template slot-scope="scope"> <template slot-scope="scope">
<el-input placeholder="请输入目标题数" v-model.number="scope.row.questionNum" type="number" /> <el-input placeholder="请输入目标题数" v-model.number="scope.row.questionNum" type="number" />
</template> </template>
</el-table-column> </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">
<template slot-scope="scope"> <template slot-scope="scope">
<el-input placeholder="请输入目标分值" v-model="scope.row.targetScore" /> <el-input placeholder="请输入目标分值" v-model="scope.row.targetScore" />
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="操作" align="center" width="120"> <el-table-column label="操作" align="center" width="120">
<template slot-scope="scope"> <template slot-scope="scope">
<i class="el-icon-circle-plus-outline action-icon m-r-10" @click="addLine(scope.$index)"></i> <i class="el-icon-circle-plus-outline action-icon m-r-10" @click="addLine(scope.$index)"></i>
<i v-if="form.paperOutline.length > 1" class="el-icon-remove-outline action-icon" <i v-if="form.paperOutline.length > 1" class="el-icon-remove-outline action-icon"
@click="delLine(scope.$index)"></i> @click="delLine(scope.$index)"></i>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
<p class="m-t-10 m-b-20 text-right">目标总题数{{ questionCount }}目标总分{{ score }}</p> <p class="m-t-10 m-b-20 text-right">目标总题数{{ questionCount }}目标总分{{ score }}</p>
<div class="line"></div> <div class="line"></div>
<div class="flex j-between a-center"> <div class="flex j-between a-center">
<h6 class="page-name" style="margin-bottom: 0">试卷试题</h6> <h6 class="page-name" style="margin-bottom: 0">试卷试题</h6>
<div> <div>
<el-button type="primary" @click="allocationAll">一键分配分值</el-button> <el-button type="primary" @click="allocationAll">一键分配分值</el-button>
<el-button type="primary" @click="showAuto">自动选题</el-button> <el-button type="primary" @click="showAuto">自动选题</el-button>
</div>
</div> </div>
</div>
<ul class="ques"> <ul class="ques">
<li v-for="(item, i) in form.paperOutline" :key="i"> <li v-for="(item, i) in form.paperOutline" :key="i">
<div class="top"> <div class="top">
<div> <div>
<span class="serial">{{ arabicToChinese(i + 1) }}大题</span> <span class="serial">{{ arabicToChinese(i + 1) }}大题</span>
<el-input placeholder="请输入大题名称" v-model="item.outlineName" /> <el-input placeholder="请输入大题名称" v-model="item.outlineName" />
</div> </div>
<div> <div>
<el-button type="primary" @click="allocation(item)">一键分配分值</el-button> <el-button type="primary" @click="allocation(item)">一键分配分值</el-button>
<el-button type="primary" @click="showManualDia(item)">批量添加</el-button> <el-button type="primary" @click="showManualDia(item)">批量添加</el-button>
<el-button type="danger" @click="batchDelQues(item)">批量移除试题</el-button> <el-button type="danger" @click="batchDelQues(item)">批量移除试题</el-button>
<img :class="['shrink', { active: item.shrink }]" src="@/assets/images/shrink.svg" alt="" <img :class="['shrink', { active: item.shrink }]" src="@/assets/images/shrink.svg" alt=""
@click="item.shrink = !item.shrink"> @click="item.shrink = !item.shrink">
</div>
</div> </div>
</div> <p class="sum">本大题共{{ item.questionNum }}小题{{ item.targetScore }}</p>
<p class="sum">本大题共{{ item.questionNum }}小题{{ item.targetScore }}</p> <el-checkbox v-if="item.examQuestions && item.examQuestions.length" class="m-l-15" v-model="item.checkAll"
<el-checkbox v-if="item.examQuestions && item.examQuestions.length" class="m-l-15" v-model="item.checkAll" @change="e => item.examQuestions.map(n => n.check = e)">全选</el-checkbox>
@change="e => item.examQuestions.map(n => n.check = e)">全选</el-checkbox>
<div :class="['ques-wrap', { hide: item.shrink }]">
<div :class="['ques-wrap', { hide: item.shrink }]"> <draggable v-model="item.examQuestions" :group="dragGroup" chosenClass="chosen" animation="1000"
<draggable v-model="item.examQuestions" :group="dragGroup" chosenClass="chosen" animation="1000" @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> {{ ques.repeat }}
{{ ques.repeat }} <div :class="['ques-info', { disabled: !ques.status, del: ques.isDel, repeat: 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="stem-info">
<div class="stem-info"> <div class="labels">
<div class="labels"> <span class="label">{{ j + 1 }} / {{ item.examQuestions.length }}</span>
<span class="label">{{ j + 1 }} / {{ item.examQuestions.length }}</span> <span class="label">{{ questionTypes.find(e => e.id === item.questionType).name }}</span>
<span class="label">{{ questionTypes.find(e => e.id === item.questionType).name }}</span> <span v-if="ques.givenYear" class="label">{{ ques.givenYear }}</span>
</div>
<el-tag v-if="ques.difficult" :type="ques.difficultTheme">{{ ques.difficult }}</el-tag>
</div> </div>
<div class="stem" :id="'stem' + ques.questionVersionId" v-html="ques.stem"></div>
</div>
</div>
<!-- 单选多选判断的选项 --> <div class="actions">
<template <p v-if="item.questionType !== 'fill_blank'" class="m-r-10 input-wrap">
v-if="item.questionType !== 'fill_blank' && item.questionType !== 'essay' && ques.questionAnswerVersionsList"> <el-input class="l-input" placeholder="请输入分值" v-model="ques.score" /></p>
<div v-for="(opt, j) in ques.questionAnswerVersionsList" :key="j" class="opt">
<span>{{ numToLetter(j) }}.&nbsp;</span> <el-popover v-else placement="bottom" width="400" trigger="click">
<div class="text" v-html="opt.optionText"></div> <div v-if="ques.fillScores" 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)" />&emsp;填空项{{ k + 1 }}
</div>
</div>
<div slot="reference" class="input-wrap">
查看每空分值<el-input class="l-input" placeholder="请输入分值" v-model="ques.score" readonly />
</div>
</el-popover>
<el-button type="text" @click="toQues(item, j, ques)">编辑试题</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>
<div class="input-wrap">
<span>排序</span>
<el-input class="l-input sort-input" v-model="ques.serialNumber"
@change="sortChange(item, ques)" />
</div>
</div>
</div> </div>
</template> <div class="stem" :id="'stem' + ques.questionVersionId" v-html="ques.stem"></div>
<!-- 单选多选判断的选项 -->
<template
v-if="item.questionType !== 'fill_blank' && item.questionType !== 'essay' && ques.questionAnswerVersionsList">
<div v-for="(opt, j) in ques.questionAnswerVersionsList" :key="j" class="opt">
<span>{{ numToLetter(j) }}.&nbsp;</span>
<div class="text" v-html="opt.optionText"></div>
</div>
</template>
<div class="bottom-line"> <div class="bottom-line">
<div class="correct">
{{ item.questionType === 'essay' ? '参考答案' : '正确答案' }} {{ item.questionType === 'essay' ? '参考答案' : '正确答案' }}
<div v-html="getCorrectAnswer(ques)"></div> <div v-html="getCorrectAnswer(ques)" class="ans"></div>
</div> </div>
</div>
<div class="actions"> <div v-if="ques.knowledgePointList && ques.knowledgePointList.length" class="bottom-line">
<p v-if="item.questionType !== 'fill_blank'" class="m-r-10 input-wrap"> <span>知识点</span>
<el-input class="l-input" placeholder="请输入分值" v-model="ques.score" /></p> <el-tag v-for="(kp, k) in ques.knowledgePointList" :key="k" class="m-r-5" type="info"
effect="plain">{{
<el-popover v-else placement="bottom" width="400" trigger="click"> kp.name }}</el-tag>
<div v-if="ques.fillScores" 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)" />&emsp;填空项{{ k + 1 }}
</div>
</div>
<div slot="reference" class="input-wrap">
查看每空分值<el-input class="l-input" placeholder="请输入分值" v-model="ques.score" readonly />
</div>
</el-popover>
<el-button type="text" @click="toQues(item, j, ques)">编辑试题</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>
<div class="input-wrap">
<span>排序</span>
<el-input class="l-input sort-input" v-model="ques.serialNumber"
@change="sortChange(item, ques)" />
</div> </div>
</div> </div>
</div> </div>
</div> </draggable>
</draggable> </div>
</div> </li>
</li> </ul>
</ul> </el-form>
</el-form> <div class="btns">
<div class="btns"> <el-button @click="submit(0)">保存草稿</el-button>
<el-button @click="submit(0)">保存草稿</el-button> <el-button type="primary" @click="submit(1)">发布</el-button>
<el-button type="primary" @click="submit(1)">发布</el-button> <el-button v-if="paperId" @click="preview">预览</el-button>
<el-button v-if="paperId" @click="preview">预览</el-button> <el-button @click="back">取消</el-button>
<el-button @click="back">取消</el-button> </div>
</div> </div>
<Template :visible.sync="templateVisible" /> <Template :visible.sync="templateVisible" />
@ -248,6 +258,7 @@ export default {
paperId: this.$route.query.paperId, paperId: this.$route.query.paperId,
libraryId: this.$route.query.libraryId, libraryId: this.$route.query.libraryId,
isCopy: this.$route.query.isCopy, isCopy: this.$route.query.isCopy,
loading: false,
headers: { headers: {
token: Util.local.get(Setting.tokenKey) token: Util.local.get(Setting.tokenKey)
}, },
@ -400,6 +411,7 @@ export default {
try { try {
const { paperId } = this const { paperId } = this
if (paperId) { if (paperId) {
this.loading = true
const res = await this.$get(this.api.examPaperDetails, { const res = await this.$get(this.api.examPaperDetails, {
id: paperId id: paperId
}) })
@ -411,7 +423,7 @@ export default {
e.examQuestions.map((n, j) => { e.examQuestions.map((n, j) => {
n.originSort = j + 1 n.originSort = j + 1
Object.assign(n, n.question) Object.assign(n, n.question)
this.handleFillScore(n) this.handleQuesInfo(n)
}) })
}) })
@ -419,7 +431,9 @@ export default {
r.professionalId = r.professionalId ? r.professionalId.split(',').map(e => +e) : [] r.professionalId = r.professionalId ? r.professionalId.split(',').map(e => +e) : []
this.form = r this.form = r
} }
} catch (e) { } } finally {
this.loading = false
}
}, },
// //
async getType () { async getType () {
@ -605,10 +619,21 @@ export default {
} }
}, },
// //
handleFillScore (ques) { handleQuesInfo (ques) {
try { try {
//
const { difficults } = QuesConst
if (ques.difficulty) {
const curDiff = difficults.find(m => m.id === ques.difficulty)
if (curDiff) {
ques.difficult = curDiff.name
ques.difficultTheme = curDiff.theme
}
}
const opts = ques.questionAnswerVersionsList const opts = ques.questionAnswerVersionsList
//
if (ques.questionType === 'fill_blank' && opts && opts.length) { if (ques.questionType === 'fill_blank' && opts && opts.length) {
// json // json
let { answerData } = opts[0] let { answerData } = opts[0]
@ -1084,7 +1109,7 @@ export default {
} }
.stem { .stem {
max-width: calc(100% - 120px); margin-bottom: 10px;
} }
/deep/.l-input { /deep/.l-input {
@ -1117,21 +1142,19 @@ export default {
.bottom-line { .bottom-line {
display: flex; display: flex;
justify-content: space-between; align-items: baseline;
align-items: center; margin-bottom: 10px;
}
.correct {
display: flex;
font-size: 13px; font-size: 13px;
color: #333; color: #333;
} }
.ans {
max-width: calc(100% - 100px);
}
.actions { .actions {
display: flex; display: inline-flex;
justify-content: flex-end;
align-items: center; align-items: center;
margin-top: 10px;
.el-button { .el-button {
margin: 0 20px 0 0; margin: 0 20px 0 0;

@ -66,7 +66,7 @@
@change="val => quesChange(val, item)"></el-checkbox> @change="val => quesChange(val, item)"></el-checkbox>
<span class="serial">{{ i + 1 }}</span> <span class="serial">{{ i + 1 }}</span>
<el-tooltip effect="dark" :content="item.stemText" placement="top-start"> <el-tooltip effect="dark" :content="item.stemText" placement="top-start">
<p class="stem">{{ item.stemText }}</p> <p class="stem cursor-pointer" @click="toShowQues(item)">{{ item.stemText }}</p>
</el-tooltip> </el-tooltip>
<el-tooltip effect="dark" :content="item.knowledgePointName" placement="top-start"> <el-tooltip effect="dark" :content="item.knowledgePointName" placement="top-start">
<p class="kl">{{ item.knowledgePointName }}</p> <p class="kl">{{ item.knowledgePointName }}</p>
@ -145,7 +145,7 @@
<el-drawer title="新增试题" :visible.sync="addQuesVisible" size="1200px" :close-on-click-modal="false" <el-drawer title="新增试题" :visible.sync="addQuesVisible" size="1200px" :close-on-click-modal="false"
custom-class="add-dia"> custom-class="add-dia">
<QuesDetail :paperType.sync="paperType" @closeAdd="closeAdd" /> <QuesDetail :key="quesKey" :paperType.sync="paperType" :curQues.sync="curRow" @closeAdd="closeAdd" />
</el-drawer> </el-drawer>
</div> </div>
</template> </template>
@ -186,6 +186,7 @@ export default {
quesVisible: false, quesVisible: false,
curRow: {}, curRow: {},
addQuesVisible: false, addQuesVisible: false,
quesKey: 1,
paperType: 1, paperType: 1,
}; };
}, },
@ -420,20 +421,21 @@ export default {
}, },
// //
toAddQues () { toAddQues () {
// this.$router.push('/ques/detail?detailType=5') this.quesKey++
this.paperType = 1
this.addQuesVisible = true
},
//
toShowQues (ques) {
this.quesKey++
this.curRow = ques
this.paperType = 3
this.addQuesVisible = true this.addQuesVisible = true
}, },
// //
closeAdd () { closeAdd () {
this.addQuesVisible = false this.addQuesVisible = false
}, },
//
updateQues (ques, id) {
// ques.questionAnswerVersionsList = ques.questionAnswerVersions
// delete ques.questionAnswerVersions
// ques.questionVersionId = id
// this.curType.examQuestions[this.curQuesIndex] = Object.assign(this.curRow, ques)
},
// //
async submit () { async submit () {
if (this.submiting) return false if (this.submiting) return false
@ -447,9 +449,9 @@ export default {
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, 'originSort', i + 1)
this.$set(e, 'score', '') this.$set(e, 'score', '')
this.$parent.handleFillScore(e) this.$parent.handleQuesInfo(e)
// this.$set(e, 'questionVersionId', e.questionVersionId)
}) })
if (curQues) { if (curQues) {
@ -572,6 +574,10 @@ export default {
width: calc(100% - 210px); width: calc(100% - 210px);
margin-right: 20px; margin-right: 20px;
@include ellipsis; @include ellipsis;
&:hover {
opacity: .9;
}
} }
.kl { .kl {

Loading…
Cancel
Save