yujialong 4 years ago
parent 22a1da2c6a
commit 97d2f4fb4a
  1. 2
      src/api/index.js
  2. 124
      src/components/pdf/index.vue
  3. 5
      src/libs/util.js
  4. 57
      src/mixins/examDo/index.js
  5. 34
      src/pages/achievement/assessment/index.vue
  6. 32
      src/pages/achievement/practice/index.vue
  7. 34
      src/pages/exam/detail/index.vue
  8. 29
      src/pages/exam/do/index.vue
  9. 1
      src/pages/exam/list/index.vue
  10. 42
      src/pages/practice/do/index.vue
  11. 11
      src/setting.js
  12. 8
      src/store/modules/exam.js
  13. 2
      src/store/modules/practice.js
  14. 3
      src/styles/pages/exam.scss

@ -1,5 +1,5 @@
import Setting from '@/setting' import Setting from '@/setting'
let uploadURL = Setting.apiUploadURL let uploadURL = Setting.upload.apiURL
export default { export default {
// 登录注册 // 登录注册

@ -0,0 +1,124 @@
<template>
<div>
<el-dialog
custom-class="pdf-dia"
:close-on-click-modal="false"
:visible.sync="visible"
@close="closePdf"
:fullscreen="true"
:modal="false"
:append-to-body="true">
<div>
<button type="button" aria-label="Close" class="el-dialog__headerbtn" @click="closePdf"><i class="el-dialog__close el-icon el-icon-close"></i></button>
<div class="pdf">
<p class="arrow">
<span @click="changePdfPage(0)" class="turn el-icon-arrow-left" :class="{grey: currentPage==1}"></span>
{{currentPage}} / {{pageCount}}
<span @click="changePdfPage(1)" class="turn el-icon-arrow-right" :class="{grey: currentPage==pageCount}"></span>
</p>
<pdf
class="pdf-wrap"
:src="src"
:page="currentPage"
@num-pages="pageCount=$event"
@page-loaded="currentPage=$event"
@loaded="loadPdfHandler"
>
</pdf>
</div>
</div>
</el-dialog>
</div>
</template>
<script>
import pdf from "vue-pdf";
export default {
props: ['visible','src'],
data() {
return {
pdfVisible: false,
pdfSrc: '',
currentPage: 0,
pageCount: 0,
fileType: 'pdf',
};
},
components: { pdf },
mounted(){
this.addEvent()
},
methods: {
closePdf(){
this.$emit('update:visible',false)
this.$emit('update:src','')
this.currentPage = 1
},
changePdfPage (val) {
if (val === 0 && this.currentPage > 1) {
this.currentPage--
}
if (val === 1 && this.currentPage < this.pageCount) {
this.currentPage++
}
},
loadPdfHandler (e) {
this.currentPage = 1
},
addEvent(){
document.onkeydown = e => {
let key = window.event.keyCode
if(key == 37){
this.changePdfPage(0)
}else if(key == 39){
this.changePdfPage(1)
}
}
this.$once('hook:beforeDestroy',() => {
document.onkeydown = null
})
}
}
};
</script>
<style lang="scss" scoped>
/deep/.pdf-dia{
border-radius: 0 !important;
.el-dialog__header{
display: none;
}
.el-dialog__body{
padding: 0;
}
.el-dialog__headerbtn{
top: 10px;
.el-dialog__close{
color: #fff;
font-size: 16px;
}
}
.pdf{
.arrow{
display: flex;
justify-content: center;
align-items: center;
width: 100%;
padding: 10px 0;
font-size: 16px;
color: #fff;
background-color: #333;
.turn{
margin: 0 10px;
font-size: 18px;
cursor: pointer;
}
}
.pdf-wrap{
height: calc(100vh - 45px);
margin: 0 auto;
overflow: auto;
}
}
}
</style>

@ -73,6 +73,11 @@ const util = {
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
}, },
// 传入文件后缀判断是否是pdf以外的文档
isDoc(ext) {
if(!util.isVideo(ext) && !util.isAudio(ext) && !util.isImg(ext) && ext != 'pdf') return true
return false
},
// 循环去除html标签 // 循环去除html标签
removeHtmlTag(list,attr) { removeHtmlTag(list,attr) {
list.map(n => { list.map(n => {

@ -1,4 +1,11 @@
import Setting from '@/setting'
import util from '@/libs/util'
export default { export default {
data() {
return {
maxSize: Setting.upload.maxSize
}
},
mounted() { mounted() {
this.insertScript() this.insertScript()
}, },
@ -56,5 +63,55 @@ export default {
document.body.removeChild(document.querySelector('#aliplayerScript')) document.body.removeChild(document.querySelector('#aliplayerScript'))
}) })
}, },
handleExceed(files, fileList) {
this.$message.warning(
`当前限制选择 1 个文件,如需更换,请删除上一个文件再重新选择!`
)
},
beforeUpload(file,item){
if(util.isDoc(file.name.substring(file.name.lastIndexOf('.') + 1)) && (file.size / 1024 / 1024) > this.maxSize){
this.$message.error(`请上传${this.maxSize}M以内的文件`)
return false
}
item.fileName = file.name
console.log('上传前:',item,file)
},
uploadSuccess(res, file, fileList, item) {
console.log('上传成功:',res, file, fileList, item)
let ext = file.response.data.filesResult.fileType
item.fileExt = ext
if(util.isVideo(ext)){
item.video = res.data.filesResult.fileId
}else{
item.fileUrl = res.data.filesResult.fileUrl
}
console.log('上传成功:',item)
},
uploadError(err, file, fileList) {
this.$message({
message: "上传出错,请重试!",
type: "error",
center: true
})
},
beforeRemove(file, fileList) {
return this.$confirm(`确定移除 ${file.name}`)
},
handleRemove(file, fileList, item) {
console.log('删除:',item)
if(util.isVideo(item.fileExt)){
this.$del(`${this.api.removeVideo}/${item.video}`).then(res => {
item.video = ''
}).catch(res => {})
}else{
console.log('删除前:',item.fileUrl)
let fileName = item.fileUrl.replace('https://cj-oss.oss-cn-guangzhou.aliyuncs.com/','')
console.log('删除前:',fileName)
this.$del(`${this.api.fileDeletion}?keys=${fileName}`).then(res => {
item.fileUrl = ''
}).catch(res => {})
}
},
} }
} }

