yujialong 3 months ago
parent 016dd0a9ab
commit 6403d33eaf
  1. 15
      package-lock.json
  2. 2
      package.json
  3. 2
      public/static/ueditorPlus/plugins/gapfilling/gapfilling.css
  4. 1
      src/api/index.js
  5. 0
      src/components/ueditorPlus/index.vue
  6. 18
      src/pages/ques/detail/index.vue
  7. 78
      src/pages/ques/list/index.vue
  8. 93
      src/pages/testPaper/detail/index.vue
  9. 4
      src/pages/testPaper/list/index.vue

15
package-lock.json generated

@ -15519,11 +15519,18 @@
"integrity": "sha512-EJkYLyyzgOJTxGreiZ9wrmXthIMVVRSeFTzV6n0OR9w4aeqW79Prvog4jZ4G0kkmW3TTTBbZtHM9VNHEl6LJDA==" "integrity": "sha512-EJkYLyyzgOJTxGreiZ9wrmXthIMVVRSeFTzV6n0OR9w4aeqW79Prvog4jZ4G0kkmW3TTTBbZtHM9VNHEl6LJDA=="
}, },
"vuedraggable": { "vuedraggable": {
"version": "2.23.2", "version": "2.24.3",
"resolved": "https://registry.npmjs.org/vuedraggable/-/vuedraggable-2.23.2.tgz", "resolved": "https://registry.npmjs.org/vuedraggable/-/vuedraggable-2.24.3.tgz",
"integrity": "sha512-PgHCjUpxEAEZJq36ys49HfQmXglattf/7ofOzUrW2/rRdG7tu6fK84ir14t1jYv4kdXewTEa2ieKEAhhEMdwkQ==", "integrity": "sha512-6/HDXi92GzB+Hcs9fC6PAAozK1RLt1ewPTLjK0anTYguXLAeySDmcnqE8IC0xa7shvSzRjQXq3/+dsZ7ETGF3g==",
"requires": { "requires": {
"sortablejs": "^1.10.1" "sortablejs": "1.10.2"
},
"dependencies": {
"sortablejs": {
"version": "1.10.2",
"resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.10.2.tgz",
"integrity": "sha512-YkPGufevysvfwn5rfdlGyrGjt7/CRHwvRPogD/lC+TnvcN29jDpCifKP+rBqf+LRldfXSTh+0CGLcSg0VIxq3A=="
}
} }
}, },
"vuex": { "vuex": {

@ -37,7 +37,7 @@
"vue-schart": "^2.0.0", "vue-schart": "^2.0.0",
"vue-seamless-scroll": "^1.1.23", "vue-seamless-scroll": "^1.1.23",
"vue-ueditor-wrap": "^2.5.6", "vue-ueditor-wrap": "^2.5.6",
"vuedraggable": "^2.17.0", "vuedraggable": "^2.24.3",
"vuex": "^3.4.0" "vuex": "^3.4.0"
}, },
"devDependencies": { "devDependencies": {

@ -6,7 +6,7 @@ body .edui-default .edui-toolbar .edui-button.edui-for-gapfilling .edui-icon {
outline: none !important; outline: none !important;
} }
.edui-for-gapfilling .edui-icon::after { .edui-for-gapfilling .edui-icon::after {
content: "点击插入填空"; content: "点击插入填空";
position: absolute; position: absolute;
left: 6px; left: 6px;
color: #333; color: #333;

@ -70,4 +70,5 @@ export default {
disableOrEnableQuestion: `/exam/exam/questions/disableOrEnableQuestion`, disableOrEnableQuestion: `/exam/exam/questions/disableOrEnableQuestion`,
findAllByQuestionBank: `/exam/exam/questions/findAllByQuestionBank`, findAllByQuestionBank: `/exam/exam/questions/findAllByQuestionBank`,
selectQuestionsByTypeAndDifficulty: `/exam/exam/questions/selectQuestionsByTypeAndDifficulty`, selectQuestionsByTypeAndDifficulty: `/exam/exam/questions/selectQuestionsByTypeAndDifficulty`,
removeQuestionKnowledge: `/exam/exam/questions/removeQuestionKnowledge`,
} }

@ -34,7 +34,7 @@
</el-radio-group> </el-radio-group>
</el-form-item> </el-form-item>
<el-form-item class="is-required" prop="stem" label="题干"> <el-form-item class="is-required" prop="stem" label="题干">
<Ueditor ref="stem" @ready="stemReady" v-model="form.stem" /> <UeditorPlus ref="stem" @ready="stemReady" v-model="form.stem" />
<Upload v-if="form.questionType === 'essay'" class="m-t-10" <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" accept=".csv,.xlsx,.xls,.docx,.doc,.pdf,.jpg,.png,.zip,.rar,.7z" :max-size="50" :file-list="uploadList"
@ -120,7 +120,7 @@
</el-radio-group> </el-radio-group>
</el-form-item> </el-form-item>
<el-form-item v-if="form.allowAttachment" prop="uploadInstructions" label="上传要求说明"> <el-form-item v-if="form.allowAttachment" prop="uploadInstructions" label="上传要求说明">
<Ueditor ref="uploadInstructions" @ready="uploadInstructionsReady" v-model="form.uploadInstructions" /> <UeditorPlus ref="uploadInstructions" @ready="uploadInstructionsReady" v-model="form.uploadInstructions" />
</el-form-item> </el-form-item>
<el-form-item label="判分标准" class="is-required"> <el-form-item label="判分标准" class="is-required">
<el-select :value="form.questionAnswerVersions[0].gradingStandard" placeholder="请选择判分标准" disabled> <el-select :value="form.questionAnswerVersions[0].gradingStandard" placeholder="请选择判分标准" disabled>
@ -128,13 +128,13 @@
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item prop="referenceAnswer" label="参考答案"> <el-form-item prop="referenceAnswer" label="参考答案">
<Ueditor ref="referenceAnswer" @ready="referenceAnswerReady" <UeditorPlus ref="referenceAnswer" @ready="referenceAnswerReady"
v-model="form.questionAnswerVersions[0].referenceAnswer" /> v-model="form.questionAnswerVersions[0].referenceAnswer" />
</el-form-item> </el-form-item>
</template> </template>
<el-form-item prop="answerAnalysis" label="解析"> <el-form-item prop="answerAnalysis" label="解析">
<Ueditor ref="answerAnalysis" @ready="answerAnalysisReady" v-model="answerAnalysis" /> <UeditorPlus ref="answerAnalysis" @ready="answerAnalysisReady" v-model="answerAnalysis" />
</el-form-item> </el-form-item>
</el-form> </el-form>
<span v-if="detailType !== 2" slot="footer" class="dialog-footer"> <span v-if="detailType !== 2" slot="footer" class="dialog-footer">
@ -178,7 +178,7 @@
<el-dialog :visible.sync="richEditor.dialogVisible" width="1000px" :show-close="false" center <el-dialog :visible.sync="richEditor.dialogVisible" width="1000px" :show-close="false" center
:close-on-click-modal="false"> :close-on-click-modal="false">
<!-- <Ueditor ref="title2" @ready="editorReady" /> --> <!-- <UeditorPlus ref="title2" @ready="editorReady" /> -->
<span slot="footer" class="dialog-footer"> <span slot="footer" class="dialog-footer">
<el-button type="primary" @click="editorSubmit">确定</el-button> <el-button type="primary" @click="editorSubmit">确定</el-button>
<el-button @click="richEditor.dialogVisible = false">取消</el-button> <el-button @click="richEditor.dialogVisible = false">取消</el-button>
@ -189,7 +189,7 @@
<script> <script>
import Setting from '@/setting' import Setting from '@/setting'
import Util from '@/libs/util' import Util from '@/libs/util'
import Ueditor from '@/components/ueditor' import UeditorPlus from '@/components/ueditorPlus'
import Upload from '@/components/upload' import Upload from '@/components/upload'
import Oss from '@/components/upload/upload.js' import Oss from '@/components/upload/upload.js'
import dayjs from 'dayjs' import dayjs from 'dayjs'
@ -197,7 +197,7 @@ import _ from 'lodash'
import Const from '@/const/ques' import Const from '@/const/ques'
export default { export default {
props: ['visible', 'row', 'detailType'], props: ['visible', 'row', 'detailType'],
components: { Ueditor, Upload }, components: { UeditorPlus, Upload },
data () { data () {
return { return {
typeId: this.$route.query.id, // id typeId: this.$route.query.id, // id
@ -339,9 +339,9 @@ export default {
givenYear: r.givenYear, givenYear: r.givenYear,
difficulty: r.difficulty, difficulty: r.difficulty,
stem: r.stem, stem: r.stem,
knowledgePointIds: r.knowledgePointList.map(e => { knowledgePointIds: r.knowledgePointList ? r.knowledgePointList.map(e => {
return e.path.split('/').map(n => +n) return e.path.split('/').map(n => +n)
}), }) : [],
specialtyIds: r.professionalList.map(e => e.specialtyId), specialtyIds: r.professionalList.map(e => e.specialtyId),
allowAttachment: r.allowAttachment, allowAttachment: r.allowAttachment,
stemAttachment: r.stemAttachment, stemAttachment: r.stemAttachment,

@ -89,9 +89,9 @@
<div style="margin-bottom: 15px;"> <div style="margin-bottom: 15px;">
<el-button type="primary" @click="add">新增试题</el-button> <el-button type="primary" @click="add">新增试题</el-button>
<el-button type="primary" @click="batchImport">批量导入</el-button> <el-button type="primary" @click="batchImport">批量导入</el-button>
<!-- <el-button type="primary" @click="add">批量转移</el-button> --> <!-- <el-button type="primary" @click="batchRemove">批量转移</el-button> -->
<el-button type="primary" @click="add">批量移除 </el-button> <el-button type="primary" :disabled="!isKnowLedge" @click="batchRemove">批量移除 </el-button>
<el-button type="primary" @click="delAllSelection">批量删除</el-button> <el-button type="primary" @click="batchDel">批量删除</el-button>
</div> </div>
</ul> </ul>
</div> </div>
@ -124,7 +124,7 @@
<el-button type="text" @click="toDetail(scope.row, 1)">复制</el-button> <el-button type="text" @click="toDetail(scope.row, 1)">复制</el-button>
<el-button type="text" @click="toDetail(scope.row, 2)">查看</el-button> <el-button type="text" @click="toDetail(scope.row, 2)">查看</el-button>
<el-button type="text" @click="toDetail(scope.row, 3)">编辑</el-button> <el-button type="text" @click="toDetail(scope.row, 3)">编辑</el-button>
<el-button type="text" @click="del(scope.row)">移除</el-button> <el-button type="text" :disabled="!isKnowLedge" @click="remove(scope.row)">移除</el-button>
<el-button type="text" @click="del([scope.row])">删除</el-button> <el-button type="text" @click="del([scope.row])">删除</el-button>
<el-switch v-model="scope.row.status" :active-value="1" :inactive-value="0" style="margin: 0 10px 0 5px" <el-switch v-model="scope.row.status" :active-value="1" :inactive-value="0" style="margin: 0 10px 0 5px"
:active-text="scope.row.status ? '开' : '关'" :active-text="scope.row.status ? '开' : '关'"
@ -204,12 +204,11 @@
<script> <script>
import Util from '@/libs/util' import Util from '@/libs/util'
import Setting from '@/setting' import Setting from '@/setting'
import Ueditor from '@/components/ueditor'
import Breadcrumb from '@/components/breadcrumb' import Breadcrumb from '@/components/breadcrumb'
import Detail from '../detail' import Detail from '../detail'
import Const from '@/const/ques' import Const from '@/const/ques'
export default { export default {
components: { Ueditor, Breadcrumb, Detail }, components: { Breadcrumb, Detail },
data () { data () {
return { return {
crumbs: [ crumbs: [
@ -285,18 +284,28 @@ export default {
uploading: false, uploading: false,
}; };
}, },
computed: {
//
isKnowLedge () {
if (this.isNotJoin === '') {
let node = this.$refs.typeTree
return node ? node.getCurrentNode().type === 1 : false
}
return false
},
},
watch: { watch: {
keyword: function (val) { keyword: function () {
clearTimeout(this.searchTimer); clearTimeout(this.searchTimer)
this.searchTimer = setTimeout(this.getType, 500); this.searchTimer = setTimeout(this.getType, 500)
}, },
'filter.keyword': function (val) { 'filter.keyword': function () {
clearTimeout(this.searchTimer); clearTimeout(this.searchTimer)
this.searchTimer = setTimeout(this.initData, 500); this.searchTimer = setTimeout(this.initData, 500)
}, },
quesVisible () { quesVisible () {
this.quesVisible || this.getList() this.quesVisible || this.getList()
} },
}, },
mounted () { mounted () {
this.getType() this.getType()
@ -425,6 +434,23 @@ export default {
this.curRow = row this.curRow = row
this.detailType = type this.detailType = type
}, },
//
async remove (row) {
try {
await this.$confirm(`确认要移除吗?`, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
closeOnClickModal: false,
})
await this.$post(this.api.removeQuestionKnowledge, {
knowledgePointId: this.$refs.typeTree.getCurrentKey() || '',
questionVersionIds: [row.questionVersionId]
})
Util.successMsg('移除成功')
this.getList()
} catch (e) { }
},
// //
async del (rows) { async del (rows) {
const ids = rows.map(e => e.questionId) const ids = rows.map(e => e.questionId)
@ -449,7 +475,7 @@ export default {
} }
}, },
// //
async delAllSelection () { async batchDel () {
const list = this.multipleSelection const list = this.multipleSelection
list.length ? this.del(list) : Util.warningMsg('请选择数据') list.length ? this.del(list) : Util.warningMsg('请选择数据')
}, },
@ -462,6 +488,30 @@ export default {
this.delVisible = false this.delVisible = false
this.getList() this.getList()
}, },
//
async batchRemove () {
const list = this.multipleSelection
if (list.length) {
try {
await this.$confirm(`确认要移除吗?`, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
closeOnClickModal: false,
})
await this.$post(this.api.removeQuestionKnowledge, {
knowledgePointId: this.$refs.typeTree.getCurrentKey() || '',
questionVersionIds: list.map(e => e.questionVersionId)
})
Util.successMsg('移除成功')
this.getList()
this.multipleSelection = []
this.$refs.table.clearSelection()
} catch (e) { }
} else {
Util.warningMsg('请选择数据')
}
},
// //
async switchOff (val, row) { async switchOff (val, row) {
try { try {

@ -62,7 +62,7 @@
</el-form-item> </el-form-item>
</div> </div>
<el-form-item prop="remarks" label="试卷说明"> <el-form-item prop="remarks" label="试卷说明">
<Ueditor ref="remarks" @ready="remarksReady" /> <UeditorPlus ref="remarks" @ready="remarksReady" />
</el-form-item> </el-form-item>
<div class="line"></div> <div class="line"></div>
@ -129,44 +129,46 @@
<p class="sum">本大题共{{ item.questionNum }}小题{{ item.targetScore }}</p> <p class="sum">本大题共{{ item.questionNum }}小题{{ item.targetScore }}</p>
<div :class="['ques-wrap', { hide: item.shrink }]"> <div :class="['ques-wrap', { hide: item.shrink }]">
<div v-for="(ques, j) in item.examQuestions" :key="j" class="ques-item"> <draggable v-model="item.examQuestions" :group="dragGroup" @update="e => updateSort(e, item)">
<el-checkbox v-model="ques.check"></el-checkbox> <div v-for="(ques, j) in item.examQuestions" :key="j" class="ques-item">
<div :class="['ques-info', { disabled: !ques.status, del: ques.isDel, repeat: ques.isRepeat }]"> <el-checkbox v-model="ques.check"></el-checkbox>
<div class="top-line"> <div :class="['ques-info', { disabled: !ques.status, del: ques.isDel, repeat: ques.isRepeat }]">
<span class="label">{{ j + 1 }} / {{ item.examQuestions.length }}</span> <div class="top-line">
<span class="label">{{ questionTypes.find(e => e.id === item.questionType).name }}</span> <span class="label">{{ j + 1 }} / {{ item.examQuestions.length }}</span>
<div :id="'stem' + ques.questionVersionId" v-html="getQuesStem(ques)"></div> <span class="label">{{ questionTypes.find(e => e.id === item.questionType).name }}</span>
<p v-if="item.questionType !== 'fill_blank'"><el-input class="score" placeholder="请输入" <div :id="'stem' + ques.questionVersionId" v-html="getQuesStem(ques)"></div>
v-model="ques.score" /></p> <p v-if="item.questionType !== 'fill_blank'"><el-input class="score" placeholder="请输入"
</div> v-model="ques.score" /></p>
<!-- 单选多选判断的选项 -->
<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 v-html="opt.optionText"></div>
</div> </div>
</template>
<div class="bottom-line"> <!-- 单选多选判断的选项 -->
<div class="correct"> <template
{{ item.questionType === 'essay' ? '参考答案' : '正确答案' }} v-if="item.questionType !== 'fill_blank' && item.questionType !== 'essay' && ques.questionAnswerVersionsList">
<div v-html="getCorrectAnswer(ques)"></div> <div v-for="(opt, j) in ques.questionAnswerVersionsList" :key="j" class="opt">
</div> <span>{{ numToLetter(j) }}.&nbsp;</span>
<div class="actions"> <div class="text" v-html="opt.optionText"></div>
<div class="sort"> </div>
<span>排序</span> </template>
<el-input class="score" v-model="ques.serialNumber" />
<div class="bottom-line">
<div class="correct">
{{ item.questionType === 'essay' ? '参考答案' : '正确答案' }}
<div v-html="getCorrectAnswer(ques)"></div>
</div>
<div class="actions">
<div class="sort">
<span>排序</span>
<el-input class="score" v-model="ques.serialNumber" />
</div>
<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> </div>
<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> </div>
</div> </div>
</div> </div>
</div> </draggable>
</div> </div>
</li> </li>
</ul> </ul>
@ -189,7 +191,9 @@
import Setting from '@/setting' import Setting from '@/setting'
import Util from '@/libs/util' import Util from '@/libs/util'
import dayjs from 'dayjs' import dayjs from 'dayjs'
import Ueditor from '@/components/ueditor' import Decimal from 'decimal.js'
import Draggable from 'vuedraggable'
import UeditorPlus from '@/components/ueditorPlus'
import Breadcrumb from '@/components/breadcrumb' import Breadcrumb from '@/components/breadcrumb'
import QuesConst from '@/const/ques' import QuesConst from '@/const/ques'
import TestPaperConst from '@/const/testPaper' import TestPaperConst from '@/const/testPaper'
@ -197,10 +201,9 @@ import Template from './template'
import Manual from './manual' import Manual from './manual'
import Auto from './auto' import Auto from './auto'
import Detail from '@/pages/ques/detail' import Detail from '@/pages/ques/detail'
import Decimal from 'decimal.js'
export default { export default {
components: { Ueditor, Breadcrumb, Template, Manual, Auto, Detail }, components: { UeditorPlus, Breadcrumb, Template, Manual, Auto, Detail, Draggable },
data () { data () {
return { return {
crumbs: [], crumbs: [],
@ -223,6 +226,9 @@ export default {
}, },
professionals: [], professionals: [],
dragGroup: {
pull: false,
},
form: { form: {
classificationId: +this.$route.query.classificationId || '', classificationId: +this.$route.query.classificationId || '',
difficult: '', difficult: '',
@ -671,6 +677,13 @@ export default {
} }
} catch (e) { } } catch (e) { }
}, },
//
updateSort (e, item) {
e.preventDefault()
item.examQuestions.map((e, i) => {
this.$set(e, 'serialNumber', i + 1)
})
},
// //
delQues (item, i) { delQues (item, i) {
item.examQuestions.splice(i, 1) item.examQuestions.splice(i, 1)
@ -848,7 +861,9 @@ export default {
}) })
}) })
if (typeof form.classificationId === 'object') form.classificationId = form.classificationId[form.classificationId.length - 1] if (typeof form.classificationId === 'object') form.classificationId = form.classificationId[form.classificationId.length - 1]
form.questionType = [...new Set(paper.map(e => e.questionType))].join('、') //
const { questionTypes } = QuesConst
form.questionType = [...new Set(paper.map(e => questionTypes.find(n => n.id === e.questionType).name))].join('、') //
form.createSource = 1 form.createSource = 1
if (isCopy) form.paperId = '' if (isCopy) form.paperId = ''
this.tempForm = form this.tempForm = form
@ -1003,6 +1018,10 @@ export default {
font-size: 14px; font-size: 14px;
color: #707070; color: #707070;
line-height: 1.6; line-height: 1.6;
.text {
max-width: calc(100% - 20px);
}
} }
.bottom-line { .bottom-line {

@ -120,8 +120,7 @@
<el-table-column prop="questionCount" label="试题总数" align="center" width="70"></el-table-column> <el-table-column prop="questionCount" label="试题总数" align="center" width="70"></el-table-column>
<el-table-column prop="score" label="总分" align="center" width="60"></el-table-column> <el-table-column prop="score" label="总分" align="center" width="60"></el-table-column>
<el-table-column prop="medianScore" label="中分位数" align="center" width="70"></el-table-column> <el-table-column prop="medianScore" label="中分位数" align="center" width="70"></el-table-column>
<el-table-column prop="name" label="题型" align="center" min-width="90"> <el-table-column prop="questionType" label="题型" align="center" min-width="90"></el-table-column>
</el-table-column>
<el-table-column prop="difficult" label="试卷难度" align="center" width="100" sortable="custom"> <el-table-column prop="difficult" label="试卷难度" align="center" width="100" sortable="custom">
<template slot-scope="scope">{{ difficults.find(e => e.id === scope.row.difficult) ? difficults.find(e => <template slot-scope="scope">{{ difficults.find(e => e.id === scope.row.difficult) ? difficults.find(e =>
e.id === scope.row.difficult).name : '' }}</template> e.id === scope.row.difficult).name : '' }}</template>
@ -417,6 +416,7 @@ export default {
type: this.isNotJoin, type: this.isNotJoin,
pageNum: this.page, pageNum: this.page,
pageSize: this.pageSize, pageSize: this.pageSize,
libraryId: this.typeId,
classificationId: this.$refs.typeTree.getCurrentKey() || '', classificationId: this.$refs.typeTree.getCurrentKey() || '',
}) })
this.list = res.pageList.records this.list = res.pageList.records

Loading…
Cancel
Save