yujialong 4 years ago
parent c10e676553
commit bb9a1e6cfb
  1. 21
      src/api/index.js
  2. BIN
      src/assets/img/index/achievement.png
  3. BIN
      src/assets/img/index/assesment.png
  4. BIN
      src/assets/img/index/msg.png
  5. BIN
      src/assets/img/index/practice.png
  6. 179
      src/components/quill/index.vue
  7. 16
      src/components/quill/options.js
  8. 12
      src/layouts/navbar/index.vue
  9. 9
      src/libs/util.js
  10. 10
      src/pages/achievement/detail/index.vue
  11. 13
      src/pages/achievement/list/examResults.vue
  12. 19
      src/pages/achievement/list/practiceResults.vue
  13. 6
      src/pages/exam/detail/index.vue
  14. 223
      src/pages/exam/do/index.vue
  15. 18
      src/pages/exam/list/index.vue
  16. 341
      src/pages/index/list/index.vue
  17. 212
      src/pages/messageBoard/list/index.vue
  18. 240
      src/pages/practice/do/index.vue
  19. 8
      src/pages/practice/list/myPractice.vue
  20. 13
      src/pages/practice/list/randomPractice.vue
  21. 216
      src/pages/practice/randomDo/index.vue
  22. 210
      src/pages/wrongBook/do/index.vue
  23. 313
      src/pages/wrongBook/list/index.vue
  24. 23
      src/router/modules/index.js
  25. 23
      src/router/modules/messageBoard.js
  26. 6
      src/router/modules/practice.js
  27. 5
      src/router/modules/wrongBook.js
  28. 4
      src/router/routes.js
  29. 2
      src/setting.js
  30. 22
      src/store/modules/wrongBook.js
  31. 24
      src/styles/common.scss
  32. 147
      src/styles/pages/exam.scss
  33. 85
      src/styles/pages/messageBoard.scss
  34. 4
      src/styles/pages/tree.scss

@ -56,4 +56,25 @@ export default {
AddRandomPractiseExamAnswerDetail: `/user/randomPractice/AddRandomPractiseExamAnswerDetail`, AddRandomPractiseExamAnswerDetail: `/user/randomPractice/AddRandomPractiseExamAnswerDetail`,
addPractiseRecordRandom: `/user/randomPractice/addPractiseRecord`, addPractiseRecordRandom: `/user/randomPractice/addPractiseRecord`,
previewPaper:`/management/testPaper/previewPaper`, previewPaper:`/management/testPaper/previewPaper`,
// 错题本
typesList:`cjEnterprise/questionTypes/typesList`,
getMineWrong:`/user/wrong/getMineWrong`,
getPaperInfo: `/user/wrong/getPaperInfo`,
questionInfo: `/user/wrong/questionInfo`,
// 留言板
delComment:`/management/messageBoard/delComment`,
delReply:`/management/messageBoard/delReply`,
delMessageBoard:`/management/messageBoard/delMessageBoard`,
queryMessageBoard:`/management/messageBoard/queryMessageBoard`,
queryMessageBoardDetail:`/management/messageBoard/queryMessageBoardDetail`,
saveComment:`/management/messageBoard/saveComment`,
saveMessageBoard:`/management/messageBoard/saveMessageBoard`,
saveReply:`/management/messageBoard/saveReply`,
// 首页
waitReply:`/management/index/waitReply`,
waitReplyDel:`/management/index/waitReplyDel`,
waitExam:`/user/index/waitExam`,
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

@ -0,0 +1,179 @@
<template>
<div class="quill" :class="classes">
<div ref="editor" :style="styles" v-loading="loading"></div>
<el-upload :action="this.api.fileupload" :before-upload="beforeUpload" :on-success="editorUploadSuccess" style="display: none">
<el-button class="editorUpload" size="small" type="primary">点击上传</el-button>
</el-upload>
</div>
</template>
<script>
import Quill from 'quill';
import 'quill/dist/quill.core.css';
import 'quill/dist/quill.snow.css';
import 'quill/dist/quill.bubble.css';
import toolbarOptions from './options'
export default {
name: 'quill',
props: {
value: {
type: String,
default: ''
},
readonly: {
type: Boolean,
default: false
},
toTop: {
type: Boolean,
default: true
},
border: {
type: Boolean,
default: false
},
height: {
type: Number
},
minHeight: {
type: Number
}
},
data () {
return {
Quill: null,
currentValue: '',
options: {
theme: 'snow',
bounds: document.body,
debug: 'warn',
modules: {
toolbar: {
container: toolbarOptions,
handlers: {
'image': function (value) {
if (value) {
// iview
document.querySelector('.editorUpload').click()
} else {
this.Quill.format('image', false);
}
}
}
}
},
placeholder: '',
readOnly: this.readonly
},
loading: false
}
},
computed: {
classes () {
return [
{
'quill-no-border': !this.border
}
];
},
styles () {
let style = {};
if (this.minHeight) {
style.minHeight = `${this.minHeight}px`;
}
if (this.height) {
style.height = `${this.height}px`;
}
return style;
}
},
watch: {
value: {
handler (val) {
if (val !== this.currentValue) {
this.currentValue = val;
if (this.Quill) {
this.Quill.pasteHTML(this.value);
}
}
},
immediate: true
}
},
mounted () {
this.init();
},
beforeDestroy () {
//
this.Quill = null;
},
methods: {
init () {
const editor = this.$refs.editor;
//
this.Quill = new Quill(editor, this.options);
//
this.Quill.pasteHTML(this.currentValue);
if(this.toTop){
this.$nextTick(() => {
window.scrollTo(0,0)
})
}
//
this.Quill.on('text-change', (delta, oldDelta, source) => {
const html = this.$refs.editor.children[0].innerHTML;
const text = this.Quill.getText();
const quill = this.Quill;
//
this.currentValue = html;
// v-model
this.$emit('input', html);
//
this.$emit('on-change', { html, text, quill });
});
// quill
this.Quill.on('text-change', (delta, oldDelta, source) => {
this.$emit('on-text-change', delta, oldDelta, source);
});
this.Quill.on('selection-change', (range, oldRange, source) => {
this.$emit('on-selection-change', range, oldRange, source);
});
this.Quill.on('editor-change', (eventName, ...args) => {
this.$emit('on-editor-change', eventName, ...args);
});
},
beforeUpload(file){
this.loading = true
},
editorUploadSuccess (res) {
//
let quill = this.Quill
//
if (res.data.filesResult.fileUrl) {
//
let length = quill.getSelection().index;
// res
quill.insertEmbed(length, 'image', res.data.filesResult.fileUrl)
//
quill.setSelection(length + 1)
} else {
this.$message.success('图片插入失败')
}
this.loading = false
},
}
}
</script>
<style lang="scss" scoped>
.quill-no-border{
.ql-toolbar.ql-snow{
border: none;
border-bottom: 1px solid #e8eaec;
}
.ql-container.ql-snow{
border: none;
}
}
</style>

@ -0,0 +1,16 @@
export default [
['bold', 'italic', 'underline', 'strike'],
['blockquote', 'code-block'],
[{ 'header': 1 }, { 'header': 2 }],
[{ 'list': 'ordered' }, { 'list': 'bullet' }],
[{ 'script': 'sub' }, { 'script': 'super' }],
[{ 'indent': '-1' }, { 'indent': '+1' }],
[{ 'direction': 'rtl' }],
[{ 'size': ['small', false, 'large', 'huge'] }],
[{ 'header': [1, 2, 3, 4, 5, 6, false] }],
[{ 'color': [] }, { 'background': [] }],
[{ 'font': [] }],
[{ 'align': [] }],
['clean'],
['link', 'image', 'video']
]

@ -13,8 +13,13 @@ export default {
activeName: this.$route.path, activeName: this.$route.path,
tabList: [ tabList: [
{ {
icon: 'el-icon-lx-home', icon: 'el-icon-folder-checked',
index: '/index/list', index: '/index/list',
title: '首页'
},
{
icon: 'el-icon-lx-home',
index: '/practice/list',
title: '我的练习' title: '我的练习'
}, },
{ {
@ -32,6 +37,11 @@ export default {
index: '/wrongBook/list', index: '/wrongBook/list',
title: '我的错题本' title: '我的错题本'
}, },
{
icon: 'el-icon-chat-dot-round',
index: '/messageBoard/list',
title: '交流互动'
}
], ],
hideNavList: ['article','matchDetail','courseSection','personalCenter'] hideNavList: ['article','matchDetail','courseSection','personalCenter']
}; };

@ -72,7 +72,14 @@ const util = {
isImg(ext) { isImg(ext) {
if('jpg,jpeg,png,gif,svg,psd'.includes(ext)) return true if('jpg,jpeg,png,gif,svg,psd'.includes(ext)) return true
return false return false
} },
// 循环去除html标签
removeHtmlTag(list,attr) {
list.map(n => {
n[attr] = n[attr].replace(/<\/?.+?>/gi,'')
})
return list
},
} }
export default util export default util