@ -21,9 +21,9 @@
</div> </div>
<ul class="tab"> <ul class="tab">
<!-- <template v-for="(item,index) in tabs"> --> <template v-for="(item,index) in tabs">
<li v-for="(item,index) in tabs" :key="index" :class="{active: active == item.id}" @click="tabChange(item.id)">{{item.name}}</li> <li v-if="item.show" :key="index" :class="{active: active == item.id}" @click="tabChange(item.id)">{{item.name}}</li>
<!-- </template> --> </template>
</ul> </ul>
<div class="wrap"> <div class="wrap">
@ -81,23 +81,23 @@ export default {
{ {
id: 1, id: 1,
name: '单选题', name: '单选题',
show: true show: false
},{ },{
id: 2, id: 2,
name: '多选题', name: '多选题',
show: true show: false
},{ },{
id: 3, id: 3,
name: '判断题', name: '判断题',
show: true show: false
},{ },{
id: 4, id: 4,
name: '简答题', name: '简答题',
show: true show: false
},{ },{
id: 5, id: 5,
name: '填空题', name: '填空题',
show: true show: false
} }
], ],
active: 1, active: 1,
@ -124,12 +124,18 @@ export default {
this.ranking = res.ranking this.ranking = res.ranking
this.allData = res.data this.allData = res.data
let tabs = this.tabs let tabs = this.tabs
res.data.list1.length || (tabs[0].show = false) res.data.list1.length && (tabs[0].show = true)
res.data.list2.length || (tabs[1].show = false) res.data.list2.length && (tabs[1].show = true)
res.data.list3.length || (tabs[2].show = false) res.data.list3.length && (tabs[2].show = true)
res.data.list4.length || (tabs[3].show = false) res.data.list4.length && (tabs[3].show = true)
res.data.list5.length || (tabs[4].show = false) res.data.list5.length && (tabs[4].show = true)
this.curType = this.allData.list1 for(let n of tabs){
if(n.show){
this.active = n.id
this.curType = this.allData[`list${n.id}`]
break
}
}
this.handleOptions() this.handleOptions()
}) })
.catch(err => {}) .catch(err => {})

