|
|
|
@ -58,23 +58,79 @@ |
|
|
|
|
<!-- 题库 --> |
|
|
|
|
<div class="item"> |
|
|
|
|
<p class="total m-b-10">题库</p> |
|
|
|
|
<el-input class="m-b-10" placeholder="请输入题库分类/题库名称" prefix-icon="el-icon-search" v-model="quesBankKeyword" |
|
|
|
|
clearable /> |
|
|
|
|
<el-tree :key="key" node-key="id" default-expand-all highlight-current ref="quesBank" :data="quesBanks" |
|
|
|
|
:props="{ label: 'name' }" @node-click="getKnowledge" @check-change="quesBankCheck"></el-tree> |
|
|
|
|
<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="getQuesBank"></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="lines"> |
|
|
|
|
<div v-for="(item, i) in quesBanks" :key="i" |
|
|
|
|
:class="['line able-check', { 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> |
|
|
|
|
|
|
|
|
|
<div class="pagination"> |
|
|
|
|
<el-pagination background @current-change="currentChangeQuesBank" :current-page="pageQuesBank" |
|
|
|
|
layout="total, prev, pager, next" :total="totalQuesBank"></el-pagination> |
|
|
|
|
</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> |
|
|
|
|
<el-input class="m-b-10" placeholder="请输入知识点分类/知识点名称" prefix-icon="el-icon-search" |
|
|
|
|
v-model="knowledgeKeyword" clearable /> |
|
|
|
|
<el-tree :data="knowledges" default-expand-all ref="knowledge" node-key="id" highlight-current |
|
|
|
|
:expand-on-click-node="false" show-checkbox @check-change="knowledgeCheck" :props="{ label: 'name' }"> |
|
|
|
|
<span class="custom-tree-node" slot-scope="{ node, data }"> |
|
|
|
|
<img v-if="data.type" class="m-r-5" src="@/assets/images/knowledge.svg" alt=""> |
|
|
|
|
<span class="org-name">{{ data.name }}</span> |
|
|
|
|
</span> |
|
|
|
|
</el-tree> |
|
|
|
|
<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 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 class="pagination"> |
|
|
|
|
<el-pagination background @current-change="currentChangeKn" :current-page="pageKn" |
|
|
|
|
layout="total, prev, pager, next" :total="totalKn"></el-pagination> |
|
|
|
|
</div> |
|
|
|
|
</template> |
|
|
|
|
<div v-else class="empty"> |
|
|
|
|
<img class="icon" src="@/assets/images/empty.svg" alt=""> |
|
|
|
|
<p>暂无数据</p> |
|
|
|
|
</div> |
|
|
|
|
</div> |
|
|
|
|
<!-- 已选知识点 --> |
|
|
|
|
<div class="item"> |
|
|
|
@ -86,16 +142,14 @@ |
|
|
|
|
</p> |
|
|
|
|
</div> |
|
|
|
|
|
|
|
|
|
<div v-for="(item, i) in checked" :key="i" class="line j-between"> |
|
|
|
|
<div v-for="(item, i) in checked" :key="i" class="j-between m-b-10"> |
|
|
|
|
<div class="flex a-center"> |
|
|
|
|
题库:{{ item.quesBank.name }} |
|
|
|
|
题库:{{ 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-10" closable |
|
|
|
|
@close="delKnowledge(i, j, item)"> |
|
|
|
|
{{ tag.name }} |
|
|
|
|
</el-tag> |
|
|
|
|
<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> |
|
|
|
|
</div> |
|
|
|
@ -133,21 +187,34 @@ export default { |
|
|
|
|
questionTypes: QuesConst.questionTypes, |
|
|
|
|
quesVisible: false, |
|
|
|
|
difficult: '', |
|
|
|
|
searchTimer: null, |
|
|
|
|
|
|
|
|
|
curQuesBank: {}, |
|
|
|
|
quesBankTypeVal: [], |
|
|
|
|
quesBankTypes: [], |
|
|
|
|
quesBankKeyword: '', |
|
|
|
|
knowledgeKeyword: '', |
|
|
|
|
searchTimer: null, |
|
|
|
|
key: 1, |
|
|
|
|
|
|
|
|
|
quesAllCheck: false, |
|
|
|
|
quesBanks: [], |
|
|
|
|
pageQuesBank: 1, |
|
|
|
|
pageSizeQuesBank: 10, |
|
|
|
|
totalQuesBank: 0, |
|
|
|
|
|
|
|
|
|
knowledgeKeyword: '', |
|
|
|
|
knowledgeTypeVal: [], |
|
|
|
|
knowledgeTypes: [], |
|
|
|
|
knowledgeCheck: false, |
|
|
|
|
knowledges: [], |
|
|
|
|
checked: [], |
|
|
|
|
pageKn: 1, |
|
|
|
|
pageSizeKn: 10, |
|
|
|
|
totalKn: 0, |
|
|
|
|
|
|
|
|
|
checked: [], |
|
|
|
|
list: [], |
|
|
|
|
years: ['暂无年份', '2024', '2023', '2022', '2021', '2020', '2019', '2018', '2017', '2016', '更早'], |
|
|
|
|
yearAll: true, |
|
|
|
|
yearCheck: [], |
|
|
|
|
submiting: false, |
|
|
|
|
diaTop: 0, |
|
|
|
|
}; |
|
|
|
|
}, |
|
|
|
|
computed: { |
|
|
|
@ -174,74 +241,125 @@ export default { |
|
|
|
|
} |
|
|
|
|
}, |
|
|
|
|
mounted () { |
|
|
|
|
console.log(5555, window.innerHeight) |
|
|
|
|
const height = (window.innerHeight - 600) / 2 |
|
|
|
|
this.diaTop = (height > 0 ? height : 0) + 'px' |
|
|
|
|
|
|
|
|
|
}, |
|
|
|
|
methods: { |
|
|
|
|
// 初始化 |
|
|
|
|
init () { |
|
|
|
|
this.yearCheck = this.years |
|
|
|
|
this.handleQuesList() |
|
|
|
|
this.getQuesBankType() |
|
|
|
|
this.getQuesBank() |
|
|
|
|
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 { list } = await this.$post(this.api.questionBankStructureLevel, { |
|
|
|
|
keyword: this.quesBankKeyword, |
|
|
|
|
createSource: 1, |
|
|
|
|
const type = this.quesBankTypeVal |
|
|
|
|
const res = await this.$post(this.api.questionBankList, { |
|
|
|
|
status: 1, |
|
|
|
|
pageNum: this.pageQuesBank, |
|
|
|
|
pageSize: this.pageSizeQuesBank, |
|
|
|
|
questionCategoryId: type.length ? type[type.length - 1] : '', |
|
|
|
|
name: this.quesBankKeyword |
|
|
|
|
}) |
|
|
|
|
this.quesBanks = list |
|
|
|
|
this.quesBanks = res.message.records |
|
|
|
|
this.totalQuesBank = res.message.total |
|
|
|
|
} catch (e) { } |
|
|
|
|
}, |
|
|
|
|
// 切换页码 |
|
|
|
|
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.$refs.quesBank.getCurrentKey() |
|
|
|
|
if (id) { |
|
|
|
|
const { data } = await this.$post(this.api.TreeStructure, { |
|
|
|
|
createSource: 1, |
|
|
|
|
questionBankId: id, |
|
|
|
|
keyword: this.knowledgeKeyword, |
|
|
|
|
const type = this.knowledgeTypeVal |
|
|
|
|
const res = await this.$post(this.api.knowledgeHierarchyList, { |
|
|
|
|
pageNum: this.pageKn, |
|
|
|
|
pageSize: this.pageSizeKn, |
|
|
|
|
questionBankId: this.curQuesBank.id, |
|
|
|
|
knowledgePointCategoryId: type.length ? type[type.length - 1] : '', |
|
|
|
|
name: this.knowledgeKeyword, |
|
|
|
|
}) |
|
|
|
|
this.knowledges = data |
|
|
|
|
} |
|
|
|
|
this.knowledges = res.message.records |
|
|
|
|
this.totalKn = res.message.total |
|
|
|
|
} catch (e) { } |
|
|
|
|
}, |
|
|
|
|
// 题库勾选回调 |
|
|
|
|
quesBankCheck (data, checked) { |
|
|
|
|
// debugger |
|
|
|
|
if (checked) { |
|
|
|
|
// this.$refs.quesBank.setCurrentKey(data.id) |
|
|
|
|
// 切换页码 |
|
|
|
|
currentChangeKn (val) { |
|
|
|
|
this.pageKn = val |
|
|
|
|
this.getKnowledge() |
|
|
|
|
} |
|
|
|
|
this.$refs.knowledge.setCheckedNodes(checked ? this.knowledges : []) |
|
|
|
|
}, |
|
|
|
|
// 知识点全选回调 |
|
|
|
|
knowledgeAllCheckChange (val) { |
|
|
|
|
this.knowledges.map(e => { |
|
|
|
|
e.check = val |
|
|
|
|
this.knowledgeChange(val, e) |
|
|
|
|
}) |
|
|
|
|
}, |
|
|
|
|
// 知识点勾选回调 |
|
|
|
|
knowledgeCheck (data, checked) { |
|
|
|
|
// 选中的是知识点才需要显示在最右边 |
|
|
|
|
if (data.type) { |
|
|
|
|
const checkQues = this.$refs.quesBank.getCurrentNode() |
|
|
|
|
const ques = this.checked.find(e => e.quesBank.id === checkQues.id) |
|
|
|
|
knowledgeChange (checked, data) { |
|
|
|
|
const checkQues = this.curQuesBank |
|
|
|
|
const index = this.checked.findIndex(e => e.quesBank.id === checkQues.id) |
|
|
|
|
// 已选中的题库数组里有该题库,则往该题库的知识点数组里 |
|
|
|
|
if (ques) { |
|
|
|
|
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 () { |
|
|
|
@ -257,25 +375,36 @@ export default { |
|
|
|
|
type: 'warning', |
|
|
|
|
closeOnClickModal: false, |
|
|
|
|
}) |
|
|
|
|
this.knowledges.map(e => e.check = false) |
|
|
|
|
this.checked = [] |
|
|
|
|
// this.$nextTick(() => { |
|
|
|
|
// this.$refs.knowledge.setCheckedKeys([]) |
|
|
|
|
// }) |
|
|
|
|
this.knowledgeCheck = false |
|
|
|
|
} catch (e) { } |
|
|
|
|
}, |
|
|
|
|
// 删除题库 |
|
|
|
|
delQuesBank (i) { |
|
|
|
|
const k = this.$refs.knowledge |
|
|
|
|
async delQuesBank (i) { |
|
|
|
|
try { |
|
|
|
|
await this.$confirm(`确认要移除吗?`, '提示', { |
|
|
|
|
confirmButtonText: '确定', |
|
|
|
|
cancelButtonText: '取消', |
|
|
|
|
type: 'warning', |
|
|
|
|
closeOnClickModal: false, |
|
|
|
|
}) |
|
|
|
|
const k = this.knowledges |
|
|
|
|
this.checked[i].knowledges.map(e => { |
|
|
|
|
k.setChecked(e.id, false, true) |
|
|
|
|
const cur = k.findIndex(n => n.id === e.id) |
|
|
|
|
if (cur !== -1) k[cur].check = false |
|
|
|
|
}) |
|
|
|
|
// this.checked.splice(i, 1) |
|
|
|
|
this.checked.splice(i, 1) |
|
|
|
|
this.knowledgeCheck = false |
|
|
|
|
} catch (e) { } |
|
|
|
|
}, |
|
|
|
|
// 删除知识点 |
|
|
|
|
delKnowledge (i, j, item) { |
|
|
|
|
this.$refs.knowledge.setChecked(item.knowledges[j].id, false) |
|
|
|
|
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 |
|
|
|
|
}, |
|
|
|
|
// 获取模板列表 |
|
|
|
|
async getList () { |
|
|
|
@ -428,22 +557,38 @@ export default { |
|
|
|
|
.el-drawer__header { |
|
|
|
|
margin-bottom: 20px; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
.overflow { |
|
|
|
|
.overflow { |
|
|
|
|
height: calc(100vh - 147px); |
|
|
|
|
padding: 0 20px; |
|
|
|
|
overflow: auto; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.wrap { |
|
|
|
|
.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%; |
|
|
|
|
max-height: calc(100vh - 190px); |
|
|
|
|
height: calc(100vh - 190px); |
|
|
|
|
padding: 15px; |
|
|
|
|
border-right: 1px solid #eee; |
|
|
|
|
overflow: auto; |
|
|
|
@ -471,5 +616,55 @@ export default { |
|
|
|
|
padding-left: 44px; |
|
|
|
|
margin-top: 10px; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.line { |
|
|
|
|
display: flex; |
|
|
|
|
padding: 5px 0; |
|
|
|
|
color: #333; |
|
|
|
|
|
|
|
|
|
&.able-check { |
|
|
|
|
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> |