parent
d79c0d0cbb
commit
b015e22c1a
15 changed files with 969 additions and 3857 deletions
@ -1,715 +0,0 @@ |
||||
<template> |
||||
<div> |
||||
<el-drawer title="自动选题" :visible.sync="quesVisible" size="1200px" :close-on-click-modal="false" |
||||
custom-class="ques-dia" @closed="closeDia"> |
||||
<div class="overflow"> |
||||
<h6 class="page-name">难度设置</h6> |
||||
<div class="tool"> |
||||
<ul class="filter"> |
||||
<li style="margin-right: 10px"> |
||||
<label>试卷难度</label> |
||||
<el-select v-model="difficult" placeholder="请选择试卷难度" @change="difficultChange"> |
||||
<el-option v-for="(item, i) in difficults" :key="i" :label="item.name" :value="item.id"></el-option> |
||||
</el-select> |
||||
</li> |
||||
<el-tooltip placement="top"> |
||||
<div class="diff-text" slot="content"> |
||||
<p>基础题:难度系数0.2</p> |
||||
<p>普通题:难度系数0.4</p> |
||||
<p>较难题:难度系数0.6</p> |
||||
<p>困难题:难度系数0.8</p> |
||||
<p>(1)<span class="em">题型难度系数</span>=对应题型所有试题的难度系数之和/总试题数</p> |
||||
<p>(2)<span class="em">试卷总难度系数</span>=所有试题的难度系数之和/总试题数</p> |
||||
<p>(3)<span class="em">难度系数评价</span>:</p> |
||||
<div class="coe"> |
||||
<p>简单:系数 <=0.3</p> |
||||
<p>普通:0.3<系数<=0.4</p> |
||||
<p>较难:0.4<系数<0.5</p> |
||||
<p>困难:系数>=0.5</p> |
||||
</div> |
||||
</div> |
||||
<i class="el-icon-question" style="font-size: 16px;color: #8f8f8f;cursor: pointer;"></i> |
||||
</el-tooltip> |
||||
</ul> |
||||
</div> |
||||
|
||||
<el-table :data="list" stripe header-align="center" row-key="libraryId"> |
||||
<el-table-column type="index" width="60" label="序号" align="center"></el-table-column> |
||||
<el-table-column label="大题" align="center" min-width="100"> |
||||
<template slot-scope="scope">第{{ arabicToChinese(scope.$index + 1) }}大题</template> |
||||
</el-table-column> |
||||
<el-table-column prop="name" label="题型" align="center" min-width="90"> |
||||
<template slot-scope="scope"> |
||||
<p v-if="scope.row.questionType">{{ questionTypes.find(e => e.id === scope.row.questionType).name }}</p> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column prop="questionNum" label="目标题数" align="center" min-width="80"></el-table-column> |
||||
<el-table-column label="基础(道题)" align="center" width="90"> |
||||
<template slot-scope="scope"> |
||||
<el-input v-model.number="scope.row.basicDifficulty" type="number" /> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column label="普通(道题)" align="center" width="90"> |
||||
<template slot-scope="scope"> |
||||
<el-input v-model.number="scope.row.normalDifficulty" type="number" /> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column label="较难(道题)" align="center" width="90"> |
||||
<template slot-scope="scope"> |
||||
<el-input v-model.number="scope.row.hardDifficulty" type="number" /> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column label="难(道题)" align="center" width="90"> |
||||
<template slot-scope="scope"> |
||||
<el-input v-model.number="scope.row.veryHardDifficulty" type="number" /> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column label="难度随机(道题)" align="center" width="100"> |
||||
<template slot-scope="scope"> |
||||
<el-input v-model.number="scope.row.randomDifficulty" type="number" /> |
||||
</template> |
||||
</el-table-column> |
||||
</el-table> |
||||
|
||||
<h6 class="page-name m-t-20">知识点设置</h6> |
||||
<div class="wrap"> |
||||
<!-- 题库 --> |
||||
<div class="item"> |
||||
<p class="total m-b-10">题库</p> |
||||
<ul class="filter"> |
||||
<li class="m-b-10"> |
||||
<label>题库分类</label> |
||||
<el-cascader style="width: 240px;" placeholder="请选择题库分类" v-model="quesBankTypeVal" |
||||
:options="quesBankTypes" :props="{ value: 'id', label: 'name', checkStrictly: true }" clearable |
||||
@change="initQuesBank"></el-cascader> |
||||
</li> |
||||
<li> |
||||
<el-input placeholder="请输入题库名称" prefix-icon="el-icon-search" v-model="quesBankKeyword" clearable /> |
||||
</li> |
||||
</ul> |
||||
|
||||
<template v-if="quesBanks.length"> |
||||
<div class="line"> |
||||
<span class="serial first">序号</span> |
||||
<span>题库名称</span> |
||||
</div> |
||||
|
||||
<div class="able-check lines"> |
||||
<div v-for="(item, i) in quesBanks" :key="i" :class="['line', { active: curQuesBank.id === item.id }]" |
||||
@click="questionBankClick(item)"> |
||||
<span class="serial first">{{ i + 1 }}</span> |
||||
<p class="stem" :title="item.questionBankName">{{ item.questionBankName }}</p> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
<div v-else class="empty"> |
||||
<img class="icon" src="@/assets/images/empty.svg" alt=""> |
||||
<p>暂无数据</p> |
||||
</div> |
||||
</div> |
||||
<!-- 知识点 --> |
||||
<div class="item"> |
||||
<p class="total m-b-10">知识点</p> |
||||
<ul class="filter"> |
||||
<li class="m-b-10"> |
||||
<label>知识点框架</label> |
||||
<el-cascader style="width: 240px;" placeholder="请选择知识点分类" v-model="knowledgeTypeVal" |
||||
:options="knowledgeTypes" :props="{ value: 'id', label: 'name', checkStrictly: true }" clearable |
||||
@change="getKnowledge"></el-cascader> |
||||
</li> |
||||
<li> |
||||
<el-input placeholder="请输入知识点名称" prefix-icon="el-icon-search" v-model="knowledgeKeyword" clearable /> |
||||
</li> |
||||
</ul> |
||||
|
||||
<template v-if="knowledges.length"> |
||||
<div class="line"> |
||||
<el-checkbox v-model="knowledgeCheck" @change="knowledgeAllCheckChange"></el-checkbox> |
||||
<span class="serial">序号</span> |
||||
<span>知识点名称</span> |
||||
</div> |
||||
|
||||
<div class="lines"> |
||||
<div v-for="(item, i) in knowledges" :key="i" class="line"> |
||||
<el-checkbox v-model="item.check" :disabled="item.disabled" |
||||
@change="val => knowledgeChange(val, item)"></el-checkbox> |
||||
<span class="serial">{{ i + 1 }}</span> |
||||
<p class="stem" :title="item.name">{{ item.name }}</p> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
<div v-else class="empty"> |
||||
<img class="icon" src="@/assets/images/empty.svg" alt=""> |
||||
<p>暂无数据</p> |
||||
</div> |
||||
</div> |
||||
<!-- 已选知识点 --> |
||||
<div class="item"> |
||||
<div class="flex j-between a-center m-b-20"> |
||||
<p class="total m-b-10">已选知识点({{ allKnowledges.length }}个)</p> |
||||
<p class="clear" @click="clearChecked"> |
||||
<i class="el-icon-delete m-r-5"></i> |
||||
清空 |
||||
</p> |
||||
</div> |
||||
|
||||
<template v-for="(item, i) in checked"> |
||||
<div :key="i" class="j-between m-b-10"> |
||||
<div class="flex a-center"> |
||||
题库:{{ item.quesBank.questionBankName }} |
||||
<i class="el-icon-delete action-icon m-l-10" @click="delQuesBank(i)"></i> |
||||
</div> |
||||
<div class="knowledges"> |
||||
<el-tag v-for="(tag, j) in item.knowledges" :key="tag.name" class="m-r-8 m-b-8" closable |
||||
@close="delKnowledge(i, j, item, tag)">{{ tag.name }}</el-tag> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
</div> |
||||
</div> |
||||
|
||||
<h6 class="page-name m-t-20">年份设置</h6> |
||||
<div class="years flex"> |
||||
<el-checkbox style="margin-right: 20px" v-model="yearAll" @change="yearAllChange">全选</el-checkbox> |
||||
<el-checkbox-group v-model="yearCheck" @change="yearChange"> |
||||
<el-checkbox v-for="(item, i) in years" :key="i" :label="item"></el-checkbox> |
||||
</el-checkbox-group> |
||||
</div> |
||||
</div> |
||||
|
||||
<div class="btns"> |
||||
<el-button @click="quesVisible = false">取消</el-button> |
||||
<el-button type="primary" :loading="submiting" @click="submit">自动选题</el-button> |
||||
</div> |
||||
</el-drawer> |
||||
</div> |
||||
</template> |
||||
<script> |
||||
import Setting from '@/setting' |
||||
import Util from '@/libs/util' |
||||
import QuesConst from '@/const/ques' |
||||
import TestPaperConst from '@/const/testPaper' |
||||
import _ from 'lodash' |
||||
import Decimal from 'decimal.js' |
||||
export default { |
||||
props: ['visible'], |
||||
data () { |
||||
return { |
||||
arabicToChinese: Util.arabicToChinese, |
||||
difficults: TestPaperConst.difficults, |
||||
questionTypes: QuesConst.questionTypes, |
||||
quesVisible: false, |
||||
difficult: '', |
||||
searchTimer: null, |
||||
|
||||
curQuesBank: {}, |
||||
quesBankTypeVal: [], |
||||
quesBankTypes: [], |
||||
quesBankKeyword: '', |
||||
|
||||
quesBanks: [], |
||||
pageQuesBank: 1, |
||||
pageSizeQuesBank: 10, |
||||
totalQuesBank: 0, |
||||
|
||||
knowledgeKeyword: '', |
||||
knowledgeTypeVal: [], |
||||
knowledgeTypes: [], |
||||
knowledgeCheck: false, |
||||
knowledges: [], |
||||
pageKn: 1, |
||||
pageSizeKn: 10, |
||||
totalKn: 0, |
||||
|
||||
checkedKeyword: '', |
||||
checked: [], |
||||
list: [], |
||||
years: ['暂无年份', '2024', '2023', '2022', '2021', '2020', '2019', '2018', '2017', '2016', '更早'], |
||||
yearAll: true, |
||||
yearCheck: [], |
||||
submiting: false, |
||||
loaded: 0, |
||||
}; |
||||
}, |
||||
computed: { |
||||
allKnowledges () { |
||||
const result = [] |
||||
this.checked.map(e => { |
||||
result.push(...e.knowledges) |
||||
}) |
||||
return result |
||||
}, |
||||
}, |
||||
watch: { |
||||
'quesBankKeyword': function (val) { |
||||
clearTimeout(this.searchTimer) |
||||
this.searchTimer = setTimeout(this.initQuesBank, 500) |
||||
}, |
||||
'knowledgeKeyword': function (val) { |
||||
clearTimeout(this.searchTimer) |
||||
this.searchTimer = setTimeout(this.getKnowledge, 500) |
||||
}, |
||||
visible () { |
||||
this.quesVisible = this.visible |
||||
this.visible && this.init() |
||||
} |
||||
}, |
||||
mounted () { |
||||
|
||||
}, |
||||
methods: { |
||||
// 初始化 |
||||
init () { |
||||
this.handleQuesList() |
||||
if (!this.loaded) { |
||||
this.loaded = 1 |
||||
this.yearCheck = this.years |
||||
this.getQuesBankType() |
||||
this.initQuesBank() |
||||
this.difficult = this.$parent.form.difficult |
||||
this.difficult && this.difficultChange(this.difficult) |
||||
} |
||||
}, |
||||
// 获取题库分类 |
||||
async getQuesBankType () { |
||||
try { |
||||
const { data } = await this.$post(this.api.getAllQuestionBankCategories, { |
||||
createSource: 1, |
||||
status: 1, |
||||
}) |
||||
this.handleList(data) |
||||
this.quesBankTypes = data |
||||
} catch (e) { } |
||||
}, |
||||
// 获取题库 |
||||
async getQuesBank () { |
||||
try { |
||||
const type = this.quesBankTypeVal |
||||
const res = await this.$post(this.api.questionBankList, { |
||||
status: 1, |
||||
pageNum: 1, |
||||
pageSize: 1000, |
||||
questionCategoryId: type.length ? type[type.length - 1] : '', |
||||
name: this.quesBankKeyword |
||||
}) |
||||
this.quesBanks = res.message.records |
||||
this.totalQuesBank = res.message.total |
||||
} catch (e) { } |
||||
}, |
||||
initQuesBank () { |
||||
this.curQuesBank = {} |
||||
this.pageQuesBank = 1 |
||||
this.getQuesBank() |
||||
}, |
||||
// 切换页码 |
||||
currentChangeQuesBank (val) { |
||||
this.pageQuesBank = val |
||||
this.getQuesBank() |
||||
}, |
||||
// 题目多选回调 |
||||
questionBankClick (item) { |
||||
this.curQuesBank = item |
||||
this.knowledgeCheck = false |
||||
this.getKnowledgeType() |
||||
this.getKnowledge() |
||||
}, |
||||
|
||||
// 处理树形 |
||||
handleList (list) { |
||||
list.map(e => { |
||||
if (e.children && e.children.length) { |
||||
this.handleList(e.children) |
||||
} else { |
||||
delete e.children |
||||
} |
||||
}) |
||||
}, |
||||
// 获取知识点分类 |
||||
async getKnowledgeType () { |
||||
try { |
||||
const { data } = await this.$post(this.api.classificationTreeStructure, { |
||||
createSource: 1, |
||||
questionBankId: this.curQuesBank.id, |
||||
}) |
||||
this.handleList(data) |
||||
this.knowledgeTypes = data |
||||
} catch (e) { } |
||||
}, |
||||
// 获取知识点 |
||||
async getKnowledge () { |
||||
try { |
||||
const { id } = this.curQuesBank |
||||
if (id) { |
||||
const type = this.knowledgeTypeVal |
||||
const res = await this.$post(this.api.knowledgeHierarchyList, { |
||||
pageNum: 1, |
||||
pageSize: 1000, |
||||
questionBankId: id, |
||||
knowledgePointCategoryId: type.length ? type[type.length - 1] : '', |
||||
name: this.knowledgeKeyword, |
||||
}) |
||||
const list = res.message.records |
||||
const { allKnowledges } = this |
||||
list.map(e => { |
||||
e.check = !!allKnowledges.find(n => n.id === e.id) |
||||
}) |
||||
this.knowledges = list |
||||
} |
||||
} catch (e) { } |
||||
}, |
||||
// 切换页码 |
||||
currentChangeKn (val) { |
||||
this.pageKn = val |
||||
this.getKnowledge() |
||||
}, |
||||
// 知识点全选回调 |
||||
knowledgeAllCheckChange (val) { |
||||
this.knowledges.map(e => { |
||||
e.check = val |
||||
this.knowledgeChange(val, e) |
||||
}) |
||||
}, |
||||
// 知识点勾选回调 |
||||
knowledgeChange (checked, data) { |
||||
const checkQues = this.curQuesBank |
||||
const index = this.checked.findIndex(e => e.quesBank.id === checkQues.id) |
||||
// 已选中的题库数组里有该题库,则往该题库的知识点数组里 |
||||
if (index !== -1) { |
||||
const ques = this.checked[index] |
||||
const i = ques.knowledges.findIndex(e => e.id === data.id) |
||||
if (checked && i === -1) { |
||||
ques.knowledges.push(data) |
||||
} else if (!checked && i >= 0) { |
||||
ques.knowledges.splice(i, 1) |
||||
} |
||||
ques.knowledges.length || this.checked.splice(index, 1) |
||||
} else { |
||||
this.checked.push({ |
||||
quesBank: checkQues, |
||||
knowledges: [data] |
||||
}) |
||||
} |
||||
}, |
||||
// 处理大纲列表 |
||||
handleQuesList () { |
||||
this.list = _.cloneDeep(this.$parent.form.paperOutline) |
||||
}, |
||||
// 清空已选 |
||||
async clearChecked () { |
||||
try { |
||||
await this.$confirm(`确认要清空吗?`, '提示', { |
||||
confirmButtonText: '确定', |
||||
cancelButtonText: '取消', |
||||
type: 'warning', |
||||
closeOnClickModal: false, |
||||
}) |
||||
this.knowledges.map(e => e.check = false) |
||||
this.checked = [] |
||||
this.knowledgeCheck = false |
||||
} catch (e) { } |
||||
}, |
||||
// 删除题库 |
||||
async delQuesBank (i) { |
||||
try { |
||||
await this.$confirm(`确认要移除吗?`, '提示', { |
||||
confirmButtonText: '确定', |
||||
cancelButtonText: '取消', |
||||
type: 'warning', |
||||
closeOnClickModal: false, |
||||
}) |
||||
const k = this.knowledges |
||||
this.checked[i].knowledges.map(e => { |
||||
const cur = k.findIndex(n => n.id === e.id) |
||||
if (cur !== -1) k[cur].check = false |
||||
}) |
||||
this.checked.splice(i, 1) |
||||
this.knowledgeCheck = false |
||||
} catch (e) { } |
||||
}, |
||||
// 删除知识点 |
||||
delKnowledge (i, j, item, k) { |
||||
const cur = this.knowledges.findIndex(e => e.id === k.id) |
||||
if (cur !== -1) this.knowledges[cur].check = false |
||||
item.knowledges.splice(j, 1) |
||||
item.knowledges.length || this.checked.splice(i, 1) // 知识点清空了则把该题库删除 |
||||
this.knowledgeCheck = false |
||||
}, |
||||
|
||||
|
||||
// 试卷难度选择回调 |
||||
difficultChange (val) { |
||||
const difficultyWeights = [0.2, 0.4, 0.6, 0.8] |
||||
const names = ['basicDifficulty', 'normalDifficulty', 'hardDifficulty', 'veryHardDifficulty'] |
||||
// 遍历题型数组 |
||||
this.list.forEach(e => { |
||||
const total = e.questionNum |
||||
|
||||
let already = 0 // 已经分配的数量 |
||||
if (val === 1) { |
||||
this.$set(e, 'basicDifficulty', Math.floor(total * 0.7)) |
||||
this.$set(e, 'normalDifficulty', Math.floor(total * 0.3)) |
||||
this.$set(e, 'hardDifficulty', 0) |
||||
this.$set(e, 'veryHardDifficulty', 0) |
||||
} else if (val === 2) { |
||||
this.$set(e, 'basicDifficulty', Math.floor(total * 0.45)) |
||||
this.$set(e, 'normalDifficulty', Math.floor(total * 0.55)) |
||||
this.$set(e, 'hardDifficulty', 0) |
||||
this.$set(e, 'veryHardDifficulty', 0) |
||||
} else if (val === 3) { |
||||
this.$set(e, 'basicDifficulty', Math.floor(total * 0.3)) |
||||
this.$set(e, 'normalDifficulty', Math.floor(total * 0.3)) |
||||
this.$set(e, 'hardDifficulty', Math.floor(total * 0.4)) |
||||
this.$set(e, 'veryHardDifficulty', 0) |
||||
} else if (val === 4) { |
||||
this.$set(e, 'basicDifficulty', Math.floor(total * 0.1)) |
||||
this.$set(e, 'normalDifficulty', Math.floor(total * 0.1)) |
||||
this.$set(e, 'hardDifficulty', Math.floor(total * 0.3)) |
||||
this.$set(e, 'veryHardDifficulty', Math.floor(total * 0.5)) |
||||
} |
||||
|
||||
|
||||
already = Decimal(already).add(e.basicDifficulty).add(e.normalDifficulty).add(e.hardDifficulty).add(e.veryHardDifficulty).toNumber() |
||||
// 如果按比例分配还没分配完 |
||||
while (total > already) { |
||||
e[names[val - 1]]++ |
||||
already++ |
||||
} |
||||
this.$set(e, 'randomDifficulty', 0) |
||||
}) |
||||
}, |
||||
// 年份全选回调 |
||||
yearAllChange (val) { |
||||
this.yearCheck = val ? this.years : [] |
||||
}, |
||||
// 年份选择回调 |
||||
yearChange (val) { |
||||
this.yearAll = val.length === 11 |
||||
}, |
||||
// 提交 |
||||
async submit () { |
||||
if (this.submiting) return false |
||||
const { list } = this |
||||
let invalid = 0 |
||||
let totalCount = 0 |
||||
for (const i in list) { |
||||
const e = list[i] |
||||
const name = `第${Util.arabicToChinese(+i + 1)}大题` |
||||
if (!e.questionType) { |
||||
Util.warningMsg(`${name}请先选择题型`) |
||||
invalid = 1 |
||||
break |
||||
} |
||||
if (!e.questionNum || isNaN(e.questionNum) || e.questionNum <= 0) { |
||||
Util.warningMsg(`${name}的目标题数请输入正整数`) |
||||
invalid = 1 |
||||
break |
||||
} |
||||
let total = Decimal(e.basicDifficulty || 0).add(e.normalDifficulty || 0).add(e.hardDifficulty || 0).add(e.veryHardDifficulty || 0).toNumber() // 先算前4个难度的题数 |
||||
if (total) { // 前面4个空有填1个,则清空随机 |
||||
this.$set(e, 'randomDifficulty', 0) |
||||
} else { |
||||
total = +e.randomDifficulty || 0 |
||||
} |
||||
|
||||
if (total > e.questionNum) { |
||||
Util.warningMsg(`${name}的小题总数大于目标题数,请重新输入`) |
||||
invalid = 1 |
||||
break |
||||
} |
||||
e.count = total |
||||
totalCount = Decimal(totalCount).add(total).toNumber() |
||||
} |
||||
if (invalid) return false |
||||
if (!totalCount) return Util.warningMsg(`请填写难度题数`) |
||||
this.submiting = true |
||||
const k = this.allKnowledges.map(e => e.id) |
||||
|
||||
const years = [] |
||||
this.yearCheck.map(e => { |
||||
if (e === '暂无年份') { |
||||
years.push('') |
||||
} else if (e === '更早') { |
||||
// 选的是更早则直接传1990~2005所有年份 |
||||
for (let i = 1990; i < 2006; i++) { |
||||
years.push(i) |
||||
} |
||||
} else { |
||||
years.push(+e) |
||||
} |
||||
}) |
||||
list.map(e => { |
||||
e.givenYears = years |
||||
e.knowledgePointsIds = k |
||||
}) |
||||
try { |
||||
const res = await this.$post(this.api.selectQuestionsByTypeAndDifficulty, list) |
||||
|
||||
let invalid = 0 |
||||
let hasQues = 0 |
||||
list.map((e, i) => { |
||||
if (+e.count !== res.list[i].questions.length) invalid = 1 |
||||
if (e.examQuestions.length) hasQues = 1 |
||||
e.score = 0 |
||||
}) |
||||
|
||||
// 3种情况提示不一样 |
||||
const tips = invalid && hasQues ? |
||||
'此操作会清空当前试卷已添加的试题,并且满足自动选题设置的试题数量不足,确定要继续自动选题吗?' : |
||||
invalid && !hasQues ? |
||||
'满足自动选题设置的试题数量不足,确认要继续自动选题吗?' : |
||||
!invalid && hasQues ? '此操作会清空当前试卷已添加的试题,是否确定要继续自动选题吗?' : |
||||
'' |
||||
|
||||
if (tips) { |
||||
await this.$confirm(tips, '提示', { |
||||
confirmButtonText: '确定', |
||||
cancelButtonText: '取消', |
||||
type: 'warning', |
||||
closeOnClickModal: false, |
||||
}) |
||||
} |
||||
list.map((e, i) => { |
||||
res.list[i].questions.map((e, i) => { |
||||
e.questionId = e.id |
||||
e.serialNumber = i + 1 |
||||
e.originSort = i + 1 |
||||
this.$parent.handleQuesInfo(e) |
||||
}) |
||||
this.$parent.form.paperOutline[i].examQuestions = res.list[i].questions |
||||
}) |
||||
this.quesVisible = false |
||||
this.$parent.calcDifficult() |
||||
this.submiting = false |
||||
} catch (e) { |
||||
this.submiting = false |
||||
} |
||||
}, |
||||
// 弹框关闭回调 |
||||
closeDia () { |
||||
this.$emit('update:visible', false) |
||||
} |
||||
} |
||||
}; |
||||
</script> |
||||
|
||||
<style lang="scss" scoped> |
||||
/deep/.ques-dia { |
||||
.el-drawer__header { |
||||
margin-bottom: 20px; |
||||
} |
||||
|
||||
.overflow { |
||||
height: calc(100vh - 147px); |
||||
padding: 0 20px; |
||||
overflow: auto; |
||||
} |
||||
|
||||
|
||||
.wrap { |
||||
display: flex; |
||||
margin-top: 20px; |
||||
border: 1px solid #eee; |
||||
|
||||
.filter { |
||||
margin-bottom: 15px; |
||||
|
||||
li { |
||||
display: flex; |
||||
align-items: center; |
||||
} |
||||
|
||||
label { |
||||
margin-right: 10px; |
||||
font-size: 14px; |
||||
color: #333; |
||||
white-space: nowrap; |
||||
} |
||||
} |
||||
|
||||
.item { |
||||
width: 30%; |
||||
padding: 15px; |
||||
border-right: 1px solid #eee; |
||||
|
||||
&:last-child { |
||||
width: 40%; |
||||
border-right: 0; |
||||
} |
||||
} |
||||
|
||||
.total { |
||||
font-size: 16px; |
||||
color: #333; |
||||
} |
||||
|
||||
.clear { |
||||
display: inline-flex; |
||||
align-items: center; |
||||
font-size: 14px; |
||||
color: #8b8b8b; |
||||
cursor: pointer; |
||||
} |
||||
|
||||
.knowledges { |
||||
padding-left: 44px; |
||||
margin-top: 10px; |
||||
} |
||||
|
||||
.lines { |
||||
height: calc(100vh - 392px); |
||||
overflow: auto; |
||||
} |
||||
|
||||
.line { |
||||
display: flex; |
||||
padding: 5px 0; |
||||
color: #333; |
||||
|
||||
} |
||||
|
||||
.able-check { |
||||
.line { |
||||
cursor: pointer; |
||||
|
||||
&:hover { |
||||
background-color: #f5f5f5; |
||||
} |
||||
|
||||
&.active { |
||||
background-color: #e5e5e5; |
||||
} |
||||
} |
||||
} |
||||
|
||||
.serial { |
||||
width: 32px; |
||||
margin: 0 12px; |
||||
text-align: center; |
||||
white-space: nowrap; |
||||
|
||||
&.first { |
||||
margin-left: 0; |
||||
} |
||||
} |
||||
|
||||
.stem { |
||||
max-width: calc(100% - 71px); |
||||
@include ellipsis; |
||||
} |
||||
|
||||
.checked-stem { |
||||
max-width: 165px; |
||||
@include ellipsis; |
||||
} |
||||
|
||||
.check-left { |
||||
display: inline-flex; |
||||
align-items: center; |
||||
} |
||||
|
||||
.action-icon { |
||||
font-size: 14px; |
||||
} |
||||
} |
||||
} |
||||
</style> |
File diff suppressed because it is too large
Load Diff
@ -1,610 +0,0 @@ |
||||
<template> |
||||
<div> |
||||
<el-drawer :title="diaTitle" :visible.sync="selectQuesVisible" size="1200px" :close-on-click-modal="false" |
||||
custom-class="ques-dia" @closed="closeDia"> |
||||
<div class="wrap"> |
||||
<!-- 题库 --> |
||||
<div class="item"> |
||||
<p class="total m-b-10">题库</p> |
||||
<ul class="filter"> |
||||
<li class="m-b-10"> |
||||
<label>题库分类</label> |
||||
<el-cascader style="width: 240px;" placeholder="请选择题库分类" v-model="quesBankTypeVal" |
||||
:options="quesBankTypes" :props="{ value: 'id', label: 'name', checkStrictly: true }" clearable |
||||
@change="initQuesBank"></el-cascader> |
||||
</li> |
||||
<li> |
||||
<el-input placeholder="请输入题库名称" prefix-icon="el-icon-search" v-model="quesBankKeyword" clearable /> |
||||
</li> |
||||
</ul> |
||||
|
||||
<template v-if="quesBanks.length"> |
||||
<div class="line"> |
||||
<span class="serial">序号</span> |
||||
<span>题库名称</span> |
||||
</div> |
||||
|
||||
<div class="able-check lines"> |
||||
<div v-for="(item, i) in quesBanks" :key="i" :class="['line', { active: curQuesBank.id === item.id }]" |
||||
@click="questionBankClick(item)"> |
||||
<span class="serial">{{ i + 1 }}</span> |
||||
<p class="quesBank" :title="item.questionBankName">{{ item.questionBankName }}</p> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
<div v-else class="empty"> |
||||
<img class="icon" src="@/assets/images/empty.svg" alt=""> |
||||
<p>暂无数据</p> |
||||
</div> |
||||
</div> |
||||
<!-- 题目 --> |
||||
<div class="item"> |
||||
<p class="total m-b-10">{{ questionTypeName }}(共{{ ques.length }}道题)</p> |
||||
|
||||
<ul class="filter"> |
||||
<li class="m-b-10"> |
||||
<label>知识点</label> |
||||
<el-cascader style="width: 240px;" placeholder="请选择知识点" v-model="knowledgeVal" :options="knowledges" |
||||
:props="{ value: 'id', label: 'name', multiple: true }" clearable @change="getQues"></el-cascader> |
||||
</li> |
||||
<li> |
||||
<el-input placeholder="请输入题干" prefix-icon="el-icon-search" v-model="knowledgeKeyword" clearable /> |
||||
</li> |
||||
</ul> |
||||
|
||||
<template v-if="ques.length"> |
||||
<div class="line"> |
||||
<el-checkbox v-model="quesAllCheck" @change="quesAllCheckChange"></el-checkbox> |
||||
<span class="serial">序号</span> |
||||
<span class="stem">题干</span> |
||||
<span class="kl">知识点</span> |
||||
</div> |
||||
|
||||
<div class="lines"> |
||||
<div v-for="(item, i) in ques" :key="i" class="line"> |
||||
<el-checkbox v-model="item.check" :disabled="item.disabled" |
||||
@change="val => quesChange(val, item)"></el-checkbox> |
||||
<span class="serial">{{ i + 1 }}</span> |
||||
<el-tooltip effect="dark" :content="item.stemText" placement="top-start"> |
||||
<p class="stem cursor-pointer" @click="toShowQues(item)">{{ item.stemText }}</p> |
||||
</el-tooltip> |
||||
<el-tooltip effect="dark" :content="item.knowledgePointName" placement="top-start"> |
||||
<p class="kl">{{ item.knowledgePointName }}</p> |
||||
</el-tooltip> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
<div v-else class="empty"> |
||||
<img class="icon" src="@/assets/images/empty.svg" alt=""> |
||||
<p>暂无数据</p> |
||||
</div> |
||||
</div> |
||||
<!-- 已选试题 --> |
||||
<div class="item"> |
||||
<div v-if="$parent.curQues" class="m-b-20"> |
||||
<p class="total m-b-10">原试题(共1道题)</p> |
||||
<div v-html="$parent.curQues.stemText"></div> |
||||
</div> |
||||
|
||||
<div class="flex j-between a-center"> |
||||
<p v-if="$parent.curQues" class="total">更换试题(共{{ checked.length }}道题)</p> |
||||
<p v-else class="total">已选试题(共{{ checkedLen }}道题)</p> |
||||
<el-button type="text" @click="batchDelChecked">批量移除</el-button> |
||||
</div> |
||||
|
||||
<el-input class="m-t-10 m-b-10" placeholder="请输入题干/知识点" prefix-icon="el-icon-search" v-model="checkedKeyword" |
||||
clearable /> |
||||
|
||||
<template v-if="checked.length"> |
||||
<div class="ques"> |
||||
<div class="line"> |
||||
<el-checkbox v-model="checkedAllCheck" @change="checkedAllCheckChange"></el-checkbox> |
||||
<span class="serial">序号</span> |
||||
<span class="stem">题干</span> |
||||
<span class="kl">知识点</span> |
||||
</div> |
||||
|
||||
<div :class="['lines', { switch: $parent.curQues }]"> |
||||
<template v-for="(item, i) in checked"> |
||||
<div v-if="item.stemText.includes(checkedKeyword) || item.knowledgePointName.includes(checkedKeyword)" |
||||
:key="i" class="line"> |
||||
<div class="check-left"> |
||||
<el-checkbox v-model="item.check"></el-checkbox> |
||||
<span class="serial">{{ i + 1 }}</span> |
||||
<el-tooltip effect="dark" :content="item.stemText" placement="top-start"> |
||||
<p class="checked-stem">{{ item.stemText }}</p> |
||||
</el-tooltip> |
||||
<el-tooltip effect="dark" :content="item.knowledgePointName" placement="top-start"> |
||||
<p class="kl checked-kl">{{ item.knowledgePointName }}</p> |
||||
</el-tooltip> |
||||
</div> |
||||
<i class="el-icon-delete action-icon" @click="delChecked(item)"></i> |
||||
</div> |
||||
</template> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
<div v-else class="empty"> |
||||
<img class="icon" src="@/assets/images/empty.svg" alt=""> |
||||
<p>暂无数据</p> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
<div class="flex j-between p-l-20 p-r-20"> |
||||
<p>未找到试题,<a class="link" @click="toAddQues">去新增</a></p> |
||||
<p>已选题数/目标题数:{{ checkedLen }}/{{ $parent.curType.questionNum }} |
||||
</p> |
||||
</div> |
||||
|
||||
<div class="btns"> |
||||
<el-button @click="selectQuesVisible = false">取消</el-button> |
||||
<el-button type="primary" :loading="submiting" @click="submit">确定</el-button> |
||||
</div> |
||||
</el-drawer> |
||||
|
||||
|
||||
<el-drawer title="新增试题" :visible.sync="addQuesVisible" size="1200px" :close-on-click-modal="false" |
||||
custom-class="add-dia"> |
||||
<QuesDetail :key="quesKey" :paperType.sync="paperType" :curQues.sync="curRow" @closeAdd="closeAdd" /> |
||||
</el-drawer> |
||||
</div> |
||||
</template> |
||||
<script> |
||||
import Setting from '@/setting' |
||||
import Util from '@/libs/util' |
||||
import _ from 'lodash' |
||||
import QuesConst from '@/const/ques' |
||||
import QuesDetail from '@/pages/ques/detail' |
||||
export default { |
||||
props: ['visible', 'questionType'], |
||||
components: { QuesDetail }, |
||||
data () { |
||||
return { |
||||
selectQuesVisible: false, |
||||
searchTimer: null, |
||||
quesBankKeyword: '', |
||||
curQuesBank: {}, |
||||
quesBankTypeVal: [], |
||||
quesBankTypes: [], |
||||
quesBanks: [], |
||||
pageQuesBank: 1, |
||||
pageSizeQuesBank: 10, |
||||
totalQuesBank: 0, |
||||
|
||||
knowledgeKeyword: '', |
||||
key: 1, |
||||
knowledgeVal: [], |
||||
knowledges: [], |
||||
quesAllCheck: false, |
||||
ques: [], |
||||
checkedAllCheck: false, |
||||
checked: [], |
||||
curCheckQues: [], |
||||
checkedKeyword: '', |
||||
submiting: false, |
||||
|
||||
quesVisible: false, |
||||
curRow: {}, |
||||
addQuesVisible: false, |
||||
quesKey: 1, |
||||
paperType: 1, |
||||
}; |
||||
}, |
||||
computed: { |
||||
// 外面已经添加的试题+当前弹框已经勾选的试题 |
||||
checkedLen () { |
||||
let len = this.curCheckQues.length + this.checked.length |
||||
if (this.$parent.curQues) len -= 1 |
||||
return len |
||||
}, |
||||
// 题型name |
||||
questionTypeName () { |
||||
return this.questionType ? QuesConst.questionTypes.find(e => e.id === this.questionType).name : '' |
||||
}, |
||||
// 弹框标题 |
||||
diaTitle () { |
||||
const { curQuesIndex, curQues } = this.$parent |
||||
return curQues ? |
||||
'更换试题' : |
||||
typeof curQuesIndex === 'number' ? |
||||
'添加试题' : |
||||
this.questionType ? `批量添加${QuesConst.questionTypes.find(e => e.id === this.questionType).name}` : '' |
||||
}, |
||||
}, |
||||
watch: { |
||||
'quesBankKeyword': function (val) { |
||||
clearTimeout(this.searchTimer) |
||||
this.searchTimer = setTimeout(this.initQuesBank, 500) |
||||
}, |
||||
'knowledgeKeyword': function (val) { |
||||
clearTimeout(this.searchTimer) |
||||
this.searchTimer = setTimeout(this.getQues, 500) |
||||
}, |
||||
visible () { |
||||
this.selectQuesVisible = this.visible |
||||
this.visible && this.init() |
||||
} |
||||
}, |
||||
mounted () { |
||||
|
||||
}, |
||||
methods: { |
||||
init () { |
||||
// 清空所有状态和数据 |
||||
this.key++ |
||||
this.knowledges = [] |
||||
this.ques = [] |
||||
this.checked = [] |
||||
this.quesAllCheck = false |
||||
this.checkedAllCheck = false |
||||
this.quesBankKeyword = '' |
||||
this.knowledgeKeyword = '' |
||||
|
||||
// 当前大题的小题列表 |
||||
const { curType, curQues } = this.$parent |
||||
if (curQues) curQues.stemText = Util.delTag(curQues.stem) |
||||
this.curCheckQues = curType.examQuestions |
||||
|
||||
this.getQuesBankType() |
||||
this.initQuesBank() |
||||
}, |
||||
// 获取题库分类 |
||||
async getQuesBankType () { |
||||
try { |
||||
const { data } = await this.$post(this.api.getAllQuestionBankCategories, { |
||||
createSource: 1, |
||||
status: 1, |
||||
}) |
||||
this.handleList(data) |
||||
this.quesBankTypes = data |
||||
} catch (e) { } |
||||
}, |
||||
// 获取题库 |
||||
async getQuesBank () { |
||||
try { |
||||
const type = this.quesBankTypeVal |
||||
const res = await this.$post(this.api.questionBankList, { |
||||
status: 1, |
||||
pageNum: 1, |
||||
pageSize: 1000, |
||||
questionCategoryId: type.length ? type[type.length - 1] : '', |
||||
name: this.quesBankKeyword |
||||
}) |
||||
const { records } = res.message |
||||
this.quesBanks = records |
||||
this.totalQuesBank = res.message.total |
||||
records.length && this.questionBankClick(records[0]) |
||||
} catch (e) { } |
||||
}, |
||||
initQuesBank () { |
||||
this.curQuesBank = {} |
||||
this.pageQuesBank = 1 |
||||
this.getQuesBank() |
||||
}, |
||||
// 切换页码 |
||||
currentChangeQuesBank (val) { |
||||
this.pageQuesBank = val |
||||
this.getQuesBank() |
||||
}, |
||||
// 题目多选回调 |
||||
questionBankClick (item) { |
||||
this.curQuesBank = item |
||||
this.knowledgeCheck = false |
||||
this.getKnowledge() |
||||
this.getQues() |
||||
this.quesAllCheck = false |
||||
}, |
||||
|
||||
// 处理树形 |
||||
handleList (list) { |
||||
list.map(e => { |
||||
if (e.children && e.children.length) { |
||||
this.handleList(e.children) |
||||
} else { |
||||
delete e.children |
||||
} |
||||
}) |
||||
}, |
||||
|
||||
// 获取知识点 |
||||
async getKnowledge () { |
||||
try { |
||||
const { id } = this.curQuesBank |
||||
if (id) { |
||||
const { data } = await this.$post(this.api.TreeStructure, { |
||||
createSource: 1, |
||||
questionBankId: id, |
||||
keyword: '', |
||||
}) |
||||
this.handleList(data) |
||||
this.knowledges = data |
||||
} |
||||
} catch (e) { } |
||||
}, |
||||
// 获取试题 |
||||
async getQues () { |
||||
const { id } = this.curQuesBank |
||||
let k = this.knowledgeVal // 选中的知识点 |
||||
k = k.map(e => { |
||||
return e[e.length - 1] |
||||
}) |
||||
if (id) { |
||||
const { list } = await this.$post(this.api.findAllByQuestionBank, { |
||||
status: 1, |
||||
questionBankIds: [id], |
||||
knowledgePointIds: k, |
||||
questionTypes: this.questionType ? [this.questionType] : [], |
||||
keyword: this.knowledgeKeyword, |
||||
}) |
||||
const data = list |
||||
const { curCheckQues, checked } = this |
||||
data.map(e => { |
||||
e.stemText = Util.delTag(e.stem) |
||||
const quesChecked = !!curCheckQues.find(n => n.questionVersionId === e.questionVersionId) |
||||
e.disabled = quesChecked |
||||
e.check = !!checked.find(n => n.questionVersionId === e.questionVersionId) || quesChecked |
||||
}) |
||||
this.ques = data |
||||
} |
||||
}, |
||||
// 知识点勾选回调 |
||||
knowledgeCheck () { |
||||
|
||||
}, |
||||
// 题目全选回调 |
||||
quesAllCheckChange (val) { |
||||
this.ques.map(e => { |
||||
if (!e.disabled) { |
||||
e.check = val |
||||
this.quesChange(val, e) |
||||
} |
||||
}) |
||||
}, |
||||
// 题目多选回调 |
||||
quesChange (val, item) { |
||||
const cur = this.checked.findIndex(e => e.questionVersionId === item.questionVersionId) |
||||
// 选中 |
||||
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) { |
||||
checked.map(e => { |
||||
const cur = this.ques.find(n => n.questionVersionId === e.questionVersionId) |
||||
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 { |
||||
const cur = this.ques.find(e => e.questionVersionId === item.questionVersionId) |
||||
if (cur) cur.check = false |
||||
this.checked.splice(this.checked.findIndex(e => e.questionVersionId === item.questionVersionId), 1) |
||||
} catch (e) { } |
||||
}, |
||||
// 新增试题 |
||||
toAddQues () { |
||||
this.quesKey++ |
||||
this.paperType = 1 |
||||
this.addQuesVisible = true |
||||
}, |
||||
// 查看试题 |
||||
toShowQues (ques) { |
||||
this.quesKey++ |
||||
this.curRow = ques |
||||
this.paperType = 3 |
||||
this.addQuesVisible = true |
||||
}, |
||||
// 关闭新增试题弹框 |
||||
closeAdd () { |
||||
this.addQuesVisible = false |
||||
}, |
||||
// 提交 |
||||
async submit () { |
||||
if (this.submiting) return false |
||||
const checked = _.cloneDeep(this.checked) |
||||
if (!checked.length) return Util.warningMsg('请选择试题') |
||||
|
||||
const { curType, curQuesIndex, curQues } = this.$parent |
||||
if (this.checkedLen > +curType.questionNum) return Util.warningMsg(`目标题数为${curType.questionNum},已选题数不得大于目标题数`) |
||||
|
||||
try { |
||||
checked.map((e, i) => { |
||||
this.$set(e, 'check', false) |
||||
this.$set(e, 'sort', i + 1) |
||||
this.$set(e, 'originSort', i + 1) |
||||
this.$set(e, 'score', '') |
||||
this.$parent.handleQuesInfo(e) |
||||
}) |
||||
|
||||
if (curQues) { |
||||
// curQues即是小题,有则说明是更换试题,需要把该小题去掉,再添加进选中的试题 |
||||
this.curCheckQues.splice(curQuesIndex, 1, ...checked) |
||||
} else { |
||||
// curQuesIndex为数字,则是小题里面的添加试题打开的弹框,则把选择的试题添加到该小题后面;否则直接添加到最后面 |
||||
typeof curQuesIndex === 'number' ? |
||||
this.curCheckQues.splice(curQuesIndex + 1, 0, ...checked) : |
||||
this.curCheckQues.push(...checked) |
||||
} |
||||
// 给题目重新排序 |
||||
this.curCheckQues.map((e, i) => { |
||||
this.$set(e, 'serialNumber', i + 1) |
||||
}) |
||||
|
||||
this.$parent.calcDifficult() |
||||
this.selectQuesVisible = false |
||||
this.submiting = false |
||||
} catch (e) { |
||||
this.submiting = false |
||||
} |
||||
}, |
||||
// 弹框关闭回调 |
||||
closeDia () { |
||||
this.$emit('update:visible', false) |
||||
} |
||||
} |
||||
}; |
||||
</script> |
||||
|
||||
<style lang="scss" scoped> |
||||
/deep/.ques-dia { |
||||
.el-drawer__header { |
||||
margin-bottom: 20px; |
||||
} |
||||
|
||||
.wrap { |
||||
display: flex; |
||||
margin-bottom: 10px; |
||||
border: 1px solid #eee; |
||||
|
||||
.filter { |
||||
margin-bottom: 15px; |
||||
|
||||
li { |
||||
display: flex; |
||||
align-items: center; |
||||
} |
||||
|
||||
label { |
||||
margin-right: 10px; |
||||
font-size: 14px; |
||||
color: #333; |
||||
white-space: nowrap; |
||||
} |
||||
} |
||||
|
||||
.item { |
||||
width: 38%; |
||||
padding: 15px; |
||||
border-right: 1px solid #eee; |
||||
|
||||
&:first-child { |
||||
width: 24%; |
||||
} |
||||
} |
||||
|
||||
.total { |
||||
font-size: 16px; |
||||
color: #333; |
||||
} |
||||
|
||||
.lines { |
||||
height: calc(100vh - 358px); |
||||
overflow: auto; |
||||
} |
||||
|
||||
.ques { |
||||
.lines { |
||||
height: calc(100vh - 328px); |
||||
overflow: auto; |
||||
|
||||
&.switch { |
||||
height: calc(100vh - 394px); |
||||
} |
||||
} |
||||
} |
||||
|
||||
.line { |
||||
display: flex; |
||||
padding: 5px 0; |
||||
color: #333; |
||||
} |
||||
|
||||
.able-check { |
||||
.line { |
||||
cursor: pointer; |
||||
|
||||
&:hover { |
||||
background-color: #f5f5f5; |
||||
} |
||||
|
||||
&.active { |
||||
background-color: #e5e5e5; |
||||
} |
||||
} |
||||
} |
||||
|
||||
.serial { |
||||
width: 32px; |
||||
margin: 0 12px; |
||||
text-align: center; |
||||
white-space: nowrap; |
||||
} |
||||
|
||||
.quesBank { |
||||
width: calc(100% - 71px); |
||||
@include ellipsis; |
||||
} |
||||
|
||||
.stem { |
||||
width: calc(100% - 210px); |
||||
margin-right: 20px; |
||||
@include ellipsis; |
||||
|
||||
&:hover { |
||||
opacity: .9; |
||||
} |
||||
} |
||||
|
||||
.kl { |
||||
width: 120px; |
||||
@include ellipsis; |
||||
|
||||
&.checked-kl { |
||||
width: 100px; |
||||
margin-right: 10px; |
||||
} |
||||
} |
||||
|
||||
.checked-stem { |
||||
width: 190px; |
||||
margin-right: 20px; |
||||
@include ellipsis; |
||||
} |
||||
|
||||
.check-left { |
||||
display: inline-flex; |
||||
align-items: center; |
||||
} |
||||
|
||||
.action-icon { |
||||
font-size: 14px; |
||||
} |
||||
} |
||||
|
||||
.link { |
||||
color: $main-color; |
||||
cursor: pointer; |
||||
} |
||||
} |
||||
|
||||
/deep/.add-dia { |
||||
.el-drawer__header { |
||||
margin-bottom: 0; |
||||
} |
||||
} |
||||
</style> |
@ -1,119 +0,0 @@ |
||||
<template> |
||||
<el-drawer title="提示" :visible.sync="listVisible" size="800px" :close-on-press-escape="false" :wrapperClosable="false" |
||||
:show-close="false" custom-class="ques-dia" @closed="closeDia"> |
||||
<div class="wrap p-20"> |
||||
<el-alert title="以下试题在试卷中疑似出现重复,是否要继续发布!" type="warning" effect="dark" :closable="false" /> |
||||
<el-table class="m-t-10" :data="data" stripe header-align="center" row-key="uuid"> |
||||
<el-table-column prop="outlineName" label="大题名称" align="center" width="90"></el-table-column> |
||||
<el-table-column prop="serialNumber" label="题号" align="center" width="60"></el-table-column> |
||||
<el-table-column prop="stem" label="题干" align="center" min-width="120"> |
||||
<template slot-scope="scope"> |
||||
<div v-html="scope.row.stem"></div> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column label="操作" align="center" width="140"> |
||||
<template slot-scope="scope"> |
||||
<el-button type="text" @click="toQues(scope.row)">详情</el-button> |
||||
<el-button type="text" @click="delQues(scope.row, scope.$index)">移除</el-button> |
||||
<!-- <el-button type="text" @click="switchQues(scope.row, scope.$index)">替换</el-button> --> |
||||
</template> |
||||
</el-table-column> |
||||
</el-table> |
||||
</div> |
||||
<div class="btns"> |
||||
<el-button type="primary" @click="check">检查一下</el-button> |
||||
<el-button :loading="submiting" @click="submit">继续发布</el-button> |
||||
</div> |
||||
</el-drawer> |
||||
</template> |
||||
<script> |
||||
import _ from 'lodash' |
||||
export default { |
||||
props: ['visible', 'list'], |
||||
data () { |
||||
return { |
||||
listVisible: false, |
||||
data: [], |
||||
submiting: false, |
||||
}; |
||||
}, |
||||
watch: { |
||||
visible () { |
||||
this.listVisible = this.visible |
||||
this.visible && this.init() |
||||
} |
||||
}, |
||||
mounted () { |
||||
|
||||
}, |
||||
methods: { |
||||
init () { |
||||
this.data = this.list |
||||
}, |
||||
// 详情 |
||||
toQues (row) { |
||||
const paper = this.$parent.form.paperOutline |
||||
this.$parent.toQues(paper[row.paperIndex], row.quesIndex, paper[row.paperIndex].examQuestions[row.quesIndex], 3) |
||||
}, |
||||
// 移除 |
||||
async delQues (row, i) { |
||||
try { |
||||
await this.$confirm(`确认要移除吗?`, '提示', { |
||||
confirmButtonText: '确定', |
||||
cancelButtonText: '取消', |
||||
type: 'warning', |
||||
closeOnClickModal: false, |
||||
}) |
||||
this.$parent.delQues(this.$parent.form.paperOutline[row.paperIndex], row.quesIndex, 1) |
||||
|
||||
const { data } = this |
||||
data.splice(i, 1) |
||||
data.map(e => e.repeat = false) |
||||
this.data = this.$parent.hasRepeatQues(data) |
||||
} catch (e) { } |
||||
}, |
||||
// 替换 |
||||
switchQues (row) { |
||||
const paper = this.$parent.form.paperOutline |
||||
this.$parent.showManualDia(paper[row.paperIndex], row.quesIndex, paper[row.paperIndex].examQuestions[row.quesIndex]) |
||||
this.listVisible = false |
||||
}, |
||||
// 检查一下 |
||||
async check () { |
||||
const { data } = this |
||||
this.$parent.form.paperOutline.map(e => { |
||||
e.examQuestions.map(n => { |
||||
this.$set(n, 'repeat', !!data.find(m => m.questionVersionId === n.questionVersionId)) |
||||
}) |
||||
}) |
||||
this.$parent.submiting = false |
||||
this.listVisible = false |
||||
}, |
||||
// 提交 |
||||
async submit () { |
||||
if (this.submiting) return false |
||||
this.submiting = true |
||||
await this.$parent.saveTestPaper() |
||||
this.submiting = false |
||||
}, |
||||
// 弹框关闭回调 |
||||
closeDia () { |
||||
this.$parent.submiting = false |
||||
this.$emit('update:visible', false) |
||||
} |
||||
} |
||||
}; |
||||
</script> |
||||
|
||||
<style lang="scss" scoped> |
||||
/deep/.ques-dia { |
||||
.el-drawer__header { |
||||
margin-bottom: 0; |
||||
} |
||||
|
||||
.wrap { |
||||
max-height: calc(100vh - 110px); |
||||
overflow: auto; |
||||
} |
||||
} |
||||
</style> |
@ -1,329 +0,0 @@ |
||||
<template> |
||||
<div> |
||||
<el-dialog title="选择试卷大纲模板" :visible.sync="listVisible" width="1200px" :close-on-click-modal="false" |
||||
@closed="closeDia"> |
||||
<div class="tool"> |
||||
<ul class="filter"> |
||||
<li> |
||||
<label>题型</label> |
||||
<el-select v-model="questionType" multiple clearable placeholder="请选择题目类型" @change="initData"> |
||||
<el-option v-for="(item, i) in questionTypes" :key="i" :value="item.id" :label="item.name"></el-option> |
||||
</el-select> |
||||
</li> |
||||
<li> |
||||
<label>搜索</label> |
||||
<el-input style="width: 250px;" placeholder="请输入模板名称" prefix-icon="el-icon-search" v-model="templateName" |
||||
clearable /> |
||||
</li> |
||||
</ul> |
||||
<div> |
||||
<el-button type="primary" @click="add">新增模板</el-button> |
||||
</div> |
||||
</div> |
||||
|
||||
<el-table :data="list" stripe header-align="center" row-key="libraryId"> |
||||
<el-table-column type="index" width="60" label="序号" align="center"></el-table-column> |
||||
<el-table-column prop="templateName" label="模板名称" align="center" min-width="100"></el-table-column> |
||||
<el-table-column prop="questionTypeName" label="题型" align="center" min-width="140"></el-table-column> |
||||
<el-table-column prop="outlineNum" label="大题数" align="center" width="60"></el-table-column> |
||||
<el-table-column prop="questionNum" label="小题总数" align="center" width="80"></el-table-column> |
||||
<el-table-column prop="totalScore" label="总分" align="center" width="60"></el-table-column> |
||||
<el-table-column prop="createTime" label="创建时间" align="center" width="160"></el-table-column> |
||||
<el-table-column prop="createUser" label="创建人" align="center" width="80"></el-table-column> |
||||
<el-table-column label="操作" align="center" width="150"> |
||||
<template slot-scope="scope"> |
||||
<el-button type="text" @click="useTemplate(scope.row, 0)">使用模板</el-button> |
||||
<el-button type="text" @click="edit(scope.row, 1)">编辑</el-button> |
||||
<el-button type="text" @click="del(scope.row)">删除</el-button> |
||||
</template> |
||||
</el-table-column> |
||||
</el-table> |
||||
<div class="pagination"> |
||||
<el-pagination background @current-change="currentChange" :current-page="page" layout="total, prev, pager, next" |
||||
:total="total"></el-pagination> |
||||
</div> |
||||
<span slot="footer" class="dialog-footer"> |
||||
<el-button @click="listVisible = false">关闭</el-button> |
||||
</span> |
||||
</el-dialog> |
||||
|
||||
<el-dialog title="新增模板" :visible.sync="detailVisible" width="800px" :close-on-click-modal="false"> |
||||
<el-form :model="form" :rules="rules" label-width="100px"> |
||||
<el-form-item prop="templateName" label="模板名称"> |
||||
<el-input placeholder="请输入模板名称" v-model="form.templateName" /> |
||||
</el-form-item> |
||||
</el-form> |
||||
|
||||
<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 prop="outlineName" label="大题" align="center" min-width="120"> |
||||
<template slot-scope="scope">第{{ arabicToChinese(scope.$index + 1) }}大题</template> |
||||
</el-table-column> |
||||
<el-table-column prop="name" label="题型" align="center" min-width="120"> |
||||
<template slot-scope="scope"> |
||||
<el-select v-model="scope.row.questionType" placeholder="请选择题型"> |
||||
<el-option v-for="(item, i) in questionTypes" :key="i" :label="item.name" :value="item.id"></el-option> |
||||
</el-select> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column prop="name" label="目标题数" align="center" min-width="120"> |
||||
<template slot-scope="scope"> |
||||
<el-input placeholder="请输入目标题数" v-model="scope.row.questionNum" type="number" /> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column prop="name" label="目标分值" align="center" min-width="120"> |
||||
<template slot-scope="scope"> |
||||
<el-input placeholder="请输入目标分值" v-model="scope.row.targetScore" /> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column label="操作" align="center" width="120"> |
||||
<template slot-scope="scope"> |
||||
<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" |
||||
@click="delLine(scope.$index)"></i> |
||||
</template> |
||||
</el-table-column> |
||||
</el-table> |
||||
<p class="m-t-10 text-right">目标总题数:{{ questionNum }};目标总分:{{ totalScore }}</p> |
||||
<span slot="footer" class="dialog-footer"> |
||||
<el-button @click="detailVisible = false">取消</el-button> |
||||
<el-button type="primary" v-loading="submiting" @click="submit">保存模板</el-button> |
||||
</span> |
||||
</el-dialog> |
||||
</div> |
||||
</template> |
||||
<script> |
||||
import Setting from '@/setting' |
||||
import Util from '@/libs/util' |
||||
import _ from 'lodash' |
||||
import QuesConst from '@/const/ques' |
||||
export default { |
||||
props: ['visible'], |
||||
data () { |
||||
return { |
||||
arabicToChinese: Util.arabicToChinese, |
||||
questionTypes: QuesConst.questionTypes, |
||||
listVisible: false, |
||||
searchTimer: null, |
||||
|
||||
templateName: '', |
||||
questionType: [], |
||||
list: [], |
||||
page: 1, |
||||
pageSize: 10, |
||||
total: 0, |
||||
|
||||
detailVisible: false, |
||||
originForm: {}, |
||||
form: { |
||||
templateName: '', |
||||
paperOutline: [ |
||||
{ |
||||
examQuestions: [], |
||||
outlineName: '单选题', |
||||
questionNum: '', |
||||
questionType: 'single_choice', |
||||
targetScore: '', |
||||
}, |
||||
{ |
||||
examQuestions: [], |
||||
outlineName: '多选题', |
||||
questionNum: '', |
||||
questionType: 'multiple_choice', |
||||
targetScore: '', |
||||
}, |
||||
{ |
||||
examQuestions: [], |
||||
outlineName: '判断题', |
||||
questionNum: '', |
||||
questionType: 'judgement', |
||||
targetScore: '', |
||||
}, |
||||
{ |
||||
examQuestions: [], |
||||
outlineName: '填空题', |
||||
questionNum: '', |
||||
questionType: 'fill_blank', |
||||
targetScore: '', |
||||
}, |
||||
{ |
||||
examQuestions: [], |
||||
outlineName: '问答题', |
||||
questionNum: '', |
||||
questionType: 'essay', |
||||
targetScore: '', |
||||
}, |
||||
], |
||||
}, |
||||
rules: { |
||||
templateName: [ |
||||
{ required: true, message: '请输入模板名称', trigger: 'blur' } |
||||
], |
||||
}, |
||||
submiting: false, |
||||
|
||||
}; |
||||
}, |
||||
computed: { |
||||
questionNum () { |
||||
return this.form.paperOutline.reduce((e, j) => (e += +j.questionNum), 0) |
||||
}, |
||||
totalScore () { |
||||
return this.form.paperOutline.reduce((e, j) => (e += +j.targetScore), 0) |
||||
} |
||||
}, |
||||
watch: { |
||||
templateName: function (val) { |
||||
clearTimeout(this.searchTimer) |
||||
this.searchTimer = setTimeout(this.initData, 500) |
||||
}, |
||||
visible () { |
||||
this.listVisible = this.visible |
||||
this.visible && this.getList() |
||||
} |
||||
}, |
||||
mounted () { |
||||
this.originForm = _.cloneDeep(this.form) |
||||
}, |
||||
methods: { |
||||
// 获取模板列表 |
||||
async getList () { |
||||
try { |
||||
const res = await this.$post(this.api.examPaperTemplateList, { |
||||
pageNum: this.page, |
||||
pageSize: this.pageSize, |
||||
questionType: this.questionType.join(), |
||||
templateName: this.templateName |
||||
}) |
||||
const list = res.pageList.records |
||||
const types = QuesConst.questionTypes |
||||
list.map(e => { |
||||
const names = [] |
||||
e.questionType.split('、').map(n => { |
||||
const item = types.find(m => m.id === n) |
||||
item && names.push(item.name) |
||||
}) |
||||
if (names.length) e.questionTypeName = names.join('、') |
||||
}) |
||||
this.list = list |
||||
this.total = res.pageList.total |
||||
} catch (e) { } |
||||
}, |
||||
// 切换页码 |
||||
currentChange (val) { |
||||
this.page = val |
||||
this.getList() |
||||
}, |
||||
initData () { |
||||
this.page = 1 |
||||
this.getList() |
||||
}, |
||||
// 新增 |
||||
add () { |
||||
this.form = _.cloneDeep(this.originForm) |
||||
this.detailVisible = true |
||||
}, |
||||
// 试卷大纲添加行 |
||||
addLine (i) { |
||||
this.form.paperOutline.splice(i + 1, 0, { |
||||
examQuestions: [], |
||||
outlineName: '', |
||||
questionNum: '', |
||||
questionType: '', |
||||
targetScore: '', |
||||
}) |
||||
}, |
||||
// 试卷大纲移除行 |
||||
delLine (i) { |
||||
this.form.paperOutline.length > 1 && this.form.paperOutline.splice(i, 1) |
||||
}, |
||||
// 使用模板 |
||||
async useTemplate (row) { |
||||
const data = await this.getDetail(row.templateId) |
||||
data.paperOutline.map(e => { |
||||
e.shrink = false |
||||
e.checkAll = false |
||||
e.examQuestions = [] |
||||
}) |
||||
this.$parent.form.paperOutline = data.paperOutline |
||||
this.$parent.templateName = data.templateName |
||||
this.listVisible = false |
||||
}, |
||||
// 获取详情 |
||||
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('、') |
||||
try { |
||||
await this.$post(this.api.saveExamPaperTemplate, form) |
||||
Util.successMsg('保存成功') |
||||
this.detailVisible = false |
||||
this.submiting = false |
||||
this.getList() |
||||
} catch (e) { |
||||
this.submiting = false |
||||
} |
||||
}, |
||||
// 弹框关闭回调 |
||||
closeDia () { |
||||
this.$emit('update:visible', false) |
||||
} |
||||
} |
||||
}; |
||||
</script> |
||||
|
||||
<style lang="scss" scoped></style> |
@ -1,706 +0,0 @@ |
||||
<template> |
||||
<div class="index"> |
||||
<div class="top"> |
||||
<p class="names">{{ form.name }}</p> |
||||
|
||||
<div class="count m-r-30"> |
||||
用时 |
||||
<span>{{ timeSum.day }}</span>天 |
||||
<span>{{ timeSum.hour }}</span>小时 |
||||
<span>{{ timeSum.minutes }}</span>分 |
||||
<span>{{ timeSum.seconds }}</span>秒 |
||||
</div> |
||||
|
||||
<img class="exit" src="@/assets/images/exit.svg" alt="" @click="close"> |
||||
</div> |
||||
|
||||
<div class="wrap"> |
||||
<div class="left"> |
||||
<h6 class="title">答题卡</h6> |
||||
<div class="progress"> |
||||
<p class="fs-14">答题进度</p> |
||||
<el-progress class="m-t-5 m-b-5" :percentage="progress" :format="progressFormat"></el-progress> |
||||
<p>共{{ form.questionCount }}题,满分{{ form.score }}分</p> |
||||
</div> |
||||
<div v-if="form.paperOutline" class="type-wrap"> |
||||
<div v-for="(item, i) in form.paperOutline" :key="i" class="type"> |
||||
<h6 class="stem">{{ arabicToChinese(i + 1) }}、{{ item.outlineName }}(本题共{{ item.questionNum }}小题,共{{ |
||||
item.targetScore }}分)</h6> |
||||
<ul class="serials"> |
||||
<template v-for="(ques, j) in item.examQuestions"> |
||||
<li |
||||
v-if="!sheetStatus || (sheetStatus === 1 && !ques.answered) || (sheetStatus === 2 && ques.answered) || (sheetStatus === 3 && ques.partAnswer) || (sheetStatus === 4 && ques.sign)" |
||||
:key="j" :class="{ answered: ques.answered, partAnswer: ques.partAnswer }" |
||||
@click="scrollToQues(ques, item)"> |
||||
<img v-if="ques.sign" class="tag" src="@/assets/images/tag-active.svg" alt=""> |
||||
{{ j + 1 }} |
||||
</li> |
||||
</template> |
||||
</ul> |
||||
</div> |
||||
</div> |
||||
<ul class="status-filter"> |
||||
<li :class="{ active: sheetStatus === 1 }" @click="filterStatus(1)">未作答</li> |
||||
<li :class="{ active: sheetStatus === 2 }" @click="filterStatus(2)">已作答</li> |
||||
<li :class="{ active: sheetStatus === 3 }" @click="filterStatus(3)">部分已作答</li> |
||||
<li :class="{ active: sheetStatus === 4 }" @click="filterStatus(4)"><img class="tag" |
||||
src="@/assets/images/tag-active.svg" alt=""> 已标记</li> |
||||
</ul> |
||||
</div> |
||||
|
||||
<ul v-if="form.paperOutline" class="ques-wrap" id="quesWrap"> |
||||
<li v-for="(item, i) in form.paperOutline" :key="i"> |
||||
<div class="outline"> |
||||
{{ arabicToChinese(i + 1) }}、{{ item.outlineName }}(本题共{{ item.questionNum }}小题,共{{ |
||||
item.targetScore }}分) |
||||
<img :class="['shrink', { active: item.shrink }]" src="@/assets/images/shrink.svg" alt="" |
||||
@click="item.shrink = !item.shrink"> |
||||
</div> |
||||
<div :class="['ques', { hide: item.shrink }]"> |
||||
<div v-for="(ques, j) in item.examQuestions" :key="j" |
||||
:class="['item', { disabled: !ques.status, del: ques.isDel, repeat: ques.repeat }]" |
||||
:id="'ques' + ques.id"> |
||||
<div class="stem-wrap"> |
||||
<span class="label">{{ j + 1 }} / {{ item.questionNum }}</span> |
||||
<span class="label">{{ item.questionTypeName }}</span> |
||||
<div class="stem html-parse" :id="'stem' + ques.id" v-html="getQuesStem(ques)"></div> |
||||
<p v-if="item.questionType !== 'fill_blank'">({{ ques.score }}分)</p> |
||||
<img class="tag" :src="require('@/assets/images/' + (ques.sign ? 'tag-active' : 'tag') + '.svg')" alt="" |
||||
@click="ques.sign = ques.sign ? 0 : 1"> |
||||
</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"> |
||||
<el-checkbox v-if="item.questionType === 'multiple_choice'" v-model="opt.answer" :true-label="1" |
||||
@change="mulChange(ques)"></el-checkbox> |
||||
<el-radio v-else v-model="opt.answer" :true-label="1" :label="1" |
||||
@change="singleChange(ques, j)"></el-radio> |
||||
|
||||
<span>{{ numToLetter(j) }}. </span> |
||||
<div class="text html-parse" v-html="opt.optionText"></div> |
||||
</div> |
||||
</template> |
||||
<!-- 简答题需要展示题干文件及富文本 --> |
||||
<template v-if="item.questionType === 'essay'"> |
||||
<div v-if="ques.stemAttachment" class="m-b-20"> |
||||
<el-link class="m-r-10" type="primary" @click="preview(ques.stemAttachment)">{{ ques.fileName |
||||
|| ques.stemAttachment |
||||
}}</el-link> |
||||
<el-button type="primary" size="mini" round |
||||
@click="download(ques.fileName || ques.stemAttachment, ques.stemAttachment)">下载</el-button> |
||||
</div> |
||||
<UeditorPlus :ref="'essayAnswer' + ques.id" v-model="ques.answer" |
||||
@ready="editor => essayAnswerReady(editor, ques)" /> |
||||
<div v-if="ques.allowAttachment" class="m-t-20"> |
||||
<div v-if="ques.uploadInstructions" class="flex m-b-10 fs-12"> |
||||
<span>上传要求说明:</span> |
||||
<div class="html-parse" v-html="ques.uploadInstructions"></div> |
||||
</div> |
||||
<el-upload action="#"> |
||||
<el-button size="small" type="primary">上传文件</el-button> |
||||
</el-upload> |
||||
</div> |
||||
</template> |
||||
</div> |
||||
</div> |
||||
</li> |
||||
</ul> |
||||
</div> |
||||
|
||||
<el-dialog title="图片预览" :visible.sync="previewImgVisible" width="800px" :close-on-click-modal="false"> |
||||
<el-image style="max-width: 100px; max-height: 100px" :src="previewImg" :preview-src-list="[previewImg]"> |
||||
</el-image> |
||||
</el-dialog> |
||||
<PdfDia :key="pdfVisible" :visible.sync="pdfVisible" :src.sync="pdfSrc" /> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import Util from '@/libs/util' |
||||
import Setting from "@/setting" |
||||
import QuesConst from '@/const/ques' |
||||
import TestPaperConst from '@/const/testPaper' |
||||
import _ from 'lodash' |
||||
import Oss from '@/components/upload/upload.js' |
||||
import Upload from '@/components/upload' |
||||
import UeditorPlus from '@/components/ueditorPlus' |
||||
import PdfDia from '@/components/pdf' |
||||
|
||||
export default { |
||||
components: { |
||||
Upload, UeditorPlus, PdfDia |
||||
}, |
||||
data () { |
||||
return { |
||||
questionTypes: QuesConst.questionTypes, |
||||
numToLetter: Util.numToLetter, |
||||
arabicToChinese: Util.arabicToChinese, |
||||
id: +this.$route.query.id, |
||||
entryTime: '', |
||||
counterTimer: null, // 获取setInterval对象值 |
||||
timeSumVal: 0, |
||||
// 用时 |
||||
timeSum: { |
||||
day: 0, |
||||
seconds: 0, |
||||
minutes: 0, |
||||
hour: 0, |
||||
}, |
||||
totalAnswered: 0, |
||||
progress: 0, |
||||
sheetStatus: '', |
||||
form: { |
||||
questionCount: 0, |
||||
}, |
||||
previewImgVisible: false, |
||||
previewImg: '', |
||||
pdfVisible: false, |
||||
pdfSrc: '', |
||||
}; |
||||
}, |
||||
mounted () { |
||||
this.$once('hook:beforeDestroy', function () { |
||||
clearInterval(this.counterTimer) |
||||
}) |
||||
|
||||
this.getPaper() |
||||
}, |
||||
methods: { |
||||
// 获取试卷详情 |
||||
async getPaper (now) { |
||||
try { |
||||
this.entryTime = await Util.getNow() |
||||
const { id } = this |
||||
if (id) { |
||||
// 试卷详情 |
||||
const { examPaper } = await this.$get(this.api.examPaperDetails, { id }) |
||||
|
||||
this.startCount() |
||||
|
||||
const r = examPaper |
||||
const paper = r.paperOutline |
||||
const types = this.questionTypes |
||||
paper.map(e => { |
||||
const type = e.questionType |
||||
e.questionTypeName = types.find(n => n.id === type).name |
||||
e.shrink = false |
||||
e.examQuestions.map(n => { |
||||
Object.assign(n, n.question) |
||||
n.sign = 0 |
||||
const opts = n.questionAnswerVersionsList |
||||
if (type !== 'fill_blank' && type !== 'essay' && opts) { // 选择题 |
||||
opts.map(m => { |
||||
m.answer = 0 |
||||
}) |
||||
} else { // 简答题 |
||||
n.answer = '' |
||||
// 附件 |
||||
n.uploadList = [] |
||||
} |
||||
}) |
||||
}) |
||||
this.form = r |
||||
|
||||
// 给填空题的每个空监听input事件,用以显示已作答状态 |
||||
this.$nextTick(() => { |
||||
paper.map(e => { |
||||
e.examQuestions.map(n => { |
||||
if (e.questionType === 'fill_blank') { |
||||
const stem = document.querySelector(`#stem` + n.id) |
||||
if (stem) { |
||||
const inputs = stem.querySelectorAll('.fill-input') |
||||
if (inputs) { |
||||
for (const e of inputs) { |
||||
e.addEventListener('input', () => { |
||||
const answers = [] |
||||
for (const e of inputs) { |
||||
e.value && answers.push(e.value) |
||||
} |
||||
n.answered = answers.length === inputs.length ? 1 : 0 |
||||
n.partAnswer = answers.length && answers.length !== inputs.length ? 1 : 0 |
||||
}) |
||||
} |
||||
} |
||||
} |
||||
} |
||||
}) |
||||
}) |
||||
this.calcProgress() |
||||
}) |
||||
} |
||||
} catch (e) { } |
||||
}, |
||||
// 计时器 |
||||
handleCounter (counterTime, isCount) { |
||||
let leave1 = counterTime % (24 * 3600) //计算天数后剩余的毫秒数 |
||||
let leave2 = leave1 % 3600 //计算小时数后剩余的毫秒数 |
||||
let leave3 = leave2 % 60 //计算分钟数后剩余的毫秒数 |
||||
let day = Math.floor(counterTime / (24 * 3600)) //计算相差天数 |
||||
let hour = Math.floor(leave1 / 3600) //计算相差小时 |
||||
let minutes = Math.floor(leave2 / 60) //计算相差分钟 |
||||
let seconds = Math.round(leave3) //计算相差秒 |
||||
day = this.timeFormat(day) |
||||
hour = this.timeFormat(hour) |
||||
minutes = this.timeFormat(minutes) |
||||
seconds = this.timeFormat(seconds) |
||||
const count = this[isCount ? 'counterVal' : 'timeSum'] |
||||
count.day = day |
||||
count.hour = hour |
||||
count.minutes = minutes |
||||
count.seconds = seconds |
||||
}, |
||||
// 启动倒计时 |
||||
startCount () { |
||||
clearInterval(this.counterTimer) |
||||
this.counterTimer = setInterval(() => { |
||||
this.timeSumVal >= 0 && this.handleCounter(this.timeSumVal++) |
||||
}, 1000) |
||||
}, |
||||
timeFormat (param) { |
||||
return param < 10 ? '0' + param : param |
||||
}, |
||||
// 计算答题进度 |
||||
calcProgress () { |
||||
let answered = 0 |
||||
this.form.paperOutline.map(e => { |
||||
answered += e.examQuestions.filter(n => n.answered).length |
||||
}) |
||||
this.totalAnswered = answered |
||||
this.progress = +(answered / this.form.questionCount * 100).toFixed(1) |
||||
}, |
||||
// 答题进度格式 |
||||
progressFormat (e) { |
||||
return this.totalAnswered + '/' + this.form.questionCount |
||||
}, |
||||
scrollToSmooth (position, duration) { |
||||
let startTime = Date.now() |
||||
|
||||
function scroll () { |
||||
let now = Date.now() |
||||
let progress = Math.min(1, (now - startTime) / duration) |
||||
document.querySelector('#quesWrap').scrollTo(0, position * progress) |
||||
|
||||
if (progress < 1) { |
||||
window.requestAnimationFrame(scroll) |
||||
} |
||||
} |
||||
|
||||
window.requestAnimationFrame(scroll) |
||||
}, |
||||
// 答题卡题目点击滚动 |
||||
scrollToQues (e, item) { |
||||
item.shrink = false |
||||
const el = document.querySelector('#ques' + e.id) |
||||
this.$nextTick(() => { |
||||
el && this.scrollToSmooth(el.offsetTop - document.querySelector('#quesWrap').offsetTop, 200) |
||||
}) |
||||
}, |
||||
// 答题卡筛选 |
||||
filterStatus (e) { |
||||
this.sheetStatus = this.sheetStatus === e ? '' : e |
||||
}, |
||||
// 处理题干显示 |
||||
getQuesStem (ques) { |
||||
let { stem } = ques |
||||
if (ques.questionType === 'fill_blank') { // 填空题 |
||||
let { fills } = ques |
||||
|
||||
const regex = /<span class="gapfilling-span" data-id="(.*?)">______<\/span>/g |
||||
let match |
||||
let index = 0 // 用于跟踪索引 |
||||
let result = stem |
||||
|
||||
while ((match = regex.exec(stem)) !== null) { |
||||
const newInput = `<input type="text" class="fill-input" value="${fills && fills.length ? fills[index] : ''}">` |
||||
result = result.replace(match[0], newInput) |
||||
index++ |
||||
} |
||||
return result |
||||
} else { |
||||
return stem |
||||
} |
||||
}, |
||||
// 单选题回调 |
||||
singleChange (ques, j) { |
||||
ques.questionAnswerVersionsList.map(e => { |
||||
e.answer = 0 |
||||
}) |
||||
ques.questionAnswerVersionsList[j].answer = 1 |
||||
|
||||
ques.answered = 1 |
||||
this.calcProgress() |
||||
}, |
||||
// 多选题回调 |
||||
mulChange (ques) { |
||||
ques.answered = ques.questionAnswerVersionsList.some(e => e.answer) |
||||
this.calcProgress() |
||||
}, |
||||
|
||||
// 简答题富文本加载完毕回调 |
||||
essayAnswerReady (editor, ques) { |
||||
editor.ques = ques |
||||
editor.addListener('contentChange', () => { |
||||
ques.answered = editor.getContent() ? 1 : 0 |
||||
this.calcProgress() |
||||
}) |
||||
ques.answer && editor.setContent(ques.answer) |
||||
}, |
||||
// 预览附件 |
||||
preview (url) { |
||||
const ext = url.split('.').pop() |
||||
if (Util.isDoc(ext)) { |
||||
window.open('https://view.officeapps.live.com/op/view.aspx?src=' + url) |
||||
} else if (Util.isImg(ext)) { |
||||
this.previewImgVisible = true |
||||
this.previewImg = url |
||||
} else if (ext === 'pdf') { |
||||
this.pdfVisible = true |
||||
this.pdfSrc = url |
||||
} |
||||
}, |
||||
// 下载附件 |
||||
download (name, url) { |
||||
Util.downloadFile(name, url) |
||||
}, |
||||
handleRemove (ques) { |
||||
Oss.del(ques.attachmentUrl) |
||||
ques.attachmentName = '' |
||||
ques.attachmentUrl = '' |
||||
}, |
||||
uploadSuccess (file, ques) { |
||||
ques.attachmentName = file.name |
||||
ques.attachmentUrl = file.url |
||||
}, |
||||
// 解析富文本加载完毕回调 |
||||
answerAnalysisReady (editor) { |
||||
this.answerAnalysis && editor.setContent(this.answerAnalysis) |
||||
}, |
||||
close () { |
||||
window.close() |
||||
} |
||||
} |
||||
}; |
||||
</script> |
||||
|
||||
<style lang="scss" scoped> |
||||
.top { |
||||
display: flex; |
||||
justify-content: space-between; |
||||
align-items: center; |
||||
padding: 10px 20px; |
||||
color: #fff; |
||||
background-color: #5786fc; |
||||
|
||||
.item { |
||||
display: inline-flex; |
||||
align-items: center; |
||||
} |
||||
|
||||
.names { |
||||
font-size: 18px; |
||||
font-weight: 600; |
||||
} |
||||
|
||||
.submit { |
||||
width: 106px; |
||||
font-size: 15px; |
||||
} |
||||
|
||||
.exit { |
||||
margin-left: 20px; |
||||
cursor: pointer; |
||||
|
||||
&:hover { |
||||
opacity: .9; |
||||
} |
||||
} |
||||
} |
||||
|
||||
/deep/.wrap { |
||||
display: flex; |
||||
padding: 15px; |
||||
|
||||
.left { |
||||
width: 300px; |
||||
margin-right: 15px; |
||||
background-color: #fff; |
||||
|
||||
.title { |
||||
padding: 10px 0; |
||||
font-size: 16px; |
||||
text-align: center; |
||||
color: #333; |
||||
} |
||||
|
||||
.progress { |
||||
padding: 10px; |
||||
color: #5a5a5a; |
||||
background-color: #d4e9ff; |
||||
} |
||||
|
||||
.type-wrap { |
||||
max-height: calc(100vh - 248px); |
||||
padding: 10px; |
||||
overflow: auto; |
||||
|
||||
.type { |
||||
margin-bottom: 20px; |
||||
} |
||||
|
||||
.stem { |
||||
font-size: 15px; |
||||
color: #333; |
||||
} |
||||
} |
||||
|
||||
.serials { |
||||
display: flex; |
||||
flex-wrap: wrap; |
||||
margin-top: 5px; |
||||
|
||||
li { |
||||
position: relative; |
||||
width: 35px; |
||||
margin: 7px 9px; |
||||
font-size: 13px; |
||||
text-align: center; |
||||
line-height: 35px; |
||||
color: #505050; |
||||
border: 1px solid #d3d3d3; |
||||
cursor: pointer; |
||||
|
||||
&:hover { |
||||
opacity: .9; |
||||
} |
||||
|
||||
&.answered { |
||||
color: #fff; |
||||
background-color: #66b2ff; |
||||
border-color: #66b2ff; |
||||
} |
||||
|
||||
&.partAnswer { |
||||
border-color: #66b2ff; |
||||
} |
||||
} |
||||
|
||||
.tag { |
||||
position: absolute; |
||||
top: -2px; |
||||
left: -4px; |
||||
} |
||||
} |
||||
|
||||
.status-filter { |
||||
display: flex; |
||||
justify-content: space-between; |
||||
padding: 10px; |
||||
border-top: 1px solid #e5e5e5; |
||||
|
||||
li { |
||||
display: inline-flex; |
||||
align-items: center; |
||||
padding: 0 3px; |
||||
font-size: 12px; |
||||
color: #333; |
||||
cursor: pointer; |
||||
border: 1px solid transparent; |
||||
|
||||
&:not(:last-child):before { |
||||
content: ''; |
||||
width: 13px; |
||||
height: 13px; |
||||
margin-right: 5px; |
||||
border: 1px solid #ccc; |
||||
} |
||||
|
||||
&:nth-child(2):before { |
||||
background-color: #56aaff; |
||||
border: 0; |
||||
} |
||||
|
||||
&:nth-child(3):before { |
||||
border-color: #56aaff; |
||||
} |
||||
|
||||
&.active { |
||||
font-weight: 600; |
||||
color: #007eff; |
||||
border-color: #007eff; |
||||
|
||||
&:last-child { |
||||
color: #d81e06; |
||||
border-color: #d81e06; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
.ques-wrap { |
||||
width: calc(100% - 315px); |
||||
height: calc(100vh - 80px); |
||||
background-color: #fff; |
||||
overflow: auto; |
||||
|
||||
&>li { |
||||
margin-bottom: 15px; |
||||
} |
||||
|
||||
.outline { |
||||
display: flex; |
||||
justify-content: space-between; |
||||
align-items: center; |
||||
padding: 10px 15px; |
||||
font-size: 15px; |
||||
font-weight: 600; |
||||
color: #333; |
||||
background-color: #e8f0ff; |
||||
} |
||||
|
||||
.shrink { |
||||
cursor: pointer; |
||||
transition: .5s; |
||||
|
||||
&.active { |
||||
transform: rotate(180deg); |
||||
} |
||||
} |
||||
|
||||
.ques { |
||||
max-height: none; |
||||
padding: 15px; |
||||
margin-bottom: 15px; |
||||
transition: all 1.5s; |
||||
overflow: hidden; |
||||
|
||||
&.hide { |
||||
max-height: 10px; |
||||
} |
||||
} |
||||
|
||||
.item { |
||||
position: relative; |
||||
overflow: hidden; |
||||
|
||||
&:not(:last-child) { |
||||
padding-bottom: 15px; |
||||
margin-bottom: 15px; |
||||
border-bottom: 1px dashed #e1e1e1; |
||||
} |
||||
|
||||
|
||||
&.disabled, |
||||
&.del, |
||||
&.repeat { |
||||
border-color: #f00; |
||||
|
||||
&:after { |
||||
content: '已 禁 用'; |
||||
position: absolute; |
||||
top: 17px; |
||||
right: -33px; |
||||
padding: 5px 36px; |
||||
font-size: 14px; |
||||
color: #fff; |
||||
background-color: #f00; |
||||
transform: rotate(45deg); |
||||
opacity: .6; |
||||
} |
||||
} |
||||
|
||||
&.del { |
||||
&:after { |
||||
content: '已 删 除'; |
||||
} |
||||
} |
||||
|
||||
&.repeat { |
||||
border-color: #ff962a; |
||||
|
||||
&:after { |
||||
content: '存在重复题'; |
||||
background-color: #ff962a; |
||||
} |
||||
} |
||||
} |
||||
|
||||
|
||||
.stem-wrap { |
||||
display: flex; |
||||
align-items: baseline; |
||||
margin-bottom: 10px; |
||||
} |
||||
|
||||
.tag { |
||||
margin-left: 10px; |
||||
cursor: pointer; |
||||
|
||||
&:hover { |
||||
opacity: .9; |
||||
} |
||||
} |
||||
|
||||
.label { |
||||
padding: 3px 5px; |
||||
margin-right: 10px; |
||||
font-size: 12px; |
||||
line-height: 1; |
||||
color: $main-color; |
||||
white-space: nowrap; |
||||
border: 1px solid; |
||||
border-radius: 2px; |
||||
} |
||||
|
||||
.stem { |
||||
max-width: calc(100% - 191px); |
||||
} |
||||
|
||||
img { |
||||
max-width: 100%; |
||||
} |
||||
|
||||
.fill-input { |
||||
width: 100px; |
||||
height: 28px; |
||||
padding: 0 15px; |
||||
margin: 0 10px; |
||||
font-size: 13px; |
||||
line-height: 28px; |
||||
color: #606266; |
||||
border: 1px solid #DCDEE0; |
||||
border-radius: 2px; |
||||
|
||||
&:focus { |
||||
outline: none; |
||||
} |
||||
} |
||||
|
||||
.opt { |
||||
display: flex; |
||||
flex-wrap: wrap; |
||||
align-items: baseline; |
||||
padding-left: 10px; |
||||
margin-bottom: 5px; |
||||
font-size: 14px; |
||||
color: #707070; |
||||
line-height: 1.6; |
||||
|
||||
.el-radio, |
||||
.el-checkbox { |
||||
margin-right: 15px; |
||||
} |
||||
|
||||
.el-radio__label { |
||||
display: none; |
||||
} |
||||
|
||||
.text { |
||||
max-width: calc(100% - 48px); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
</style> |
@ -0,0 +1,262 @@ |
||||
<template> |
||||
<div> |
||||
<el-drawer title="分配评阅人员" :visible.sync="allocationVisible" size="1200px" :close-on-click-modal="false" |
||||
custom-class="allo-dia" @closed="closeDia"> |
||||
<div class="overflow"> |
||||
<div class="tool"> |
||||
<ul class="filter"> |
||||
<li style="align-items: flex-start;"> |
||||
<label>分配方式</label> |
||||
<div> |
||||
<el-radio v-model="radio" label="1">按整卷分配</el-radio> |
||||
<p class="tips m-b-20">(每份答卷将从以下已选的评阅人员中,按照评阅设置的每题评阅人数随机挑选评阅人员对整卷进行评阅,且以下已选的每位评阅人员分配到的答卷数量基本平均)</p> |
||||
<el-radio v-model="radio" label="2">按每道人工判分题分配</el-radio> |
||||
<p class="tips">(每份答卷的每道人工判分题将从以下题目已选的评阅人员中,按照评阅设置的每题评阅人数随机挑选评阅人员对该题进行评阅,且以下已选的每位评阅人员分配到的该题答卷数量基本平均)</p> |
||||
</div> |
||||
</li> |
||||
</ul> |
||||
</div> |
||||
|
||||
<!-- <People /> --> |
||||
|
||||
<div> |
||||
<div class="flex a-center m-b-10"> |
||||
<h6 class="page-name m-r-10" style="margin-bottom: 0">选择评阅人员</h6> |
||||
<el-button type="primary" size="mini" @click="batchAlloc">批量分配</el-button> |
||||
</div> |
||||
<el-table :data="ques" class="table" ref="table" stripe header-align="center" row-key="id" |
||||
@selection-change="handleSelectionChange"> |
||||
<el-table-column type="selection" width="55" 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"></el-table-column> |
||||
<el-table-column label="操作" align="center" width="100"> |
||||
<template slot-scope="scope"> |
||||
<i class="el-icon-edit-outline"></i> |
||||
</template> |
||||
</el-table-column> |
||||
</el-table> |
||||
</div> |
||||
</div> |
||||
|
||||
<div class="btns"> |
||||
<el-button @click="allocationVisible = false">取消</el-button> |
||||
<el-button type="primary" :loading="submiting" @click="submit">确定</el-button> |
||||
</div> |
||||
</el-drawer> |
||||
|
||||
|
||||
<el-drawer title="分配评阅人员" :visible.sync="peopleVisible" :with-header="false" size="1000px" |
||||
:close-on-click-modal="false" custom-class="allo-dia"> |
||||
<div class="p-l-20 p-r-20"> |
||||
<People /> |
||||
</div> |
||||
|
||||
<div class="btns"> |
||||
<el-button @click="peopleVisible = false">取消</el-button> |
||||
<el-button type="primary" :loading="submiting" @click="peopleSubmit">确定</el-button> |
||||
</div> |
||||
</el-drawer> |
||||
</div> |
||||
</template> |
||||
<script> |
||||
import People from './people' |
||||
import Setting from '@/setting' |
||||
import Util from '@/libs/util' |
||||
import QuesConst from '@/const/ques' |
||||
import TestPaperConst from '@/const/testPaper' |
||||
import _ from 'lodash' |
||||
import Decimal from 'decimal.js' |
||||
export default { |
||||
components: { People }, |
||||
props: ['visible'], |
||||
data () { |
||||
return { |
||||
radio: '', |
||||
allocationVisible: false, |
||||
searchTimer: null, |
||||
|
||||
userType: '', |
||||
ques: [], |
||||
multipleSelection: [], |
||||
submiting: false, |
||||
|
||||
peopleVisible: false, |
||||
}; |
||||
}, |
||||
watch: { |
||||
visible () { |
||||
this.allocationVisible = this.visible |
||||
this.visible && this.init() |
||||
} |
||||
}, |
||||
mounted () { |
||||
|
||||
}, |
||||
methods: { |
||||
// 初始化 |
||||
init () { |
||||
this.handleQuesList() |
||||
|
||||
}, |
||||
// 获取题库分类 |
||||
async getQuesBankType () { |
||||
try { |
||||
const { data } = await this.$post(this.api.getAllQuestionBankCategories, { |
||||
createSource: 1, |
||||
status: 1, |
||||
}) |
||||
this.handleList(data) |
||||
this.quesBankTypes = data |
||||
} catch (e) { } |
||||
}, |
||||
handleSelectionChange (val) { |
||||
this.multipleSelection = val |
||||
}, |
||||
// 批量分配 |
||||
async batchAlloc () { |
||||
try { |
||||
this.peopleVisible = true |
||||
return |
||||
const checked = this.multipleSelection |
||||
if (checked.length) { |
||||
this.peopleVisible = true |
||||
} else { |
||||
Util.warningMsg('请选择数据') |
||||
} |
||||
} catch (e) { } |
||||
}, |
||||
// 单个分配 |
||||
alloc () { |
||||
this.peopleVisible = true |
||||
}, |
||||
// 弹框选择人员提交 |
||||
peopleSubmit () { |
||||
|
||||
}, |
||||
|
||||
// 提交 |
||||
async submit () { |
||||
if (this.submiting) return false |
||||
const { list } = this |
||||
let invalid = 0 |
||||
let totalCount = 0 |
||||
for (const i in list) { |
||||
const e = list[i] |
||||
const name = `第${Util.arabicToChinese(+i + 1)}大题` |
||||
if (!e.questionType) { |
||||
Util.warningMsg(`${name}请先选择题型`) |
||||
invalid = 1 |
||||
break |
||||
} |
||||
if (!e.questionNum || isNaN(e.questionNum) || e.questionNum <= 0) { |
||||
Util.warningMsg(`${name}的目标题数请输入正整数`) |
||||
invalid = 1 |
||||
break |
||||
} |
||||
let total = Decimal(e.basicDifficulty || 0).add(e.normalDifficulty || 0).add(e.hardDifficulty || 0).add(e.veryHardDifficulty || 0).toNumber() // 先算前4个难度的题数 |
||||
if (total) { // 前面4个空有填1个,则清空随机 |
||||
this.$set(e, 'randomDifficulty', 0) |
||||
} else { |
||||
total = +e.randomDifficulty || 0 |
||||
} |
||||
|
||||
if (total > e.questionNum) { |
||||
Util.warningMsg(`${name}的小题总数大于目标题数,请重新输入`) |
||||
invalid = 1 |
||||
break |
||||
} |
||||
e.count = total |
||||
totalCount = Decimal(totalCount).add(total).toNumber() |
||||
} |
||||
if (invalid) return false |
||||
if (!totalCount) return Util.warningMsg(`请填写难度题数`) |
||||
this.submiting = true |
||||
const k = this.allKnowledges.map(e => e.id) |
||||
|
||||
const years = [] |
||||
this.yearCheck.map(e => { |
||||
if (e === '暂无年份') { |
||||
years.push('') |
||||
} else if (e === '更早') { |
||||
// 选的是更早则直接传1990~2005所有年份 |
||||
for (let i = 1990; i < 2006; i++) { |
||||
years.push(i) |
||||
} |
||||
} else { |
||||
years.push(+e) |
||||
} |
||||
}) |
||||
list.map(e => { |
||||
e.givenYears = years |
||||
e.knowledgePointsIds = k |
||||
}) |
||||
try { |
||||
const res = await this.$post(this.api.selectQuestionsByTypeAndDifficulty, list) |
||||
|
||||
let invalid = 0 |
||||
let hasQues = 0 |
||||
list.map((e, i) => { |
||||
if (+e.count !== res.list[i].questions.length) invalid = 1 |
||||
if (e.examQuestions.length) hasQues = 1 |
||||
e.score = 0 |
||||
}) |
||||
|
||||
// 3种情况提示不一样 |
||||
const tips = invalid && hasQues ? |
||||
'此操作会清空当前试卷已添加的试题,并且满足自动选题设置的试题数量不足,确定要继续自动选题吗?' : |
||||
invalid && !hasQues ? |
||||
'满足自动选题设置的试题数量不足,确认要继续自动选题吗?' : |
||||
!invalid && hasQues ? '此操作会清空当前试卷已添加的试题,是否确定要继续自动选题吗?' : |
||||
'' |
||||
|
||||
if (tips) { |
||||
await this.$confirm(tips, '提示', { |
||||
confirmButtonText: '确定', |
||||
cancelButtonText: '取消', |
||||
type: 'warning', |
||||
closeOnClickModal: false, |
||||
}) |
||||
} |
||||
list.map((e, i) => { |
||||
res.list[i].questions.map((e, i) => { |
||||
e.questionId = e.id |
||||
e.serialNumber = i + 1 |
||||
e.originSort = i + 1 |
||||
this.$parent.handleQuesInfo(e) |
||||
}) |
||||
this.$parent.form.paperOutline[i].examQuestions = res.list[i].questions |
||||
}) |
||||
this.allocationVisible = false |
||||
this.$parent.calcDifficult() |
||||
this.submiting = false |
||||
} catch (e) { |
||||
this.submiting = false |
||||
} |
||||
}, |
||||
// 弹框关闭回调 |
||||
closeDia () { |
||||
this.$emit('update:visible', false) |
||||
} |
||||
} |
||||
}; |
||||
</script> |
||||
|
||||
<style lang="scss" scoped> |
||||
/deep/.allo-dia { |
||||
.el-drawer__header { |
||||
margin-bottom: 20px; |
||||
} |
||||
|
||||
.overflow { |
||||
height: calc(100vh - 147px); |
||||
padding: 0 20px; |
||||
overflow: auto; |
||||
} |
||||
|
||||
.tips { |
||||
margin-top: 3px; |
||||
font-size: 12px; |
||||
color: #585858; |
||||
} |
||||
} |
||||
</style> |
@ -0,0 +1,336 @@ |
||||
<template> |
||||
<div class="page"> |
||||
<Breadcrumb :data="crumbs" /> |
||||
<h6 class="page-name">筛选</h6> |
||||
<div class="tool"> |
||||
<ul class="filter"> |
||||
<li> |
||||
<label>省份</label> |
||||
<el-select v-model="filter.provinceId" clearable placeholder="请选择省份" @change="provinceChange" |
||||
@clear="clearprovince"> |
||||
<el-option v-for="(item, i) in provinces" :key="i" :label="item.provinceName" |
||||
:value="item.provinceId"></el-option> |
||||
</el-select> |
||||
</li> |
||||
<li> |
||||
<label>城市</label> |
||||
<el-select v-model="filter.cityId" clearable placeholder="请选择城市" :disabled="!filter.provinceId" |
||||
@clear="clearcity" @change="getSchool"> |
||||
<el-option v-for="(item, i) in cities" :key="i" :label="item.cityName" :value="item.cityId"></el-option> |
||||
</el-select> |
||||
</li> |
||||
<li> |
||||
<label>学校</label> |
||||
<el-select v-model="filter.schoolId" clearable filterable placeholder="请选择学校" :disabled="!filter.cityId" |
||||
@change="initData"> |
||||
<el-option v-for="(item, i) in schools" :key="i" :label="item.schoolName" |
||||
:value="item.schoolId"></el-option> |
||||
</el-select> |
||||
</li> |
||||
<li> |
||||
<label>评阅状态</label> |
||||
<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> |
||||
<li> |
||||
<label>是否完成分配</label> |
||||
<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> |
||||
<li> |
||||
<label>搜索</label> |
||||
<el-input style="width: 400px;" placeholder="请输入学生姓名、学生学号、团队名称、答卷ID、提交名称" prefix-icon="el-icon-search" |
||||
v-model="filter.keyword" clearable /> |
||||
</li> |
||||
</ul> |
||||
<div> |
||||
<el-button type="primary" @click="batchReview">修改评阅设置</el-button> |
||||
<!-- <el-button type="primary">批量导出评分表</el-button> --> |
||||
<el-button type="primary">批量导出列表</el-button> |
||||
</div> |
||||
</div> |
||||
|
||||
<el-table :data="list" class="table" ref="table" stripe header-align="center" row-key="id" |
||||
@selection-change="handleSelectionChange"> |
||||
<el-table-column type="selection" width="55" 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"></el-table-column> |
||||
<el-table-column prop="professionalName" label="城市" align="center" min-width="100"></el-table-column> |
||||
<el-table-column prop="knowledgePointName" label="学生所在学校" align="center" min-width="100"></el-table-column> |
||||
<el-table-column prop="lastEditor" label="团队名称" align="center" width="90"></el-table-column> |
||||
<el-table-column prop="lastEditor" label="学生姓名" align="center" width="90"></el-table-column> |
||||
<el-table-column prop="lastEditor" label="学号" align="center" width="90"></el-table-column> |
||||
<el-table-column prop="lastEditor" label="答卷ID" align="center" width="90"></el-table-column> |
||||
<el-table-column prop="lastEditor" label="用时" align="center" width="90"></el-table-column> |
||||
<el-table-column prop="lastEditor" label="提交时间" align="center" width="90"></el-table-column> |
||||
<el-table-column prop="lastEditor" label="提交名称" align="center" width="90"></el-table-column> |
||||
<el-table-column prop="lastEditor" label="是否完成分配" align="center" width="90"></el-table-column> |
||||
<el-table-column prop="lastEditor" label="评阅人员" align="center" width="90"></el-table-column> |
||||
<el-table-column prop="lastEditor" label="评阅人数" align="center" width="90"></el-table-column> |
||||
<el-table-column prop="lastEditor" label="评阅状态" align="center" width="90"></el-table-column> |
||||
<el-table-column prop="lastEditor" label="成绩" align="center" width="90"></el-table-column> |
||||
<el-table-column prop="lastEditor" label="最新分配时间" align="center" width="90"></el-table-column> |
||||
<el-table-column prop="lastEditor" label="最新分配人" align="center" width="90"></el-table-column> |
||||
<el-table-column label="操作" align="center" width="100" fixed="right"> |
||||
<template slot-scope="scope"> |
||||
<el-button type="text" @click="allocation(scope.row)">分配评阅人员</el-button> |
||||
<!-- <el-button type="text" @click="toScore(scope.row)">查看评分表</el-button> |
||||
<el-button type="text" @click="exportScore(scope.row)">导出评分表</el-button> --> |
||||
</template> |
||||
</el-table-column> |
||||
</el-table> |
||||
<div class="pagination"> |
||||
<el-pagination background @current-change="currentChange" :current-page="page" layout="total, prev, pager, next" |
||||
:total="total"></el-pagination> |
||||
</div> |
||||
|
||||
<Allocation :visible.sync="allocationVisible" /> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import Allocation from './allocation' |
||||
import Breadcrumb from '@/components/breadcrumb' |
||||
import Util from '@/libs/util' |
||||
import Setting from '@/setting' |
||||
import Const from '@/const/ques' |
||||
import Qs from 'qs' |
||||
import dayjs from 'dayjs' |
||||
export default { |
||||
components: { Allocation, Breadcrumb }, |
||||
data () { |
||||
return { |
||||
crumbs: [], |
||||
paperName: this.$route.query.paperName, |
||||
difficults: Const.difficults, |
||||
questionTypes: Const.questionTypes, |
||||
loading: false, |
||||
|
||||
provinces: [], |
||||
cities: [], |
||||
schools: [], |
||||
status: [ |
||||
{ |
||||
id: 1, |
||||
name: '启用' |
||||
}, |
||||
{ |
||||
id: 0, |
||||
name: '禁用' |
||||
}, |
||||
], |
||||
date: [], |
||||
filter: { |
||||
month: '', |
||||
startTime: null, |
||||
endTime: null, |
||||
status: '', |
||||
keyword: '', |
||||
}, |
||||
list: [{}], |
||||
page: +this.$route.query.page || 1, |
||||
pageSize: 10, |
||||
total: 0, |
||||
multipleSelection: [], |
||||
|
||||
allocationVisible: false, |
||||
}; |
||||
}, |
||||
watch: { |
||||
'filter.month': function (val) { |
||||
if (val) { |
||||
let unit = 24 * 60 * 60 * 1000 |
||||
this.date = [dayjs(new Date(Date.now() - unit * 30 * val)).format('YYYY-MM-DD'), dayjs(new Date(Date.now() + unit)).format('YYYY-MM-DD')] |
||||
} else { |
||||
this.date = [] |
||||
} |
||||
}, |
||||
date: function (val) { |
||||
if (val) { |
||||
this.filter.startTime = val[0]; |
||||
this.filter.endTime = val[1]; |
||||
} else { |
||||
this.filter.startTime = '' |
||||
this.filter.endTime = '' |
||||
} |
||||
// this.initData(); |
||||
}, |
||||
'filter.keyword': function () { |
||||
clearTimeout(this.searchTimer) |
||||
this.searchTimer = setTimeout(this.initData, 500) |
||||
}, |
||||
}, |
||||
mounted () { |
||||
this.crumbs = [ |
||||
{ |
||||
name: '分配评阅任务', |
||||
route: '/allocationReview' |
||||
}, |
||||
{ |
||||
name: '任务分配' |
||||
}, |
||||
|
||||
] |
||||
|
||||
const { query } = this.$route |
||||
if (query.page) { |
||||
const { questionTypes, correctRateEnd, correctRateStart, difficultys, specialtyIds, status, keyword, questionTypeSort, givenYearSort, difficultySort, correctRateSort, updateTimeSort, referenceCountSort, givenYears, knowledgePointIds, questionBankId, questionBankName, questionBankCategory } = query |
||||
this.filter = { |
||||
questionTypes: questionTypes ? questionTypes.split(',') : [], |
||||
correctRateEnd: correctRateEnd || '', |
||||
correctRateStart: correctRateStart || '', |
||||
difficultys: difficultys ? difficultys.split(',') : [], |
||||
specialtyIds: specialtyIds ? specialtyIds.split(',').map(e => +e) : [], |
||||
status: status ? +status : '', |
||||
keyword: keyword || '', |
||||
questionTypeSort: questionTypeSort || '', |
||||
givenYearSort: givenYearSort || '', |
||||
difficultySort: difficultySort || '', |
||||
correctRateSort: correctRateSort || '', |
||||
updateTimeSort: updateTimeSort || '', |
||||
referenceCountSort: referenceCountSort || '', |
||||
} |
||||
this.givenYears = givenYears || '' |
||||
this.knowledgePointIds = knowledgePointIds ? JSON.parse(knowledgePointIds) : [] |
||||
|
||||
this.$router.push(`/myReview?questionBankId=${questionBankId}&questionBankName=${questionBankName}&questionBankCategory=${questionBankCategory}`).catch(() => { }) |
||||
} |
||||
|
||||
this.getProvince() |
||||
// this.getProfessional() |
||||
// this.getKnowledge() |
||||
}, |
||||
methods: { |
||||
async getList () { |
||||
let type = this.$refs.typeTree.getCurrentKey() |
||||
const k = this.knowledgePointIds |
||||
if (k.length) { // 右边筛选里的知识点 |
||||
type = k.map(e => { |
||||
return e[e.length - 1] |
||||
}) |
||||
} else if (type) { |
||||
type = [type] |
||||
} |
||||
const { message } = await this.$post(this.api.listQuestion, { |
||||
...this.filter, |
||||
givenYears: this.givenYears ? [this.givenYears] : [], |
||||
isNotJoin: this.isNotJoin || '', |
||||
pageNum: this.page, |
||||
pageSize: this.pageSize, |
||||
questionBankId: this.questionBankId, |
||||
knowledgePointIds: type || [], |
||||
}) |
||||
this.list = Util.removeTag(message.records) |
||||
this.total = message.total |
||||
}, |
||||
// 切换页码 |
||||
currentChange (val) { |
||||
this.page = val |
||||
this.getList() |
||||
}, |
||||
handleSelectionChange (val) { // 多选 |
||||
this.multipleSelection = val |
||||
}, |
||||
initData () { |
||||
this.$refs.table.clearSelection() |
||||
this.page = 1 |
||||
this.getList() |
||||
}, |
||||
|
||||
// 获取省份 |
||||
async getProvince () { |
||||
const { list } = await this.$get(this.api.queryProvince) |
||||
this.provinces = list |
||||
}, |
||||
// 清除省份 |
||||
clearprovince () { |
||||
this.filter.cityId = '', |
||||
this.filter.schoolId = '' |
||||
}, |
||||
// 省份选择回调 |
||||
provinceChange () { |
||||
this.clearprovince() |
||||
this.getCity() |
||||
this.initData() |
||||
}, |
||||
// 获取城市 |
||||
async getCity () { |
||||
const { list } = await this.$get(this.api.queryCity, { |
||||
provinceId: this.filter.provinceId |
||||
}) |
||||
this.cities = list |
||||
}, |
||||
// 清除城市 |
||||
clearcity () { |
||||
this.filter.schoolId = '' |
||||
}, |
||||
// 城市选择回调 |
||||
cityChange () { |
||||
this.filter.schoolId = '' |
||||
this.getSchool() |
||||
this.initData() |
||||
}, |
||||
// 获取学校 |
||||
async getSchool () { |
||||
const { list } = await this.$get(this.api.querySchoolByReadAndAppraise, { |
||||
provinceId: this.filter.provinceId, |
||||
cityId: this.filter.cityId, |
||||
}) |
||||
this.schools = list |
||||
}, |
||||
|
||||
// 批量评阅 |
||||
async batchReview () { |
||||
const list = this.multipleSelection |
||||
if (list.length) { |
||||
try { |
||||
await this.$confirm(`确定要删除已选定的${list.length}份试卷吗?`, '提示', { |
||||
confirmButtonText: '确定', |
||||
cancelButtonText: '取消', |
||||
type: 'warning', |
||||
closeOnClickModal: false, |
||||
}) |
||||
await this.$post(this.api.paperDel, { |
||||
delete: false, |
||||
ids: list.map(e => e.paperId) |
||||
}) |
||||
Util.successMsg('删除成功') |
||||
this.multipleSelection = [] |
||||
this.$refs.table.clearSelection() |
||||
this.getList() |
||||
} catch (e) { } |
||||
} else { |
||||
Util.warningMsg('请选择数据') |
||||
} |
||||
}, |
||||
// 分配评阅人员 |
||||
allocation (row) { |
||||
this.allocationVisible = true |
||||
}, |
||||
// 查看评分表 |
||||
toScore (row) { |
||||
|
||||
}, |
||||
// 导出评分表 |
||||
exportScore (row) { |
||||
|
||||
}, |
||||
} |
||||
}; |
||||
</script> |
||||
|
||||
<style lang="scss" scoped> |
||||
.tool { |
||||
margin-bottom: 0; |
||||
|
||||
.filter { |
||||
flex-wrap: wrap; |
||||
|
||||
li { |
||||
margin-bottom: 15px; |
||||
} |
||||
} |
||||
} |
||||
</style> |
@ -0,0 +1,351 @@ |
||||
<template> |
||||
<div> |
||||
<h6 class="page-name m-t-20">选择评阅人员</h6> |
||||
<div class="wrap"> |
||||
<div class="item"> |
||||
<el-radio-group class="m-b-10" v-model="userType" size="small"> |
||||
<el-radio-button label="平台用户"></el-radio-button> |
||||
<el-radio-button label="专家"></el-radio-button> |
||||
</el-radio-group> |
||||
|
||||
<el-tree :data="nakadais" default-expand-all ref="nakadais" node-key="id" highlight-current |
||||
:expand-on-click-node="false" @node-click="getNakadaiUser" |
||||
:props="{ children: 'children', label: 'organizationName', isLeaf: 'leaf' }"></el-tree> |
||||
</div> |
||||
<div class="item"> |
||||
<p class="total m-b-10">用户</p> |
||||
<el-input class="m-b-10" placeholder="请输入姓名、现所在单位" prefix-icon="el-icon-search" v-model="userKeyword" |
||||
clearable /> |
||||
|
||||
<template v-if="users.length"> |
||||
<div class="line"> |
||||
<el-checkbox v-model="userCheck" @change="userAllCheckChange"></el-checkbox> |
||||
<span class="username">姓名</span> |
||||
<!-- <span>现所在单位</span> |
||||
<span>职务</span> --> |
||||
</div> |
||||
|
||||
<div class="lines"> |
||||
<div v-for="(item, i) in users" :key="i" class="line"> |
||||
<el-checkbox v-model="item.check" :disabled="item.disabled" |
||||
@change="val => userChange(val, item)"></el-checkbox> |
||||
<p class="username" :title="item.userName">{{ item.userName }}</p> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
<div v-else class="empty"> |
||||
<img class="icon" src="@/assets/images/empty.svg" alt=""> |
||||
<p>暂无数据</p> |
||||
</div> |
||||
</div> |
||||
<div class="item"> |
||||
<div class="flex j-between a-center"> |
||||
<p class="total">已选人</p> |
||||
<el-button type="text" @click="batchDelChecked">批量移除</el-button> |
||||
</div> |
||||
|
||||
<el-input class="m-b-10" placeholder="请输入姓名、现所在单位" prefix-icon="el-icon-search" v-model="checkedKeyword" |
||||
clearable /> |
||||
|
||||
<template v-if="checked.length"> |
||||
<div class="line"> |
||||
<el-checkbox v-model="checkedAllCheck" @change="checkedAllCheckChange"></el-checkbox> |
||||
<span class="username">姓名</span> |
||||
</div> |
||||
|
||||
<div class="lines"> |
||||
<template v-for="(item, i) in checked"> |
||||
<div v-if="item.userName.includes(checkedKeyword)" :key="i" class="line"> |
||||
<div class="check-left"> |
||||
<el-checkbox v-model="item.check"></el-checkbox> |
||||
<p class="username" :title="item.userName">{{ item.userName }}</p> |
||||
</div> |
||||
<i class="el-icon-delete action-icon" @click="delChecked(item)"></i> |
||||
</div> |
||||
</template> |
||||
</div> |
||||
</template> |
||||
<div v-else class="empty"> |
||||
<img class="icon" src="@/assets/images/empty.svg" alt=""> |
||||
<p>暂无数据</p> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
<script> |
||||
import Setting from '@/setting' |
||||
import Util from '@/libs/util' |
||||
import _ from 'lodash' |
||||
import Decimal from 'decimal.js' |
||||
export default { |
||||
data () { |
||||
return { |
||||
nakadais: [], |
||||
searchTimer: null, |
||||
|
||||
userType: '', |
||||
userCheck: false, |
||||
users: [], |
||||
userKeyword: '', |
||||
|
||||
checkedKeyword: '', |
||||
checkedAllCheck: false, |
||||
checked: [], |
||||
submiting: false, |
||||
}; |
||||
}, |
||||
watch: { |
||||
'quesBankKeyword': function (val) { |
||||
clearTimeout(this.searchTimer) |
||||
this.searchTimer = setTimeout(this.initQuesBank, 500) |
||||
}, |
||||
'userKeyword': function (val) { |
||||
clearTimeout(this.searchTimer) |
||||
this.searchTimer = setTimeout(this.getKnowledge, 500) |
||||
}, |
||||
}, |
||||
mounted () { |
||||
this.getNakadais() |
||||
}, |
||||
methods: { |
||||
// 获取中台部门 |
||||
async getNakadais () { |
||||
const res = await this.$post(this.api.treeListArch) |
||||
const list = res.treeList |
||||
this.handleList(list) |
||||
this.nakadais = list |
||||
}, |
||||
// 处理树形 |
||||
handleList (list) { |
||||
list.map(e => { |
||||
if (e.children && e.children.length) { |
||||
this.handleList(e.children) |
||||
} else { |
||||
delete e.children |
||||
} |
||||
}) |
||||
}, |
||||
async getNakadaiUser (data) { |
||||
console.log(11, data) |
||||
const { page } = await this.$post(this.api.staffList, { |
||||
type: 1, |
||||
staffArchitectureId: data.id || '', |
||||
keyWord: this.userKeyword, |
||||
pageNum: 1, |
||||
pageSize: 1000 |
||||
}) |
||||
this.users = page.records |
||||
}, |
||||
nakadaiClick () { |
||||
|
||||
}, |
||||
// 获取题库 |
||||
async getQuesBank () { |
||||
try { |
||||
const type = this.quesBankTypeVal |
||||
const res = await this.$post(this.api.questionBankList, { |
||||
status: 1, |
||||
pageNum: 1, |
||||
pageSize: 1000, |
||||
questionCategoryId: type.length ? type[type.length - 1] : '', |
||||
name: this.quesBankKeyword |
||||
}) |
||||
this.quesBanks = res.message.records |
||||
this.totalQuesBank = res.message.total |
||||
} catch (e) { } |
||||
}, |
||||
// 题目多选回调 |
||||
questionBankClick (item) { |
||||
this.curQuesBank = item |
||||
this.userCheck = false |
||||
this.getKnowledgeType() |
||||
this.getKnowledge() |
||||
}, |
||||
|
||||
// 处理树形 |
||||
handleList (list) { |
||||
list.map(e => { |
||||
if (e.children && e.children.length) { |
||||
this.handleList(e.children) |
||||
} else { |
||||
delete e.children |
||||
} |
||||
}) |
||||
}, |
||||
// 用户全选回调 |
||||
userAllCheckChange (val) { |
||||
this.users.map(e => { |
||||
e.check = val |
||||
this.userChange(val, e) |
||||
}) |
||||
}, |
||||
// 用户勾选回调 |
||||
userChange (val, item) { |
||||
const cur = this.checked.findIndex(e => e.userId === item.userId) |
||||
// 选中 |
||||
if (val) { |
||||
if (cur === -1) { |
||||
const e = _.cloneDeep(item) |
||||
e.check = false |
||||
this.checked.push(e) |
||||
} |
||||
} else { |
||||
// 取消选中 |
||||
cur >= 0 && this.checked.splice(cur, 1) |
||||
} |
||||
}, |
||||
// 处理大纲列表 |
||||
handleQuesList () { |
||||
this.list = _.cloneDeep(this.$parent.form.paperOutline) |
||||
}, |
||||
// 已选全选回调 |
||||
checkedAllCheckChange (val) { |
||||
this.checked.map(e => e.check = val) |
||||
}, |
||||
// 批量移除已选 |
||||
async batchDelChecked (val) { |
||||
try { |
||||
const checked = this.checked.filter(e => e.check) |
||||
if (checked.length) { |
||||
checked.map(e => { |
||||
const cur = this.users.find(n => n.userId === e.userId) |
||||
if (cur) { |
||||
cur.check = false |
||||
} |
||||
}) |
||||
this.userCheck = false |
||||
this.checkedAllCheck = false |
||||
this.checked = this.checked.filter(e => !e.check) |
||||
} else { |
||||
Util.warningMsg('请选择数据') |
||||
} |
||||
} catch (e) { } |
||||
}, |
||||
// 已选单个删除 |
||||
async delChecked (item) { |
||||
try { |
||||
const cur = this.users.find(e => e.userId === item.userId) |
||||
if (cur) cur.check = false |
||||
this.checked.splice(this.checked.findIndex(e => e.userId === item.userId), 1) |
||||
} catch (e) { } |
||||
}, |
||||
|
||||
|
||||
// 提交 |
||||
async submit () { |
||||
if (this.submiting) return false |
||||
|
||||
this.submiting = true |
||||
|
||||
try { |
||||
const res = await this.$post(this.api.selectQuestionsByTypeAndDifficulty, list) |
||||
|
||||
let invalid = 0 |
||||
let hasQues = 0 |
||||
list.map((e, i) => { |
||||
if (+e.count !== res.list[i].questions.length) invalid = 1 |
||||
if (e.examQuestions.length) hasQues = 1 |
||||
e.score = 0 |
||||
}) |
||||
|
||||
// 3种情况提示不一样 |
||||
const tips = invalid && hasQues ? |
||||
'此操作会清空当前试卷已添加的试题,并且满足自动选题设置的试题数量不足,确定要继续自动选题吗?' : |
||||
invalid && !hasQues ? |
||||
'满足自动选题设置的试题数量不足,确认要继续自动选题吗?' : |
||||
!invalid && hasQues ? '此操作会清空当前试卷已添加的试题,是否确定要继续自动选题吗?' : |
||||
'' |
||||
|
||||
if (tips) { |
||||
await this.$confirm(tips, '提示', { |
||||
confirmButtonText: '确定', |
||||
cancelButtonText: '取消', |
||||
type: 'warning', |
||||
closeOnClickModal: false, |
||||
}) |
||||
} |
||||
list.map((e, i) => { |
||||
res.list[i].questions.map((e, i) => { |
||||
e.questionId = e.id |
||||
e.serialNumber = i + 1 |
||||
e.originSort = i + 1 |
||||
this.$parent.handleQuesInfo(e) |
||||
}) |
||||
this.$parent.form.paperOutline[i].examQuestions = res.list[i].questions |
||||
}) |
||||
this.allocationVisible = false |
||||
this.$parent.calcDifficult() |
||||
this.submiting = false |
||||
} catch (e) { |
||||
this.submiting = false |
||||
} |
||||
}, |
||||
// 弹框关闭回调 |
||||
closeDia () { |
||||
this.$emit('update:visible', false) |
||||
} |
||||
} |
||||
}; |
||||
</script> |
||||
|
||||
<style lang="scss" scoped> |
||||
/deep/.wrap { |
||||
display: flex; |
||||
margin-top: 20px; |
||||
border: 1px solid #eee; |
||||
|
||||
.el-radio-button:focus:not(.is-focus):not(:active):not(.is-disabled) { |
||||
box-shadow: none; |
||||
} |
||||
|
||||
.item { |
||||
width: 30%; |
||||
padding: 15px; |
||||
border-right: 1px solid #eee; |
||||
|
||||
&:last-child { |
||||
width: 40%; |
||||
border-right: 0; |
||||
} |
||||
} |
||||
|
||||
.total { |
||||
font-size: 16px; |
||||
color: #333; |
||||
} |
||||
|
||||
|
||||
.users { |
||||
padding-left: 44px; |
||||
margin-top: 10px; |
||||
} |
||||
|
||||
.lines { |
||||
height: calc(100vh - 392px); |
||||
overflow: auto; |
||||
} |
||||
|
||||
.line { |
||||
display: flex; |
||||
align-items: center; |
||||
padding: 5px 0; |
||||
color: #333; |
||||
|
||||
.username { |
||||
margin: 0 12px; |
||||
} |
||||
} |
||||
|
||||
.check-left { |
||||
display: inline-flex; |
||||
align-items: center; |
||||
width: calc(100% - 30px); |
||||
} |
||||
|
||||
|
||||
.action-icon { |
||||
font-size: 14px; |
||||
} |
||||
} |
||||
</style> |
Loading…
Reference in new issue