@ -17,9 +17,9 @@
</div> </div>
<ul class="tab"> <ul class="tab">
<!-- <template v-for="(item,index) in tabs"> --> <template v-for="(item,index) in tabs">
<li v-for="(item,index) in tabs" :key="index" :class="{active: active == item.id}" @click="tabChange(item.id)">{{item.name}}</li> <li v-if="item.show" :key="index" :class="{active: active == item.id}" @click="tabChange(item.id)">{{item.name}}</li>
<!-- </template> --> </template>
</ul> </ul>
<div class="wrap"> <div class="wrap">
@ -77,23 +77,23 @@ export default {
{ {
id: 1, id: 1,
name: '单选题', name: '单选题',
show: true show: false
},{ },{
id: 2, id: 2,
name: '多选题', name: '多选题',
show: true show: false
},{ },{
id: 3, id: 3,
name: '判断题', name: '判断题',
show: true show: false
},{ },{
id: 4, id: 4,
name: '简答题', name: '简答题',
show: true show: false
},{ },{
id: 5, id: 5,
name: '填空题', name: '填空题',
show: true show: false
} }
], ],
typeNameList: ['单项选择','多项选择','判断题','简答题','填空题'], typeNameList: ['单项选择','多项选择','判断题','简答题','填空题'],
@ -132,11 +132,17 @@ export default {
}) })
this.list = data.list this.list = data.list
let tabs = this.tabs let tabs = this.tabs
data.list.find(n => n.typeName == '单项选择') || (tabs[0].show = false) data.list.find(n => n.typeName == '单项选择') && (tabs[0].show = true)
data.list.find(n => n.typeName == '多项选择') || (tabs[1].show = false) data.list.find(n => n.typeName == '多项选择') && (tabs[1].show = true)
data.list.find(n => n.typeName == '判断题') || (tabs[2].show = false) data.list.find(n => n.typeName == '判断题') && (tabs[2].show = true)
data.list.find(n => n.typeName == '简答题') || (tabs[3].show = false) data.list.find(n => n.typeName == '简答题') && (tabs[3].show = true)
data.list.find(n => n.typeName == '填空题') || (tabs[4].show = false) data.list.find(n => n.typeName == '填空题') && (tabs[4].show = true)
for(let n of tabs){
if(n.show){
this.active = n.id
break
}
}
this.handleOptions() this.handleOptions()
this.paperName = data.paperName this.paperName = data.paperName
this.userName = data.stuName this.userName = data.stuName

@ -17,9 +17,9 @@
</div> </div>
<ul class="tab"> <ul class="tab">
<!-- <template v-for="(item,index) in tabs"> --> <template v-for="(item,index) in tabs">
<li v-for="(item,index) in tabs" :key="index" :class="{active: active == item.id}" @click="tabChange(item.id)">{{item.name}}</li> <li v-if="item.show" :key="index" :class="{active: active == item.id}" @click="tabChange(item.id)">{{item.name}}</li>
<!-- </template> --> </template>
</ul> </ul>
<div class="wrap"> <div class="wrap">
@ -77,23 +77,23 @@ export default {
{ {
id: 1, id: 1,
name: '单选题', name: '单选题',
show: true show: false
},{ },{
id: 2, id: 2,
name: '多选题', name: '多选题',
show: true show: false
},{ },{
id: 3, id: 3,
name: '判断题', name: '判断题',
show: true show: false
},{ },{
id: 4, id: 4,
name: '简答题', name: '简答题',
show: true show: false
},{ },{
id: 5, id: 5,
name: '填空题', name: '填空题',
show: true show: false
} }
], ],
active: 1, active: 1,
@ -120,12 +120,18 @@ export default {
this.time = res.time this.time = res.time
this.allData = res.data this.allData = res.data
let tabs = this.tabs let tabs = this.tabs
res.data.list1.length || (tabs[0].show = false) res.data.list1.length && (tabs[0].show = true)
res.data.list2.length || (tabs[1].show = false) res.data.list2.length && (tabs[1].show = true)
res.data.list3.length || (tabs[2].show = false) res.data.list3.length && (tabs[2].show = true)
res.data.list4.length || (tabs[3].show = false) res.data.list4.length && (tabs[3].show = true)
res.data.list5.length || (tabs[4].show = false) res.data.list5.length && (tabs[4].show = true)
this.curType = this.allData.list1 for(let n of tabs){
if(n.show){
this.active = n.id
this.curType = this.allData[`list${n.id}`]
break
}
}
this.handleOptions() this.handleOptions()
}).catch(err => {}) }).catch(err => {})
}, },

