试卷联调

master
yujialong 7 months ago
parent 80594b8338
commit df0b8172f2
  1. 12
      src/components/ueditor/index.vue
  2. 34
      src/const/testPaper.js
  3. 52
      src/pages/ques/detail/index.vue
  4. 20
      src/pages/ques/list/index.vue
  5. 5
      src/pages/quesBank/index.vue
  6. 280
      src/pages/testPaper/detail/index.vue
  7. 253
      src/pages/testPaper/detail/manual.vue
  8. 2
      src/pages/testPaper/detail/template.vue
  9. 173
      src/pages/testPaper/list/index.vue
  10. 7
      src/pages/testPaperLibrary/index.vue
  11. 5
      src/styles/common.scss

@ -25,7 +25,6 @@ export default {
},
watch: {
value: function (val, oldVal) {
console.log("🚀 ~ val:", val, this.ready)
if (val != null && this.ready) {
// eslint-disable-next-line no-undef
this.instance = UE.getEditor(this.randomId)
@ -48,17 +47,6 @@ export default {
// eslint-disable-next-line no-undef
this.instance = UE.getEditor(this.randomId)
this.instance.addListener('ready', () => {
// UE.Editor.prototype._bkGetActionUrl = UE.Editor.prototype.getActionUrl;
// UE.Editor.prototype.getActionUrl = function (action) {
// console.log("🚀 ~ initEditor ~ action:", action)
// if (action == 'uploadimage' || action == 'uploadscrawl' || action == 'uploadimage') {
// return 'http://192.168.31.51:9000/nakadai/nakadai/oss/fileUpload';
// } else {
// return this._bkGetActionUrl.call(this, action);
// }
// }
this.ready = true
this.$emit('ready', this.instance)
})

@ -0,0 +1,34 @@
export default {
difficults: [
{
id: 1,
name: '简单'
},
{
id: 2,
name: '普通'
},
{
id: 3,
name: '较难'
},
{
id: 4,
name: '难'
},
],
paperTypes: [
{
id: 0,
name: '练习'
},
{
id: 1,
name: '考核'
},
{
id: 2,
name: '竞赛'
},
],
}

@ -92,12 +92,12 @@
</div>
</div>
</el-form-item>
<el-form-item prop="gradingStandard" label="判分标准" required>
<el-form-item label="判分标准" class="is-required">
<el-select :value="form.questionAnswerVersions[0].gradingStandard" placeholder="请选择判分标准" disabled>
<el-option label="完全一致" value="exact_match"></el-option>
</el-select>
</el-form-item>
<el-form-item label="判分标准" required>
<el-form-item label="判分规则">
<div>
<el-switch disabled active-text="判分时忽略答案中的字母大小写"></el-switch>
</div>
@ -124,7 +124,7 @@
<el-form-item v-if="form.allowAttachment" prop="uploadInstructions" label="上传要求说明">
<Ueditor ref="uploadInstructions" @ready="uploadInstructionsReady" v-model="form.uploadInstructions" />
</el-form-item>
<el-form-item label="判分标准" required>
<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>
@ -187,7 +187,7 @@
import Setting from '@/setting'
import Util from '@/libs/util'
import Ueditor from '@/components/ueditor'
import Upload from '@/components/upload';
import Upload from '@/components/upload'
import Oss from '@/components/upload/upload.js'
import dayjs from 'dayjs'
import _ from 'lodash'
@ -281,16 +281,16 @@ export default {
this.originForm = _.cloneDeep(this.form)
},
methods: {
//
init () {
this.form = _.cloneDeep(this.originForm)
//
for (let i = 1; i < 5; i++) {
const opt = _.cloneDeep(this.originOpt)
opt.optionNumber = i
this.form.questionAnswerVersions.push(opt)
}
this.form.questionAnswerVersions[0].answerIsCorrect = 1
this.handleSingleMultiple()
//
const knowledgeCheck = this.$parent.$refs.typeTree.getCurrentNode()
if (knowledgeCheck && knowledgeCheck.type) this.form.knowledgePointIds = [knowledgeCheck.path.split('/').map(e => +e)]
//
this.$refs.stem && this.$refs.stem.setText('')
this.$refs.answerAnalysis && this.$refs.answerAnalysis.setText('')
this.$refs.uploadInstructions && this.$refs.uploadInstructions.setText('')
@ -371,6 +371,18 @@ export default {
}
})
},
//
handleSingleMultiple () {
//
const opts = []
for (let i = 1; i < 5; i++) {
const opt = _.cloneDeep(this.originOpt)
opt.optionNumber = i
opts.push(opt)
}
this.form.questionAnswerVersions = opts
this.form.questionAnswerVersions[0].answerIsCorrect = 1
},
//
questionTypeChange (val) {
//
@ -395,7 +407,12 @@ export default {
const opt = _.cloneDeep(this.originOpt)
opt.gradingStandard = 'manual'
opt.referenceAnswer = ''
this.form.allowAttachment = 0
this.form.stemAttachment = ''
this.form.uploadInstructions = ''
this.form.questionAnswerVersions = [opt]
} else {
this.handleSingleMultiple()
}
},
//
@ -559,11 +576,11 @@ export default {
}
} catch (e) {
//
setTimeout(() => {
this.repeatVisible = true
this.repeats = Util.removeTag(e)
this.submiting = false
}, 1500)
// setTimeout(() => {
this.repeatVisible = true
this.repeats = Util.removeTag(e)
this.submiting = false
// }, 1500)
}
}
})
@ -588,9 +605,6 @@ export default {
<style lang="scss" scoped>
.action-icon {
margin-right: 10px;
font-size: 18px;
color: $main-color;
cursor: pointer;
}
.ques {

@ -46,7 +46,8 @@
<li>
<label>专业</label>
<el-select v-model="filter.specialtyIds" clearable placeholder="请选择专业" multiple @change="initData">
<el-option v-for="(item, i) in status" :key="i" :label="item.name" :value="item.id"></el-option>
<el-option v-for="(item, i) in professionals" :key="i" :label="item.professionalName"
:value="item.professionalId"></el-option>
</el-select>
</li>
<li>
@ -99,7 +100,8 @@
@selection-change="handleSelectionChange" row-key="id">
<el-table-column type="selection" width="45" align="center" :reserve-selection="true"></el-table-column>
<el-table-column type="index" width="50" label="序号" align="center"></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"
show-overflow-tooltip></el-table-column>
<el-table-column prop="account" label="题型" align="center" width="100">
<template slot-scope="scope">{{ questionTypes.find(e => e.id === scope.row.questionType) ?
questionTypes.find(e => e.id === scope.row.questionType).name : '' }}</template>
@ -207,6 +209,7 @@ export default {
keyword: '',
type: 1,
types: [],
professionals: [],
status: [
{
id: 1,
@ -266,6 +269,7 @@ export default {
},
mounted () {
this.getType()
this.getProfessional()
this.getKnowledge()
},
methods: {
@ -321,7 +325,17 @@ export default {
this.knowledges = data
} catch (e) { }
},
//
//
async getProfessional () {
try {
const res = await this.$post(this.api.queryProfessional, {
pageNum: 1,
pageSize: 1000,
})
this.professionals = res.pageList.records
} catch (e) { }
},
//
async getList () {
let type = this.$refs.typeTree.getCurrentKey()
const k = this.knowledgePointIds

@ -99,8 +99,8 @@
</template>
<script>
import Util from "@/libs/util";
import Setting from "@/setting";
import Setting from '@/setting'
import Util from '@/libs/util'
import _ from 'lodash'
export default {
data () {
@ -307,7 +307,6 @@ export default {
if (!form.questionBankName) return Util.warningMsg('请输入题库名称')
this.submiting = true
if (form.categoryIds.length) form.categoryIds = [form.categoryIds[form.categoryIds.length - 1]]
// form.systemId = this.systemId
form.createSource = 1
try {
await this.$post(this.api[this.isCopy ? 'copyQuestionBank' : 'questionBankSave'], form)

@ -2,7 +2,7 @@
<div class="page">
<Breadcrumb :data="crumbs" />
<p class="page-name mb">试卷</p>
<el-form :model="form" :rules="rules" class="input-form model" label-width="140px">
<el-form :model="form" :rules="rules" class="input-form model" ref="form" label-width="140px">
<el-form-item prop="name" label="试卷名称">
<el-input style="width: 940px" placeholder="请输入试卷名称" v-model="form.name" clearable maxlength="100" />
</el-form-item>
@ -12,8 +12,8 @@
</el-date-picker>
</el-form-item>
<el-form-item required label="所属试卷分类">
<el-cascader placeholder="请选择所属试卷分类" :options="types" v-model="cascaderValue" :props="cascaderProps" clearable
style="width: 100%">
<el-cascader placeholder="请选择所属试卷分类" :options="types" v-model="form.classificationId" :props="cascaderProps"
clearable style="width: 100%">
</el-cascader>
</el-form-item>
</div>
@ -42,8 +42,8 @@
</el-select>
</el-form-item>
</div>
<el-form-item prop="userName" label="试卷说明">
<Ueditor @ready="editorReady" />
<el-form-item prop="remarks" label="试卷说明">
<Ueditor ref="remarks" @ready="remarksReady" />
</el-form-item>
<div class="line"></div>
@ -88,8 +88,8 @@
<div class="flex j-between a-center">
<p>选择试题</p>
<div>
<el-button type="primary" @click="submit(0)">一键分配分值</el-button>
<el-button type="primary" @click="submit(1)">自动选题</el-button>
<el-button type="primary">一键分配分值</el-button>
<el-button type="primary">自动选题</el-button>
</div>
</div>
@ -101,34 +101,64 @@
<el-input placeholder="请输入大题名称" v-model="item.outlineName" />
</div>
<div>
<el-button type="primary" @click="submit(0)">一键分配分值</el-button>
<el-button type="primary" @click="allocation(item)">一键分配分值</el-button>
<el-button type="primary" @click="showQuesDia(item)">批量添加</el-button>
<el-button type="danger" @click="submit(1)">批量删除试题</el-button>
<el-button type="danger" @click="batchDelQues(item)">批量删除试题</el-button>
</div>
</div>
<p class="sum">本大题共{{ item.questionNum }}小题{{ item.targetScore }}</p>
<div v-for="(ques, j) in item.examQuestions" :key="j" class="ques-wrap">
<el-checkbox v-model="ques.check"></el-checkbox>
<div class="ques-info">
<div class="top-line">
<span class="label">{{ j + 1 }} / 10</span>
<span class="label">{{ item.questionType }}</span>
<div v-html="ques.stem"></div>{{ ques.score }}
<p><el-input class="score" placeholder="请输入" v-model="ques.score" /></p>
</div>
<!-- <div v-for="(opt, j) in ques.examQuestions" :key="j" class="opts">
<div v-html=""></div>
</div> -->
<div class="bottom-line">
<div class="correct">正确答案A</div>
<div class="actions">
<div class="sort">
<span>排序</span>
<el-input class="score" v-model="ques.sort" />
</div>
<el-button type="text">编辑试题</el-button>
<el-button type="text">更换试题</el-button>
<el-button type="text" @click="showQuesDia(item, j)">添加试题</el-button>
<el-button type="text" @click="delQues(item, j)">移除试题</el-button>
</div>
</div>
</div>
</div>
</li>
</ul>
</el-form>
<div class="btns">
<el-button @click="submit(0)">保存草稿</el-button>
<el-button type="primary" @click="submit(1)">发布</el-button>
<el-button @click="submit(1)">保存草稿</el-button>
<el-button type="primary" @click="submit(0)">发布</el-button>
<el-button v-if="$route.query.id" @click="preview">预览</el-button>
<el-button @click="back">取消</el-button>
</div>
<Template :visible.sync="templateVisible" />
<Manual :visible.sync="quesVisible" />
<Manual :visible.sync="quesVisible" :questionType.sync="curType.questionType" />
</div>
</template>
<script>
import Setting from '@/setting'
import Util from '@/libs/util'
import dayjs from 'dayjs'
import Ueditor from '@/components/ueditor'
import Breadcrumb from '@/components/breadcrumb'
import Template from './template'
import Manual from './manual'
import QuesConst from '@/const/ques'
import TestPaperConst from '@/const/testPaper'
export default {
components: { Ueditor, Breadcrumb, Template, Manual },
data () {
@ -142,76 +172,24 @@ export default {
name: '创建试卷'
},
],
questionTypes: QuesConst.questionTypes,
difficults: TestPaperConst.difficults,
paperTypes: TestPaperConst.paperTypes,
arabicToChinese: Util.arabicToChinese,
libraryId: this.$route.query.libraryId,
headers: {
token: Util.local.get(Setting.tokenKey)
},
arabicToChinese: Util.arabicToChinese,
types: [],
cascaderValue: [],
cascaderProps: {
checkStrictly: true,
label: "classificationName",
value: "classificationId"
},
paperTypes: [
{
id: 0,
name: '练习'
},
{
id: 1,
name: '考核'
},
{
id: 2,
name: '竞赛'
},
],
professionals: [],
difficults: [
{
id: 1,
name: '简单'
},
{
id: 2,
name: '普通'
},
{
id: 3,
name: '较难'
},
{
id: 4,
name: '难'
},
],
questionTypes: [
{
name: '单选题'
},
{
name: '多选题'
},
{
name: '判断题'
},
{
name: '填空题'
},
{
name: '问答题'
},
],
richEditor: {
object: null,
parameterName: '',
instance: null
},
form: {
classificationId: '',
classificationId: +this.$route.query.classificationId || '',
difficult: '',
libraryId: '',
name: '',
@ -280,6 +258,8 @@ export default {
},
templateVisible: false,
quesVisible: false,
curType: {},
curQuesIndex: 0,
};
},
computed: {
@ -328,12 +308,9 @@ export default {
}
})
},
editorReady (instance) {
// this.richEditor.instance = instance
// let currentContent = this.richEditor.object[this.richEditor.parameterName]
// this.richEditor.instance.setContent(currentContent)
// // Ueditor
// this.richEditor.instance.focus(true)
//
remarksReady (editor) {
this.form.remarks && editor.setContent(this.form.remarks)
},
//
showTemplate () {
@ -354,16 +331,96 @@ export default {
this.form.paperOutline.length > 1 && this.form.paperOutline.splice(i, 1)
},
//
showQuesDia () {
showQuesDia (item, i) {
// debugger
this.curType = item
this.curQuesIndex = i
this.quesVisible = true
},
//
async batchDelQues (item) {
try {
const checked = item.examQuestions.filter(e => e.check)
if (checked.length) {
await this.$confirm(`确认要删除吗?`, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
closeOnClickModal: false,
})
checked.map(e => {
const cur = item.examQuestions.findIndex(n => n.questionVersionId === e.questionVersionId)
cur >= 0 && item.examQuestions.splice(cur, 1)
})
} else {
Util.warningMsg('请选择数据')
}
} catch (e) { }
},
//
allocation (item) {
const total = +item.targetScore
const len = item.examQuestions.length
const quotient = Math.floor(total / len) //
let remainder = total % len //
//
item.examQuestions.forEach(e => {
e.score = quotient
})
//
while (remainder > 0) {
for (let i = 0; i < len && remainder > 0; i++) {
item.examQuestions[i].score += 1
remainder -= 1
}
}
},
//
delQues (item, i) {
item.examQuestions.splice(i, 1)
},
//
submit () {
async submit (status) {
if (this.submiting) return false
this.$refs.form.validate(async (valid) => {
if (valid) {
const form = _.cloneDeep(this.form)
// if (!form.categoryIds.length) return Util.warningMsg('')
this.submiting = true
form.particularYear = +(dayjs(form.particularYear).format('YYYY'))
form.libraryId = this.libraryId
form.questionCount = this.questionCount
form.remarks = this.$refs.remarks.getUEContent()
form.score = this.score
form.status = status
form.paperOutline.map(e => {
e.targetScore = +e.targetScore
e.examQuestions = e.examQuestions.map(n => {
return {
questionVersionId: n.questionVersionId,
score: +n.score,
}
})
})
if (typeof form.classificationId === 'object') form.classificationId = form.classificationId[form.classificationId.length - 1]
form.questionType = [...new Set(form.paperOutline.map(e => e.questionType))].join('、')
form.createSource = 1
try {
await this.$post(this.api.saveExamPaper, form)
Util.successMsg('保存成功')
this.submiting = false
this.back()
} catch (e) {
this.submiting = false
}
}
})
},
//
back () {
this.$router.back()
}
}
};
@ -372,9 +429,6 @@ export default {
<style lang="scss" scoped>
.action-icon {
margin-right: 10px;
font-size: 18px;
color: $main-color;
cursor: pointer;
}
.ques {
@ -400,5 +454,69 @@ export default {
font-size: 13px;
color: $main-color;
}
.ques-wrap {
display: flex;
align-items: flex-start;
margin-bottom: 20px;
}
.ques-info {
width: calc(100% - 40px);
padding: 10px;
margin-left: 20px;
border: 1px solid #e9e9e9;
}
.top-line {
display: flex;
align-items: center;
}
.label {
padding: 3px;
margin-right: 10px;
font-size: 12px;
line-height: 1;
color: $main-color;
border: 1px solid;
border-radius: 2px;
}
/deep/.score {
width: 70px;
margin: 0 10px;
.el-input__inner {
height: 28px;
line-height: 28px;
}
}
.bottom-line {
display: flex;
justify-content: space-between;
align-items: center;
}
.correct {
font-size: 13px;
}
.actions {
display: inline-flex;
align-items: center;
.el-button {
margin-left: 20px;
}
}
.sort {
display: inline-flex;
align-items: center;
font-size: 12px;
}
}
</style>

@ -7,15 +7,15 @@
<div class="item">
<el-input class="m-b-10" placeholder="请输入题库分类/题库名称" prefix-icon="el-icon-search" v-model="quesBankKeyword"
clearable />
<el-tree node-key="id" default-expand-all ref="quesBank" :data="quesBanks" :props="{ label: 'name' }"
show-checkbox @node-click="getKnowledge" @check-change="quesBankCheck"></el-tree>
<el-tree :key="key" node-key="id" default-expand-all ref="quesBank" :data="quesBanks"
:props="{ label: 'name' }" show-checkbox @node-click="getKnowledge" @check-change="quesBankCheck"></el-tree>
</div>
<!-- 知识点 -->
<div class="item">
<el-input class="m-b-10" placeholder="请输入知识点分类/知识点名称" prefix-icon="el-icon-search" v-model="knowledgeKeyword"
clearable />
<el-tree :data="knowledges" default-expand-all ref="knowledge" node-key="id" highlight-current
:expand-on-click-node="false" show-checkbox @node-click="knowledgeClick" @check-change="knowledgeCheck"
:expand-on-click-node="false" show-checkbox @node-click="getQues" @check-change="knowledgeCheck"
:props="{ label: 'name' }">
<span class="custom-tree-node" slot-scope="{ node, data }">
<img v-if="data.type" class="m-r-5" src="@/assets/images/knowledge.svg" alt="">
@ -28,32 +28,39 @@
<p class="total">单选题{{ ques.length }}道题</p>
<div class="ques">
<div class="line">
<el-checkbox v-model="checked"></el-checkbox>
<el-checkbox v-model="quesAllCheck" @change="quesAllCheckChange"></el-checkbox>
<span class="serial">序号</span>
<span>题干</span>
</div>
<div v-for="(item, i) in ques" :key="i" class="line">
<el-checkbox v-model="checked"></el-checkbox>
<el-checkbox v-model="item.check" :disabled="item.disabled"
@change="val => quesChange(val, item)"></el-checkbox>
<span class="serial">{{ i + 1 }}</span>
<span>题干</span>
<span>{{ item.stem }}</span>
</div>
</div>
</div>
<!-- 已选试题 -->
<div class="item">
<p class="total">已选试题{{ ques.length }}道题</p>
<div class="flex j-between a-center">
<p class="total">已选试题{{ checkedLen }}道题</p>
<el-button type="text" @click="batchDelChecked">批量移除</el-button>
</div>
<div class="ques">
<div class="line">
<el-checkbox v-model="checked"></el-checkbox>
<el-checkbox v-model="checkedAllCheck" @change="checkedAllCheckChange"></el-checkbox>
<span class="serial">序号</span>
<span>题干</span>
</div>
<div v-for="(item, i) in ques" :key="i" class="line">
<el-checkbox v-model="checked"></el-checkbox>
<span class="serial">{{ i + 1 }}</span>
<span>题干</span>
<div v-for="(item, i) in checked" :key="i" class="line j-between">
<div class="check-left">
<el-checkbox v-model="item.check"></el-checkbox>
<span class="serial">{{ i + 1 }}</span>
<span>{{ item.stem }}</span>
</div>
<i class="el-icon-delete action-icon" @click="delChecked(item)"></i>
</div>
</div>
</div>
@ -66,7 +73,7 @@
<span slot="footer" class="dialog-footer">
<el-button @click="quesVisible = false">取消</el-button>
<el-button type="primary" v-loading="submiting" @click="submit">确定</el-button>
<el-button type="primary" :loading="submiting" @click="submit">确定</el-button>
</span>
</el-dialog>
</div>
@ -75,22 +82,33 @@
import Setting from '@/setting'
import Util from '@/libs/util'
import _ from 'lodash'
import QuesConst from '@/const/ques'
export default {
props: ['visible'],
props: ['visible', 'questionType'],
data () {
return {
checked: false,
quesVisible: false,
quesBankKeyword: '',
knowledgeKeyword: '',
searchTimer: null,
key: 1,
quesBanks: [],
knowledges: [],
ques: [{}, {}],
quesAllCheck: false,
ques: [],
checkedAllCheck: false,
checked: [],
curCheckQues: [],
submiting: false,
};
},
computed: {
// +
checkedLen () {
return this.curCheckQues.length + this.checked.length
}
},
watch: {
'quesBankKeyword': function (val) {
clearTimeout(this.searchTimer)
@ -110,9 +128,22 @@ export default {
},
methods: {
init () {
//
this.key++
this.knowledges = []
this.ques = []
this.checked = []
this.quesAllCheck = false
this.checkedAllCheck = false
this.quesBankKeyword = ''
this.knowledgeKeyword = ''
const parent = this.$parent.curType
this.curCheckQues = parent.examQuestions
this.getQuesBank()
},
//
//
async getQuesBank () {
try {
const { data } = await this.$post(this.api.getAllQuestionBankCategories, {
@ -136,6 +167,36 @@ export default {
}
} catch (e) { }
},
//
async getQues () {
let k = this.$refs.knowledge.getCurrentNode() //
//
if (k && k.type) {
let { questionType } = this
if (questionType) questionType = QuesConst.questionTypes.find(e => e.name === questionType).id
const { message } = await this.$post(this.api.listQuestion, {
pageNum: 1,
pageSize: 1000,
status: 1,
// questionBankId: this.$refs.quesBank.getCurrentKey(),
// knowledgePointIds: [k.id],
questionTypes: questionType ? [questionType] : [],
questionBankId: 26,
knowledgePointIds: [18],
})
const data = message.records
const checked = this.curCheckQues
data.map(e => {
const el = document.createElement('div')
el.innerHTML = e.stem
e.stem = el.innerText
e.check = !!this.checked.find(n => n.questionId === e.questionId)
e.disabled = !!checked.find(n => n.questionVersionId === e.questionId)
})
this.ques = data
console.log("🚀 ~ getQues ~ data:", data, checked)
}
},
//
quesBankCheck (data, checked) {
// debugger
@ -152,6 +213,71 @@ export default {
//
knowledgeCheck () {
},
//
quesAllCheckChange (val) {
this.ques.map(e => {
e.check = val
this.quesChange(val, e)
})
},
//
quesChange (val, item) {
const cur = this.checked.findIndex(e => e.questionId === item.questionId)
//
if (val) {
if (cur === -1) {
const e = _.cloneDeep(item)
e.check = false
this.checked.push(e)
}
} else {
//
cur >= 0 && this.checked.splice(cur, 1)
}
},
//
checkedAllCheckChange (val) {
this.checked.map(e => e.check = val)
},
//
async batchDelChecked (val) {
try {
const checked = this.checked.filter(e => e.check)
if (checked.length) {
await this.$confirm(`确认要删除吗?`, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
closeOnClickModal: false,
})
checked.map(e => {
const cur = this.ques.find(n => n.questionId === e.questionId)
if (cur) {
cur.check = false
}
})
this.quesAllCheck = false
this.checkedAllCheck = false
this.checked = this.checked.filter(e => !e.check)
} else {
Util.warningMsg('请选择数据')
}
} catch (e) { }
},
//
async delChecked (item) {
try {
// await this.$confirm(``, '', {
// confirmButtonText: '',
// cancelButtonText: '',
// type: 'warning',
// closeOnClickModal: false,
// })
const cur = this.ques.find(e => e.questionId === item.questionId)
if (cur) cur.check = false
this.checked.splice(this.checked.findIndex(e => e.questionId === item.questionId), 1)
} catch (e) { }
},
//
toAddQues () {
@ -160,78 +286,27 @@ export default {
//
toEditQues () {
},
// 使
async useTemplate (row) {
const data = await this.getDetail(row.templateId)
this.$parent.form.paperOutline = data.paperOutline
this.closeDia()
},
//
async getDetail (id) {
const res = await this.$get(this.api.templateDetails, {
id
})
return res.template
},
//
async edit (row) {
this.detailVisible = true
const data = await this.getDetail(row.templateId)
this.form = data
},
//
async del (row) {
try {
await this.$confirm(`确认要删除【${row.templateName}】吗?`, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
closeOnClickModal: false,
})
await this.$post(this.api.deleteTemplate, {
ids: [row.templateId]
})
Util.successMsg('删除成功')
this.getList()
} catch (e) { }
},
//
async submit () {
if (this.submiting) return false
const { form } = this
if (!form.templateName) return Util.warningMsg('请输入模板名称')
let invalid = 0
for (const e of form.paperOutline) {
if (!e.questionType) {
Util.warningMsg('请选择题型')
invalid = 1
break
}
if (!e.questionNum) {
Util.warningMsg('请输入目标题数')
invalid = 1
break
}
if (!e.targetScore) {
Util.warningMsg('请输入目标分值')
invalid = 1
break
}
}
if (invalid) return false
this.submiting = true
form.createSource = 1
form.questionNum = this.questionNum
form.totalScore = this.totalScore
form.outlineNum = form.paperOutline.length
form.questionType = [...new Set(form.paperOutline.map(e => e.questionType))].join('、')
const checked = _.cloneDeep(this.checked)
if (!checked.length) return Util.warningMsg('请选择试题')
const { curType, curQuesIndex } = this.$parent
if (this.checkedLen > +curType.questionNum) return Util.warningMsg(`目标题数为${curType.questionNum},已选题数不得大于目标题数`)
try {
await this.$post(this.api.saveExamPaperTemplate, form)
Util.successMsg('保存成功')
this.detailVisible = false
checked.map((e, i) => {
this.$set(e, 'check', false)
this.$set(e, 'sort', i + 1)
this.$set(e, 'score', '')
this.$set(e, 'questionVersionId', e.questionId)
})
// debugger
typeof curQuesIndex === 'number' ? curType.examQuestions.splice(curQuesIndex + 1, 0, ...checked) : curType.examQuestions.push(...checked)
this.quesVisible = false
this.submiting = false
this.getList()
} catch (e) {
this.submiting = false
}
@ -263,12 +338,13 @@ export default {
}
.total {
margin-bottom: 10px;
font-size: 16px;
color: #333;
}
.ques {
margin-top: 10px;
.line {
display: flex;
align-items: center;
@ -280,6 +356,15 @@ export default {
margin: 0 12px;
text-align: center;
}
.check-left {
display: inline-flex;
align-items: center;
}
.action-icon {
font-size: 14px;
}
}
}

@ -246,7 +246,7 @@ export default {
async useTemplate (row) {
const data = await this.getDetail(row.templateId)
this.$parent.form.paperOutline = data.paperOutline
this.closeDia()
this.listVisible = false
},
//
async getDetail (id) {

@ -21,8 +21,9 @@
</div>
<div style="overflow: auto">
<el-tree v-loading="loading" :data="types" default-expand-all ref="typeTree" node-key="id" highlight-current
:expand-on-click-node="false" @node-click="handleNodeClick" :props="{ label: 'name', isLeaf: 'leaf' }">
<el-tree v-loading="loading" :data="types" default-expand-all ref="typeTree" node-key="classificationId"
highlight-current :expand-on-click-node="false" @node-click="handleNodeClick"
:props="{ value: 'classificationId', label: 'classificationName' }">
<span class="custom-tree-node" slot-scope="{ node, data }">
<span class="org-name">{{ data.classificationName }}</span>
<span>
@ -63,37 +64,38 @@
<ul class="filter">
<li>
<label>题目类型</label>
<el-select v-model="filter.status" clearable placeholder="请选择题目类型" @change="getList">
<el-option v-for="(item, i) in status" :key="i" :label="item.name" :value="item.id"></el-option>
<el-select v-model="questionType" clearable multiple placeholder="请选择题目类型" @change="initData">
<el-option v-for="(item, i) in questionTypes" :key="i" :label="item.name" :value="item.id"></el-option>
</el-select>
</li>
<li>
<label>试卷难度</label>
<el-select v-model="filter.status" clearable placeholder="请选择试卷难度" @change="getList">
<el-option v-for="(item, i) in status" :key="i" :label="item.name" :value="item.id"></el-option>
<el-select v-model="filter.difficult" clearable multiple placeholder="请选择试卷难度" @change="initData">
<el-option v-for="(item, i) in difficults" :key="i" :label="item.name" :value="item.id"></el-option>
</el-select>
</li>
<li>
<label>所属专业</label>
<el-select v-model="filter.status" clearable placeholder="请选择所属专业" @change="getList">
<el-option v-for="(item, i) in status" :key="i" :label="item.name" :value="item.id"></el-option>
<el-select v-model="filter.professionalId" clearable placeholder="请选择所属专业" multiple @change="initData">
<el-option v-for="(item, i) in professionals" :key="i" :label="item.professionalName"
:value="item.professionalId"></el-option>
</el-select>
</li>
<li>
<label>年份</label>
<el-select v-model="filter.status" clearable placeholder="请选择年份" @change="getList">
<el-option v-for="(item, i) in status" :key="i" :label="item.name" :value="item.id"></el-option>
</el-select>
<el-date-picker v-model="particularYear" type="year" placeholder="请选择年份" format="yyyy" value-format="yyyy"
multiple @change="initData">
</el-date-picker>
</li>
<li>
<label>建议用途</label>
<el-select v-model="filter.status" clearable placeholder="请选择状态" @change="getList">
<el-option v-for="(item, i) in status" :key="i" :label="item.name" :value="item.id"></el-option>
<el-select v-model="filter.paperType" clearable placeholder="请选择状态" @change="initData">
<el-option v-for="(item, i) in paperTypes" :key="i" :label="item.name" :value="item.id"></el-option>
</el-select>
</li>
<li>
<label>状态</label>
<el-select v-model="filter.status" clearable placeholder="请选择状态" @change="getList">
<el-select v-model="filter.status" clearable placeholder="请选择状态" @change="initData">
<el-option v-for="(item, i) in status" :key="i" :label="item.name" :value="item.id"></el-option>
</el-select>
</li>
@ -105,7 +107,7 @@
<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="add">批量删除</el-button>
<el-button type="primary" @click="delAllSelection">批量删除</el-button>
</div>
</ul>
</div>
@ -114,30 +116,46 @@
@selection-change="handleSelectionChange" row-key="id" @sort-change="sortChange">
<el-table-column type="selection" width="55" align="center" :reserve-selection="true"></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>
<el-table-column prop="name" label="试题总数" align="center" min-width="120"></el-table-column>
<el-table-column prop="name" label="总分" align="center" width="90"></el-table-column>
<el-table-column prop="name" label="中分位数" align="center" min-width="120"></el-table-column>
<el-table-column prop="name" label="题型" align="center" min-width="120"></el-table-column>
<el-table-column prop="name" label="试卷难度" align="center" min-width="120"></el-table-column>
<el-table-column prop="name" label="建议用时" align="center" min-width="120"></el-table-column>
<el-table-column prop="knowledgePointsClassification" label="试卷分类" align="center" min-width="120"
<el-table-column prop="name" label="试卷名称" align="center" min-width="100"></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="name" label="中分位数" align="center" width="70"></el-table-column>
<el-table-column prop="name" label="题型" align="center" min-width="90">
</el-table-column>
<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 =>
e.id === scope.row.difficult).name : '' }}</template>
</el-table-column>
<el-table-column prop="suggestTime" label="建议用时" align="center" width="70">
<template slot-scope="scope">{{ scope.row.suggestTime }}min</template>
</el-table-column>
<el-table-column prop="classificationPath" label="试卷分类" align="center" width="90"
show-overflow-tooltip></el-table-column>
<el-table-column prop="relatedQuestionsNum" label="所属专业" align="center" width="90"></el-table-column>
<el-table-column prop="relatedQuestionsNum" label="年份" align="center" width="90"></el-table-column>
<el-table-column prop="relatedQuestionsNum" label="建议用途" align="center" width="90"></el-table-column>
<el-table-column prop="relatedQuestionsNum" label="状态" align="center" width="90"></el-table-column>
<el-table-column prop="professionalName" label="所属专业" align="center" width="100"></el-table-column>
<el-table-column prop="particularYear" label="年份" align="center" width="70" sortable="custom">
<template slot-scope="scope">{{ scope.row.particularYear }}</template>
</el-table-column>
<el-table-column label="建议用途" align="center" width="70">
<template slot-scope="scope">{{ paperTypes.find(e => e.id === scope.row.paperType) ? paperTypes.find(e =>
e.id === scope.row.paperType).name : '' }}</template>
</el-table-column>
<el-table-column label="状态" align="center" width="60">
<template slot-scope="scope">{{ scope.row.status ? '发布' : '草稿' }}</template>
</el-table-column>
<el-table-column prop="createTime" label="创建时间" align="center" width="160"
sortable="custom"></el-table-column>
<el-table-column prop="createTime" label="最近编辑时间" align="center" width="160"
<el-table-column prop="updateTime" label="最近编辑时间" align="center" width="160"
sortable="custom"></el-table-column>
<el-table-column prop="createUserName" label="最近编辑人" align="center" width="100"></el-table-column>
<el-table-column prop="createUser" label="最近编辑人" align="center" width="90"></el-table-column>
<el-table-column label="操作" align="center" width="240">
<template slot-scope="scope">
<el-button type="text" @click="edit(scope.row)">复制</el-button>
<el-button type="text" @click="edit(scope.row)">预览</el-button>
<el-button type="text" @click="edit(scope.row)">编辑</el-button>
<el-button type="text" @click="del(scope.row)">删除</el-button>
<el-switch v-if="!scope.row.status" v-model="scope.row.isDisable" :active-value="false"
:inactive-value="true" style="margin: 0 10px 0 5px" :active-text="scope.row.isDisable ? '关' : '开'"
@change="switchOff($event, scope.row, scope.$index)"></el-switch>
</template>
</el-table-column>
</el-table>
@ -169,21 +187,21 @@
import Util from '@/libs/util'
import _ from 'lodash'
import Breadcrumb from '@/components/breadcrumb'
import QuesConst from '@/const/ques'
import TestPaperConst from '@/const/testPaper'
export default {
components: { Breadcrumb },
data () {
return {
questionTypes: QuesConst.questionTypes,
difficults: TestPaperConst.difficults,
paperTypes: TestPaperConst.paperTypes,
typeId: this.$route.query.id,
createSource: 1,
loading: false,
keyword: '',
types: [],
isNotJoin: 1,
typeVisible: false, //
typeForm: {
classificationId: '',
classificationName: ''
},
cascaderValue: [],
cascaderProps: {
checkStrictly: true,
@ -191,30 +209,42 @@ export default {
value: "classificationId"
},
status: [],
form: {
name: '',
parentId: []
typeForm: {
classificationId: '',
classificationName: ''
},
typeRules: {
classificationName: [
{ required: true, message: '请输入试卷分类名称', trigger: 'blur' }
]
},
rules: {
name: [
{ required: true, message: '请输入试卷名称', trigger: 'blur' }
],
},
professionals: [],
status: [
{
id: 0,
name: '启用'
},
{
id: 1,
name: '禁用'
},
{
id: 2,
name: '草稿'
},
],
particularYear: '',
questionType: [],
filter: {
difficultOrder: '',
yearOrder: '',
difficult: [],
professionalId: [],
paperType: '',
status: '',
updateTimeOrder: '',
crateTimeOrder: '',
yearOrder: '',
keyWord: '',
difficult: '',
particularYear: '',
keyWord: '',
difficultOrder: '',
},
listLoading: false,
list: [],
@ -233,10 +263,6 @@ export default {
};
},
watch: {
keyword: function () {
clearTimeout(this.searchTimer)
this.searchTimer = setTimeout(this.getType, 500)
},
'filter.keyWord': function () {
clearTimeout(this.searchTimer)
this.searchTimer = setTimeout(this.getList, 500)
@ -253,6 +279,7 @@ export default {
},
],
this.getType()
this.getProfessional()
},
methods: {
//
@ -367,12 +394,24 @@ export default {
this.cascaderValue = []
this.getType()
},
//
async getProfessional () {
try {
const res = await this.$post(this.api.queryProfessional, {
pageNum: 1,
pageSize: 1000,
})
this.professionals = res.pageList.records
} catch (e) { }
},
//
async getList () {
try {
this.listLoading = true
const res = await this.$post(this.api.examPaperList, {
...this.filter,
particularYear: this.particularYear ? [this.particularYear] : [],
questionType: this.questionType.length ? this.questionType.join() : '',
type: this.isNotJoin,
pageNum: this.page,
pageSize: this.pageSize,
@ -399,27 +438,39 @@ export default {
},
//
sortChange (column) {
if (column.prop === 'createTime') this.filter.timeOrderBy = column.order ? column.order === 'ascending' ? 'asc' : 'desc' : ''
if (column.prop === 'difficult') this.filter.difficultOrder = column.order ? column.order === 'ascending' ? 1 : 2 : ''
if (column.prop === 'particularYear') this.filter.yearOrder = column.order ? column.order === 'ascending' ? 1 : 2 : ''
if (column.prop === 'createTime') this.filter.crateTimeOrder = column.order ? column.order === 'ascending' ? 1 : 2 : ''
if (column.prop === 'updateTime') this.filter.updateTimeOrder = column.order ? column.order === 'ascending' ? 1 : 2 : ''
this.getList()
},
//
async del (row) {
try {
await this.$confirm(`<p>确认要删除【${row.name}】吗?</p><p style="color: #f56c6c;">删除后,关联此试卷的试题将自动移除此试卷!</p>`, '提示', {
await this.$confirm(`确认要删除【${row.name}】吗?`, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
closeOnClickModal: false,
dangerouslyUseHTMLString: true,
})
await this.$post(this.api.knowledgeHierarchyDel, [row.id])
await this.$post(this.api.paperDel, {
delete: false,
ids: [row.paperId]
})
Util.successMsg('删除成功')
this.getList()
} catch (e) { }
},
async switchOff (val, row) {
await this.$post(this.api.paperDisable, {
id: row.paperId,
isDisable: val,
})
this.getList()
},
//
add () {
this.$router.push(`detail?libraryId=${this.typeId}`)
this.$router.push(`detail?libraryId=${this.typeId}&classificationId=${this.$refs.typeTree.getCurrentKey() || ''}`)
},
//
async edit (row) {
@ -437,14 +488,16 @@ export default {
const list = this.multipleSelection
if (list.length) {
try {
await this.$confirm(`<p style="margin-bottom: 10px;">确认要删除已选定的${list.length}个试卷吗?</p><p style="color: #f56c6c;">删除后,关联这些试卷的试题将自动移除这些试卷!</p>`, '提示', {
await this.$confirm(`确定要删除已选定的${list.length}份试卷吗?`, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
closeOnClickModal: false,
dangerouslyUseHTMLString: true,
})
await this.$post(this.api.knowledgeHierarchyDel, list.map(e => e.id))
await this.$post(this.api.paperDel, {
delete: false,
ids: list.map(e => e.paperId)
})
Util.successMsg('删除成功')
this.multipleSelection = []
this.$refs.table.clearSelection()

@ -26,6 +26,7 @@
<div class="right">
<h6 class="page-name">筛选</h6>
<!-- <UeditorPlus /> -->
<div class="tool">
<ul class="filter">
<li>
@ -101,10 +102,12 @@
</template>
<script>
import Util from "@/libs/util";
import Setting from "@/setting";
import Util from '@/libs/util'
import Setting from '@/setting'
// import UeditorPlus from '@/components/ueditorPlus'
import _ from 'lodash'
export default {
// components: { UeditorPlus },
data () {
return {
loading: false,

@ -410,6 +410,11 @@
.tinymce-load {
z-index: 3000 !important;
}
.action-icon {
font-size: 18px;
color: $main-color;
cursor: pointer;
}
.del-dia {
.el-dialog__body {

Loading…
Cancel
Save