@ -2,14 +2,18 @@
<div class="box"> <div class="box">
<h1 class="title">{{paperName }}</h1> <h1 class="title">{{paperName }}</h1>
<div class="metas"> <div class="metas">
<div style="margin-right: 20px;"> <div class="m-r-20">
<span class="name">总分</span> <span class="name">总分</span>
<span class="val">100</span> <span class="val">100</span>
</div> </div>
<div> <div class="m-r-20">
<span class="name">考试时长</span> <span class="name">考试时长</span>
<span class="val">{{time}}分钟</span> <span class="val">{{time}}分钟</span>
</div> </div>
<div>
<span class="name">排名</span>
<span class="val">{{ranking}}</span>
</div>
</div> </div>
<ul class="tab"> <ul class="tab">
@ -65,6 +69,7 @@ export default {
return { return {
paperName: '', paperName: '',
time: 0, time: 0,
ranking: 1,
selectVisible: false, selectVisible: false,
tabs: [ tabs: [
{ {
@ -105,6 +110,7 @@ export default {
.then(res => { .then(res => {
this.paperName = res.paperName this.paperName = res.paperName
this.time = res.time this.time = res.time
this.ranking = res.ranking
this.allData = res.data this.allData = res.data
this.curType = this.allData.list1 this.curType = this.allData.list1
this.handleOptions() this.handleOptions()

@ -2,18 +2,13 @@
<div> <div>
<el-card shadow="hover" class="m-b-20"> <el-card shadow="hover" class="m-b-20">
<div> <div>
<div class="flex a-center m-b-20"> <div class="p-title m-b-20">筛选</div>
<p class="hr_tag"></p>
<span>筛选</span>
</div>
<div>
<div class="flex"> <div class="flex">
<div> <div>
<el-input placeholder="请输入考核名称" prefix-icon="el-icon-search" v-model="keyword" clearable></el-input> <el-input placeholder="请输入考核名称" prefix-icon="el-icon-search" v-model="keyword" clearable></el-input>
</div> </div>
</div> </div>
</div> </div>
</div>
</el-card> </el-card>
<el-card shadow="hover"> <el-card shadow="hover">
@ -80,11 +75,11 @@ export default {
this.$post(`${this.api.getMyAchievement}?userId=${this.userId}&pageSize=${this.pageSize}&pageNum=${this.page}`).then(res => { this.$post(`${this.api.getMyAchievement}?userId=${this.userId}&pageSize=${this.pageSize}&pageNum=${this.page}`).then(res => {
this.listData = res.data.list.list this.listData = res.data.list.list
this.total = res.data.list.totalCount this.total = res.data.list.totalCount
}).catch(res => {}); }).catch(res => {})
}, },
handleCurrentChange(val) { handleCurrentChange(val) {
this.page = val; this.page = val
this.getData(); this.getData()
}, },
show(row){ show(row){
this.setInfo({ this.setInfo({

@ -2,18 +2,14 @@
<div> <div>
<el-card shadow="hover" class="m-b-20"> <el-card shadow="hover" class="m-b-20">
<div> <div>
<div class="flex a-center m-b-20"> <div class="p-title m-b-20">筛选</div>
<p class="hr_tag"></p>
<span>筛选</span>
</div>
<div>
<div class="flex"> <div class="flex">
<div> <div>
<el-input placeholder="请输入练习/试卷名称" prefix-icon="el-icon-search" v-model="keyword" clearable></el-input> <el-input placeholder="请输入练习/试卷名称" prefix-icon="el-icon-search" v-model="keyword" clearable></el-input>
</div> </div>
</div> </div>
</div> </div>
</div>
</el-card> </el-card>
<el-card shadow="hover"> <el-card shadow="hover">
@ -31,7 +27,7 @@
<el-table-column prop="score" label="最新得分" align="center"></el-table-column> <el-table-column prop="score" label="最新得分" align="center"></el-table-column>
<el-table-column label="操作" align="center" width="180"> <el-table-column label="操作" align="center" width="180">
<template slot-scope="scope"> <template slot-scope="scope">
<el-button type="text" @click="show(scope.row)">查看详情</el-button> <el-button v-if="scope.row.practiseId" type="text" @click="show(scope.row)">查看详情</el-button>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
@ -90,14 +86,13 @@ export default {
}) })
.then(() => { .then(() => {
this.$del(`${this.api.deleteCourse}/${row.id}`).then(res => { this.$del(`${this.api.deleteCourse}/${row.id}`).then(res => {
this.$message.success('删除成功'); this.$message.success('删除成功')
this.getData() this.getData()
}).catch(res => {}); }).catch(res => {})
}) }).catch(() => {})
.catch(() => {});
}, },
handleSelectionChange(val) { handleSelectionChange(val) {
this.multipleSelection = val; this.multipleSelection = val
}, },
handleCurrentChange(val) { handleCurrentChange(val) {
this.page = val this.page = val

@ -102,16 +102,13 @@ export default {
methods: { methods: {
getData() { getData() {
this.$post(`${this.api.answerDetail}?userId=${this.userId}&assessmentId=${this.assessmentId}&paperId=${this.testPaperId}`) this.$post(`${this.api.answerDetail}?userId=${this.userId}&assessmentId=${this.assessmentId}&paperId=${this.testPaperId}`)
// this.$post(`${this.api.answerDetail}?userId=${1}&assessmentId=${1}&paperId=${1}`)
.then(res => { .then(res => {
this.paperName = res.paperName this.paperName = res.paperName
this.time = res.time this.time = res.time
this.allData = res.data this.allData = res.data
this.curType = this.allData.list1 this.curType = this.allData.list1
this.handleOptions() this.handleOptions()
}) }).catch(err => {})
.catch(err => {});
}, },
tabChange(id){ tabChange(id){
this.active = id this.active = id
@ -125,7 +122,6 @@ export default {
let options = {} let options = {}
for(let i in n){ for(let i in n){
if(i.includes('option') && n[i]){ if(i.includes('option') && n[i]){
console.log(i.replace('option_',''))
options[i.replace('option_','')] = n[i] options[i.replace('option_','')] = n[i]
} }
} }

@ -53,23 +53,26 @@
<span class="index">{{index+1}}.</span> <span class="index">{{index+1}}.</span>
<div class="name" :class="'stem' + k + index" v-html="item.questionStem"></div> <div class="name" :class="'stem' + k + index" v-html="item.questionStem"></div>
</div> </div>
<div class="media" :id="item.mediaEleId"></div>
<div class="options"> <div class="options">
<template v-if="item.typeId == 1 || item.typeId == 3"> <template v-if="item.typeId == 1 || item.typeId == 3">
<div class="option" v-for="(option,i) in item.options" :key="i"> <div class="option">
<el-radio v-model="item.val" :label="i"> <el-radio-group v-model="item.val" @change.once="updateProgress">
<el-radio v-for="(option,i) in item.options" :key="i" :label="i">
{{i}}.{{item.options[i]}} {{i}}.{{item.options[i]}}
</el-radio> </el-radio>
</el-radio-group>
</div> </div>
</template> </template>
<template v-if="item.typeId == 2"> <template v-if="item.typeId == 2">
<el-checkbox-group v-model="item.val"> <el-checkbox-group v-model="item.val" @change="updateProgress">
<el-checkbox class="option-check" :label="i" v-for="(option,i) in item.options" :key="i"> <el-checkbox class="option-check" :label="i" v-for="(option,i) in item.options" :key="i">
{{i}}.{{item.options[i]}} {{i}}.{{item.options[i]}}
</el-checkbox> </el-checkbox>
</el-checkbox-group> </el-checkbox-group>
</template> </template>
<template v-if="item.typeId == 4"> <template v-if="item.typeId == 4">
<el-input type="textarea" rows="5" v-model="item.val"></el-input> <el-input type="textarea" rows="5" v-model="item.val" @input="updateProgress"></el-input>
</template> </template>
</div> </div>
</div> </div>
@ -120,7 +123,8 @@ export default {
time: '00:00:00', time: '00:00:00',
progress: 0, progress: 0,
isSubmit: false, isSubmit: false,
isDone: false isDone: false,
totalLen: 0
}; };
}, },
computed: { computed: {
@ -157,6 +161,7 @@ export default {
} }
}, },
mounted() { mounted() {
this.insertScript()
this.getData() this.getData()
this.addLeaveEvent() this.addLeaveEvent()
this.queryState() this.queryState()
@ -165,6 +170,7 @@ export default {
clearInterval(this.timer) clearInterval(this.timer)
clearInterval(this.queryStateTimer) clearInterval(this.queryStateTimer)
window.onbeforeunload = null window.onbeforeunload = null
window.updateProgress = null
this.addRecords() this.addRecords()
}, },
methods: { methods: {
@ -191,6 +197,7 @@ export default {
this.fillBlanksScore = data.fillInTheBlanklist.length ? data.fillInTheBlanklist[0].fillBlanksScore : 0 this.fillBlanksScore = data.fillInTheBlanklist.length ? data.fillInTheBlanklist[0].fillBlanksScore : 0
this.briefAnswerScore = data.shortAnswerList.length ? data.shortAnswerList[0].briefAnswerScore : 0 this.briefAnswerScore = data.shortAnswerList.length ? data.shortAnswerList[0].briefAnswerScore : 0
this.scoreList = [this.singlePoint,this.multipleChoiceScore,this.fillBlanksScore,this.briefAnswerScore,this.briefAnswerScore] this.scoreList = [this.singlePoint,this.multipleChoiceScore,this.fillBlanksScore,this.briefAnswerScore,this.briefAnswerScore]
this.handleOptions() this.handleOptions()
}) })
.catch(err => {}) .catch(err => {})
@ -201,6 +208,7 @@ export default {
let records = res.data.data let records = res.data.data
let len = 0 let len = 0
this.subjects.map(n => len += n.length) this.subjects.map(n => len += n.length)
this.totalLen = len
this.progress = len ? Math.floor((records.length / len * 100)) : 0 this.progress = len ? Math.floor((records.length / len * 100)) : 0
this.singleAnsweredCount = records.filter(n => n.typeId == 1).length this.singleAnsweredCount = records.filter(n => n.typeId == 1).length
@ -235,12 +243,19 @@ export default {
}, },
handleOptions(){ handleOptions(){
let subjects = this.subjects let subjects = this.subjects
window.updateProgress = (item) => {
this.updateProgress(item,1)
}
let index = 0
subjects.forEach((e,i) => { subjects.forEach((e,i) => {
e.forEach(n => { e.forEach((n,j) => {
index++
n.mediaEleId = `player${index}`
this.initMedia(n)
if(i == 1){ if(i == 1){
this.$set(n,'val',[]) this.$set(n,'val',[])
}else if(i == 3){ }else if(i == 3){
n.questionStem = n.questionStem.replace(/\(\)\(\)\(\)/g,`<input class="input"></input>`) n.questionStem = n.questionStem.replace(/\(\)\(\)\(\)/g,`<input class="input" data-index="${j}" oninput="updateProgress(this)"></input>`)
}else{ }else{
this.$set(n,'val','') this.$set(n,'val','')
} }
@ -258,6 +273,23 @@ export default {
this.subjects = subjects this.subjects = subjects
this.getAnswer() this.getAnswer()
}, },
initMedia(item){
if(item.videoAudio && !item.player){
this.$get(`${this.api.getPlayAuth}/${item.videoAudio}`).then(res => {
let playAuth = res.data.playAuth
this.$nextTick(() => {
item.player = new Aliplayer({
id: item.mediaEleId,
width: '100%',
autoplay: false,
vid : item.videoAudio,
playauth : playAuth,
encryptType:1, //
})
})
}).catch(res => {})
}
},
addLeaveEvent(){ addLeaveEvent(){
window.onbeforeunload = e => { window.onbeforeunload = e => {
e = e || window.event; e = e || window.event;
@ -373,150 +405,47 @@ export default {
}) })
.catch(err => {}) .catch(err => {})
} }
},
updateProgress(item,isFillBlank){
let subjects = this.subjects
if(isFillBlank){
let index = item.getAttribute('data-index')
if([...item.parentElement.querySelectorAll('input')].some(n => n.value)){
subjects[3][index].hadAnswer = 1
}else{
subjects[3][index].hadAnswer = 0
} }
this.fillBlankAnsweredCount = subjects[3].filter(n => n.hadAnswer).length
}else{
this.singleAnsweredCount = subjects[0].filter(n => n.val).length
this.multipleAnsweredCount = subjects[1].filter(n => n.val.length).length
this.judgeAnsweredCount = subjects[2].filter(n => n.val).length
this.briefAnswerAnsweredCount = subjects[4].filter(n => n.val).length
}
let answered = this.singleAnsweredCount + this.multipleAnsweredCount + this.judgeAnsweredCount + this.fillBlankAnsweredCount + this.briefAnswerAnsweredCount
this.progress = this.totalLen ? Math.floor((answered / this.totalLen * 100)) : 0
},
insertScript(){
const linkTag = document.createElement('link')
linkTag.id = 'aliplayerLink'
linkTag.rel = 'stylesheet'
linkTag.href = 'https://g.alicdn.com/de/prismplayer/2.8.2/skins/default/aliplayer-min.css'
document.body.appendChild(linkTag)
const scriptTag = document.createElement('script')
scriptTag.id = 'aliplayerScript'
scriptTag.type = 'text/javascript'
scriptTag.src = 'https://g.alicdn.com/de/prismplayer/2.8.2/aliplayer-min.js'
document.body.appendChild(scriptTag)
this.$once('hook:beforeDestroy', function () {
document.body.removeChild(document.querySelector('#aliplayerLink'))
document.body.removeChild(document.querySelector('#aliplayerScript'))
})
},
}, },
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
$borderColor: #ececec; @import "@/styles/pages/exam.scss";
.box{
display: flex;
justify-content: space-between;
width: 90%;
margin: 0 auto;
.left,.middle,.right{
border: 1px solid $borderColor;
}
.left,.right{
width: 160px;
padding: 10px;
margin-right: 10px;
box-sizing: border-box;
.title{
padding: 10px 0;
font-size: 14px;
color: #444;
text-align: center;
}
.item{
padding: 10px 0;
margin-bottom: 10px;
border-bottom: 1px solid $borderColor;
.type,.total{
color: #444;
font-size: 12px;
}
.total{
margin: 10px 0;
}
.nums{
display: flex;
flex-wrap: wrap;
span{
width: 24px;
margin: 2px 1px;
line-height: 24px;
text-align: center;
color: #888;
font-size: 10px;
box-sizing: border-box;
border: 1px solid #e6e6e6;
border-radius: 50%;
}
.active{
color: #fff;
background-color: #e80909;
border-color: #e80909;
}
}
}
.btn{
margin: 20px 0;
text-align: center;
}
}
.middle{
flex: 1;
margin-right: 10px;
overflow: auto;
.title{
padding: 10px;
margin-bottom: 10px;
font-size: 14px;
color: #444;
border-bottom: 1px solid $borderColor;
}
.ques{
.ques-wrap{
padding: 0 15px;
margin: 10px 0 20px;
}
.item{
margin: 10px 0 20px;
&:first-child{
margin-top: 0;
}
.name-wrap{
display: flex;
align-items: center;
margin-bottom: 10px;
font-size: 13px;
color: #444;
.index{
font-size: 13px;
color: #444;
}
/deep/.input{
width: 100px;
height: 28px;
padding: 0 5px;
margin: 0 5px;
color: #444;
background-color: #fff;
border: 1px solid #ebebeb;
box-sizing: border-box;
&:focus{
outline: none;
}
&:disabled{
background-color: #e8e8e8;
cursor: not-allowed;
}
}
}
.options{
margin-top: 10px;
font-size: 14px;
color: #8b8b8b;
.option{
margin: 5px 0;
&.selected{
font-weight: bold;
color: #555;
}
}
.option-check{
display: block;
margin-right: 6px;
}
/deep/.el-radio__label{
padding-left: 6px;
}
}
}
}
}
.right{
.time,.ans{
font-size: 14px;
color: #444;
text-align: center;
}
.ans{
margin: 20px 0 10px;
font-size: 15px;
}
}
}
</style> </style>

@ -2,11 +2,8 @@
<div class="box"> <div class="box">
<el-card shadow="hover" class="m-b-20"> <el-card shadow="hover" class="m-b-20">
<div> <div>
<div class="flex a-center m-b-20"> <div class="p-title m-b-20">筛选</div>
<p class="hr_tag"></p>
<span>筛选</span>
</div>
<div>
<div class="flex j-between"> <div class="flex j-between">
<el-form label-width="80px"> <el-form label-width="80px">
<el-form-item class="no-mb" label="考试类型"> <el-form-item class="no-mb" label="考试类型">
@ -21,7 +18,6 @@
</div> </div>
</div> </div>
</div> </div>
</div>
</el-card> </el-card>
<el-card shadow="hover"> <el-card shadow="hover">
@ -39,7 +35,7 @@
{{getDegreeName(scope.row.degree)}} {{getDegreeName(scope.row.degree)}}
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="startTime" label="考开始时间" align="center"></el-table-column> <el-table-column prop="startTime" label="考开始时间" align="center"></el-table-column>
<el-table-column prop="endTime" label="考试结束时间" align="center"></el-table-column> <el-table-column prop="endTime" label="考试结束时间" align="center"></el-table-column>
<el-table-column prop="timeCost" label="用时(分钟)" width="120" align="center"> <el-table-column prop="timeCost" label="用时(分钟)" width="120" align="center">
<template slot-scope="scope"> <template slot-scope="scope">
@ -122,9 +118,9 @@ export default {
'setInfo' 'setInfo'
]), ]),
getData() { getData() {
this.$get(`${this.api.queryExam}?type=${this.type}&assessmentName=${this.keyword}&userId=${this.userId}`).then(res => { this.$get(`${this.api.queryExam}?type=${this.type}&assessmentName=${this.keyword}&userId=${this.userId}&pageSize=${this.pageSize}&pageNum=${this.page}`).then(res => {
this.listData = res.data.Assessment this.listData = res.data.Assessment.list
this.total = res.data.total this.total = res.data.Assessment.totalCount
}).catch(err => { }).catch(err => {
clearInterval(this.timer) clearInterval(this.timer)
}) })
@ -152,7 +148,7 @@ export default {
query(row){ query(row){
this.setInfo({ this.setInfo({
testPaperId: row.testPaperId, testPaperId: row.testPaperId,
assessmentId: row.id assessmentId: row.assessmentId
}) })
this.$router.push('detail') this.$router.push('detail')
} }

@ -0,0 +1,341 @@
<template>
<div>
<el-card shadow="hover" class="m-b-10">
<div class="title m-b-20"><img src="../../../assets/img/index/assesment.png" alt=""> 我的考试安排</div>
<div>
<el-date-picker v-model="date" align="right" unlink-panels type="daterange" start-placeholder="开始日期" end-placeholder="结束日期" format="yyyy-MM-dd" value-format="yyyy-MM-dd" clearable></el-date-picker>
</div>
</el-card>
<el-card shadow="hover" class="m-b-30">
<div class="text-center text-grey m-b-10">待考试列表</div>
<el-table
:data="listData"
ref="table"
row-key="id"
class="table"
stripe
header-align="center"
>
<el-table-column type="index" width="100" label="序号" align="center">
<template
slot-scope="scope"
>{{scope.$index + (page - 1) * pageSize + 1}}</template>
</el-table-column>
<el-table-column prop="assessmentName" label="考试名称" align="center"></el-table-column>
<el-table-column prop="startTime" label="考试开始时间" align="center"></el-table-column>
<el-table-column prop="endTime" label="考试结束时间" align="center"></el-table-column>
<el-table-column label="操作" width="200">
<template slot-scope="scope">
<el-button type="text" @click="toExam(scope.row)" v-if="scope.row.assessmentState == 2" :disabled="scope.row.studentState == 2">进入考试</el-button>
</template>
</el-table-column>
</el-table>
<div class="pagination">
<el-pagination
background
@current-change="handleCurrentChange"
:current-page="page"
:page-size="pageSize"
layout="total,prev, pager, next"
:total="total"
></el-pagination>
</div>
</el-card>
<el-card shadow="hover" class="m-b-10">
<div class="title"><img src="../../../assets/img/index/practice.png" alt=""> 我的练习</div>
</el-card>
<div class="flex m-b-30">
<el-card shadow="hover" class="flex-1 m-r-20">
<div class="text-center text-grey m-b-10">平均分 {{avgScore}}&emsp;&emsp;总时长 {{totalDuration}}h</div>
<el-table
:data="practiceData"
ref="table"
row-key="id"
class="table"
stripe
header-align="center"
>
<el-table-column type="index" width="100" label="序号" align="center">
<template
slot-scope="scope"
>{{scope.$index + (page - 1) * pageSize + 1}}</template>
</el-table-column>
<el-table-column prop="practiseName" label="练习试卷名称" align="center"></el-table-column>
<el-table-column prop="startTime" label="开始时间" align="center"></el-table-column>
<el-table-column prop="duration" label="练习时长(分钟)" align="center"></el-table-column>
<el-table-column prop="lastScore" label="得分" align="center"></el-table-column>
</el-table>
<div class="pagination">
<el-pagination
background
@current-change="handlePracticeCurrentChange"
:current-page="pagePractice"
:page-size="pageSizePractice"
layout="total,prev, pager, next"
:total="totalPractice"
></el-pagination>
</div>
</el-card>
<el-card shadow="hover" class="flex-1">
<div class="chart" id="practiceDuration"></div>
</el-card>
</div>
<el-card shadow="hover" class="m-b-10">
<div class="title"><img src="../../../assets/img/index/achievement.png" alt=""> 我的成绩</div>
</el-card>
<el-card shadow="hover" class="m-b-30">
<div class="chart" id="achievement"></div>
</el-card>
<el-card shadow="hover" class="m-b-10">
<div class="title"><img src="../../../assets/img/index/msg.png" alt=""> 回复反馈</div>
</el-card>
<el-card shadow="hover">
<ul class="list">
<li v-for="(item,index) in msgList" :key="index">
<div class="item">
<div class="inner">
<img class="avatar" :src="item.userAvatars" alt="">
<div class="texts">
<div class="title">
<span class="username">{{item.userName}}</span>
<span class="publish">发表于</span>
<span class="date">{{item.createTime}}</span>
</div>
<div class="desc" v-html="item.content"></div>
</div>
</div>
<div class="action">
<button v-if="item.userId != userId" class="btn" @click="showReply(item)">回复</button>
<button v-else class="btn" @click="delMsg(item)">删除</button>
</div>
<div class="reply" v-if="item.showReply">
<quill :border="true" v-model="item.replyContent" :toTop="false" :height="150" />
<div class="m-t-10 text-right">
<el-button type="primary" size="mini" @click="submitComment(item)">提交</el-button>
</div>
</div>
</div>
</li>
</ul>
</el-card>
</div>
</template>
<script>
import { mapState,mapGetters,mapActions } from 'vuex'
import quill from '@/components/quill'
import echarts from 'echarts'
import util from '@/libs/util'
export default {
data() {
return {
date: [util.formatDate('yyyy-MM-dd'),util.formatDate('yyyy-MM-dd')],
startTime: '',
endTime: '',
page: 1,
pageSize: 10,
total: 0,
listData: [],
avgScore: 0,
totalDuration: 0,
pagePractice: 1,
pageSizePractice: 10,
totalPractice: 0,
practiceData: [],
practiceDateList: [],
practiceDurationList: [],
assesmentNameList: [],
assesmentScoreList: [],
msgList: [],
};
},
computed: {
...mapState('user', [
'userId','clientId'
]),
...mapGetters('assessment', [
'getTypeName','getStateName'
])
},
watch: {
date: function(val){
if(val){
this.startTime = val[0]
this.endTime = val[1]
}else{
this.startTime = ''
this.endTime = ''
}
this.getData()
}
},
components: {
quill
},
mounted() {
this.getData()
this.getPractice()
this.getAchievement()
this.getMsg()
},
methods: {
...mapActions('exam', [
'setInfo'
]),
getData() {
this.$post(`${this.api.waitExam}?userId=${this.userId}&pageNum=${this.page}&pageSize=${this.pageSize}&startTime=${this.startTime}&endTime=${this.endTime}`)
.then(res => {
this.listData = this.handleList(res.data.list.list)
this.total = res.data.list.totalCount
}).catch(err => {})
},
handleCurrentChange(val) {
this.page = val
this.getData()
},
toExam(row){
this.setInfo({
testPaperId: row.testPaperId,
assessmentId: row.assessmentId,
teacherId: row.teacherId,
classId: row.classId,
duration: row.duration
})
this.$router.push('/exam/do')
},
getPractice() {
this.$post(`${this.api.getMinePractise}?pageNum=${this.pagePractice}&pageSize=${this.pageSizePractice}&userId=${this.userId}&practiseName=`).then(res => {
let list = res.data.pageUtils.list
this.practiceData = list
this.totalPractice = res.data.pageUtils.totalCount
let avgScore = 0
list.map(n => avgScore += n.lastScore)
this.avgScore = (avgScore / list.length).toFixed(2)
let totalDuration = 0
list.map(n => totalDuration += n.duration)
this.totalDuration = (totalDuration / 60).toFixed(2)
this.practiceDateList = list.map(n => {
let date = new Date(n.startTime)
return `${date.getMonth() + 1}.${date.getDate()}`
})
this.practiceDurationList = list.map(n => n.duration)
this.getPracticeDuration()
}).catch(res => {})
},
handlePracticeCurrentChange(val) {
this.pagePractice = val
this.getPractice()
},
getPracticeDuration(){
console.log(11,this.practiceDateList,this.practiceDurationList)
let myChart = echarts.init(document.getElementById('practiceDuration'))
myChart.setOption({
title: { text: '总练习时长' },
tooltip: {},
xAxis: {
type: 'category',
boundaryGap: false,
data: this.practiceDateList
},
yAxis: {
type: 'value'
},
series: [{
data: this.practiceDurationList,
type: 'line',
areaStyle: {}
}]
});
},
getAchievement() {
this.$post(`${this.api.getMyAchievement}?userId=${this.userId}&pageSize=1000&pageNum=1`).then(res => {
let list = res.data.list.list
this.assesmentNameList = list.map(n => n.assessmentName)
this.assesmentScoreList = list.map(n => n.thisScore)
this.getAchievementChart()
}).catch(res => {})
},
getAchievementChart(){
let myChart = echarts.init(document.getElementById('achievement'))
myChart.setOption({
xAxis: {
type: 'category',
data: this.assesmentNameList
},
yAxis: {
type: 'value'
},
series: [{
data: this.assesmentScoreList,
type: 'bar'
}]
});
},
getMsg() {
this.$post(`${this.api.waitReply}?schoolId=${this.clientId}&userId=${this.userId}`)
.then(res => {
this.msgList = this.handleList(res.data.list)
}).catch(err => {})
},
handleList(list){
list.map(n => {
n.userAvatars = n.userAvatars ? n.userAvatars : 'https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png'
n.showReply = false
n.replyContent = ''
n.children = []
n.showChildren = false
})
return list
},
showReply(row){
row.showReply = !row.showReply
},
delMsg(row){
this.$post(`${this.api.waitReplyDel}?userId=${this.userId}&bid=${row.bid}`).then(res => {
this.$message.success('删除成功')
this.getMsg()
}).catch(res => {})
},
submitComment(row){
let data = {
bid: row.bid,
content: row.replyContent,
commentUserId: this.userId,
schoolId: this.clientId,
}
this.$post(this.api.saveComment,data).then(res => {
this.$message.success('提交成功')
row.replyContent = ''
this.getMsg()
}).catch(res => {})
},
}
};
</script>
<style lang="scss" scoped>
@import "@/styles/pages/messageBoard.scss";
.title{
display: flex;
align-items: center;
font-size: 16px;
color: #6f6f6f;
img{
width: 20px;
margin-right: 5px;
}
}
.chart{
height: 400px;
}
</style>

@ -0,0 +1,212 @@
<template>
<div>
<el-card shadow="hover">
<ul class="list">
<li v-for="(item,index) in listData" :key="index">
<div class="item">
<div class="inner">
<img class="avatar" :src="item.userAvatars" alt="">
<div class="texts">
<div class="title">
<span class="username">{{item.userName}}</span>
<span class="publish">发表于</span>
<span class="date">{{item.createTime}}</span>
</div>
<div class="desc" v-html="item.content"></div>
</div>
<div class="right">
<p class="index">[ {{index+1}} # ]</p>
</div>
</div>
<div class="action">
<button v-if="item.userId != userId" class="btn" @click="showReply(item)">回复</button>
<button v-else class="btn" @click="delMsg(item)">删除</button>
</div>
<div class="reply" v-if="item.showReply">
<quill :border="true" v-model="item.replyContent" :toTop="false" :height="150" />
<div class="m-t-10 text-right">
<el-button type="primary" size="mini" @click="submitComment(item)">提交</el-button>
</div>
</div>
<ul class="list children" v-if="item.showChildren">
<li v-for="(reply,i) in item.children" :key="i">
<div class="inner">
<img class="avatar" :src="reply.userAvatars" alt="">
<div class="texts">
<div class="title">
<span class="username">{{reply.userName}}</span>
<span class="publish">发表于</span>
<span class="date">{{reply.commentTime}}</span>
</div>
<div class="desc" v-html="reply.content"></div>
</div>
</div>
<div class="action">
<button v-if="reply.commentUserId != userId" class="btn" @click="showReply(reply)">回复</button>
<button v-else class="btn" @click="delReply(reply,i,index)">删除</button>
</div>
<div class="reply" v-if="reply.showReply">
<quill :border="true" v-model="reply.replyContent" :toTop="false" :height="150" />
<div class="m-t-10 text-right">
<el-button type="primary" size="mini" @click="submitReply(reply)">提交</el-button>
</div>
</div>
</li>
</ul>
<div v-if="item.getCommentReplyNum" class="toggle"><span @click="toggleReply(item)">{{item.showChildren ? '收起所有回复' : `查看所有${item.getCommentReplyNum}条回复`}} <i class="el-icon-arrow-down"></i></span></div>
</div>
</li>
</ul>
<div class="pagination">
<el-pagination
background
@current-change="handleCurrentChange"
:current-page="page"
:page-size="pageSize"
layout="total,prev, pager, next"
:total="total"
></el-pagination>
</div>
<div class="input-wrap">
<quill class="m-t-20" :border="true" v-model="content" :toTop="false" :height="150" />
<div class="m-t-10 text-right">
<el-button type="primary" size="mini" @click="submitMsg">提交</el-button>
</div>
</div>
</el-card>
</div>
</template>
<script>
import { mapState } from 'vuex'
import quill from '@/components/quill'
export default {
data() {
return {
page: 1,
pageSize: 10,
total: 0,
listData: [],
content: ''
};
},
computed: {
...mapState('user', [
'userId','clientId'
])
},
components: {
quill
},
mounted() {
this.getData()
},
methods: {
getData() {
this.$post(`${this.api.queryMessageBoard}?schoolId=${this.clientId}&pageNum=${this.page}&pageSize=${this.pageSize}`)
.then(res => {
this.listData = this.handleList(res.data.list.list)
this.total = res.data.list.totalCount
}).catch(err => {})
},
handleList(list){
list.map(n => {
n.userAvatars = n.userAvatars ? n.userAvatars : 'https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png'
n.showReply = false
n.replyContent = ''
n.children = []
n.showChildren = false
})
return list
},
handleCurrentChange(val) {
this.page = val
this.getData()
},
toggleReply(row){
if(row.showChildren) return row.showChildren = false
this.$post(`${this.api.queryMessageBoardDetail}?bid=${row.bid}`).then(res => {
let children = res.data.list
let replyList = []
children.map(n => {
n.replyList.map(e => {
e.bid = n.bid
e.content = e.replyComment
e.commentTime = e.replyTime
e.commentUserId = e.userIdByReply
})
replyList = replyList.concat(n.replyList)
})
children = children.concat(replyList)
row.children = this.handleList(children)
row.showChildren = true
}).catch(res => {})
},
showReply(row){
row.showReply = !row.showReply
},
delMsg(row){
this.$post(`${this.api.delMessageBoard}?bid=${row.bid}`).then(res => {
this.$message.success('删除成功')
this.getData()
}).catch(res => {})
},
submitComment(row){
let data = {
bid: row.bid,
content: row.replyContent,
commentUserId: this.userId,
schoolId: this.clientId,
}
this.$post(this.api.saveComment,data).then(res => {
this.$message.success('提交成功')
row.replyContent = ''
this.getData()
}).catch(res => {})
},
delReply(row,i,index){
if(row.identification == 1){
this.$post(`${this.api.delComment}?commentId=${row.commentId}`).then(res => {
this.$message.success('删除成功')
this.listData[index].children.splice(i,1)
}).catch(res => {})
}else{
this.$post(`${this.api.delReply}?replyId=${row.replyId}`).then(res => {
this.$message.success('删除成功')
this.listData[index].children.splice(i,1)
}).catch(res => {})
}
},
submitReply(row){
let data = {
bid: row.bid,
commentId: row.commentId,
replyComment: row.replyContent,
replyUserId: row.commentUserId ? row.commentUserId : row.userIdByReply,
userId: this.userId,
}
this.$post(this.api.saveReply,data).then(res => {
this.$message.success('提交成功')
row.replyContent = ''
this.getData()
}).catch(res => {})
},
submitMsg(){
let data = {
content: this.content,
schoolId: this.clientId,
userId: this.userId
}
this.$post(this.api.saveMessageBoard,data).then(res => {
this.$message.success('提交成功')
this.content = ''
this.getData()
}).catch(res => {})
}
}
};
</script>
<style lang="scss" scoped>
@import "@/styles/pages/messageBoard.scss";
</style>

@ -53,23 +53,26 @@
<span class="index">{{index+1}}.</span> <span class="index">{{index+1}}.</span>
<div class="name" :class="'stem' + k + index" v-html="item.questionStem"></div> <div class="name" :class="'stem' + k + index" v-html="item.questionStem"></div>
</div> </div>
<div class="media" :id="item.mediaEleId"></div>
<div class="options"> <div class="options">
<template v-if="item.name == '单项选择' || item.name == '判断题'"> <template v-if="item.name == '单项选择' || item.name == '判断题'">
<div class="option" v-for="(option,i) in item.options" :key="i"> <div class="option">
<el-radio v-model="item.val" :label="i"> <el-radio-group v-model="item.val" @change.once="updateProgress">
<el-radio v-for="(option,i) in item.options" :key="i" :label="i">
{{i}}.{{item.options[i]}} {{i}}.{{item.options[i]}}
</el-radio> </el-radio>
</el-radio-group>
</div> </div>
</template> </template>
<template v-if="item.name == '多项选择'"> <template v-if="item.name == '多项选择'">
<el-checkbox-group v-model="item.val"> <el-checkbox-group v-model="item.val" @change="updateProgress">
<el-checkbox class="option-check" :label="i" v-for="(option,i) in item.options" :key="i"> <el-checkbox class="option-check" :label="i" v-for="(option,i) in item.options" :key="i">
{{i}}.{{item.options[i]}} {{i}}.{{item.options[i]}}
</el-checkbox> </el-checkbox>
</el-checkbox-group> </el-checkbox-group>
</template> </template>
<template v-if="item.name == '简答题'"> <template v-if="item.name == '简答题'">
<el-input type="textarea" rows="5" v-model="item.val"></el-input> <el-input type="textarea" rows="5" v-model="item.val" @input="updateProgress"></el-input>
</template> </template>
</div> </div>
</div> </div>
@ -88,10 +91,12 @@
import { mapState,mapGetters,mapActions } from 'vuex' import { mapState,mapGetters,mapActions } from 'vuex'
import mixins from '@/mixins/setBackground' import mixins from '@/mixins/setBackground'
import util from '@/libs/util' import util from '@/libs/util'
export default { export default {
mixins: [ mixins ], mixins: [ mixins ],
data() { data() {
return { return {
identification: this.$store.state.identification,
subjects: [], subjects: [],
singleCount: 0, singleCount: 0,
multipleCount: 0, multipleCount: 0,
@ -116,7 +121,8 @@ export default {
time: '00:00:00', time: '00:00:00',
progress: 0, progress: 0,
isSubmit: false, isSubmit: false,
isDone: false isDone: false,
totalLen: 0
}; };
}, },
computed: { computed: {
@ -124,15 +130,17 @@ export default {
'userId' 'userId'
]), ]),
...mapState('practice', [ ...mapState('practice', [
'practiseId','paperId','isContinue','identification' 'practiseId','paperId','isContinue'
]), ]),
}, },
mounted() { mounted() {
this.insertScript()
this.getData() this.getData()
this.addLeaveEvent() this.addLeaveEvent()
}, },
beforeDestroy(){ beforeDestroy(){
window.onbeforeunload = null window.onbeforeunload = null
window.updateProgress = null
this.addRecords() this.addRecords()
}, },
methods: { methods: {
@ -160,12 +168,18 @@ export default {
this.briefAnswerScore = data.list5.length ? data.list5[0].briefAnswerScore * this.briefAnswerCount : 0 this.briefAnswerScore = data.list5.length ? data.list5[0].briefAnswerScore * this.briefAnswerCount : 0
this.scoreList = [this.singlePoint,this.multipleChoiceScore,this.fillBlanksScore,this.briefAnswerScore,this.briefAnswerScore] this.scoreList = [this.singlePoint,this.multipleChoiceScore,this.fillBlanksScore,this.briefAnswerScore,this.briefAnswerScore]
window.updateProgress = (item) => {
this.updateProgress(item,1)
}
let index = 0
subjects.forEach((e,i) => { subjects.forEach((e,i) => {
e.forEach(n => { e.forEach((n,j) => {
index++
n.mediaEleId = `player${index}`
if(i == 1){ if(i == 1){
this.$set(n,'val',[]) this.$set(n,'val',[])
}else if(i == 3){ }else if(i == 3){
n.questionStem = n.questionStem.replace(/\(\)\(\)\(\)/g,`<input class="input"></input>`) n.questionStem = n.questionStem.replace(/\(\)\(\)\(\)/g,`<input class="input" data-index="${j}" oninput="updateProgress(this)"></input>`)
}else{ }else{
this.$set(n,'val','') this.$set(n,'val','')
} }
@ -188,10 +202,19 @@ export default {
getAnswer() { getAnswer() {
this.$post(`${this.api.enterPractise}?paperId=${this.paperId}&userId=${this.userId}&practiseId=${this.practiseId}&isContinue=${this.isContinue}&identification=${this.identification}`) this.$post(`${this.api.enterPractise}?paperId=${this.paperId}&userId=${this.userId}&practiseId=${this.practiseId}&isContinue=${this.isContinue}&identification=${this.identification}`)
.then(res => { .then(res => {
let records = [...res.data.list1,...res.data.list2,...res.data.list3,...res.data.list4,...res.data.list5]
records = records.filter(n => n.user_answer)
let len = 0 let len = 0
this.subjects.map(n => len += n.length) this.subjects.map(n => len += n.length)
this.totalLen = len
if(this.isContinue){
this.identification = res.data.Identification
this.subjects.forEach((e,i) => {
e.forEach((n,k) => {
this.initMedia(n)
})
})
}else{
let records = [...res.data.list1,...res.data.list2,...res.data.list3,...res.data.list4,...res.data.list5]
records = records.filter(n => n.user_answer)
this.progress = len ? Math.floor((records.length / len * 100)) : 0 this.progress = len ? Math.floor((records.length / len * 100)) : 0
this.singleAnsweredCount = records.filter(n => n.typeName == '单项选择').length this.singleAnsweredCount = records.filter(n => n.typeName == '单项选择').length
@ -202,6 +225,7 @@ export default {
this.subjects.forEach((e,i) => { this.subjects.forEach((e,i) => {
e.forEach((n,k) => { e.forEach((n,k) => {
this.initMedia(n)
let answered = records.find(j => j.questionId == n.questionId) let answered = records.find(j => j.questionId == n.questionId)
if(answered){ if(answered){
if(i == 1){ if(i == 1){
@ -219,9 +243,26 @@ export default {
} }
}) })
}) })
console.log(22,this.subjects) }
}).catch(err => {}) }).catch(err => {})
}, },
initMedia(item){
if(item.videoAudio && !item.player){
this.$get(`${this.api.getPlayAuth}/${item.videoAudio}`).then(res => {
let playAuth = res.data.playAuth
this.$nextTick(() => {
item.player = new Aliplayer({
id: item.mediaEleId,
width: '100%',
autoplay: false,
vid : item.videoAudio,
playauth : playAuth,
encryptType:1, //
})
})
}).catch(res => {})
}
},
addLeaveEvent(){ addLeaveEvent(){
window.onbeforeunload = e => { window.onbeforeunload = e => {
e = e || window.event; e = e || window.event;
@ -300,150 +341,47 @@ export default {
.then(res => {}) .then(res => {})
.catch(err => {}) .catch(err => {})
} }
},
updateProgress(item,isFillBlank){
let subjects = this.subjects
if(isFillBlank){
let index = item.getAttribute('data-index')
if([...item.parentElement.querySelectorAll('input')].some(n => n.value)){
subjects[3][index].hadAnswer = 1
}else{
subjects[3][index].hadAnswer = 0
} }
this.fillBlankAnsweredCount = subjects[3].filter(n => n.hadAnswer).length
}else{
this.singleAnsweredCount = subjects[0].filter(n => n.val).length
this.multipleAnsweredCount = subjects[1].filter(n => n.val.length).length
this.judgeAnsweredCount = subjects[2].filter(n => n.val).length
this.briefAnswerAnsweredCount = subjects[4].filter(n => n.val).length
}
let answered = this.singleAnsweredCount + this.multipleAnsweredCount + this.judgeAnsweredCount + this.fillBlankAnsweredCount + this.briefAnswerAnsweredCount
this.progress = this.totalLen ? Math.floor((answered / this.totalLen * 100)) : 0
},
insertScript(){
const linkTag = document.createElement('link')
linkTag.id = 'aliplayerLink'
linkTag.rel = 'stylesheet'
linkTag.href = 'https://g.alicdn.com/de/prismplayer/2.8.2/skins/default/aliplayer-min.css'
document.body.appendChild(linkTag)
const scriptTag = document.createElement('script')
scriptTag.id = 'aliplayerScript'
scriptTag.type = 'text/javascript'
scriptTag.src = 'https://g.alicdn.com/de/prismplayer/2.8.2/aliplayer-min.js'
document.body.appendChild(scriptTag)
this.$once('hook:beforeDestroy', function () {
document.body.removeChild(document.querySelector('#aliplayerLink'))
document.body.removeChild(document.querySelector('#aliplayerScript'))
})
},
}, },
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
$borderColor: #ececec; @import "@/styles/pages/exam.scss";
.box{
display: flex;
justify-content: space-between;
width: 90%;
margin: 0 auto;
.left,.middle,.right{
border: 1px solid $borderColor;
}
.left,.right{
width: 160px;
padding: 10px;
margin-right: 10px;
box-sizing: border-box;
.title{
padding: 10px 0;
font-size: 14px;
color: #444;
text-align: center;
}
.item{
padding: 10px 0;
margin-bottom: 10px;
border-bottom: 1px solid $borderColor;
.type,.total{
color: #444;
font-size: 12px;
}
.total{
margin: 10px 0;
}
.nums{
display: flex;
flex-wrap: wrap;
span{
width: 24px;
margin: 2px 1px;
line-height: 24px;
text-align: center;
color: #888;
font-size: 10px;
box-sizing: border-box;
border: 1px solid #e6e6e6;
border-radius: 50%;
}
.active{
color: #fff;
background-color: #e80909;
border-color: #e80909;
}
}
}
.btn{
margin: 20px 0;
text-align: center;
}
}
.middle{
flex: 1;
margin-right: 10px;
overflow: auto;
.title{
padding: 10px;
margin-bottom: 10px;
font-size: 14px;
color: #444;
border-bottom: 1px solid $borderColor;
}
.ques{
.ques-wrap{
padding: 0 15px;
margin: 10px 0 20px;
}
.item{
margin: 10px 0 20px;
&:first-child{
margin-top: 0;
}
.name-wrap{
display: flex;
align-items: center;
margin-bottom: 10px;
font-size: 13px;
color: #444;
.index{
font-size: 13px;
color: #444;
}
/deep/.input{
width: 100px;
height: 28px;
padding: 0 5px;
margin: 0 5px;
color: #444;
background-color: #fff;
border: 1px solid #ebebeb;
box-sizing: border-box;
&:focus{
outline: none;
}
&:disabled{
background-color: #e8e8e8;
cursor: not-allowed;
}
}
}
.options{
margin-top: 10px;
font-size: 14px;
color: #8b8b8b;
.option{
margin: 5px 0;
&.selected{
font-weight: bold;
color: #555;
}
}
.option-check{
display: block;
margin-right: 6px;
}
/deep/.el-radio__label{
padding-left: 6px;
}
}
}
}
}
.right{
.time,.ans{
font-size: 14px;
color: #444;
text-align: center;
}
.ans{
margin: 20px 0 10px;
font-size: 15px;
}
}
}
</style> </style>

@ -2,18 +2,14 @@
<div> <div>
<el-card shadow="hover" class="m-b-20"> <el-card shadow="hover" class="m-b-20">
<div> <div>
<div class="flex a-center m-b-20"> <div class="p-title m-b-20">筛选</div>
<p class="hr_tag"></p>
<span>筛选</span>
</div>
<div>
<div class="flex"> <div class="flex">
<div> <div>
<el-input placeholder="请输入练习名称" prefix-icon="el-icon-search" v-model="keyword" clearable></el-input> <el-input placeholder="请输入练习名称" prefix-icon="el-icon-search" v-model="keyword" clearable></el-input>
</div> </div>
</div> </div>
</div> </div>
</div>
</el-card> </el-card>
<el-card shadow="hover"> <el-card shadow="hover">

@ -2,32 +2,25 @@
<div> <div>
<el-card shadow="hover" class="m-b-20"> <el-card shadow="hover" class="m-b-20">
<div> <div>
<div class="flex a-center m-b-20"> <div class="p-title m-b-20">筛选</div>
<p class="hr_tag"></p>
<span>筛选</span>
</div>
<div>
<div class="flex"> <div class="flex">
<div> <div>
<el-input placeholder="请输入练习名称" prefix-icon="el-icon-search" v-model="keyword" clearable></el-input> <el-input placeholder="请输入练习名称" prefix-icon="el-icon-search" v-model="keyword" clearable></el-input>
</div> </div>
</div> </div>
</div> </div>
</div>
</el-card> </el-card>
<el-card shadow="hover"> <el-card shadow="hover">
<div class="flex-end-content m-b-20"> <div class="m-b-20">
<div>
<el-button <el-button
type="primary" type="primary"
size="small" size="small"
round round
class="bt_one"
@click="practice" @click="practice"
>进入随机练习</el-button> >进入随机练习</el-button>
</div> </div>
</div>
<el-table :data="listData" class="table" stripe header-align="center" @selection-change="handleSelectionChange" row-key="id"> <el-table :data="listData" class="table" stripe header-align="center" @selection-change="handleSelectionChange" row-key="id">
<el-table-column type="index" width="100" label="序号" align="center"> <el-table-column type="index" width="100" label="序号" align="center">
<template slot-scope="scope"> <template slot-scope="scope">

@ -53,23 +53,26 @@
<span class="index">{{index+1}}.</span> <span class="index">{{index+1}}.</span>
<div class="name" :class="'stem' + k + index" v-html="item.questionStem"></div> <div class="name" :class="'stem' + k + index" v-html="item.questionStem"></div>
</div> </div>
<div class="media" :id="item.mediaEleId"></div>
<div class="options"> <div class="options">
<template v-if="item.name == '单项选择' || item.name == '判断题'"> <template v-if="item.name == '单项选择' || item.name == '判断题'">
<div class="option" v-for="(option,i) in item.options" :key="i"> <div class="option">
<el-radio v-model="item.val" :label="i"> <el-radio-group v-model="item.val" @change.once="updateProgress">
<el-radio v-for="(option,i) in item.options" :key="i" :label="i">
{{i}}.{{item.options[i]}} {{i}}.{{item.options[i]}}
</el-radio> </el-radio>
</el-radio-group>
</div> </div>
</template> </template>
<template v-if="item.name == '多项选择'"> <template v-if="item.name == '多项选择'">
<el-checkbox-group v-model="item.val"> <el-checkbox-group v-model="item.val" @change="updateProgress">
<el-checkbox class="option-check" :label="i" v-for="(option,i) in item.options" :key="i"> <el-checkbox class="option-check" :label="i" v-for="(option,i) in item.options" :key="i">
{{i}}.{{item.options[i]}} {{i}}.{{item.options[i]}}
</el-checkbox> </el-checkbox>
</el-checkbox-group> </el-checkbox-group>
</template> </template>
<template v-if="item.name == '简答题'"> <template v-if="item.name == '简答题'">
<el-input type="textarea" rows="5" v-model="item.val"></el-input> <el-input type="textarea" rows="5" v-model="item.val" @input="updateProgress"></el-input>
</template> </template>
</div> </div>
</div> </div>
@ -107,7 +110,6 @@ export default {
briefAnswerScore: 0, briefAnswerScore: 0,
scoreList: [], scoreList: [],
questionType: ['单选题','多选题','判断题','填空题','简答题'], questionType: ['单选题','多选题','判断题','填空题','简答题'],
progress: 0,
}; };
}, },
computed: { computed: {
@ -116,6 +118,7 @@ export default {
]) ])
}, },
mounted() { mounted() {
this.insertScript()
this.getData() this.getData()
}, },
methods: { methods: {
@ -147,12 +150,19 @@ export default {
this.briefAnswerScore = data.list5.length ? data.list5[0].briefAnswerScore * this.briefAnswerCount : 0 this.briefAnswerScore = data.list5.length ? data.list5[0].briefAnswerScore * this.briefAnswerCount : 0
this.scoreList = [this.singlePoint,this.multipleChoiceScore,this.fillBlanksScore,this.briefAnswerScore,this.briefAnswerScore] this.scoreList = [this.singlePoint,this.multipleChoiceScore,this.fillBlanksScore,this.briefAnswerScore,this.briefAnswerScore]
window.updateProgress = (item) => {
this.updateProgress(item,1)
}
let index = 0
subjects.forEach((e,i) => { subjects.forEach((e,i) => {
e.forEach(n => { e.forEach((n,j) => {
index++
n.mediaEleId = `player${index}`
this.initMedia(n)
if(i == 1){ if(i == 1){
this.$set(n,'val',[]) this.$set(n,'val',[])
}else if(i == 3){ }else if(i == 3){
n.questionStem = n.questionStem.replace(/\(\)\(\)\(\)/g,`<input class="input"></input>`) n.questionStem = n.questionStem.replace(/\(\)\(\)\(\)/g,`<input class="input" data-index="${j}" oninput="updateProgress(this)"></input>`)
}else{ }else{
this.$set(n,'val','') this.$set(n,'val','')
} }
@ -172,6 +182,23 @@ export default {
}).catch(err => {}) }).catch(err => {})
}).catch(err => {}) }).catch(err => {})
}, },
initMedia(item){
if(item.videoAudio && !item.player){
this.$get(`${this.api.getPlayAuth}/${item.videoAudio}`).then(res => {
let playAuth = res.data.playAuth
this.$nextTick(() => {
item.player = new Aliplayer({
id: item.mediaEleId,
width: '100%',
autoplay: false,
vid : item.videoAudio,
playauth : playAuth,
encryptType:1, //
})
})
}).catch(res => {})
}
},
save(){ save(){
let data1 = [] let data1 = []
this.subjects.map((e,i) => { this.subjects.map((e,i) => {
@ -204,150 +231,45 @@ export default {
.catch(err => {}) .catch(err => {})
}) })
.catch(err => {}) .catch(err => {})
},
updateProgress(item,isFillBlank){
let subjects = this.subjects
if(isFillBlank){
let index = item.getAttribute('data-index')
if([...item.parentElement.querySelectorAll('input')].some(n => n.value)){
subjects[3][index].hadAnswer = 1
}else{
subjects[3][index].hadAnswer = 0
}
this.fillBlankAnsweredCount = subjects[3].filter(n => n.hadAnswer).length
}else{
this.singleAnsweredCount = subjects[0].filter(n => n.val).length
this.multipleAnsweredCount = subjects[1].filter(n => n.val.length).length
this.judgeAnsweredCount = subjects[2].filter(n => n.val).length
this.briefAnswerAnsweredCount = subjects[4].filter(n => n.val).length
} }
}, },
insertScript(){
const linkTag = document.createElement('link')
linkTag.id = 'aliplayerLink'
linkTag.rel = 'stylesheet'
linkTag.href = 'https://g.alicdn.com/de/prismplayer/2.8.2/skins/default/aliplayer-min.css'
document.body.appendChild(linkTag)
const scriptTag = document.createElement('script')
scriptTag.id = 'aliplayerScript'
scriptTag.type = 'text/javascript'
scriptTag.src = 'https://g.alicdn.com/de/prismplayer/2.8.2/aliplayer-min.js'
document.body.appendChild(scriptTag)
this.$once('hook:beforeDestroy', function () {
document.body.removeChild(document.querySelector('#aliplayerLink'))
document.body.removeChild(document.querySelector('#aliplayerScript'))
})
},
},
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
$borderColor: #ececec; @import "@/styles/pages/exam.scss";
.box{
display: flex;
justify-content: space-between;
width: 90%;
margin: 0 auto;
.left,.middle,.right{
border: 1px solid $borderColor;
}
.left,.right{
width: 160px;
padding: 10px;
margin-right: 10px;
box-sizing: border-box;
.title{
padding: 10px 0;
font-size: 14px;
color: #444;
text-align: center;
}
.item{
padding: 10px 0;
margin-bottom: 10px;
border-bottom: 1px solid $borderColor;
.type,.total{
color: #444;
font-size: 12px;
}
.total{
margin: 10px 0;
}
.nums{
display: flex;
flex-wrap: wrap;
span{
width: 24px;
margin: 2px 1px;
line-height: 24px;
text-align: center;
color: #888;
font-size: 10px;
box-sizing: border-box;
border: 1px solid #e6e6e6;
border-radius: 50%;
}
.active{
color: #fff;
background-color: #e80909;
border-color: #e80909;
}
}
}
.btn{
margin: 20px 0;
text-align: center;
}
}
.middle{
flex: 1;
margin-right: 10px;
overflow: auto;
.title{
padding: 10px;
margin-bottom: 10px;
font-size: 14px;
color: #444;
border-bottom: 1px solid $borderColor;
}
.ques{
.ques-wrap{
padding: 0 15px;
margin: 10px 0 20px;
}
.item{
margin: 10px 0 20px;
&:first-child{
margin-top: 0;
}
.name-wrap{
display: flex;
align-items: center;
margin-bottom: 10px;
font-size: 13px;
color: #444;
.index{
font-size: 13px;
color: #444;
}
/deep/.input{
width: 100px;
height: 28px;
padding: 0 5px;
margin: 0 5px;
color: #444;
background-color: #fff;
border: 1px solid #ebebeb;
box-sizing: border-box;
&:focus{
outline: none;
}
&:disabled{
background-color: #e8e8e8;
cursor: not-allowed;
}
}
}
.options{
margin-top: 10px;
font-size: 14px;
color: #8b8b8b;
.option{
margin: 5px 0;
&.selected{
font-weight: bold;
color: #555;
}
}
.option-check{
display: block;
margin-right: 6px;
}
/deep/.el-radio__label{
padding-left: 6px;
}
}
}
}
}
.right{
.time,.ans{
font-size: 14px;
color: #444;
text-align: center;
}
.ans{
margin: 20px 0 10px;
font-size: 15px;
}
}
}
</style> </style>

@ -0,0 +1,210 @@
<template>
<div class="box">
<div class="left">
<p class="title">答题卡</p>
<div class="item">
<p class="type">单选题</p>
<p class="total">{{singleCount}}合计{{singlePoint}}</p>
<div class="nums">
<span v-for="n in singleCount" :class="{active: n <= singleAnsweredCount}" :key="n">{{n}}</span>
</div>
</div>
<div class="item">
<p class="type">多选题</p>
<p class="total">{{multipleCount}}合计{{multipleChoiceScore}}</p>
<div class="nums">
<span v-for="n in multipleCount" :class="{active: n <= multipleAnsweredCount}" :key="n">{{n}}</span>
</div>
</div>
<div class="item">
<p class="type">判断题</p>
<p class="total">{{judgeCount}}合计{{judgeScore}}</p>
<div class="nums">
<span v-for="n in judgeCount" :class="{active: n <= judgeAnsweredCount}" :key="n">{{n}}</span>
</div>
</div>
<div class="item">
<p class="type">填空题</p>
<p class="total">{{fillBlankCount}}合计{{fillBlanksScore}}</p>
<div class="nums">
<span v-for="n in fillBlankCount" :class="{active: n <= fillBlankAnsweredCount}" :key="n">{{n}}</span>
</div>
</div>
<div class="item">
<p class="type">简答题</p>
<p class="total">{{briefAnswerCount}}合计{{briefAnswerScore}}</p>
<div class="nums">
<span v-for="n in briefAnswerCount" :class="{active: n <= briefAnswerAnsweredCount}" :key="n">{{n}}</span>
</div>
</div>
<div class="btn">
<el-button size="mini" type="primary" @click="save">提交练习</el-button>
</div>
</div>
<div class="middle">
<div class="ques">
<template v-for="(subject,k) in subjects">
<div class="item" v-if="subject.length" :key="k">
<p v-if="subjects[k].length" class="title">{{questionType[k]}}{{subjects[k].length}}合计{{scoreList[k]}}</p>
<div class="ques-wrap" v-for="(item,index) in subject" :key="index">
<div class="name-wrap">
<span class="index">{{index+1}}.</span>
<div class="name" :class="'stem' + k + index" v-html="item.questionStem"></div>
</div>
<div class="options">
<template v-if="item.name == '单项选择' || item.name == '判断题'">
<div class="option">
<el-radio-group v-model="item.val" @change.once="updateProgress">
<el-radio v-for="(option,i) in item.options" :key="i" :label="i">
{{i}}.{{item.options[i]}}
</el-radio>
</el-radio-group>
</div>
</template>
<template v-if="item.name == '多项选择'">
<el-checkbox-group v-model="item.val" @change="updateProgress">
<el-checkbox class="option-check" :label="i" v-for="(option,i) in item.options" :key="i">
{{i}}.{{item.options[i]}}
</el-checkbox>
</el-checkbox-group>
</template>
<template v-if="item.name == '简答题'">
<el-input type="textarea" rows="5" v-model="item.val" @input="updateProgress"></el-input>
</template>
</div>
</div>
</div>
</template>
</div>
</div>
</div>
</template>
<script>
import { mapState,mapGetters,mapActions } from 'vuex'
import mixins from '@/mixins/setBackground'
import util from '@/libs/util'
export default {
mixins: [ mixins ],
data() {
return {
subjects: [],
singleCount: 0,
multipleCount: 0,
judgeCount: 0,
fillBlankCount: 0,
briefAnswerCount: 0,
singleAnsweredCount: 0,
multipleAnsweredCount: 0,
judgeAnsweredCount: 0,
fillBlankAnsweredCount: 0,
briefAnswerAnsweredCount: 0,
singlePoint: 0,
multipleChoiceScore: 0,
judgeScore: 0,
fillBlanksScore: 0,
briefAnswerScore: 0,
scoreList: [],
questionType: ['单选题','多选题','判断题','填空题','简答题'],
};
},
computed: {
...mapState('user', [
'userId','clientId'
]),
...mapState('wrongBook', [
'qid'
]),
},
beforeDestroy(){
window.updateProgress = null
},
mounted() {
this.getData()
},
methods: {
getData() {
if(this.qid){
this.$post(`${this.api.previewPaper}?qid=${this.qid}`)
.then(res => {
let data = res.data
let subjects = [
[...data.list1],
[...data.list2],
[...data.list4],
[...data.list3],
[...data.list5],
]
this.singleCount = data.list1.length
this.multipleCount = data.list2.length
this.fillBlankCount = data.list3.length
this.judgeCount = data.list4.length
this.briefAnswerCount = data.list5.length
this.singlePoint = data.list1.length ? data.list1[0].singleChoiceScore * this.singleCount : 0
this.multipleChoiceScore = data.list2.length ? data.list2[0].multipleChoiceScore * this.multipleCount : 0
this.judgeScore = data.list4.length ? data.list4[0].judgeScore * this.judgeCount : 0
this.fillBlanksScore = data.list3.length ? data.list3[0].fillBlanksScore * this.fillBlankCount : 0
this.briefAnswerScore = data.list5.length ? data.list5[0].briefAnswerScore * this.briefAnswerCount : 0
this.scoreList = [this.singlePoint,this.multipleChoiceScore,this.fillBlanksScore,this.briefAnswerScore,this.briefAnswerScore]
window.updateProgress = (item) => {
this.updateProgress(item,1)
}
subjects.forEach((e,i) => {
e.forEach((n,j) => {
if(i == 1){
this.$set(n,'val',[])
}else if(i == 3){
n.questionStem = n.questionStem.replace(/\(\)\(\)\(\)/g,`<input class="input" data-index="${j}" oninput="updateProgress(this)"></input>`)
}else{
this.$set(n,'val','')
}
if(!n.options){
let options = {}
for(let i in n){
if(i.includes('option') && n[i]){
options[i.replace('option','')] = n[i]
}
}
n.options = options
}
n.questionStatus = 0
})
})
this.subjects = subjects
}).catch(err => {})
}
},
save(){
this.$message.success('提交成功')
this.$router.back()
},
updateProgress(item,isFillBlank){
let subjects = this.subjects
if(isFillBlank){
let index = item.getAttribute('data-index')
if([...item.parentElement.querySelectorAll('input')].some(n => n.value)){
subjects[3][index].hadAnswer = 1
}else{
subjects[3][index].hadAnswer = 0
}
this.fillBlankAnsweredCount = subjects[3].filter(n => n.hadAnswer).length
}else{
this.singleAnsweredCount = subjects[0].filter(n => n.val).length
this.multipleAnsweredCount = subjects[1].filter(n => n.val.length).length
this.judgeAnsweredCount = subjects[2].filter(n => n.val).length
this.briefAnswerAnsweredCount = subjects[4].filter(n => n.val).length
}
}
},
}
</script>
<style lang="scss" scoped>
@import "@/styles/pages/exam.scss";
</style>

@ -1,159 +1,172 @@
<template> <template>
<div class="box">
<el-card shadow="hover" class="m-b-20">
<div>
<div class="flex a-center m-b-20">
<p class="hr_tag"></p>
<span>筛选</span>
</div>
<div> <div>
<el-row :gutter="20">
<el-col :span="24">
<el-card shadow="hover" class="m-b-20">
<div class="p-title m-b-20">筛选</div>
<div class="flex j-between"> <div class="flex j-between">
<el-form label-width="80px" inline> <el-form label-width="80px" inline>
<el-form-item class="no-mb" label="题库来源"> <el-form-item class="no-mb" label="题库来源">
<el-select v-model="publishStatus" clearable placeholder="请选择题库来源" @change="getData"> <el-select v-model="type" clearable placeholder="请选择题库来源" @change="getName">
<el-option v-for="(item,index) in statusList" :key="index" :label="item.name" :value="item.value"></el-option> <el-option v-for="(item,index) in sourceList" :key="index" :label="item.name" :value="item.id"></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item class="no-mb" label="试卷名称"> <el-form-item class="no-mb" label="试卷名称">
<el-select v-model="publishStatus" clearable placeholder="请选择试卷名称" @change="getData"> <el-select v-model="paperId" clearable placeholder="请选择试卷名称" @change="getData">
<el-option v-for="(item,index) in statusList" :key="index" :label="item.name" :value="item.value"></el-option> <el-option v-for="(item,index) in nameList" :key="index" :label="item.paperName" :value="item.paperId"></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item class="no-mb" label="试题类型"> <el-form-item class="no-mb" label="试题类型">
<el-select v-model="publishStatus" clearable placeholder="请选择试题类型" @change="getData"> <el-select v-model="typeId" clearable placeholder="请选择试题类型" @change="getData">
<el-option v-for="(item,index) in statusList" :key="index" :label="item.name" :value="item.value"></el-option> <el-option label="不限" value=""></el-option>
<el-option v-for="(item,index) in typeList" :key="index" :label="item.name" :value="item.id"></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
</el-form> </el-form>
</div> <div>
<el-input
placeholder="请输入知识点"
prefix-icon="el-icon-search"
v-model="keyword"
clearable
></el-input>
</div> </div>
</div> </div>
</el-card> </el-card>
</el-col>
<el-col :span="24">
<el-card shadow="hover" class="m-b-20">
<div class="m-b-20">
<el-button
type="primary"
size="small"
round
@click="practice"
>错题练习</el-button>
</div>
<el-card shadow="hover"> <el-table
<el-table :data="listData" class="table" ref="table" stripe header-align="center" @selection-change="handleSelectionChange" row-key="id"> :data="listData"
<el-table-column type="selection" width="55" align="center" :reserve-selection="true"></el-table-column> ref="table"
row-key="id"
class="table"
stripe
header-align="center"
@selection-change="handleSelectionChange"
>
<el-table-column
type="selection"
width="55"
align="center"
:reserve-selection="true"
></el-table-column>
<el-table-column type="index" width="100" label="序号" align="center"> <el-table-column type="index" width="100" label="序号" align="center">
<template slot-scope="scope"> <template
{{scope.$index + (page - 1) * pageSize + 1}} slot-scope="scope"
>{{scope.$index + (page - 1) * pageSize + 1}}</template>
</el-table-column>
<el-table-column prop="questionStem" label="错题题干名称" align="center" :show-overflow-tooltip="true"></el-table-column>
<el-table-column label="题目来源" width="120" align="center">
<template>
{{type == 1 ? '考试' : '练习'}}
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="name" label="错题题干名称" align="center"></el-table-column> <el-table-column prop="courses" label="对应课程" width="140" align="center"></el-table-column>
<el-table-column prop="gmtCreate" label="题目来源" align="center"></el-table-column> <el-table-column prop="knowledgePoints" label="对应知识点" width="140" align="center"></el-table-column>
<el-table-column prop="founder" label="题目类型" align="center"></el-table-column> <el-table-column prop="wrongNum" label="错题次数" width="100" align="center"></el-table-column>
<el-table-column prop="classification" label="对应课程" align="center"></el-table-column> <el-table-column label="操作" width="100" align="center">
<el-table-column prop="classification" label="对应知识点" align="center"></el-table-column>
<el-table-column prop="classification" label="错题次数" align="center"></el-table-column>
<el-table-column label="操作" align="center" width="180">
<template slot-scope="scope"> <template slot-scope="scope">
<el-button type="text" @click="show(scope.row)">查看</el-button> <el-button type="text" @click="show(scope.row)">查看</el-button>
<el-button type="text" @click="showError(scope.row)">去纠错</el-button>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
<div class="pagination"> <div class="pagination">
<el-pagination background layout="total, prev, pager, next" :total="total" @current-change="handleCurrentChange" :current-page="page"> <el-pagination
</el-pagination> background
@current-change="handleCurrentChange"
:current-page="page"
:page-size="pageSize"
layout="total,prev, pager, next"
:total="total"
></el-pagination>
</div> </div>
</el-card> </el-card>
</el-col>
</el-row>
<el-dialog title="查看" :visible.sync="showVisible" width="30%" @close="closeShow" :close-on-click-modal="false"> <el-dialog title="错题详情" :visible.sync="detailVisible" width="40%">
<div class="show-wrap"> <div class="ques">
<div class="metas">
<div style="margin-right: 20px;">
<span class="name">序号</span>
<sapn class="val">01</sapn>
</div>
<div>
<span class="name">得分</span>
<sapn class="val">100</sapn>
</div>
</div>
<div class="detail">
<div class="meta"> <div class="meta">
<p class="key">题干</p> <p class="key">题干</p>
<p class="val">测试测试测试测试测试测试测试测试测试测试测试测试测试测试</p> <p class="val" v-html="quesInfo.questionStem"></p>
<div class="media" :id="quesInfo.mediaEleId"></div>
</div> </div>
<div class="meta"> <div class="meta">
<p class="key">选项</p> <p class="key">选项</p>
<div class="val"> <div class="val">
<p>A.抑制性</p> <p v-for="(option,i) in quesInfo.options" :key="i">{{i}}.{{quesInfo.options[i]}}</p>
<p>B.抑制性</p>
<p>C.抑制性</p>
</div> </div>
</div> </div>
<div class="meta ans"> <div class="meta ans">
<div class="info"> <div class="info">
<p class="key">正确答案</p> <p class="key">正确答案</p>
<p class="val">A</p> <p class="val">{{quesInfo.answer}}</p>
</div>
<div class="info">
<p class="key">学生答案</p>
<p class="val">A</p>
</div> </div>
</div> </div>
<div class="meta"> <div class="meta">
<p class="key">答案解析</p> <p class="key">答案解析</p>
<p class="val">测试测试测试测试测试测试测试测试测试测试测试测试测试测试</p> <p class="val" v-html="quesInfo.answerAnalysis"></p>
</div>
</div> </div>
</div> </div>
</el-dialog> </el-dialog>
<el-dialog title="纠错" :visible.sync="errorVisible" width="30%" @close="closeError" :close-on-click-modal="false">
<div class="show-wrap">
<div class="metas">
<div style="margin-right: 20px;">
<span class="name">序号</span>
<sapn class="val">01</sapn>
</div>
<div>
<span class="name">得分</span>
<sapn class="val">100</sapn>
</div>
</div>
<div class="detail">
<div class="meta">
<p class="key">题干</p>
<p class="val">测试测试测试测试测试测试测试测试测试测试测试测试测试测试</p>
</div>
<div class="meta">
<p class="key">选项</p>
<div class="val">
<p>A.抑制性</p>
<p>B.抑制性</p>
<p>C.抑制性</p>
</div>
</div>
</div>
</div>
<span slot="footer" class="dialog-footer">
<el-button @click="errorVisible = false"> </el-button>
<el-button type="primary" @click="classSubmit"> </el-button>
</span>
</el-dialog>
</div> </div>
</template> </template>
<script> <script>
import { mapState,mapActions } from 'vuex'
import util from '@/libs/util'
export default { export default {
data() { data() {
return { return {
schoolId: this.$store.state.schoolId,
keyword: '', keyword: '',
classificationId: '', type: 1,
sourceList: [
{
id: 1,
name: '用于考试'
},{
id: 2,
name: '用于练习'
}
],
paperId: '',
nameList: [],
typeId: '',
typeList: [],
listData: [], listData: [],
multipleSelection: [],
page: 1, page: 1,
pageSize: 10, pageSize: 10,
total: 0, total: 0,
paperName: '',
searchTimer: null, searchTimer: null,
showVisible: false, numVisible: false,
errorVisible: false numList: [],
pageNum: 1,
pageSizeNum: 10,
totalNum: 0,
detailVisible: false,
quesInfo: {}
}; };
}, },
computed: {
...mapState('user', [
'userId','clientId'
]),
},
mounted() {
this.getType()
this.getName()
},
watch: { watch: {
keyword: function(val) { keyword: function(val) {
clearTimeout(this.searchTimer) clearTimeout(this.searchTimer)
@ -162,46 +175,65 @@ export default {
},500) },500)
} }
}, },
mounted() {
this.getData()
},
methods: { methods: {
...mapActions('wrongBook', [
'setInfo'
]),
getData() { getData() {
let data = { this.$post(`${this.api.getMineWrong}?type=${this.type}&pageNum=${this.page}&pageSize=${this.pageSize}&paperId=${this.paperId}&userId=${this.userId}&typeId=${this.typeId}&knowledgePoints=${this.keyword}`)
classificationId: this.classificationId, .then(res => {
name: this.keyword, this.listData = util.removeHtmlTag(res.data.pageUtils.list,'questionStem')
schoolId: this.schoolId this.total = res.data.pageUtils.totalCount
} }).catch(err => {})
this.$get(`${this.api.queryCourseByCondition}/${this.page}/${this.pageSize}`,data).then(res => {
this.listData = res.data.courseList
this.total = res.data.total
}).catch(res => {});
}, },
handleDelete(row) { getName() {
this.$confirm('确定要删除吗?', '提示', { this.$post(`${this.api.getPaperInfo}?type=${this.type}&userId=${this.userId}`)
type: 'warning' .then(res => {
}) this.nameList = res.data.list
.then(() => { if(this.nameList.length){
this.$del(`${this.api.deleteCourse}/${row.id}`).then(res => { this.paperId = this.nameList[0].paperId
this.$message.success('删除成功'); this.getData()
}else{
this.paperId = ''
this.listData = []
}
}).catch(err => {})
},
handleCurrentChange(val) {
this.page = val
this.getData() this.getData()
}).catch(res => {});
})
.catch(() => {});
}, },
handleSelectionChange(val) { handleSelectionChange(val) {
this.multipleSelection = val; this.multipleSelection = val
}, },
handleCurrentChange(val) { getType(){
this.page = val; this.$get(this.api.typesList)
this.getData(); .then(res => {
this.typeList = res.data.list
}).catch(err => {})
}, },
show(row){ show(row){
this.showVisible = true this.detailVisible = true
}, this.$post(`${this.api.questionInfo}?qid=${row.questionId}`)
showError(row){ .then(res => {
this.errorVisible = true let info = res.data.list
let options = {}
for(let i in info){
if(i.includes('option') && info[i]){
options[i.replace('option','')] = info[i]
}
}
info.options = options
this.quesInfo = info
}).catch(err => {})
}, },
practice(){
let qid = this.listData.map(n => n.questionId).join()
this.setInfo({
qid
})
this.$router.push('do')
}
} }
}; };
</script> </script>
@ -210,21 +242,31 @@ export default {
/deep/.no-mb.el-form-item{ /deep/.no-mb.el-form-item{
margin-bottom: 0; margin-bottom: 0;
} }
.show-wrap{ .ques{
.metas{ .key{
display: flex; font-weight: bold;
justify-content: center; color: #333;
margin: 0 0 30px; font-size: 14px;
.name{
font-size: 12px;
color: #717171;
} }
.val{ .val{
line-height: 1.6;
color: #757575;
font-size: 14px;
}
.answer{
display: flex;
align-items: center;
padding: 15px;
margin: 15px 0;
font-size: 12px; font-size: 12px;
color: #929292; border: 1px solid #e8e8e8;
background-color: #f3f2f2;
.info{
display: inline-flex;
align-items: center;
margin-right: 30px;
} }
} }
.detail{
.meta{ .meta{
padding-left: 10px; padding-left: 10px;
margin: 20px 0; margin: 20px 0;
@ -239,8 +281,9 @@ export default {
.key{ .key{
margin-bottom: 5px; margin-bottom: 5px;
} }
.media{
margin-top: 10px;
} }
} }
} }
</style> </style>

@ -0,0 +1,23 @@
import BasicLayout from '@/layouts/home';
const meta = {};
const pre = 'index-';
export default {
path: '/index',
name: 'index',
redirect: {
name: `${pre}list`
},
meta,
component: BasicLayout,
children: [
{
name: `${pre}list`,
path: `list`,
component: () => import('@/pages/index/list'),
meta: { title: '首页' }
},
]
};

@ -0,0 +1,23 @@
import BasicLayout from '@/layouts/home';
const meta = {};
const pre = 'messageBoard-';
export default {
path: '/messageBoard',
name: 'messageBoard',
redirect: {
name: `${pre}list`
},
meta,
component: BasicLayout,
children: [
{
name: `${pre}list`,
path: `list`,
component: () => import('@/pages/messageBoard/list'),
meta: { title: '交流互动' }
},
]
};

@ -2,11 +2,11 @@ import BasicLayout from '@/layouts/home';
const meta = {}; const meta = {};
const pre = 'index-'; const pre = 'practice-';
export default { export default {
path: '/index', path: '/practice',
name: 'index', name: 'practice',
redirect: { redirect: {
name: `${pre}list` name: `${pre}list`
}, },

@ -18,6 +18,11 @@ export default {
path: `list`, path: `list`,
component: () => import('@/pages/wrongBook/list'), component: () => import('@/pages/wrongBook/list'),
meta: { title: '我的错题本' } meta: { title: '我的错题本' }
},{
name: `${pre}do`,
path: `do`,
component: () => import('@/pages/wrongBook/do'),
meta: { title: '错题练习' }
}, },
] ]
}; };

@ -1,8 +1,10 @@
import index from './modules/index';
import practice from './modules/practice'; import practice from './modules/practice';
import exam from './modules/exam'; import exam from './modules/exam';
import achievement from './modules/achievement'; import achievement from './modules/achievement';
import wrongBook from './modules/wrongBook'; import wrongBook from './modules/wrongBook';
import setting from './modules/setting'; import setting from './modules/setting';
import messageBoard from './modules/messageBoard';
import BasicLayout from '@/layouts/home'; import BasicLayout from '@/layouts/home';
@ -17,11 +19,13 @@ const frameIn = [
meta: { title: '首页' }, meta: { title: '首页' },
children: [] children: []
}, },
index,
practice, practice,
exam, exam,
achievement, achievement,
wrongBook, wrongBook,
setting, setting,
messageBoard
] ]
/** /**

@ -53,7 +53,7 @@ const Setting = {
menuSideWidth: 256, menuSideWidth: 256,
layout: { layout: {
// 需要隐藏顶栏的页面路径 // 需要隐藏顶栏的页面路径
hideNavList: ['index-do','index-randomDo','setting-person','achievement-detail','achievement-practice','exam-do','exam-detail'], hideNavList: ['practice-do','practice-randomDo','setting-person','achievement-detail','achievement-practice','exam-do','exam-detail','wrongBook-do'],
// 侧边栏风格,可选值为 dark 或 light // 侧边栏风格,可选值为 dark 或 light
siderTheme: 'dark', siderTheme: 'dark',
// 顶栏风格,可选值为 light、dark 或 primary // 顶栏风格,可选值为 light、dark 或 primary

@ -0,0 +1,22 @@
/**
* 我的错题本
* */
export default {
namespaced: true,
state: {
qid: ''
},
getters: {
},
mutations: {
SET_INFO: (state, info) => {
state.qid = info.qid
},
},
actions: {
setInfo({ commit },info) {
commit('SET_INFO',info)
},
}
}

@ -60,25 +60,17 @@
margin-right: 5px; margin-right: 5px;
color: #F56C6C; color: #F56C6C;
} }
.hr_tag{ .p-title{
background-color: $--color-primary; display: flex;
align-items: center;
&:before{
content: '';
display: inline-block;
width: 3px; width: 3px;
height: 15px; height: 15px;
margin-right: 5px; margin-right: 5px;
} background-color: $--color-primary;
}
.per_title span{
font-size: 16px;
font-weight: bold;
}
.per_back{
margin-left: 5px;
}
.per_school{
margin-left: 30px;
}
.per_title:hover{
cursor:pointer;
} }
[v-cloak] { [v-cloak] {

@ -0,0 +1,147 @@
$borderColor: #ececec;
.box{
display: flex;
justify-content: space-between;
width: 90%;
margin: 0 auto;
.left,.middle,.right{
border: 1px solid $borderColor;
}
.left,.right{
width: 160px;
padding: 10px;
margin-right: 10px;
box-sizing: border-box;
.title{
padding: 10px 0;
font-size: 14px;
color: #444;
text-align: center;
}
.item{
padding: 10px 0;
margin-bottom: 10px;
border-bottom: 1px solid $borderColor;
.type,.total{
color: #444;
font-size: 12px;
}
.total{
margin: 10px 0;
}
.nums{
display: flex;
flex-wrap: wrap;
span{
width: 24px;
margin: 2px 1px;
line-height: 24px;
text-align: center;
color: #888;
font-size: 10px;
box-sizing: border-box;
border: 1px solid #e6e6e6;
border-radius: 50%;
}
.active{
color: #fff;
background-color: #e80909;
border-color: #e80909;
}
}
}
.btn{
margin: 20px 0;
text-align: center;
}
}
.middle{
flex: 1;
margin-right: 10px;
overflow: auto;
.title{
padding: 10px;
margin-bottom: 10px;
font-size: 14px;
color: #444;
border-bottom: 1px solid $borderColor;
}
.ques{
.ques-wrap{
padding: 0 15px;
margin: 10px 0 20px;
}
.item{
margin: 10px 0 20px;
&:first-child{
margin-top: 0;
}
.name-wrap{
display: flex;
align-items: center;
margin-bottom: 10px;
font-size: 13px;
color: #444;
.index{
font-size: 13px;
color: #444;
}
/deep/.input{
width: 100px;
height: 28px;
padding: 0 5px;
margin: 0 5px;
color: #444;
background-color: #fff;
border: 1px solid #ebebeb;
box-sizing: border-box;
&:focus{
outline: none;
}
&:disabled{
background-color: #e8e8e8;
cursor: not-allowed;
}
}
}
.options{
margin-top: 10px;
font-size: 14px;
color: #8b8b8b;
.option{
margin: 5px 0;
&.selected{
font-weight: bold;
color: #555;
}
.el-radio-group{
display: flex;
flex-direction: column;
.el-radio{
margin: 3px 0;
}
}
}
.option-check{
display: block;
margin-right: 6px;
}
/deep/.el-radio__label{
padding-left: 6px;
}
}
}
}
}
.right{
.time,.ans{
font-size: 14px;
color: #444;
text-align: center;
}
.ans{
margin: 20px 0 10px;
font-size: 15px;
}
}
}

@ -0,0 +1,85 @@
.list{
li{
padding-bottom: 10px;
border-top: 1px solid #f1f1f1;
&:first-child{
border-top: 0;
}
.inner{
position: relative;
display: flex;
justify-content: space-between;
padding: 10px 0 20px;
.avatar{
width: 40px;
height: 40px;
border-radius: 50%;
}
.texts{
flex: 1;
margin-left: 10px;
.title{
margin-bottom: 5px;
font-size: 14px;
.username{
color: $main-color;
}
.publish{
margin: 0 5px;
color: #d6d6d6;
}
.date{
color: #b5b5b5;
}
}
}
.right{
.index{
font-size: 12px;
color: #ccc;
}
}
}
.action{
text-align: right;
.btn{
padding: 2px 4px;
color: $main-color;
font-size: 12px;
background-color: #fff;
border: 1px solid;
border-radius: 4px;
cursor: pointer;
&:hover{
opacity: .8;
}
&:first-child{
margin-right: 5px;
}
}
}
.reply{
margin-top: 20px;
}
}
&.children{
padding: 0 10px 10px;
margin: 10px 0 0 30px;
background-color: #f3f4f6;
li{
border-top-color: #fff;
}
}
}
.toggle{
margin: 10px 0;
text-align: center;
color: $main-color;
font-size: 12px;
span{
cursor: pointer;
}
}
/deep/.quill{
background-color: #fff;
}

@ -1,3 +1,5 @@
@import "../default/index.scss";
$insideColor: rgba(245, 242, 255, 0.8); //内部节点的边框颜色 $insideColor: rgba(245, 242, 255, 0.8); //内部节点的边框颜色
$outColor: rgba(255, 255, 255, 0.8); //外部节点的边框颜色 $outColor: rgba(255, 255, 255, 0.8); //外部节点的边框颜色
//混合代码,提取item共同样式 //混合代码,提取item共同样式
@ -59,7 +61,7 @@ $outColor: rgba(255, 255, 255, 0.8); //外部节点的边框颜色
margin-left:95px margin-left:95px
} }
.item2:hover{ .item2:hover{
color: #cb221c; color: $--color-primary;
} }
.edit{ .edit{
display: inline-block; display: inline-block;

Loading…
Cancel
Save