@ -72,6 +72,19 @@
</el-checkbox-group> </el-checkbox-group>
</template> </template>
<template v-if="item.typeId == 4"> <template v-if="item.typeId == 4">
<el-upload
class="upload"
:before-upload="file => beforeUpload(file,item)"
:on-remove="(file, fileList) => handleRemove(file, fileList, item)"
:on-error="uploadError"
:on-success="(res, file, fileList) => uploadSuccess(res, file, fileList, item)"
:before-remove="beforeRemove"
:limit="1"
:on-exceed="handleExceed"
:action="api.fileupload"
>
<el-button type="primary" class="ml20">上传文件</el-button>
</el-upload>
<el-input type="textarea" rows="5" v-model="item.val" @input="updateProgress"></el-input> <el-input type="textarea" rows="5" v-model="item.val" @input="updateProgress"></el-input>
</template> </template>
</div> </div>
@ -165,7 +178,7 @@ export default {
mounted() { mounted() {
this.getData() this.getData()
this.addLeaveEvent() this.addLeaveEvent()
this.queryState() // this.queryState()
}, },
beforeDestroy(){ beforeDestroy(){
clearInterval(this.timer) clearInterval(this.timer)
@ -313,14 +326,22 @@ export default {
}else{ }else{
userAnswer = n.val userAnswer = n.val
} }
if(userAnswer){ if(userAnswer || n.fileUrl || n.video){
data1.push({ if(n.fileUrl){
n.fileUrl = n.fileName + ',' + n.fileUrl
}
if(n.video){
n.video = n.fileName + ',' + n.video
}
data1.push({
assessmentId: this.assessmentId, assessmentId: this.assessmentId,
questionId: n.id, questionId: n.id,
questionStatus : n.questionStatus, questionStatus : n.questionStatus,
testPaperId: this.testPaperId, testPaperId: this.testPaperId,
userAnswer, userAnswer,
userId: this.userId userId: this.userId,
fileUrl: n.fileUrl,
videoAudio: n.video
}) })
} }
}) })

@ -57,6 +57,7 @@
<!-- 学生考试状态:考试状态 state: (0未考 1在考 2已考) <!-- 学生考试状态:考试状态 state: (0未考 1在考 2已考)
考核状态: state: 考核状态(1待开始 2进行中 3已结束) --> 考核状态: state: 考核状态(1待开始 2进行中 3已结束) -->
<el-button type="text" @click="toExam(scope.row)" v-if="scope.row.assessmentState == 2" :disabled="scope.row.state == 2">进入考试</el-button> <el-button type="text" @click="toExam(scope.row)" v-if="scope.row.assessmentState == 2" :disabled="scope.row.state == 2">进入考试</el-button>
<!-- <el-button type="text" @click="toExam(scope.row)">进入考试</el-button> -->
<!-- <el-button type="text" @click="query(scope.row)" v-if="scope.row.state == 2">成绩查询</el-button> --> <!-- <el-button type="text" @click="query(scope.row)" v-if="scope.row.state == 2">成绩查询</el-button> -->
</template> </template>
</el-table-column> </el-table-column>

@ -72,6 +72,19 @@
</el-checkbox-group> </el-checkbox-group>
</template> </template>
<template v-if="item.name == '简答题'"> <template v-if="item.name == '简答题'">
<el-upload
class="upload"
:before-upload="file => beforeUpload(file,item)"
:on-remove="(file, fileList) => handleRemove(file, fileList, item)"
:on-error="uploadError"
:on-success="(res, file, fileList) => uploadSuccess(res, file, fileList, item)"
:before-remove="beforeRemove"
:limit="1"
:on-exceed="handleExceed"
:action="api.fileupload"
>
<el-button type="primary" class="ml20">上传文件</el-button>
</el-upload>
<el-input type="textarea" rows="5" v-model="item.val" @input="updateProgress"></el-input> <el-input type="textarea" rows="5" v-model="item.val" @input="updateProgress"></el-input>
</template> </template>
</div> </div>
@ -92,7 +105,6 @@ import { mapState,mapGetters,mapActions } from 'vuex'
import setBackground from '@/mixins/setBackground' import setBackground from '@/mixins/setBackground'
import examDo from '@/mixins/examDo' import examDo from '@/mixins/examDo'
import util from '@/libs/util' import util from '@/libs/util'
export default { export default {
mixins: [ setBackground,examDo ], mixins: [ setBackground,examDo ],
data() { data() {
@ -271,15 +283,25 @@ export default {
}else{ }else{
userAnswer = n.val userAnswer = n.val
} }
data1.push({ if(userAnswer || n.fileUrl || n.video){
identification: this.identification, if(n.fileUrl){
practiseId: this.practiseId, n.fileUrl = n.fileName + ',' + n.fileUrl
questionId: n.questionId, }
questionStatus : n.questionStatus, if(n.video){
testPaperId: this.paperId, n.video = n.fileName + ',' + n.video
userAnswer, }
userId: this.userId data1.push({
}) identification: this.identification,
practiseId: this.practiseId,
questionId: n.questionId,
questionStatus : n.questionStatus,
testPaperId: this.paperId,
userAnswer,
userId: this.userId,
fileUrl: n.fileUrl,
videoAudio: n.video
})
}
}) })
}) })

@ -16,9 +16,7 @@ const Setting = {
showProgressBar: true, showProgressBar: true,
// 接口请求地址 // 接口请求地址
// apiBaseURL: env === 'development' ? 'http://192.168.31.152:8001' : 'http://39.108.250.202:8000', // apiBaseURL: env === 'development' ? 'http://192.168.31.152:8001' : 'http://39.108.250.202:8000',
apiBaseURL: env === 'development' ? 'http://39.108.250.202:9000' : 'http://39.108.250.202:9000', apiBaseURL: env === 'development' ? 'http://192.168.31.152:8001' : 'http://39.108.250.202:9000',
// oss文件管理接口地址
apiUploadURL: 'http://8.134.8.197:8001',
// 接口请求返回错误时,弹窗的持续时间,单位:秒 // 接口请求返回错误时,弹窗的持续时间,单位:秒
modalDuration: 3, modalDuration: 3,
// 接口请求返回错误时,弹窗的类型,可选值为 Message 或 Notice // 接口请求返回错误时,弹窗的类型,可选值为 Message 或 Notice
@ -59,7 +57,12 @@ const Setting = {
// 相同路由,不同参数间进行切换,是否强力更新 // 相同路由,不同参数间进行切换,是否强力更新
sameRouteForceUpdate: false, sameRouteForceUpdate: false,
// 是否使用动态路由 // 是否使用动态路由
dynamicRoute: false dynamicRoute: false,
// 文件上传
upload: {
apiURL: 'http://8.134.8.197:8001',
maxSize: 30,
},
}; };
export default Setting; export default Setting;

@ -65,16 +65,16 @@ export default {
}, },
getters: { getters: {
getDegreeName: state => id => { getDegreeName: state => id => {
return state.degreeList.find(n => n.id == id).label return id != null ? state.degreeList.find(n => n.id == id).label : ''
}, },
getTypeName: state => id => { getTypeName: state => id => {
return state.typeList.find(n => n.id == id).name return id != null ? state.typeList.find(n => n.id == id).name : ''
}, },
getStateName: state => id => { getStateName: state => id => {
return state.stateList.find(n => n.id == id).name return id != null ? state.stateList.find(n => n.id == id).name : ''
}, },
getAssessmentStateName: state => id => { getAssessmentStateName: state => id => {
return state.assessmentStateList.find(n => n.id == id).name return id != null ? state.assessmentStateList.find(n => n.id == id).name : ''
}, },
}, },
mutations: { mutations: {

@ -26,7 +26,7 @@ export default {
}, },
getters: { getters: {
getDegreeName: state => id => { getDegreeName: state => id => {
return state.degreeList.find(n => n.id == id).label return id != null ? state.degreeList.find(n => n.id == id).label : ''
} }
}, },
mutations: { mutations: {

@ -129,6 +129,9 @@ $borderColor: #ececec;
/deep/.el-radio__label{ /deep/.el-radio__label{
padding-left: 6px; padding-left: 6px;
} }
.upload{
margin: 20px 0 10px;
}
} }
} }
} }

Loading…
Cancel
Save