yujialong 4 years ago
parent 0c602151a6
commit b1d31b8c32
  1. 62
      src/api/index.js
  2. BIN
      src/assets/img/login_bg.png
  3. 80
      src/components/testPaperDetail/index.vue
  4. 145
      src/layouts/header/index.vue
  5. 14
      src/layouts/navbar/index.vue
  6. 15
      src/libs/util.js
  7. 3
      src/pages/account/login/index.vue
  8. 10
      src/pages/achievement/list/examResults.vue
  9. 177
      src/pages/achievement/list/practiceResults.vue
  10. 262
      src/pages/assessment/detail/index.vue
  11. 79
      src/pages/assessment/list/index.vue
  12. 280
      src/pages/assessment/scoreQuery/index.vue
  13. 298
      src/pages/messageBoard/list/index.vue
  14. 279
      src/pages/practice/detail/index.vue
  15. 274
      src/pages/practice/doReview/index.vue
  16. 487
      src/pages/practice/list/index.vue
  17. 121
      src/pages/practice/list/studentSide.vue
  18. 135
      src/pages/practice/list/studentTree.vue
  19. 142
      src/pages/practice/result/index.vue
  20. 155
      src/pages/practice/review/index.vue
  21. 269
      src/pages/practice/scoreQuery/index.vue
  22. 28
      src/pages/quesBank/list/myQuesBank.vue
  23. 121
      src/pages/quesBank/list/quesDialog.vue
  24. 26
      src/pages/setting/person/index.vue
  25. 33
      src/pages/testPaper/add/index.vue
  26. 6
      src/router/modules/assessment.js
  27. 23
      src/router/modules/messageBoard.js
  28. 52
      src/router/modules/practice.js
  29. 4
      src/router/routes.js
  30. 4
      src/setting.js
  31. 40
      src/store/modules/achievement.js
  32. 107
      src/store/modules/practice.js
  33. 22
      src/store/modules/user.js
  34. 4
      src/styles/lib/_reset.scss
  35. 1
      src/styles/lib/index.scss
  36. 9
      src/styles/lib/mixin.scss

@ -1,15 +1,26 @@
let host = 'http://192.168.31.152:8001'
import Setting from '@/setting'
// let host = 'http://192.168.31.152:8001'
let uploadURL = Setting.apiUploadURL
export default {
logins: `management/userInfo/login`, //登录 
// 登录 
logins: `management/userInfo/login`,
// oss文件管理
fileDeletion: `${uploadURL}/oss/manage/fileDeletion`,
fileupload: `${uploadURL}/oss/manage/fileupload`,
getPlayAuth: `${uploadURL}/oss/manage/getPlayAuth`,
removeMoreVideo: `${uploadURL}/oss/manage/removeMoreVideo`,
removeVideo: `${uploadURL}/oss/manage/removeVideo`,
// 查询省份城市
queryProvince: `cjEnterprise/province/queryProvince`,
queryCity: `cjEnterprise/city/queryCity`,
queryClient: `cjEnterprise/client/list`,
userinfoUpdate:`management/userInfo/update`,//个人中心信息修改
userinfo:`management/userInfo/getUserInfo`,//个人中心信息展示
getAccount:`management/userInfo/getAccount`,//账号判重
// 个人中心
userinfoUpdate:`management/userInfo/update`,
userinfo:`management/userInfo/getUserInfo`,
getAccount:`management/userInfo/getAccount`,
// 学生班级
addClass: `management/class/addClass`,
@ -77,13 +88,6 @@ export default {
queryPermissionMenu: `management/permission/queryManagementPermissionMenu`,
toAssign: `management/permission/toAssign`,
// 视频管理
fileDeletion: `oss/manage/fileDeletion`, //批量删除文件
fileupload: `oss/manage/fileupload`, //文件上传
getPlayAuth: `oss/manage/getPlayAuth`, //获取播放凭证
removeMoreVideo: `oss/manage/removeMoreVideo`, //批量删除视频文件
removeVideo: `oss/manage/removeVideo`, //删除视频文件
getTypeByOneLever:`cjEnterprise/questionBank/getTypeByOneLever`,
typesList:`cjEnterprise/questionTypes/typesList`,
// 共享相关
@ -109,6 +113,7 @@ export default {
getModifyByList:`management/testPaper/getModifyByList`,
modifyState:`management/testPaper/modifyState`,
schoolTestPaperByRelease:`management/testPaper/schoolTestPaperByRelease`,
previewPaper:`/management/testPaper/previewPaper`,
// 试题信息相关
addQuestions:`management/questions/addQuestions`,
@ -144,7 +149,7 @@ export default {
getExcel:`cjEnterprise/questions/getExcel`,
impExcel:`management/questions/impExcel`,
// 成绩管理
// 考核成绩管理
answerDetail:`management/paperRecord/answerDetail`,
findByIdpaperRecord:`management/paperRecord/findById`,
getAssessmentByClass:`management/paperRecord/getAssessmentByClass`,
@ -152,4 +157,35 @@ export default {
savepaperRecord:`management/paperRecord/save`,
teacherByGetAchievement:`management/paperRecord/teacherByGetAchievement`,
achievementStatistics:`/management/paperRecord/achievementStatistics`,
// 留言板
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`,
// 练习管理
cancelPractise:`/management/practise/cancelPractise`,
createPractise:`/management/practise/createPractise`,
pageByName:`/management/practise/pageByName`,
seeDetails:`/management/practise/seeDetails`,
updatePractise:`/management/practise/updatePractise`,
// 练习批阅
practiceReviewList:`/management/practise/review/reviewList`,
reviewListByStudent:`/management/practise/review/reviewListByStudent`,
reviewDetail:`/management/practise/review/reviewDetail`,
reviewByidPractice:`/management/practise/review/reviewByid`,
// 练习成绩管理
AchievementDetail:`/management/practise/review/AchievementDetail`,
AchievementList:`/management/practise/review/AchievementList`,
exportPractice:`/management/practise/review/export`,
getMineClass:`/management/practise/review/getMineClass`,
AchievementListByClassId:`/management/practise/review/AchievementListByClassId`,
byClassIdGetPractise:`/management/practise/review/byClassIdGetPractise`,
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 MiB

After

Width:  |  Height:  |  Size: 985 KiB

@ -27,6 +27,7 @@
<div class="meta">
<p class="key">题干</p>
<p class="val" v-html="item.questionStem"></p>
<div class="media" :id="item.mediaEleId"></div>
</div>
<div class="meta">
<p class="key">选项</p>
@ -52,6 +53,7 @@
import mixins from '@/mixins/setBackground'
import { mapState } from 'vuex'
export default {
props: ['data'],
mixins: [ mixins ],
data() {
return {
@ -77,6 +79,7 @@ export default {
}
],
active: 1,
allData: {},
curType: []
};
},
@ -89,33 +92,66 @@ export default {
])
},
mounted() {
this.insertScript()
this.getData()
},
methods: {
getData() {
this.$post(`${this.api.previewtestPaper}?id=${this.id}`)
.then(res => {
this.allData = res.data
this.curType = this.allData.list1
this.handleOptions()
})
.catch(err => {
});
if(this.data){
this.initData(this.data)
}else{
this.$post(`${this.api.previewtestPaper}?id=${this.id}`)
.then(res => {
this.initData(res.data)
}).catch(err => {})
}
},
initData(data){
let index = 0
for(let i in data){
data[i].map(n => {
index++
n.mediaEleId = `player${index}`
})
}
this.allData = data
this.curType = this.allData.list1
this.handleOptions()
},
initMedia(item){
if(item.videoAudio && !item.player){
// let fileId = '312d8a6efd1747ae9de519da574195db'
this.$get(`${this.api.getPlayAuth}/${item.videoAudio}`).then(res => {
let playAuth = res.data.playAuth
this.$nextTick(() => {
console.log('初始化开始',item.mediaEleId)
item.player = new Aliplayer({
id: item.mediaEleId,
width: '100%',
autoplay: false,
vid : item.videoAudio,
playauth : playAuth,
encryptType:1, //
})
console.log('初始化结束')
})
}).catch(res => {})
}
},
tabChange(id){
this.active = id
this.curType = this.allData[`list${id}`]
this.handleOptions()
},
handleOptions(){
let curType = this.curType
curType.forEach(n => {
this.initMedia(n)
if(!n.options){
let options = {}
for(let i in n){
if(i.includes('option') && n[i]){
console.log(i.replace('option',''))
options[i.replace('option','')] = n[i]
}
}
@ -123,13 +159,24 @@ export default {
}
})
this.curType = curType
console.log(22,this.curType)
}
},
insertScript(){
const linkTag = document.createElement('link')
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.type = 'text/javascript'
scriptTag.src = 'https://g.alicdn.com/de/prismplayer/2.8.2/aliplayer-min.js'
document.body.appendChild(scriptTag)
},
},
};
</script>
<style lang="scss" scoped>
$mainColor: #e80909;
.box{
width: 90%;
margin: 0 auto;
@ -176,7 +223,7 @@ export default {
left: 0;
width: 100%;
height: 4px;
background-color: #e80909;
background-color: $mainColor;
}
}
}
@ -223,6 +270,9 @@ export default {
.key{
margin-bottom: 5px;
}
.media{
margin-top: 10px;
}
}
}
}
@ -243,8 +293,8 @@ export default {
cursor: pointer;
&.submit{
color: #fff;
background-color: #e80909;
border-color: #e80909;
background-color: $mainColor;
border-color: $mainColor;
}
&:hover{
opacity: .8;

@ -6,48 +6,41 @@
</div>
<div class="header-right">
<div class="header-user-con">
<message-board></message-board>
<div class="user" @click="toPerson">
<el-avatar :size="40" :src="circleUrl"></el-avatar>
<span class="user-avator">{{username}}</span>
<el-avatar :size="40" :src="avatar"></el-avatar>
<span class="user-avator">{{userName}}</span>
</div>
<el-divider class="ml20" direction="vertical"></el-divider>
<el-button type="text" class="ml20" @click="loginout">退出</el-button>
<el-divider class="m-l-20" direction="vertical"></el-divider>
<el-button type="text" class="m-l-20" @click="loginout">退出</el-button>
</div>
</div>
</div>
</template>
<script>
import bus from '@/libs/bus';
import Setting from '@/setting';
import messageBoard from '@/components/messageBoard';
import { mapState,mapActions } from 'vuex'
import Setting from '@/setting'
export default {
data() {
return {
collapse: false,
fullscreen: false,
name: 'huoran',
message: 2,
circleUrl: "https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png",
showBackList: Setting.layout.hideNavList,
messageVisible: false
};
},
components: {messageBoard},
computed: {
username() {
let username = sessionStorage.getItem(Setting.usernameKey);
return username ? username : this.name;
},
...mapState('user', [
'userId','avatar','userName'
]),
showBack(){
let route = this.$route.name
if(this.showBackList.includes(route)) return true
return false
}
},
mounted(){
},
methods: {
toPerson(){
this.$router.push('/setting/person')
this.$router.push('/setting/person')
},
loginout() {
sessionStorage.removeItem(Setting.usernameKey);
@ -56,12 +49,6 @@ export default {
},
back(){
this.$router.back()
},
closeMessage(){
},
showMessage(){
this.messageVisible = true
}
},
};
@ -74,10 +61,10 @@ export default {
font-size: 16px;
font-weight: bold;
margin-left: 20px;
}
.goBack i{
color: #cb221c;
font-size: 20px;
i{
color: #cb221c;
font-size: 20px;
}
}
.header {
position: relative;
@ -88,65 +75,47 @@ export default {
color: #333;
border-bottom: 1px solid #efefef;
box-shadow: 0 0 1.5625rem 0.125rem rgba(255, 45, 45, 0.14);
}
.header .logo {
float: left;
width: 170px;
height: 40px;
margin-left: 20px;
}
.header .logo img{
height: 100%;
}
.header-right {
float: right;
padding-right: 50px;
}
.header-user-con {
display: flex;
height: 70px;
align-items: center;
.user{
display: inline-flex;
align-items: center;
cursor: pointer;
}
}
.user-avator {
margin-left: 10px;
}
.ml20{
margin-left: 20px;
}
.user-avator img {
display: block;
width: 40px;
height: 40px;
border-radius: 50%;
}
.header-right .el-button--text{
color: #333;
}
.header-right .el-divider--vertical{
width: 2px;
height: 15px;
}
.header-right .el-divider{
background-color: #333;
}
.message{
display: inline-flex;
align-items: center;
margin-right: 20px;
color: #666;
font-size: 12px;
cursor: pointer;
&:hover{
opacity: .8;
.logo {
float: left;
width: 170px;
height: 40px;
margin-left: 20px;
img{
height: 100%;
}
}
img{
margin-right: 5px;
.header-right {
float: right;
padding-right: 50px;
.header-user-con {
display: flex;
height: 70px;
align-items: center;
.user{
display: inline-flex;
align-items: center;
cursor: pointer;
}
}
.el-button--text{
color: #333;
}
.el-divider--vertical{
width: 2px;
height: 15px;
}
.el-divider{
background-color: #333;
}
.user-avator {
margin-left: 10px;
img {
display: block;
width: 40px;
height: 40px;
border-radius: 50%;
}
}
}
}
</style>

@ -74,6 +74,11 @@ export default {
index: '/testPaper/list',
title: '试卷管理'
},
{
icon: 'el-icon-s-order',
index: '/practice/list',
title: '练习管理'
},
{
icon: 'el-icon-data-analysis',
index: '/assessment/list',
@ -88,6 +93,11 @@ export default {
icon: 'el-icon-setting',
index: '/system/list',
title: '系统设置'
},
{
icon: 'el-icon-chat-dot-round',
index: '/messageBoard/list',
title: '交流互动'
}
],
menus: []
@ -103,8 +113,8 @@ export default {
// Event Bus
bus.$on('collapse', msg => {
this.collapse = msg;
bus.$emit('collapse-content', msg);
});
bus.$emit('collapse-content', msg)
})
},
methods: {
initMenu(){

@ -57,6 +57,21 @@ const util = {
break;
}
}
},
// 传入文件后缀判断是否是视频
isVideo(ext) {
if('mp4,3gp,mov,m4v,avi,dat,mkv,flv,vob,rmvb,rm,qlv'.includes(ext)) return true
return false
},
// 传入文件后缀判断是否是音频
isAudio(ext) {
if('mp3,aac,ape,flac,wav,wma,amr,mid'.includes(ext)) return true
return false
},
// 传入文件后缀判断是否是图片
isImg(ext) {
if('jpg,jpeg,png,gif,svg,psd'.includes(ext)) return true
return false
}
};

@ -58,7 +58,6 @@ export default {
data: function() {
return {
loginForm: {
// username: '18818574533',
username: 'manager',
password: 'huoran123',
},
@ -110,7 +109,7 @@ export default {
display: flex;
justify-content: center;
align-items: center;
background-color: #333;
background-color: rgba(51,51,51,.7);
.inner{
display: inline-flex;
justify-content: space-between;

@ -15,7 +15,7 @@
</el-select>
</el-form-item>
<el-form-item class="no-mb" label="考试名称">
<el-select v-model="assessmentName" clearable placeholder="请选择考试名称" @change="getData" :disabled="classId == ''">
<el-select v-model="assessmentName" clearable placeholder="请选择考试名称" @change="getData">
<el-option v-for="(item,index) in assessmentNameList" :key="index" :label="item.assessmentName" :value="item.assessmentName"></el-option>
</el-select>
</el-form-item>
@ -137,7 +137,7 @@ export default {
},
methods: {
...mapActions('achievement', [
'setInfo'
'setAssListInfo','setAssDetailInfo'
]),
getData() {
this.$post(this.api.teacherByGetAchievement, {
@ -189,7 +189,7 @@ export default {
this.multipleSelection = val;
},
show(row){
this.setInfo({
this.setAssDetailInfo({
id: row.paperId,
assessmentId: row.id,
stuId: row.stuId
@ -198,7 +198,7 @@ export default {
},
toStat(){
if(this.listData.length){
this.setInfo({
this.setAssDetailInfo({
id: this.listData[0].paperId,
assessmentId: this.assessmentId,
assessmentName: this.assessmentName,
@ -212,7 +212,7 @@ export default {
},
exportData(){
}
},
}
};
</script>

@ -8,10 +8,15 @@
<span>筛选</span>
</div>
<div class="flex j-between">
<el-form label-width="80px">
<el-form label-width="80px" inline>
<el-form-item class="no-mb" label="教学班级">
<el-select v-model="classId" clearable placeholder="请选择教学班级" @change="getData">
<el-option v-for="(item,index) in classList" :key="index" :label="item.name" :value="item.value"></el-option>
<el-select v-model="classId" clearable placeholder="请选择教学班级" @change="getPrac">
<el-option v-for="(item,index) in classList" :key="index" :label="item.className" :value="item.classId"></el-option>
</el-select>
</el-form-item>
<el-form-item class="no-mb" label="练习名称">
<el-select v-model="practiseId" clearable placeholder="请选择练习名称" @change="getData">
<el-option v-for="(item,index) in practiceNameList" :key="index" :label="item.practiseName" :value="item.practiseId"></el-option>
</el-select>
</el-form-item>
</el-form>
@ -32,7 +37,7 @@
<div class="flex j-between m-b-20">
<div class="flex a-center">
<p class="hr_tag"></p>
<span>练习成绩</span>
<span>考试成绩</span>
</div>
<div>
<el-button
@ -64,14 +69,14 @@
slot-scope="scope"
>{{scope.$index + (page - 1) * pageSize + 1}}</template>
</el-table-column>
<el-table-column prop="name" label="真实姓名" align="center"></el-table-column>
<el-table-column prop="name" label="学号" align="center"></el-table-column>
<el-table-column prop="name" label="最高分" align="center"></el-table-column>
<el-table-column prop="name" label="最低分" align="center"></el-table-column>
<el-table-column prop="name" label="平均分" align="center"></el-table-column>
<el-table-column prop="userName" label="真实姓名" align="center"></el-table-column>
<el-table-column prop="workNumber" label="学号" align="center"></el-table-column>
<el-table-column prop="max" label="最高分" align="center"></el-table-column>
<el-table-column prop="min" label="最低分" align="center"></el-table-column>
<el-table-column prop="avg" label="平均分" align="center"></el-table-column>
<el-table-column label="操作" align="center">
<template slot-scope="scope">
<el-button type="text" @click="show(scope.row)">查看详情</el-button>
<el-button type="text" @click="showDetail(scope.row)">查看详情</el-button>
</template>
</el-table-column>
</el-table>
@ -89,77 +94,90 @@
</el-col>
</el-row>
<!-- <el-dialog title="练习成绩详情" :visible.sync="detailVisible" width="40%" @close="closeSelect" :close-on-click-modal="false">
<div class="flex-justify-end">
<el-dialog title="练习成绩详情" :visible.sync="detailVisible" width="40%" :close-on-click-modal="false">
<div class="flex flex-j-e">
<div class="m-b-20">
<el-input
placeholder="请输入练习项目名称"
prefix-icon="el-icon-search"
v-model="keyword"
v-model="keywordAch"
clearable
></el-input>
</div>
</div>
<el-table
:data="projectData"
:data="achiList"
ref="table"
row-key="id"
class="table"
stripe
header-align="center"
@selection-change="handleSelectionChange"
>
<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="name" label="练习试卷名称" align="center"></el-table-column>
<el-table-column prop="name" label="开始时间" align="center"></el-table-column>
<el-table-column prop="name" label="得分" align="center"></el-table-column>
<el-table-column prop="paperName" label="练习试卷名称" align="center"></el-table-column>
<el-table-column prop="examTime" label="开始时间" align="center"></el-table-column>
<el-table-column prop="score" label="得分" align="center"></el-table-column>
<el-table-column label="操作" align="center">
<template slot-scope="scope">
<el-button type="text" @click="showQues(scope.row)">查看</el-button>
<el-button type="text" @click="show(scope.row)">查看</el-button>
</template>
</el-table-column>
</el-table>
<div class="pagination">
<el-pagination
background
@current-change="handleCurrentChange"
:current-page="page"
:page-size="pageSize"
@current-change="handleAchCurrentChange"
:current-page="pageAch"
:page-size="pageSizeAch"
layout="total,prev, pager, next"
:total="total"
:total="totalAch"
></el-pagination>
</div>
<span slot="footer" class="dialog-footer">
<el-button @click="detailVisible = false">取消</el-button>
<el-button type="primary" @click="uploadSure">确定</el-button>
<el-button type="primary">确定</el-button>
</span>
</el-dialog> -->
</el-dialog>
</div>
</template>
<script>
import { mapState,mapActions } from 'vuex'
import Setting from '@/setting'
export default {
data() {
return {
keyword: '',
listData: [],
classId: '',
classList: [],
total: 0,
practiseId: '',
practiceNameList: [],
keyword: '',
listData: [],
page: 1,
pageSize: 10,
multipleSelection: [],
total: 0,
searchTimer: null,
detailVisible: false
detailVisible: false,
keywordAch: '',
achiList: [],
multipleSelectionAch: [],
pageAch: 1,
pageSizeAch: 10,
totalAch: 0,
};
},
computed: {
...mapState('user', [
'userId'
]),
},
mounted() {
this.getData()
this.getClass()
},
watch: {
keyword: function(val) {
@ -167,37 +185,73 @@ export default {
this.searchTimer = setTimeout(() => {
this.getData()
},500)
},
keywordAch: function(val) {
clearTimeout(this.searchTimer)
this.searchTimer = setTimeout(() => {
this.getData()
},500)
}
},
methods: {
...mapActions('achievement', [
'setPracDetailInfo'
]),
getData() {
// this.$get(this.api.list, {
// page: this.page,
// size: this.pageSize,
// questionStem: this.keyword,
// questionType: this.subject
// })
// .then(res => {
// this.total = res.page.totalCount; //
// this.page = res.page.currPage; //
// this.listData = res.page.list;
// this.$refs.table.clearSelection()
// })
// .catch(err => {})
this.$post(`${this.api.AchievementList}?pageNum=${this.page}&pageSize=${this.pageSize}&keyword=${this.keyword}&practiseId=${this.practiseId}&classId=${this.classId}`)
.then(res => {
this.listData = res.data.list.list
this.total = res.data.list.totalCount
}).catch(err => {})
},
getClass() {
this.$post(`${this.api.getMineClass}?userId=${this.userId}`)
.then(res => {
let list = res.data.list
this.classList = list
this.classId = this.classList[0].classId
this.getPrac()
}).catch(err => {})
},
getPrac() {
this.$post(`${this.api.byClassIdGetPractise}?classId=${this.classId}`)
.then(res => {
this.practiceNameList = res.data.list
this.practiseId = this.practiceNameList[0].practiseId
this.getData()
}).catch(err => {})
},
handleCurrentChange(val) {
this.page = val
this.getData()
},
showDetail(row){
this.getDetail(row)
this.detailVisible = true
},
getDetail(row){
this.$post(`${this.api.AchievementDetail}?userId=${row.userId}&practiseId=${this.practiseId}&pageNum=${this.page}&pageSize=${this.pageSize}`)
.then(res => {
this.achiList = res.data.list.list
this.totalAch = res.data.list.totalCount
}).catch(err => {})
},
handleSelectionChange(val) {
this.multipleSelection = val;
this.multipleSelection = val
},
show(row){
this.detailVisible = true
this.setPracDetailInfo({
practiseId: this.practiseId,
})
this.$router.push('/practice/detail')
},
handleAchCurrentChange(val) {
this.page = val
this.getData()
},
exportData(){
}
location.href = `${Setting.apiBaseURL}${this.api.exportPractice}?practiseId=${this.practiseId}&classId=${this.classId}`
},
}
};
</script>
@ -206,31 +260,4 @@ export default {
/deep/.no-mb.el-form-item{
margin-bottom: 0;
}
/deep/.el-radio{
margin-right: 15px;
}
::v-deep .el-checkbox-group{
font-size: 2px;
}
.Upload {
text-align: center;
}
.bt {
margin-bottom: 15px;
}
.flex_around {
display: flex;
justify-content: space-around;
align-items: center;
}
.card_m {
margin: 10px 0 20px 0;
}
.input ::v-deep .el-input {
width: 50%;
}
.radio {
margin: 0 15px 0 30px;
font-weight: 600;
}
</style>

@ -0,0 +1,262 @@
<template>
<div class="box">
<h1 class="title">{{paperName }}</h1>
<div class="metas">
<div style="margin-right: 20px;">
<span class="name">总分</span>
<span class="val">100</span>
</div>
<div>
<span class="name">考试时长</span>
<span class="val">{{time}}分钟</span>
</div>
</div>
<ul class="tab">
<li v-for="(item,index) in tabs" :key="index" :class="{active: active == item.id}" @click="tabChange(item.id)">{{item.name}}</li>
</ul>
<div class="wrap">
<div class="item" v-for="(item,index) in curType" :key="index">
<div class="answer">
<div class="info">
<p class="key">序号</p>
<p class="val">{{index+1}}</p>
</div>
<div class="info">
<p class="key">得分</p>
<p class="val">{{item.question_score}}</p>
</div>
</div>
<div class="meta">
<p class="key">题干</p>
<p class="val" v-html="item.question_stem"></p>
</div>
<div class="meta">
<p class="key">选项</p>
<div class="val">
<p v-for="(option,i) in item.options" :key="i">{{i}}.{{item.options[i]}}</p>
</div>
</div>
<div class="meta ans">
<div class="info">
<p class="key">正确答案</p>
<p class="val">{{item.answer}}</p>
</div>
<div class="info">
<p class="key">学生答案</p>
<p class="val">{{item.user_answer}}</p>
</div>
</div>
<div class="meta">
<p class="key">答案解析</p>
<p class="val" v-html="item.answer_analysis"></p>
</div>
</div>
</div>
</div>
</template>
<script>
import mixins from '@/mixins/setBackground'
import { mapState } from 'vuex'
export default {
mixins: [ mixins ],
data() {
return {
paperName: '',
time: 0,
selectVisible: false,
tabs: [
{
id: 1,
name: '单选题'
},{
id: 2,
name: '多选题'
},{
id: 3,
name: '判断题'
},{
id: 4,
name: '简答题'
},{
id: 5,
name: '填空题'
}
],
active: 1,
curType: []
};
},
computed: {
...mapState('user', [
'userId'
]),
...mapState('achievement', [
'id','assessmentId','stuId'
])
},
mounted() {
this.getData()
},
methods: {
getData() {
this.$post(`${this.api.answerDetail}?userId=${this.stuId}&assessmentId=${this.assessmentId}&paperId=${this.id}`)
.then(res => {
this.paperName = res.paperName
this.time = res.time
this.allData = res.data
this.curType = this.allData.list1
this.handleOptions()
})
.catch(err => {})
},
tabChange(id){
this.active = id
this.curType = this.allData[`list${id}`]
this.handleOptions()
},
handleOptions(){
let curType = this.curType
curType.forEach(n => {
if(!n.options){
let options = {}
let answer = []
for(let i in n){
if(i.includes('option') && n[i]){
options[i.replace('option_','')] = n[i]
if(n.typeName == '填空题') answer.push(n[i])
}
}
if(n.typeName == '填空题') n.answer = answer.join('|')
n.options = options
}
})
this.curType = curType
}
},
};
</script>
<style lang="scss" scoped>
.box{
width: 90%;
margin: 0 auto;
}
.title{
text-align: center;
font-size: 18px;
font-weight: 600;
}
.metas{
display: flex;
justify-content: center;
margin: 20px 0 30px;
.name{
font-size: 12px;
color: #717171;
}
.val{
font-size: 12px;
color: #929292;
}
}
.tab{
display: flex;
align-items: center;
margin-bottom: 10px;
li{
position: relative;
padding: 0 44px;
margin-right: 7px;
font-size: 13px;
line-height: 46px;
text-align: center;
color: #444;
border: 1px solid #ececec;
cursor: pointer;
&:hover{
opacity: .8;
}
&.active:after{
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 4px;
background-color: #e80909;
}
}
}
.wrap{
.item{
padding-bottom: 30px;
margin-bottom: 30px;
border-bottom: 1px dashed #f4f4f4;
.key{
font-weight: bold;
color: #333;
font-size: 14px;
}
.val{
color: #757575;
font-size: 14px;
}
.answer{
display: flex;
align-items: center;
padding: 15px;
margin: 15px 0;
font-size: 12px;
border: 1px solid #e8e8e8;
background-color: #f3f2f2;
.info{
display: inline-flex;
align-items: center;
margin-right: 30px;
}
}
.meta{
padding-left: 10px;
margin: 20px 0;
font-size: 12px;
&.ans{
display: flex;
.info{
margin-right: 20px;
}
}
.key{
margin-bottom: 5px;
}
}
}
}
.btns{
display: flex;
justify-content: center;
margin-top: 20px;
button{
height: 30px;
padding: 0 30px;
margin: 0 15px;
font-size: 14px;
color: #333;
line-height: 30px;
background-color: #fff;
border: 1px solid #ededed;
border-radius: 4px;
cursor: pointer;
&.submit{
color: #fff;
background-color: #e80909;
border-color: #e80909;
}
&:hover{
opacity: .8;
}
}
}
</style>

@ -61,13 +61,37 @@
<el-table-column prop="className" label="考试班级" align="center"></el-table-column>
<el-table-column label="操作" width="180">
<template slot-scope="scope">
<el-button type="text" @click="show(scope.row)" v-auth>查看</el-button>
<el-popover
placement="bottom"
width="400"
trigger="click">
<div class="details">
<div class="line">
<span class="key">考核内容</span>
<p class="val">{{assContent}}</p>
</div>
<div class="line">
<span class="key">考核题数</span>
<p class="val">{{quesNum}}</p>
</div>
<div class="line">
<span class="key">考核人数</span>
<p class="val">{{assPeopleNum}}</p>
</div>
<div class="line">
<span class="key">考核总分</span>
<p class="val">100</p>
</div>
</div>
<el-button type="text" slot="reference" @click="show(scope.row)" v-auth>查看</el-button>
</el-popover>&nbsp;
<template v-if="scope.row.state == 1">
<el-button type="text" @click="edit(scope.row)" v-auth>修改</el-button>
<el-button class="m-l-10" type="text" @click="edit(scope.row)" v-auth>修改</el-button>
<el-button type="text" @click="delData(scope.row)" v-auth>取消</el-button>
</template>
<template v-if="scope.row.state == 2">
<el-button type="text" @click="monitor(scope.row)" v-auth>监控</el-button>
<el-button class="m-l-10" type="text" @click="monitor(scope.row)" v-auth>监控</el-button>
<el-button type="text" @click="finish(scope.row)" v-auth>结束考试</el-button>
</template>
<template v-if="scope.row.state == 3">
@ -195,25 +219,8 @@
</span>
</el-dialog>
<el-dialog title="详情" :visible.sync="detailVisible" width="40%" @close="closeDetail" :close-on-click-modal="false">
<div class="details">
<div class="line">
<span class="key">考核内容</span>
<p class="val">{{assContent}}</p>
</div>
<div class="line">
<span class="key">考核题数</span>
<p class="val">{{quesNum}}</p>
</div>
<div class="line">
<span class="key">考核人数</span>
<p class="val">{{assPeopleNum}}</p>
</div>
<div class="line">
<span class="key">考核总分</span>
<p class="val">100</p>
</div>
</div>
<el-dialog title="试卷详情" :visible.sync="previewVisible" width="40%" fullscreen>
<test-paper-detail :key="previewId"></test-paper-detail>
</el-dialog>
</div>
</template>
@ -221,6 +228,7 @@
<script>
import { mapState,mapGetters,mapActions } from 'vuex'
import studentSide from './studentSide'
import testPaperDetail from '@/components/testPaperDetail'
import util from '@/libs/util'
export default {
data() {
@ -275,11 +283,13 @@ export default {
assPeopleNum: 0,
assContent: '',
timer: null,
stuCompKey: 1
stuCompKey: 1,
previewVisible: false,
previewId: ''
};
},
components: {
studentSide
studentSide,testPaperDetail
},
computed: {
...mapState('user', [
@ -326,6 +336,9 @@ export default {
...mapActions('assessment', [
'setAssInfo'
]),
...mapActions('achievement', [
'setAssListInfo'
]),
getData() {
this.$get(this.api.queryAssessment, {
page: this.page,
@ -520,7 +533,13 @@ export default {
})
.catch(err => {})
},
scoreQuery(){
scoreQuery(row){
this.setAssListInfo({
assessmentIdAss: row.id,
assessmentNameAss: row.name,
classIdAss: row.classId,
classNameAss: row.className
})
this.$router.push('scoreQuery')
},
review(row){
@ -609,7 +628,7 @@ export default {
.catch(err => {})
},
getPapers() {
this.$post(`${this.api.schoolTestPaperByRelease}?schoolId=${this.clientId}`)
this.$post(`${this.api.schoolTestPaperByRelease}?schoolId=${this.clientId}&effect=0`)
.then(res => {
this.testPaperData = res.data.list
// this.totalPaper = res.data.list.totalCount
@ -617,12 +636,14 @@ export default {
.catch(err => {})
},
preview(row){
this.previewId = row.id
this.setInfo({
id: row.id,
paperName: row.name,
totalDuration: row.duration
})
this.$router.push('/testPaper/show')
// this.$router.push('/testPaper/show')
this.previewVisible = true
},
savePaper(){
if(this.testPaperId === '') return this.$message.error('请选择试卷')
@ -642,10 +663,6 @@ export default {
this.assPeopleNum = data.number
})
.catch(err => {})
this.detailVisible = true
},
closeDetail(){
},
}
}

@ -1,103 +1,134 @@
<template>
<div>
<el-card shadow="hover" class="m-b-20">
<div class="flex a-center m-b-20">
<p class="hr_tag"></p>
<span>筛选</span>
</div>
<div class="flex j-between">
<el-form label-width="80px" inline>
<el-form-item class="no-mb" label="教学班级">
<el-select v-model="publishStatus" clearable placeholder="请选择教学班级" @change="getData">
<el-option v-for="(item,index) in statusList" :key="index" :label="item.name" :value="item.value"></el-option>
</el-select>
</el-form-item>
<el-form-item class="no-mb" label="考试名称">
<el-select v-model="publishStatus" clearable placeholder="请选择考试名称" @change="getData">
<el-option v-for="(item,index) in statusList" :key="index" :label="item.name" :value="item.value"></el-option>
</el-select>
</el-form-item>
</el-form>
<div>
<el-input
placeholder="请输入学生姓名/学号"
prefix-icon="el-icon-search"
v-model="keyword"
clearable
></el-input>
</div>
</div>
</el-card>
<el-row :gutter="20">
<el-col :span="24">
<el-card shadow="hover" class="m-b-20">
<div class="flex a-center m-b-20">
<p class="hr_tag"></p>
<span>筛选</span>
</div>
<div class="flex j-between">
<el-form label-width="80px" inline>
<el-form-item class="no-mb" label="教学班级">
<el-select v-model="classId" clearable placeholder="请选择教学班级" @change="getData">
<el-option v-for="(item,index) in classList" :key="index" :label="item.className" :value="item.classId"></el-option>
</el-select>
</el-form-item>
<el-form-item class="no-mb" label="考试名称">
<el-select v-model="assessmentName" clearable placeholder="请选择考试名称" @change="getData" disabled>
<el-option v-for="(item,index) in assessmentNameList" :key="index" :label="item.assessmentName" :value="item.assessmentName"></el-option>
</el-select>
</el-form-item>
</el-form>
<div>
<el-input
placeholder="请输入学生姓名或学号"
prefix-icon="el-icon-search"
v-model="keyword"
clearable
></el-input>
</div>
</div>
</el-card>
</el-col>
<el-card shadow="hover" class="m-b-20">
<div class="flex j-between m-b-20">
<div class="flex a-center">
<p class="hr_tag"></p>
<span>成绩查询</span>
</div>
<div>
<el-button type="primary" size="small" round @click="stat">成绩统计</el-button>
<el-button type="primary" size="small" round>导出</el-button>
</div>
</div>
<el-table
:data="listData"
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">
<template
slot-scope="scope"
>{{scope.$index + (page - 1) * pageSize + 1}}</template>
</el-table-column>
<el-table-column prop="name" label="真实姓名" align="center"></el-table-column>
<el-table-column prop="name" label="学号" align="center"></el-table-column>
<el-table-column prop="name" label="得分" align="center"></el-table-column>
<el-table-column prop="name" label="用时(分钟)" align="center"></el-table-column>
<el-table-column prop="name" label="考试时间" align="center"></el-table-column>
<el-table-column label="操作" align="center">
<template slot-scope="scope">
<el-button type="text" @click="show(scope.row)">查看</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-col :span="24">
<el-card shadow="hover" class="m-b-20">
<div class="flex j-between m-b-20">
<div class="flex a-center">
<p class="hr_tag"></p>
<span>考试成绩</span>
</div>
<div>
<el-button
type="primary"
size="small"
round
@click="toStat"
>成绩统计</el-button>
<el-button
type="primary"
size="small"
round
@click="exportData"
>导出</el-button>
</div>
</div>
<el-table
:data="listData"
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">
<template
slot-scope="scope"
>{{scope.$index + (page - 1) * pageSize + 1}}</template>
</el-table-column>
<el-table-column prop="stuName" label="真实姓名" align="center"></el-table-column>
<el-table-column prop="stuNo" label="学号" align="center"></el-table-column>
<el-table-column prop="thisScore" label="得分" align="center"></el-table-column>
<el-table-column prop="timeSpent" label="用时(分钟)" align="center"></el-table-column>
<el-table-column prop="totalDuration" label="考试时间" align="center"></el-table-column>
<el-table-column label="操作" align="center">
<template slot-scope="scope">
<el-button type="text" @click="show(scope.row)">查看详情</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-col>
</el-row>
</div>
</template>
<script>
import { mapState,mapActions } from 'vuex'
export default {
data() {
return {
listData: [{}],
classId: '',
classList: [],
assessmentId: '',
assessmentName: '',
assessmentNameList: [],
keyword: '',
listData: [],
page: 1,
pageSize: 10,
total: 0,
searchTimer: null,
};
},
computed: {
...mapState('user', [
'userId'
]),
...mapState('achievement', [
'assessmentIdAss','assessmentNameAss','classIdAss','classNameAss'
]),
},
mounted() {
this.getData()
this.getClass()
},
watch: {
keyword: function(val) {
@ -108,28 +139,79 @@ export default {
}
},
methods: {
...mapActions('achievement', [
'setAssDetailInfo'
]),
getData() {
// this.$get(this.api.list, {
// page: this.page,
// size: this.pageSize,
// questionStem: this.keyword,
// questionType: this.subject
// })
// .then(res => {
// this.total = res.page.totalCount; //
// this.page = res.page.currPage; //
// this.listData = res.page.list;
// this.$refs.table.clearSelection()
// })
// .catch(err => {})
this.$post(this.api.teacherByGetAchievement, {
userId: this.userId,
pageNum: this.page,
pageSize: this.pageSize,
keyword: this.keyword,
assessmentId: this.assessmentId,
classId: this.classId
})
.then(res => {
this.listData = res.data.list.list
this.total = res.data.list.totalCount
})
.catch(err => {})
},
getClass() {
let classId = this.classIdAss.split(',')
let className = this.classNameAss.split(',')
let classList = []
classId.map((n,i) => {
classList.push({
classId: n,
className: className[i]
})
})
this.classId = classId[0]
this.classList = classList
this.assessmentNameList = [{
assessmentName: this.assessmentNameAss
}]
this.assessmentId = this.assessmentIdAss
this.assessmentName = this.assessmentNameAss
this.getData()
},
handleCurrentChange(val) {
this.page = val
this.getData()
},
stat(row){
this.$router.push('/achievement/statistics')
}
closeTopics() {
this.isShowTopics = false
this.resetForm()
},
handleSelectionChange(val) {
this.multipleSelection = val;
},
show(row){
this.setAssDetailInfo({
id: row.paperId,
assessmentId: row.id,
stuId: row.stuId
})
this.$router.push('detail')
},
toStat(){
if(this.listData.length){
this.setAssDetailInfo({
id: this.listData[0].paperId,
assessmentId: this.assessmentId,
assessmentName: this.assessmentName,
classId: this.classId,
stuId: this.listData[0].stuId
})
this.$router.push('statistics')
}else{
this.$message.warning('没有考试成绩')
}
},
exportData(){
},
}
};
</script>

@ -0,0 +1,298 @@
<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="https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png" 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" :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="https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png" 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)">删除</button>
</div>
<div class="reply" v-if="reply.showReply">
<quill :border="true" v-model="reply.replyContent" :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" :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.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)
console.log(11,replyList,children)
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){
if(row.identification == 1){
this.$post(`${this.api.delComment}?commentId=${row.commentId}`).then(res => {
this.$message.success('删除成功')
this.getData()
}).catch(res => {})
}else{
this.$post(`${this.api.delReply}?replyId=${row.replyId}`).then(res => {
this.$message.success('删除成功')
this.getData()
}).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>
$mainColor: #cc201c;
.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: $mainColor;
}
.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: $mainColor;
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: $mainColor;
font-size: 12px;
span{
cursor: pointer;
}
}
/deep/.quill{
background-color: #fff;
}
</style>

@ -0,0 +1,279 @@
<template>
<div class="box">
<h1 class="title">{{paperName }}</h1>
<div class="metas">
<div style="margin-right: 20px;">
<span class="name">总分</span>
<span class="val">100</span>
</div>
<div>
<span class="name">考试时长</span>
<span class="val">{{duration}}</span>
</div>
</div>
<ul class="tab">
<li v-for="(item,index) in tabs" :key="index" :class="{active: active == item.id}" @click="tabChange(item.id)">{{item.name}}</li>
</ul>
<div class="wrap">
<div class="item" v-for="(item,index) in curType" :key="index">
<div class="answer">
<div class="info">
<p class="key">序号</p>
<p class="val">{{index+1}}</p>
</div>
<div class="info">
<p class="key">得分</p>
<p class="val">{{item.questionScore}}</p>
</div>
</div>
<div class="meta">
<p class="key">题干</p>
<p class="val" v-html="item.questionStem"></p>
</div>
<div class="meta">
<p class="key">选项</p>
<div class="val">
<p v-for="(option,i) in item.options" :key="i">{{i}}.{{item.options[i]}}</p>
</div>
</div>
<div class="meta ans">
<div class="info">
<p class="key">正确答案</p>
<p class="val">{{item.answer}}</p>
</div>
<div class="info">
<p class="key">学生答案</p>
<p class="val">{{item.userAnswer}}</p>
</div>
</div>
<div class="meta">
<p class="key">答案解析</p>
<p class="val" v-html="item.answerAnalysis"></p>
</div>
</div>
</div>
</div>
</template>
<script>
import mixins from '@/mixins/setBackground'
import { mapState } from 'vuex'
export default {
mixins: [ mixins ],
data() {
return {
paperName: '',
duration: 0,
selectVisible: false,
tabs: [
{
id: 1,
name: '单选题'
},{
id: 2,
name: '多选题'
},{
id: 3,
name: '判断题'
},{
id: 4,
name: '简答题'
},{
id: 5,
name: '填空题'
}
],
typeNameList: ['单项选择','多项选择','判断题','简答题','填空题'],
active: 1,
list: [],
curType: []
};
},
computed: {
...mapState('user', [
'userId'
]),
...mapState('achievement', [
'practiseId','stuId'
])
},
mounted() {
this.getData()
},
methods: {
getData() {
this.$post(`${this.api.reviewDetail}?id=${this.practiseId}`)
.then(res => {
let data = res.data
data.list.forEach(n => {
n.isCorrecting == 0 && (n.questionScore = '')
n.isSub = n.typeName == '简答题'
if(n.typeName == '填空题'){
let answer = []
for(let i in n){
if(i.includes('option')) answer.push(n[i])
}
n.answer = answer.join('|')
n.userAnswer = n.userAnswer.replace(/&lt;&gt;/g,'|')
}
})
this.list = data.list
this.handleOptions()
this.paperName = data.paperName
this.userName = data.stuName
this.this_score = data.score
this.duration = data.timeCost
})
.catch(err => {})
},
tabChange(id){
this.active = id
this.handleOptions()
},
handleOptions(){
let list = this.list
let typeName = this.typeNameList[this.active-1]
list = list.filter(n => n.typeName == typeName)
list.forEach(n => {
if(!n.options){
let options = {}
let answer = []
for(let i in n){
if(i.includes('option') && n[i]){
options[i.replace('option','')] = n[i]
if(n.typeName == '填空题') answer.push(n[i])
}
}
if(n.typeName == '填空题') n.answer = answer.join('|')
n.options = options
}
})
this.curType = list
}
},
};
</script>
<style lang="scss" scoped>
.box{
width: 90%;
margin: 0 auto;
}
.title{
text-align: center;
font-size: 18px;
font-weight: 600;
}
.metas{
display: flex;
justify-content: center;
margin: 20px 0 30px;
.name{
font-size: 12px;
color: #717171;
}
.val{
font-size: 12px;
color: #929292;
}
}
.tab{
display: flex;
align-items: center;
margin-bottom: 10px;
li{
position: relative;
padding: 0 44px;
margin-right: 7px;
font-size: 13px;
line-height: 46px;
text-align: center;
color: #444;
border: 1px solid #ececec;
cursor: pointer;
&:hover{
opacity: .8;
}
&.active:after{
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 4px;
background-color: #e80909;
}
}
}
.wrap{
.item{
padding-bottom: 30px;
margin-bottom: 30px;
border-bottom: 1px dashed #f4f4f4;
.key{
font-weight: bold;
color: #333;
font-size: 14px;
}
.val{
color: #757575;
font-size: 14px;
}
.answer{
display: flex;
align-items: center;
padding: 15px;
margin: 15px 0;
font-size: 12px;
border: 1px solid #e8e8e8;
background-color: #f3f2f2;
.info{
display: inline-flex;
align-items: center;
margin-right: 30px;
}
}
.meta{
padding-left: 10px;
margin: 20px 0;
font-size: 12px;
&.ans{
display: flex;
.info{
margin-right: 20px;
}
}
.key{
margin-bottom: 5px;
}
}
}
}
.btns{
display: flex;
justify-content: center;
margin-top: 20px;
button{
height: 30px;
padding: 0 30px;
margin: 0 15px;
font-size: 14px;
color: #333;
line-height: 30px;
background-color: #fff;
border: 1px solid #ededed;
border-radius: 4px;
cursor: pointer;
&.submit{
color: #fff;
background-color: #e80909;
border-color: #e80909;
}
&:hover{
opacity: .8;
}
}
}
</style>

@ -0,0 +1,274 @@
<template>
<div class="box">
<h1 class="title">{{paperName}}</h1>
<div class="metas">
<div>
<span class="name">学生姓名</span>
<span class="val">{{userName}}</span>
</div>
<div>
<span class="name">学生得分</span>
<span class="val">{{(reviewStatus == 2 || reviewStatus == 3) ? this_score : '--'}}</span>
</div>
<div>
<span class="name">试卷总分</span>
<span class="val">100</span>
</div>
<div>
<span class="name">练习时长</span>
<span class="val">{{duration}}</span>
</div>
</div>
<div class="wrap">
<div class="select">
<el-radio v-model="look" label="1">查看全部</el-radio>
<el-radio v-model="look" label="2" v-if="reviewStatus == 2 || reviewStatus == 3">只看错题</el-radio>
</div>
<div class="item" v-for="(item,index) in list" :key="index">
<div class="status" :class="{done: item.isCorrecting}">{{item.isSub ? '简答题' : '客观题'}}{{getCorrectingName(item.isCorrecting)}}</div>
<div class="name" v-html="item.questionStem"></div>
<div class="answer">
<div class="info" v-if="!item.isSub">
<p class="key">正确答案</p>
<p class="val">{{item.answer}}</p>
</div>
<div class="info">
<p class="key">学生答案</p>
<p class="val">{{item.userAnswer}}</p>
</div>
</div>
<div class="meta">
<span class="key">知识点</span>
<span class="val">{{item.knowledgePoints}}</span>
</div>
<div class="meta">
<span class="key">答案解析</span>
<span class="val">{{item.answerAnalysis}}</span>
</div>
<div class="meta">
<span class="key">考试得分</span>
<div class="val">
<input type="text" v-model.number="item.questionScore" :disabled="!isReview || !item.isSub">
</div>
</div>
</div>
</div>
<div class="btns" v-if="isReview">
<button type="button" class="submit" @click="save(1)">提交</button>
<button type="button" @click="save(0)">保存</button>
</div>
</div>
</template>
<script>
import mixins from '@/mixins/setBackground'
import { mapState,mapGetters,mapActions } from 'vuex'
export default {
mixins: [ mixins ],
data() {
return {
paperName: '',
userName: '',
this_score: '',
duration: '',
list: [],
look: '1',
};
},
computed: {
...mapState('user', [
'userId','clientId'
]),
...mapState('practice', [
'id','paperId','isReview','reviewStatus','stuId','identification','practiseId'
]),
...mapGetters('practice', [
'getCorrectingName'
])
},
watch: {
look(val,oldVal){
val == 1 ? this.getData() : this.getWrong()
}
},
mounted() {
this.getData()
},
methods: {
getData() {
this.$post(`${this.api.reviewDetail}?id=${this.id}`)
.then(res => {
let data = res.data
data.list.forEach(n => {
n.isCorrecting == 0 && (n.questionScore = '')
n.isSub = n.typeName == '简答题'
if(n.typeName == '填空题'){
let answer = []
for(let i in n){
if(i.includes('option')) answer.push(n[i])
}
n.answer = answer.join('|')
n.userAnswer = n.userAnswer.replace(/&lt;&gt;/g,'|')
}
})
this.list = data.list
this.paperName = data.paperName
this.userName = data.stuName
this.this_score = data.score
this.duration = data.timeCost
})
.catch(err => {})
},
getWrong(){
this.$post(`${this.api.getWrong}?assessmentId=${this.id}&userId=${this.stuId}&paperId=${this.paperId}`)
.then(res => {
this.list = res.data.list
})
.catch(err => {})
},
save(status) {
let isEmpty = false
let isNotNum = false
let invalid = false
this.list.map(n => {
if(n.questionScore === '') isEmpty = true
if(isNaN(n.questionScore)) isNotNum = true
if(Number(n.questionScore) > Number(n.question_points)) invalid = true
})
if(status){
if(isEmpty) return this.$message.warning('请批阅完所有题目')
if(isNotNum) return this.$message.warning('考试得分请输入数字')
}
if(invalid) return this.$message.warning('考试得分不得大于题目分数')
let data = {
identification: this.identification,
review: [],
practiseId: this.practiseId,
paperId: this.paperId,
}
let totalScore = 0
this.list.map(n => {
n.questionScore !== '' && n.isSub && data.review.push({
detailId: Number(n.detailId) ,
score: Number(n.questionScore)
})
totalScore += Number(n.questionScore)
})
if(!data.review.length) return this.$message.warning('请至少批阅一道题目')
if(status || this.list.filter(n => n.isSub).length == data.review.length){
data.totalScore = totalScore
}
this.$post(this.api.reviewByidPractice,data).then(res => {
this.$message.success(status ? '提交成功' : '保存成功')
this.$router.back()
}).catch(err => {})
},
},
};
</script>
<style lang="scss" scoped>
.title{
text-align: center;
font-size: 18px;
font-weight: 600;
}
.metas{
display: flex;
justify-content: space-between;
margin: 20px 0 30px;
.name{
font-size: 12px;
color: #717171;
}
.val{
font-size: 12px;
color: #929292;
}
}
.wrap{
padding: 20px;
background-color: #fbfbfb;
.select{
padding: 10px;
margin-bottom: 20px;
border-bottom: 1px solid #f4f4f4;
}
.item{
padding-bottom: 30px;
margin-bottom: 30px;
border-bottom: 1px dashed #d2d2d2;
&:last-child{
border-bottom: 0;
}
.status{
color: #cb221c;
&.done{
color: #56d5bf;
}
}
.name{
margin-top: 15px;
font-size: 14px;
color: #555555;
}
.key{
font-weight: bold;
color: #333;
}
.val{
color: #757575;
}
.answer{
display: flex;
align-items: center;
padding: 15px;
margin: 15px 0;
font-size: 12px;
border: 1px solid #e8e8e8;
background-color: #f3f2f2;
.info{
display: inline-flex;
align-items: center;
margin-right: 30px;
}
}
.meta{
display: flex;
align-items: center;
padding-left: 10px;
margin: 10px 0;
font-size: 12px;
.key{
width: 80px;
margin-right: 10px;
text-align: right;
white-space: nowrap;
}
input{
width: 60px;
height: 28px;
padding: 0 5px;
margin-right: 5px;
color: #444;
background-color: #fff;
border: 1px solid #ebebeb;
box-sizing: border-box;
&:focus{
outline: none;
}
&:disabled{
background-color: #e8e8e8;
cursor: not-allowed;
}
}
}
}
}
</style>

@ -0,0 +1,487 @@
<template>
<div>
<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 class="flex">
<div>
<el-input placeholder="请输入练习名称" prefix-icon="el-icon-search" v-model="keyword" clearable></el-input>
</div>
</div>
</div>
</div>
</el-card>
<el-card shadow="hover">
<div class="flex j-between m-b-20">
<div class="flex a-center">
<p class="hr_tag"></p>
<span>练习列表</span>
</div>
<div>
<el-button type="primary" size="small" round @click="addAss" v-auth>创建练习</el-button>
</div>
</div>
<el-table :data="listData" class="table" stripe header-align="center" row-key="id">
<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>
<el-table-column prop="practiseName" label="练习名称" align="center"></el-table-column>
<el-table-column prop="createTime" label="创建时间" align="center"></el-table-column>
<el-table-column prop="className" label="练习班级" align="center"></el-table-column>
<el-table-column label="操作" width="250">
<template slot-scope="scope">
<el-popover
placement="bottom"
width="400"
trigger="click">
<div class="details">
<div class="line">
<span class="key">练习内容</span>
<p class="val">{{assContent}}</p>
</div>
<div class="line">
<span class="key">练习题数</span>
<p class="val">{{quesNum}}</p>
</div>
<div class="line">
<span class="key">练习人数</span>
<p class="val">{{assPeopleNum}}</p>
</div>
<div class="line">
<span class="key">练习总分</span>
<p class="val">100</p>
</div>
</div>
<el-button type="text" slot="reference" @click="show(scope.row)" v-auth>查看</el-button>
</el-popover>&nbsp;
<el-button type="text" @click="edit(scope.row)" v-auth>修改</el-button>
<el-button type="text" @click="delData(scope.row)" v-auth>取消</el-button>
<el-button type="text" @click="review(scope.row)" v-auth>批阅</el-button>
<el-button type="text" @click="scoreQuery(scope.row)" v-auth>成绩查询</el-button>
</template>
</el-table-column>
</el-table>
<div class="pagination">
<el-pagination background @current-change="handleCurrentChange" :current-page="page" layout="total, prev, pager, next" :total="total">
</el-pagination>
</div>
</el-card>
<el-dialog :title="isAdd ? '创建练习' : '修改练习'" :visible.sync="addVisible" width="50%" @close="closeAdd" :close-on-click-modal="false">
<el-form ref="form" label-width="100px">
<el-form-item label="练习名称">
<el-input v-model="form.practiseName" size="small" placeholder="请输入练习名称"></el-input>
</el-form-item>
<el-form-item label="试卷选择">
<el-button type="primary" size="small" @click="openSelect">试卷选择</el-button>
<el-tag
class="m-l-10"
v-if="testPaperName"
closable
@close="removeTestPaper">
{{testPaperName}}
</el-tag>
</el-form-item>
<el-form-item label="发布班级">
<studentSide ref="getSelectData" :classId="form.classId" :key="stuCompKey" @fircheck="fircheck" @twocheck="twocheck" @threecheck="threecheck"></studentSide>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="addVisible = false">取消</el-button>
<el-button type="primary" @click="save">确定</el-button>
</span>
</el-dialog>
<el-dialog title="试卷选择" :visible.sync="selectVisible" width="40%" @close="closeSelect" :close-on-click-modal="false">
<div class="flex j-end m-b-20">
<el-form label-width="80px" inline>
<el-form-item class="no-mb" label="所属课程">
<el-select v-model="cid" clearable placeholder="请选择所属课程" >
<el-option v-for="(item,index) in coursesList" :key="index" :label="item.typeName" :value="item.cid"></el-option>
</el-select>
</el-form-item>
<el-form-item class="no-mb">
<el-input
placeholder="请输入试卷名称"
prefix-icon="el-icon-search"
v-model="keywordPaper"
clearable
></el-input>
</el-form-item>
</el-form>
</div>
<el-table
:data="testPaperData"
max-height="400"
ref="table"
row-key="id"
class="table"
stripe
header-align="center"
>
<el-table-column width="60" label="选择" align="center">
<template slot-scope="scope">
<el-radio v-model="testPaperId" :label="scope.row.id">&nbsp;</el-radio>
</template>
</el-table-column>
<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="name" label="试卷名称" align="center"></el-table-column>
<el-table-column label="操作" align="center">
<template slot-scope="scope">
<el-button type="text" @click="preview(scope.row)">预览</el-button>
</template>
</el-table-column>
</el-table>
<!-- <div class="pagination">
<el-pagination
background
@current-change="handleCurrentChange"
:current-page="pagePaper"
:page-size="pageSizePaper"
layout="total,prev, pager, next"
:total="totalPaper"
></el-pagination>
</div> -->
<span slot="footer" class="dialog-footer">
<el-button @click="selectVisible = false">取消</el-button>
<el-button type="primary" @click="savePaper">确定</el-button>
</span>
</el-dialog>
<el-dialog title="试卷详情" :visible.sync="previewVisible" width="40%" fullscreen>
<test-paper-detail :key="previewId"></test-paper-detail>
</el-dialog>
</div>
</template>
<script>
import { mapState,mapGetters,mapActions } from 'vuex'
import studentSide from './studentSide'
import testPaperDetail from '@/components/testPaperDetail'
import util from '@/libs/util'
export default {
data() {
return {
keyword: '',
type: '',
state: '',
listData: [],
page: 1,
pageSize: 10,
total: 0,
searchTimer: null,
isAdd: false,
addVisible: false,
selectVisible: false,
detailVisible: false,
form: {
classId: '',
practiseName: '',
testPaperId: '',
},
permissions: [],
classList: [],
checkedIds: [],
defaultProps: {
children: 'children',
label: 'className'
},
keywordPaper: '',
cid: '',
coursesList: [],
pagePaper: 1,
pageSizePaper: 10,
totalPaper: 0,
testPaperData: [],
testPaperId: '',
testPaperName: '',
quesNum: 0,
assPeopleNum: 0,
assContent: '',
stuCompKey: 1,
previewVisible: false,
previewId: ''
};
},
components: {
studentSide,testPaperDetail
},
computed: {
...mapState('user', [
'userId','clientId'
]),
...mapState('practice', [
'typeList','stateList'
]),
...mapGetters('practice', [
'getStateName'
])
},
mounted() {
this.getData()
},
watch: {
keyword: function(val) {
clearTimeout(this.searchTimer)
this.searchTimer = setTimeout(() => {
this.getData()
},500)
},
keywordPaper: function(val) {
clearTimeout(this.searchTimer)
this.searchTimer = setTimeout(() => {
this.getPapers()
},500)
}
},
methods: {
...mapActions('testpaper', [
'setInfo'
]),
...mapActions('practice', [
'setPracInfo'
]),
...mapActions('achievement', [
'setPracListInfo'
]),
getData() {
this.$post(`${this.api.pageByName}?pageNum=${this.page}&pageSize=${this.pageSize}&practiseName=${this.keyword}&userId=${this.userId}`)
.then(res => {
this.listData = res.data.list.list
this.total = res.data.list.totalCount
})
.catch(err => {})
},
handleCheck(data){
let professionalStudentIds = []
let gradeIds = []
let classIds = []
data.forEach( e => {
if(e.ischeck){
professionalStudentIds.push(e.stuProfessionalArchitectureId)
}else{
util.removeByValue(professionalStudentIds, e.stuProfessionalArchitectureId);
}
e.children.forEach( r => {
if(r.ischeck){
gradeIds.push(r.gradeId)
}else{
util.removeByValue(gradeIds, r.gradeId);
}
r.children.forEach( n => {
if(n.ischeck){
classIds.push(n.classId)
}else{
util.removeByValue(classIds, n.classId);
}
})
})
})
this.form.classId = classIds.toString()
},
fircheck(val,val2){
val.ischeck = !val.ischeck
val.children.map( e => e.ischeck = val.ischeck)
val.children.map( e => e.children.map(n => n.ischeck = e.ischeck))
this.handleCheck(val2)
},
twocheck(val,val2){
val.ischeck = !val.ischeck
val.children.map( e => e.ischeck = val.ischeck)
val.children.map( e => e.children && e.children.map(n => n.ischeck = e.ischeck))
val2.forEach( e => {
e.children.forEach( r => {
if(r.gradeId == val.gradeId){
if(e.children.every(i => i.ischeck)){
e.ischeck = true
}else{
e.ischeck = false
}
}
})
})
this.handleCheck(val2)
},
threecheck(val,val2){
val.ischeck = !val.ischeck
this.handleCheck(val2)
},
handleCurrentChange(val) {
this.page = val;
this.getData();
},
delData(row) {
this.$confirm('确定要删除吗?', '提示', {
type: 'warning'
})
.then(() => {
this.$post(`${this.api.cancelPractise}?practiseId=${row.practiseId}`).then(res => {
this.$message.success('删除成功')
this.getData()
}).catch(res => {})
})
.catch(() => {})
},
edit(row){
this.form = JSON.parse(JSON.stringify(row))
this.testPaperName = row.name
this.addVisible = true
this.isAdd = false
},
scoreQuery(row){
this.setPracListInfo({
practiceIdAss: row.practiseId,
practiceNameAss: row.practiseName,
classIdAss: row.classId,
classNameAss: row.className
})
this.$router.push('scoreQuery')
},
review(row){
this.setPracInfo({
practiseId: row.practiseId
})
this.$router.push('review')
},
addAss(){
this.isAdd = true
this.addVisible = true
},
save(){
let form = this.form
if(form.practiseName === '') return this.$message.warning('请填写练习名称')
if(form.testPaperId === '') return this.$message.warning('请选择试卷')
if(form.classId === '') return this.$message.warning('请选择发布班级')
let data = {
practiseId: form.practiseId,
userId: this.userId,
practiseName: form.practiseName,
classId: form.classId,
testPaperId: form.testPaperId,
}
if(this.form.practiseId){
this.$post(this.api.updatePractise, data).then(res => {
this.$message.success('修改成功')
this.addVisible = false
this.getData()
})
.catch(err => {})
}else{
this.$post(this.api.createPractise, data).then(res => {
this.$message.success('创建成功')
this.addVisible = false
this.getData()
})
.catch(err => {})
}
},
closeAdd(){
this.form = {
classId: '',
practiseName: '',
testPaperId: '',
}
this.time = []
this.testPaperName = ''
this.testPaperId = ''
this.cid = ''
this.keywordPaper = ''
this.stuCompKey++
},
openSelect(){
this.selectVisible = true
this.getCourses()
this.getPapers()
},
removeTestPaper(){
this.form.testPaperId = ''
this.testPaperName = ''
},
getCourses() {
this.$get(this.api.getTypeByOneLever)
.then(res => {
this.coursesList = res.data.list
})
.catch(err => {})
},
getPapers() {
this.$post(`${this.api.schoolTestPaperByRelease}?schoolId=${this.clientId}&effect=1`)
.then(res => {
this.testPaperData = res.data.list
// this.totalPaper = res.data.list.totalCount
})
.catch(err => {})
},
preview(row){
this.previewId = row.id
this.setInfo({
id: row.id,
paperName: row.name,
totalDuration: row.duration
})
// this.$router.push('/testPaper/show')
this.previewVisible = true
},
savePaper(){
if(this.testPaperId === '') return this.$message.error('请选择试卷')
this.form.testPaperId = this.testPaperId
this.testPaperName = this.testPaperData.find(n => n.id == this.testPaperId).name
this.selectVisible = false
},
closeSelect(){
},
show(row){
this.$post(`${this.api.seeDetails}?id=${row.practiseId}`)
.then(res => {
let data = res.data.list
this.assContent = data.paperName
this.quesNum = data.questionsNum
this.assPeopleNum = data.peopleNum
})
.catch(err => {})
},
closeDetail(){
},
}
}
</script>
<style lang="scss" scoped>
/deep/.no-mb.el-form-item{
margin-bottom: 0;
}
.details{
.line{
display: flex;
align-items: center;
margin: 10px 0;
&:first-child{
margin-top: 0;
}
.key{
font-weight: bold;
color: #333;
font-size: 14px;
}
.val{
color: #757575;
font-size: 14px;
}
}
}
</style>

@ -0,0 +1,121 @@
<template>
<div>
<div>
<lctree :data="majorList" @fircheckitem="fircheckitem" @twocheckitem="twocheckitem" @threecheckitem="threecheckitem"></lctree>
</div>
</div>
</template>
<script>
import lctree from './studentTree'
import { mapState } from 'vuex'
export default {
props:["Data",'classId'],
data() {
return {
majorList: [],
firactive: 0,
twoactive: 0,
threeactive: 0,
isaddClassMajor: false,
isAddDepartment: false,
isAddClass: false,
Form: {
classmajorId: '',
classmajorName: '',
},
Form2: {
departmentId: '',
departmentName: '',
},
Form3: {
classId: '',
className: ''
},
majorNoAdd: true,
};
},
computed: {
...mapState('user', [
'userId','clientId'
])
},
components: {
lctree
},
mounted(){
this.getStaff()
},
methods: {
getStaff(){
let data = {
schoolId: this.clientId
}
let classId = this.classId ? this.classId.split(',') : []
this.$get(this.api.queryStudentProfessionalArchitecture,data).then(res => {
let StaffProfessionalArchitectureList = res.data.StaffProfessionalArchitectureList
StaffProfessionalArchitectureList.map(n => {
(n.ifVisible = false), (n.ischeck = false), (n.label = n.stuProfessionalArchitectureName);
let data = {
stuProfessionalArchitectureId: n.stuProfessionalArchitectureId
}
this.$get(this.api.queryGrade,data).then(res => {
n.children = res.data.Grade
n.children.map(j => {
(j.ifVisible = false), (j.ischeck = false), (j.label = j.gradeName);
let data = {
gradeId: j.gradeId
}
this.$get(this.api.queryClass,data).then(res => {
res.data.Class.map(e => {
(e.ifVisible = false), (e.ischeck = false), (e.label = e.className)
let data = {
searchContent: '',
professionalIds: n.stuProfessionalArchitectureId,
gradeIds: j.gradeId,
classIds: e.classId,
schoolId: this.clientId
}
if(classId.includes(String(e.classId))){
e.ischeck = true
j.ifVisible = true
n.ifVisible = true
}
})
j.children = res.data.Class
if(j.children.every(i => i.ischeck)){
j.ischeck = true
}
if(n.children.every(i => i.ischeck)){
n.ischeck = true
}
}).catch(res => {});
})
}).catch(res => {});
})
setTimeout(() => {
this.majorList = StaffProfessionalArchitectureList
this.majorList[0].ifVisible = true
}, 500);
}).catch(res => {});
},
//
fircheckitem(item){
this.$emit("fircheck",item,this.majorList)
},
//
twocheckitem(item){
this.$emit("twocheck",item,this.majorList)
},
threeClick(index){
this.threeactive = index
},
//
threecheckitem(three){
this.$emit("threecheck",three,this.majorList)
},
}
};
</script>
<style lang="scss" scoped>
</style>

@ -0,0 +1,135 @@
<template>
<div class="side_view">
<div class="side_tree" @click.stop="open(item)" v-for="(item,index) in data" :key="index">
<div class="item" @click.stop="open(item)">
<img
v-if="item.children&&item.children.length!=0"
:class="{ 'arrowTransform': !item.ifVisible, 'arrowTransformReturn': item.ifVisible}"
src="../../../assets/img/icon-xiangyou.png"
alt
/>
<i v-else class="empty"></i>
<i :class="item.ischeck ? 'icon-yigouxuan' : 'icon-weigouxuan'" @click.stop="fircheckitem(item)"></i>
<span>{{item.label}}</span>
</div>
<div v-show="item.ifVisible" v-if="item.children&&item.children.length!=0">
<div v-for="(item1,index1) in item.children" :key="index1">
<div class="item1" @click.stop="open(item1)">
<img
v-if="item1.children&&item1.children.length!=0"
:class="{ 'arrowTransform': !item1.ifVisible, 'arrowTransformReturn': item1.ifVisible}"
src="../../../assets/img/icon-xiangyou.png"
alt
/>
<i v-else class="empty"></i>
<i :class="item1.ischeck ? 'icon-yigouxuan' : 'icon-weigouxuan'" @click.stop="twocheckitem(item1)"></i>
<span>{{item1.label}}年级</span>
</div>
<div v-show="item1.ifVisible" v-if="item1.children&&item1.children.length!=0">
<div v-for="(item2,index2) in item1.children" :key="index2">
<div class="item2" @click.stop="open(item2)">
<i :class="item2.ischeck ? 'icon-yigouxuan' : 'icon-weigouxuan'" @click.stop="threecheckitem(item2)"></i>
<span>{{item2.label}}</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
Array.prototype.removeByValue = function (val) {
for (var i = 0; i < this.length; i++) {
if (JSON.stringify(this[i]).indexOf(JSON.stringify(val)) != -1) {
this.splice(i, 1);
break;
}
}
};
export default {
data() {
return {
chooseList: []
};
},
watch: {
chooseList(n, o) {
this.$emit('chooseNode', n);
}
},
props: {
data: {
type: Array
}
},
methods: {
//
open(item) {
item.ifVisible = !item.ifVisible;
},
//removeByvaluemain.js
choose(item) {
item.ifVisible = !item.ifVisible;
if (item.ifVisible) {
this.chooseList.push(item);
} else {
this.chooseList.removeByValue(item);
}
},
fircheckitem(item){
this.$emit('fircheckitem',item);
},
twocheckitem(item){
console.log(22,item)
this.$emit('twocheckitem',item);
},
threecheckitem(item){
this.$emit('threecheckitem',item);
},
//
isHasObj(arr, val) {
var flag = 0; //1 0
for (var i = 0; i < arr.length; i++) {
if (JSON.stringify(arr[i]).indexOf(JSON.stringify(val)) != -1) {
flag = 1;
}
}
if (flag == 1) {
return true;
} else {
return false;
}
}
}
};
</script>
<style lang="scss" scoped>
@import '../../../styles/pages/tree.scss';
.side_view{
max-height: 300px;
overflow: auto;;
padding: 10px 20px;
i {
color: #cb221c;
}
}
.item{
padding: 5px 0;
margin-top: 10px;
}
.item2 {
margin-left: 80px
}
.item1,.item2{
padding: 0;
margin-top: 0;
}
</style>

@ -0,0 +1,142 @@
<template>
<div>
<el-card shadow="hover" class="m-b-20">
<div class="flex a-center m-b-20">
<p class="hr_tag"></p>
<span>筛选</span>
</div>
<div class="flex j-between">
<el-form label-width="80px" inline>
<el-form-item class="no-mb" label="批阅状态">
<el-select v-model="state" clearable placeholder="请选择批阅状态" @change="getData">
<el-option label="不限" value="3"></el-option>
<el-option v-for="(item,index) in reviewStatusList" :key="index" :label="item.name" :value="item.id"></el-option>
</el-select>
</el-form-item>
</el-form>
</div>
</el-card>
<el-card shadow="hover" class="m-b-20">
<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="userName" label="真实姓名" align="center"></el-table-column>
<el-table-column prop="workNumber" label="学号" align="center"></el-table-column>
<el-table-column prop="examTime" label="开始时间" align="center"></el-table-column>
<el-table-column prop="timeCost" label="答题用时(分钟)" align="center"></el-table-column>
<el-table-column prop="workNumber" label="考试状态" align="center">
<template slot-scope="scope">
{{getExamStatusName(scope.row.state)}}
</template>
</el-table-column>
<el-table-column label="批阅状态" align="center">
<template slot-scope="scope">
{{getReviewStatusName(scope.row.reviewStatus)}}
</template>
</el-table-column>
<el-table-column label="操作" align="center">
<template slot-scope="scope">
<el-button type="text" @click="review(scope.row,false)">查看</el-button>
<el-button type="text" @click="review(scope.row,true)" v-if="(scope.row.reviewStatus == 0 || scope.row.reviewStatus == 1) && scope.row.state == 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>
</div>
</template>
<script>
import { mapState,mapGetters,mapActions } from 'vuex'
export default {
data() {
return {
state: '3',
reviewStatusList: [
{
id: 0,
name: '未批阅'
},{
id: 1,
name: '批阅部分'
},{
id: 2,
name: '已批阅'
}
],
keyword: '',
listData: [],
page: 1,
pageSize: 10,
total: 0,
searchTimer: null,
};
},
computed: {
...mapState('practice', [
'practiseId','userId'
]),
...mapGetters('practice', [
'getReviewStatusName','getExamStatusName'
])
},
mounted() {
this.getData()
},
methods: {
...mapActions('practice', [
'setReviewInfo'
]),
getData() {
this.$post(`${this.api.reviewListByStudent}?pageNum=${this.page}&pageSize=${this.pageSize}&practiseId=${this.practiseId}&userId=${this.userId}&state=${this.state}`)
.then(res => {
this.listData = res.data.list.list
this.total = res.data.list.totalCount
})
.catch(err => {})
},
handleCurrentChange(val) {
this.page = val
this.getData()
},
review(row,isReview){
this.setReviewInfo({
isReview,
id: row.id,
practiseId: row.practiseId,
paperId: row.testPaperId,
stuId: row.userId,
reviewStatus: row.reviewStatus,
identification: row.identification
})
this.$router.push('doReview')
}
}
};
</script>
<style lang="scss" scoped>
/deep/.no-mb.el-form-item{
margin-bottom: 0;
}
</style>

@ -0,0 +1,155 @@
<template>
<div>
<el-card shadow="hover" class="m-b-20">
<div class="flex a-center m-b-20">
<p class="hr_tag"></p>
<span>筛选</span>
</div>
<div class="flex j-between">
<el-form label-width="80px" inline>
<el-form-item class="no-mb" label="批阅状态">
<el-select v-model="state" clearable placeholder="请选择批阅状态" @change="getData">
<el-option label="不限" value="3"></el-option>
<el-option v-for="(item,index) in reviewStatusList" :key="index" :label="item.name" :value="item.id"></el-option>
</el-select>
</el-form-item>
</el-form>
<div>
<el-input
placeholder="请输入真实姓名/学号"
prefix-icon="el-icon-search"
v-model="keyword"
clearable
></el-input>
</div>
</div>
</el-card>
<el-card shadow="hover" class="m-b-20">
<div class="flex j-between m-b-20">
<div class="flex a-center">
<p class="hr_tag"></p>
<span>练习批阅</span>
</div>
</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="userName" label="真实姓名" align="center"></el-table-column>
<el-table-column prop="workNumber" label="学号" align="center"></el-table-column>
<el-table-column label="批阅状态" align="center">
<template slot-scope="scope">
{{getReviewStatusName(scope.row.reviewStatus)}}
</template>
</el-table-column>
<el-table-column label="操作" align="center">
<template slot-scope="scope">
<el-button type="text" @click="review(scope.row,false)">查看</el-button>
<el-button type="text" @click="review(scope.row,true)" v-if="(scope.row.reviewStatus == 0 || scope.row.reviewStatus == 1) && scope.row.examinationStatus == 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>
</div>
</template>
<script>
import { mapState,mapGetters,mapActions } from 'vuex'
export default {
data() {
return {
state: '3',
reviewStatusList: [
{
id: 0,
name: '未批阅'
},{
id: 1,
name: '批阅部分'
},{
id: 2,
name: '已批阅'
}
],
keyword: '',
listData: [],
page: 1,
pageSize: 10,
total: 0,
searchTimer: null,
};
},
computed: {
...mapState('user', [
'userId','clientId'
]),
...mapState('practice', [
'practiseId'
]),
...mapGetters('practice', [
'getReviewStatusName'
])
},
mounted() {
this.getData()
},
watch: {
keyword: function(val) {
clearTimeout(this.searchTimer)
this.searchTimer = setTimeout(() => {
this.getData()
},500)
}
},
methods: {
...mapActions('practice', [
'setReviewByStudentInfo'
]),
getData() {
this.$post(`${this.api.practiceReviewList}?pageNum=${this.page}&pageSize=${this.pageSize}&practiseId=${this.practiseId}&keyword=${this.keyword}&state=${this.state}`)
.then(res => {
this.listData = res.data.list.list
this.total = res.data.list.totalCount
})
.catch(err => {})
},
handleCurrentChange(val) {
this.page = val
this.getData()
},
review(row,isReview){
this.setReviewByStudentInfo({
userId: row.userId
})
this.$router.push('result')
}
}
};
</script>
<style lang="scss" scoped>
/deep/.no-mb.el-form-item{
margin-bottom: 0;
}
</style>

@ -0,0 +1,269 @@
<template>
<div>
<el-row :gutter="20">
<el-col :span="24">
<el-card shadow="hover" class="m-b-20">
<div class="flex a-center m-b-20">
<p class="hr_tag"></p>
<span>筛选</span>
</div>
<div class="flex j-between">
<el-form label-width="80px" inline>
<el-form-item class="no-mb" label="教学班级">
<el-select v-model="classId" clearable placeholder="请选择教学班级" @change="getData">
<el-option v-for="(item,index) in classList" :key="index" :label="item.className" :value="item.classId"></el-option>
</el-select>
</el-form-item>
<el-form-item class="no-mb" label="练习名称">
<el-select v-model="practiseId" clearable placeholder="请选择练习名称" @change="getData" :disabled="classIdAss ? true : classId == ''">
<el-option v-for="(item,index) in practiceNameList" :key="index" :label="item.practiseName" :value="item.practiseId"></el-option>
</el-select>
</el-form-item>
</el-form>
<div>
<el-input
placeholder="请输入学生姓名或学号"
prefix-icon="el-icon-search"
v-model="keyword"
clearable
></el-input>
</div>
</div>
</el-card>
</el-col>
<el-col :span="24">
<el-card shadow="hover" class="m-b-20">
<div class="flex j-between m-b-20">
<div class="flex a-center">
<p class="hr_tag"></p>
<span>练习成绩</span>
</div>
<div>
<el-button
type="primary"
size="small"
round
@click="exportData"
>导出</el-button>
</div>
</div>
<el-table
:data="listData"
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">
<template
slot-scope="scope"
>{{scope.$index + (page - 1) * pageSize + 1}}</template>
</el-table-column>
<el-table-column prop="userName" label="真实姓名" align="center"></el-table-column>
<el-table-column prop="workNumber" label="学号" align="center"></el-table-column>
<el-table-column prop="max" label="最高分" align="center"></el-table-column>
<el-table-column prop="min" label="最低分" align="center"></el-table-column>
<el-table-column prop="avg" label="平均分" align="center"></el-table-column>
<el-table-column label="操作" align="center">
<template slot-scope="scope">
<el-button type="text" @click="showDetail(scope.row)">查看详情</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-col>
</el-row>
<el-dialog title="练习成绩详情" :visible.sync="detailVisible" width="40%" :close-on-click-modal="false">
<div class="flex flex-j-e">
<div class="m-b-20">
<el-input
placeholder="请输入练习项目名称"
prefix-icon="el-icon-search"
v-model="keywordAch"
clearable
></el-input>
</div>
</div>
<el-table
:data="achiList"
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="paperName" label="练习试卷名称" align="center"></el-table-column>
<el-table-column prop="examTime" label="开始时间" align="center"></el-table-column>
<el-table-column prop="score" label="得分" align="center"></el-table-column>
<el-table-column label="操作" align="center">
<template slot-scope="scope">
<el-button type="text" @click="show(scope.row)">查看</el-button>
</template>
</el-table-column>
</el-table>
<div class="pagination">
<el-pagination
background
@current-change="handleAchCurrentChange"
:current-page="pageAch"
:page-size="pageSizeAch"
layout="total,prev, pager, next"
:total="totalAch"
></el-pagination>
</div>
<span slot="footer" class="dialog-footer">
<el-button @click="detailVisible = false">取消</el-button>
<el-button type="primary">确定</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import { mapState,mapActions } from 'vuex'
import Setting from '@/setting'
export default {
data() {
return {
classId: '',
classList: [],
practiseId: '',
practiceNameList: [],
keyword: '',
listData: [],
page: 1,
pageSize: 10,
total: 0,
searchTimer: null,
detailVisible: false,
keywordAch: '',
achiList: [],
multipleSelectionAch: [],
pageAch: 1,
pageSizeAch: 10,
totalAch: 0,
};
},
computed: {
...mapState('user', [
'userId'
]),
...mapState('achievement', [
'practiceIdAss','practiceNameAss','classIdAss','classNameAss'
]),
},
mounted() {
this.getClass()
},
watch: {
keyword: function(val) {
clearTimeout(this.searchTimer)
this.searchTimer = setTimeout(() => {
this.getData()
},500)
},
keywordAch: function(val) {
clearTimeout(this.searchTimer)
this.searchTimer = setTimeout(() => {
this.getData()
},500)
}
},
methods: {
...mapActions('achievement', [
'setPracDetailInfo'
]),
getData() {
this.$post(`${this.api.AchievementList}?pageNum=${this.page}&pageSize=${this.pageSize}&keyword=${this.keyword}&practiseId=${this.practiseId}&classId=${this.classId}`)
.then(res => {
this.listData = res.data.list.list
this.total = res.data.list.totalCount
})
.catch(err => {})
},
getClass() {
let classId = this.classIdAss.split(',')
let className = this.classNameAss.split(',')
let classList = []
classId.map((n,i) => {
classList.push({
classId: n,
className: className[i]
})
})
this.classId = classId[0]
this.classList = classList
this.practiceNameList = [{
practiseId: this.practiceIdAss,
practiseName: this.practiceNameAss
}]
this.practiseId = this.practiceIdAss
this.getData()
},
handleCurrentChange(val) {
this.page = val
this.getData()
},
showDetail(row){
this.getDetail(row)
this.detailVisible = true
},
getDetail(row){
this.$post(`${this.api.AchievementDetail}?userId=${row.userId}&practiseId=${this.practiseId}&pageNum=${this.page}&pageSize=${this.pageSize}`)
.then(res => {
this.achiList = res.data.list.list
this.totalAch = res.data.list.totalCount
}).catch(err => {})
},
handleSelectionChange(val) {
this.multipleSelection = val
},
show(row){
this.setPracDetailInfo({
practiseId: this.practiseId,
})
this.$router.push('detail')
},
handleAchCurrentChange(val) {
this.page = val
this.getData()
},
exportData(){
location.href = `${Setting.apiBaseURL}${this.api.exportPractice}?practiseId=${this.practiseId}&classId=${this.classId}`
},
}
};
</script>
<style lang="scss" scoped>
/deep/.no-mb.el-form-item{
margin-bottom: 0;
}
</style>

@ -91,7 +91,7 @@
</el-table-column>
<el-table-column prop="questionStem" label="题干" align="center">
<template slot-scope="scope">
<div v-html="scope.row.questionStem"></div>
<div class="ellipsis" v-html="scope.row.questionStem"></div>
</template>
</el-table-column>
<el-table-column prop="name" label="试题类型" width="100" align="center"></el-table-column>
@ -206,7 +206,11 @@ export default {
userId: this.userId
})
.then(res => {
this.listData = res.data.list.list
let list = res.data.list.list
list.map(n => {
n.questionStem = n.questionStem.replace(/<\/?.+?>/gi,'')
})
this.listData = list
this.total = res.data.list.totalCount
})
.catch(err => {})
@ -290,10 +294,10 @@ export default {
.catch(() => {});
},
handleSelectionChange(val) {
this.multipleSelection = val;
this.multipleSelection = val
},
shareDataBatch() {
if(this.multipleSelection.length != ''){
if(this.multipleSelection.length){
let newArr = this.multipleSelection
let shareList = newArr.map(item => {
return item.id
@ -309,19 +313,20 @@ export default {
}
this.$post(this.api.batchSave,data).then(res => {
this.multipleSelection = [];
this.$message.success('共享成功');
this.$message.success('共享成功')
this.getData()
this.$refs.table.clearSelection()
}).catch(res => {
this.getData()
})
})
.catch(() => {});
}else{
this.$message.error('请先选择数据');
this.$message.error('请先选择数据')
}
},
cancelShareBatch() {
if(this.multipleSelection.length != ''){
if(this.multipleSelection.length){
let newArr = this.multipleSelection
let shareList = newArr.map(item => {
return item.id
@ -361,15 +366,16 @@ export default {
this.multipleSelection = [];
this.$message.success('删除成功');
this.getData()
}).catch(res => {});
this.$refs.table.clearSelection()
}).catch(res => {})
})
.catch(() => {});
.catch(() => {})
}else{
this.$message.error('请先选择数据!');
this.$message.error('请先选择数据!')
}
},
downLoad() {
location.href = this.api.getExcel
location.href = 'http://39.108.250.202:9000/cjEnterprise/questions/getExcel'
},
showimportVisible() {
this.importVisible = true

@ -14,11 +14,6 @@
<el-option v-for="(item,index) in quesBankList" :key="index" :label="item.typeName" :value="item.cid"></el-option>
</el-select>
</el-form-item>
<!-- <el-form-item label="考试题型" prop="questionStem">
<el-select v-model="topicForm.typeId" clearable placeholder="请选择考试题型">
<el-option v-for="(item,index) in typeList" :key="index" :label="item.name" :value="item.name"></el-option>
</el-select>
</el-form-item> -->
<el-form-item label="所属课程" prop="courses">
<el-input v-model="topicForm.courses"></el-input>
</el-form-item>
@ -36,6 +31,7 @@
</el-form-item>
<el-form-item label="上传" prop="source">
<el-upload
:accept="acceptExt"
:on-remove="handleRemove"
:on-error="uploadError"
:on-success="uploadSuccess"
@ -44,28 +40,38 @@
:on-exceed="handleExceed"
:action="this.api.fileupload"
:file-list="uploadList"
name="file"
>
<el-button type="primary" class="ml20">上传视频/音频</el-button>
</el-upload>
<el-link v-if="uploadFaild" type="primary" @click="showFaild">导入失败查看原因</el-link>
</el-form-item>
<el-form-item label="题干" prop="questionStem">
<quill :border="true" :readonly="isDetail" :key="isDetail" v-model="topicForm.questionStem" :minHeight="150" :height="150" />
</el-form-item>
<el-form-item label="选项" prop="optionA" v-if="topicForm.questionType != '填空题' && topicForm.questionType != '简答题'">
<div class="input flex_around bt">
<span>A</span>
<el-input placeholder="请输入题目" v-model="topicForm.optionA"></el-input>
<el-checkbox v-model="topicForm.aisTrue">设为正确答案</el-checkbox>
</div>
<div class="input flex_around bt">
<span>B</span>
<el-input placeholder="请输入题目" v-model="topicForm.optionB"></el-input>
<el-checkbox v-model="topicForm.bisTrue">设为正确答案</el-checkbox>
</div>
<template v-if="topicForm.questionType != '判断题'">
<template v-if="topicForm.questionType == '判断题'">
<div class="input flex_around bt">
<span>A</span>
<el-input placeholder="请输入题目" v-model="topicForm.judgeOptionA" disabled></el-input>
<el-radio v-model="topicForm.aisTrue" label="1">设为正确答案</el-radio>
</div>
<div class="input flex_around bt">
<span>B</span>
<el-input placeholder="请输入题目" v-model="topicForm.judgeOptionB" disabled></el-input>
<el-radio v-model="topicForm.aisTrue" label="2">设为正确答案</el-radio>
</div>
</template>
<template v-else>
<div class="input flex_around bt">
<span>A</span>
<el-input placeholder="请输入题目" v-model="topicForm.optionA"></el-input>
<el-checkbox v-model="topicForm.aisTrue">设为正确答案</el-checkbox>
</div>
<div class="input flex_around bt">
<span>B</span>
<el-input placeholder="请输入题目" v-model="topicForm.optionB"></el-input>
<el-checkbox v-model="topicForm.bisTrue">设为正确答案</el-checkbox>
</div>
<div class="input flex_around bt">
<span>C</span>
<el-input placeholder="请输入题目" v-model="topicForm.optionC"></el-input>
@ -124,11 +130,11 @@ export default {
props: ['visible','title','isDetail'],
data() {
return {
acceptExt: '.avi,.wmv,.mpg,.mpeg,.mov,.rm,.ram,.swf,.flv,.mp4,.mp3,.wma,.avi,.rm,.rmvb,.flv,.mpg,.mkv',
quesBankList: [],
typeList: [],
topicForm: {
userId: this.userId,
schoolId: this.clientId,
cid : '',
typeId: '',
courses: '',
@ -148,6 +154,8 @@ export default {
disTrue: false,
eisTrue: false,
fisTrue: false,
judgeOptionA: '正确',
judgeOptionB: '错误',
answerAnalysis: '',
videoAudio: ''
},
@ -157,31 +165,22 @@ export default {
knowledgePoints: [{ required: true, message: '请填写知识点', trigger: 'blur' }],
questionType: [{ required: true, message: '请选择题型', trigger: 'change' }],
questionStem: [{ required: true, message: '请填写题干', trigger: 'blur' }],
// optionA: [{ required: true, message: '', trigger: 'change' }],
// optionB: [{ required: true, message: '', trigger: 'change' }]
},
options: 'ABCDEF',
questionType: ['','单选题','多选题','判断题','简答题','填空题'],
fillList: [''],
uploadList: [],
uploadFaild: false
};
},
computed: {
...mapState('user', [
'userId','clientId'
'userId'
])
},
components: { quill },
mounted() {
this.topicForm.schoolId = this.clientId
this.getQuesBank()
},
// watch: {
// visible(val){
// this.toTop()
// }
// },
methods: {
getData(id) {
this.$post(`${this.api.findById}?id=${id}`)
@ -190,7 +189,6 @@ export default {
this.topicForm = {
id: list.id,
userId: list.userId,
schoolId: list.schoolId,
cid : list.cid,
typeId: list.typeId,
courses: list.courses,
@ -210,16 +208,24 @@ export default {
disTrue: false,
eisTrue: false,
fisTrue: false,
judgeOptionA: '正确',
judgeOptionB: '错误',
answerAnalysis: list.answerAnalysis,
videoAudio: list.videoAudio
},
this.topicForm.questionType = this.questionType[this.topicForm.typeId]
let typeId = this.topicForm.typeId
if(typeId == 1 || typeId == 2 || typeId == 3){
if(typeId == 1 || typeId == 2){
let answer = this.topicForm.answer.toLowerCase().split('')
answer.forEach(n => {
this.topicForm[`${n}isTrue`] = true
})
}else if(typeId == 3){
if(this.topicForm.answer == 'A'){
this.topicForm.aisTrue = '1'
}else{
this.topicForm.aisTrue = '2'
}
}else if(typeId == 5){
let fillList = []
for(let n in this.topicForm) {
@ -245,6 +251,9 @@ export default {
for(let i in this.topicForm){
if(i.includes('isTrue')) this.topicForm[i] = false
}
if(this.topicForm.questionType == '判断题'){
this.topicForm.aisTrue = '1'
}
},
saveTopics() {
this.$refs.topicForm.validate((valid) => {
@ -254,7 +263,18 @@ export default {
let answer = ''
let isInvalidAnswer = false
this.topicForm.typeId = this.questionType.indexOf(topicForm.questionType)
if(topicForm.typeId != 4 && topicForm.typeId != 5){
if(this.topicForm.typeId == 3){
this.topicForm.optionA = '正确'
this.topicForm.optionB = '错误'
if(this.topicForm.aisTrue == 1){
this.topicForm.aisTrue = true
this.topicForm.answer = 'A'
}else{
this.topicForm.bisTrue = true
this.topicForm.answer = 'B'
}
}
if(topicForm.typeId == 1 || topicForm.typeId == 2 || topicForm.typeId == 3){
for(let n in topicForm) {
if(n.includes('option')) {
topicForm[n] != '' && ++optionCount
@ -265,9 +285,10 @@ export default {
if(!topicForm[`option${curOpt.toUpperCase()}`].length) isInvalidAnswer = true
}
}
if(optionCount < 2) return this.$message.warning('请至少添加两个选项!');
if(!answer) return this.$message.warning('请设置正确答案!');
if(topicForm.questionType != '多选题' && answer.length > 1) return this.$message.warning('单选题、判断题只能设置一个正确答案!');
if(optionCount < 2) return this.$message.warning('请至少添加两个选项!')
if(!answer) return this.$message.warning('请设置正确答案!')
if(topicForm.questionType == '单选题' && answer.length > 1) return this.$message.warning('单选题只能设置一个正确选项!')
if(topicForm.questionType == '多选题' && answer.length < 2) return this.$message.warning('多选题必须设置至少两个正确选项!')
if(isInvalidAnswer) return this.$message.warning('正确答案选项为空,请重新设置!');
this.topicForm.answer = answer.toUpperCase()
}else if(this.topicForm.typeId == 5){
@ -284,24 +305,24 @@ export default {
if(this.topicForm.id) {
this.$post(this.api.updateQuestions,this.topicForm).then(res => {
if(res.success) {
this.$message.success('修改成功');
this.$message.success('修改成功')
this.$emit('getData')
}else{
this.$message.error(res.data.message);
this.$message.error(res.data.message)
}
}).catch(res => {});
}).catch(res => {})
}else{
this.$post(this.api.addQuestions,this.topicForm).then(res => {
if(res.success) {
this.$message.success('新增成功');
this.$message.success('新增成功')
this.$emit('getData')
}else{
this.$message.error(res.data.message);
this.$message.error(res.data.message)
}
}).catch(res => {});
}).catch(res => {})
}
}else{
return false;
return false
}
})
},
@ -311,7 +332,6 @@ export default {
resetForm() {
this.topicForm = {
userId: this.userId,
schoolId: this.clientId,
cid : '',
typeId: '',
courses: '',
@ -331,6 +351,8 @@ export default {
disTrue: false,
eisTrue: false,
fisTrue: false,
judgeOptionA: '正确',
judgeOptionB: '错误',
answerAnalysis: '',
videoAudio: ''
}
@ -345,7 +367,7 @@ export default {
this.topicForm.id = id
this.topicForm.questionType = this.questionType[this.topicForm.questionType]
this.NewTopics = true
}).catch(res => {});
}).catch(res => {})
},
addFill(){
if(this.fillList.some(n => n === '')) return this.$message.warning('请先填写当前答案')
@ -357,14 +379,10 @@ export default {
handleExceed(files, fileList) {
this.$message.warning(
`当前限制选择 1 个文件,如需更换,请删除上一个文件再重新选择!`
);
)
},
uploadSuccess(res, file, fileList) {
this.uploadFaild = false
if(res.data.token){
this.token = res.data.token
this.uploadFaild = true
}
this.topicForm.videoAudio = res.data.filesResult.fileId
},
showFaild(){
location.href = `${this.api.export_failure}?token=${this.token}`
@ -442,5 +460,4 @@ export default {
padding-right: 20px;
overflow: auto;
}
</style>
</style>

@ -1,26 +1,14 @@
<template>
<div
style="width:100%;height:100%;display:flex;
align-items: center;flex-direction:column "
>
<!-- 头像部分 -->
<div style="width:100%;height:100%;display:flex;align-items: center;flex-direction:column">
<div class="header">
<img :src="avatar" class="HeadPortrait" />
<div style="color:#cb221c;font-size:14px;font-family:MicrosoftYaHei;margin-top:5px;">
<el-upload
class="upload-demo"
action="http://www.liuwanr.cn:8080/user/uploadUserAvatars"
:data="{userId:this.userId}"
name="file"
:limit="3"
:on-success="getRes"
>
<el-upload :action="this.api.fileupload" :on-success="changeAvatar">
<div>点击更改头像</div>
</el-upload>
</div>
</div>
<!-- 用户信息 -->
<div class="card">
<p class="block-title" style="display: flex;justify-content: space-between;align-items: center;">
用户信息
@ -272,7 +260,7 @@
</template>
<script>
import { mapState,mapActions } from 'vuex';
import { mapState,mapActions } from 'vuex'
export default {
data() {
return {
@ -390,12 +378,8 @@ export default {
}
}).catch(res => {});
},
//
getRes(res) {
this.setAvatar(res.message)
},
uploadHeadImg: function() {
this.$el.querySelector('.hiddenInput').click();
changeAvatar(res) {
this.setAvatar(res.data.filesResult.fileUrl)
},
getdata() {
this.$get(`${this.api.userinfo}?userId=${this.userId}`)

@ -242,11 +242,16 @@
<el-button type="primary" v-throttle @click="submitInte">确定</el-button>
</span>
</el-dialog>
<el-dialog title="选择试题" :visible.sync="previewVisible" width="60%">
<test-paper :data="previewList" :key="previewIndex"></test-paper>
</el-dialog>
</div>
</template>
<script>
import mixins from '@/mixins/setBackground';
import mixins from '@/mixins/setBackground'
import { mapState } from 'vuex'
import testPaper from '@/components/testPaperDetail'
export default {
mixins: [ mixins ],
data() {
@ -273,6 +278,9 @@ export default {
briefAnswerScore: '',
multipleSelected: [],
typeNameList: ['单选题','多选题','判断题','填空题','简答题'],
previewVisible: false,
previewIndex: 0,
previewList: [],
//
isFirstSubmitMana: true,
@ -324,6 +332,7 @@ export default {
selectedData: []
};
},
components: {testPaper},
computed: {
...mapState('user', [
'userId','clientId'
@ -470,7 +479,7 @@ export default {
this.total = newData.length
this.$refs.listTable.clearSelection()
})
.catch(err => {});
.catch(err => {})
},
handleSelecteChange(val){
this.multipleSelected = val;
@ -496,15 +505,16 @@ export default {
}
},
preview(){
if(this.multipleSelected.length == 1){
this.$router.push(`show?id=${this.multipleSelected[0].id}`)
}else{
this.$message.error('请选择一条数据')
}
this.$post(`${this.api.previewPaper}?qid=${this.selectedData.map(n => n.id).join(',')}`)
.then(res => {
this.previewIndex++
this.previewList = res.data
this.previewVisible = true
}).catch(err => {})
},
handleCurrentChange(val) {
this.page = val;
this.getManualData();
this.page = val
this.getManualData()
},
handleSelectionChange(val) {
this.multipleSelection = val
@ -513,14 +523,13 @@ export default {
this.$post(`${this.api.getSelectInfo}?type=1`)
.then(res => {
this.pointList = res.data.pointList
})
.catch(err => {});
}).catch(err => {})
this.$post(`${this.api.getSelectInfo}?type=2`)
.then(res => {
this.courseList = res.data.pointList
})
.catch(err => {});
.catch(err => {})
},
getType() {
this.$get(this.api.typesList)

@ -31,6 +31,12 @@ export default {
component: () => import('@/pages/assessment/scoreQuery/index.vue'),
meta: { title: '成绩查询' }
},
{
name: `${pre}detail`,
path: `detail`,
component: () => import('@/pages/assessment/detail'),
meta: { title: '答题详情' }
},
{
name: `${pre}monitor`,
path: `monitor`,

@ -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: '交流互动' }
},
]
};

@ -0,0 +1,52 @@
import BasicLayout from '@/layouts/home';
const meta = {};
const pre = 'practice-';
export default {
path: '/practice',
name: 'practice',
redirect: {
name: `${pre}list`
},
meta,
component: BasicLayout,
children: [
{
name: `${pre}list`,
path: `list`,
component: () => import('@/pages/practice/list'),
meta: { title: '练习管理' }
},
{
name: `${pre}review`,
path: `review`,
component: () => import('@/pages/practice/review'),
meta: { title: '练习批阅' }
},
{
name: `${pre}scoreQuery`,
path: `scoreQuery`,
component: () => import('@/pages/practice/scoreQuery/index.vue'),
meta: { title: '成绩查询' }
},
{
name: `${pre}result`,
path: `result`,
component: () => import('@/pages/practice/result'),
meta: { title: '查看成绩' }
},
{
name: `${pre}detail`,
path: `detail`,
component: () => import('@/pages/practice/detail'),
meta: { title: '答题详情' }
},{
name: `${pre}doReview`,
path: `doReview`,
component: () => import('@/pages/practice/doReview'),
meta: { title: '批阅' }
},
]
};

@ -5,6 +5,8 @@ import assessment from './modules/assessment';
import achievement from './modules/achievement';
import system from './modules/system';
import setting from './modules/setting';
import messageBoard from './modules/messageBoard';
import practice from './modules/practice';
import BasicLayout from '@/layouts/home';
@ -26,6 +28,8 @@ const frameIn = [
achievement,
system,
setting,
messageBoard,
practice
]
/**

@ -17,6 +17,8 @@ const Setting = {
// 接口请求地址
// 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:9000',
// oss文件管理接口地址
apiUploadURL: 'http://8.134.8.197:8001',
// 接口请求返回错误时,弹窗的持续时间,单位:秒
modalDuration: 3,
// 接口请求返回错误时,弹窗的类型,可选值为 Message 或 Notice
@ -51,7 +53,7 @@ const Setting = {
menuSideWidth: 256,
layout: {
// 需要隐藏顶栏的页面路径
hideNavList: ['testPaper-add','testPaper-review','testPaper-show','testPaper-doReview','assessment-review','assessment-scoreQuery','assessment-monitor','achievement-show','achievement-statistics','achievement-detail','setting-person'],
hideNavList: ['testPaper-add','testPaper-review','testPaper-show','testPaper-doReview','assessment-review','assessment-scoreQuery','assessment-detail','assessment-monitor','achievement-show','achievement-statistics','achievement-detail','setting-person','practice-review','practice-scoreQuery','practice-result','practice-detail','practice-doReview'],
// 侧边栏风格,可选值为 dark 或 light
siderTheme: 'dark',
// 顶栏风格,可选值为 light、dark 或 primary

@ -8,23 +8,55 @@ export default {
stuId: '',
assessmentId: '',
assessmentName: '',
classId: ''
classId: '',
assessmentIdAss: '',
assessmentNameAss: '',
classIdAss: '',
classNameAss: '',
practiseId: '',
practiceIdAss: '',
practiceNameAss: ''
},
getters: {
},
mutations: {
SET_INFO: (state, info) => {
SET_ASS_DETAIL_INFO: (state, info) => {
state.id = info.id
state.stuId = info.stuId
state.assessmentId = info.assessmentId
state.assessmentName = info.assessmentName
state.classId = info.classId
},
SET_ASS_LIST_INFO: (state, info) => {
state.assessmentIdAss = info.assessmentIdAss
state.assessmentNameAss = info.assessmentNameAss
state.classIdAss = info.classIdAss
state.classNameAss = info.classNameAss
},
SET_RRAC_DETAIL_INFO: (state, info) => {
state.practiseId = info.practiseId
state.stuId = info.stuId
},
SET_PRAC_LIST_INFO: (state, info) => {
state.practiceIdAss = info.practiceIdAss
state.practiceNameAss = info.practiceNameAss
state.classIdAss = info.classIdAss
state.classNameAss = info.classNameAss
},
},
actions: {
setInfo({ commit },info) {
commit('SET_INFO',info)
setAssListInfo({ commit },info) {
commit('SET_ASS_LIST_INFO',info)
},
setAssDetailInfo({ commit },info) {
commit('SET_ASS_DETAIL_INFO',info)
},
setPracListInfo({ commit },info) {
commit('SET_PRAC_LIST_INFO',info)
},
setPracDetailInfo({ commit },info) {
commit('SET_RRAC_DETAIL_INFO',info)
},
}
}

@ -0,0 +1,107 @@
/**
* 考核管理
* */
export default {
namespaced: true,
state: {
practiseId: '',
endTime: '',
id: '',
paperId: '',
stuId: '',
isReview: false,
reviewStatus: '',
userId: '',
stateList: [
{
id: 1,
name: '待开始'
},{
id: 2,
name: '进行中'
},{
id: 3,
name: '已结束'
}
],
reviewStatusList: [
{
id: 0,
name: '未批阅'
},{
id: 1,
name: '批阅部分'
},{
id: 2,
name: '已批阅'
},{
id: 3,
name: '没有主观题,不需要批阅'
}
],
examStatusList: [
{
id: 0,
name: '未考'
},{
id: 1,
name: '在考'
},{
id: 2,
name: '已考'
}
],
correctingList: [
{
id: 0,
name: '待阅'
},{
id: 1,
name: '已阅'
}
],
},
getters: {
getStateName: state => id => {
return state.stateList.find(n => n.id == id).name
},
getReviewStatusName: state => id => {
return state.reviewStatusList.find(n => n.id == id).name
},
getExamStatusName: state => id => {
return state.examStatusList.find(n => n.id == id).name
},
getCorrectingName: state => id => {
return state.correctingList.find(n => n.id == id).name
},
},
mutations: {
SET_INFO: (state, info) => {
state.practiseId = info.practiseId
state.endTime = info.endTime
},
SET_REVIEW_INFO: (state, info) => {
state.id = info.id
state.practiseId = info.practiseId
state.paperId = info.paperId
state.stuId = info.stuId
state.isReview = info.isReview
state.reviewStatus = info.reviewStatus
state.identification = info.identification
},
SET_REVIEW_BY_STUDENT_INFO: (state, info) => {
state.userId = info.userId
},
},
actions: {
setPracInfo({ commit },info) {
commit('SET_INFO',info)
},
setReviewByStudentInfo({ commit },info) {
commit('SET_REVIEW_BY_STUDENT_INFO',info)
},
setReviewInfo({ commit },info) {
commit('SET_REVIEW_INFO',info)
},
}
}

@ -1,9 +1,10 @@
import addRoutes from '@/libs/route/addRoutes';
import Setting from '@/setting';
import util from '@/libs/util';
import { Message } from 'element-ui';
import {post,get,del,put} from '@/plugins/requests/index.js'
import api from '@/api';
import addRoutes from '@/libs/route/addRoutes'
import Setting from '@/setting'
import util from '@/libs/util'
import { Message } from 'element-ui'
import {post,get} from '@/plugins/requests/index.js'
import api from '@/api'
import bus from '@/libs/bus'
/**
* 用户信息
@ -23,6 +24,7 @@ export default {
},
mutations: {
SET_INFO: (state, info) => {
info.avatar && (state.avatar = info.avatar)
state.userId = info.userId
state.roleId = info.roleId
state.userName = info.userName
@ -60,6 +62,7 @@ export default {
if(user.isPort == 0 || user.isPort == 2){
let routes = res.data.permissions[0].children
commit('SET_INFO',{
avatar: user.userAvatars,
userId: user.userId,
roleId: user.roleId,
userName: user.userName,
@ -92,8 +95,13 @@ export default {
resolve()
})
},
setAvatar({ commit },avatar) {
setAvatar({ state,commit },avatar) {
commit('SET_AVATAR',avatar)
let data = {
userId: state.userId,
userAvatars: avatar
}
post(api.userinfoUpdate,data).then(res => {}).catch(res => {})
},
}
}

@ -228,6 +228,10 @@ select {
text-transform: none;
}
button:focus{
outline: none;
}
button,
html [type="button"],
[type="reset"],

@ -26,3 +26,4 @@
@import "white-space";
@import "style";
@import "mixin";

@ -0,0 +1,9 @@
@mixin ellipsis {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.ellipsis{
@include ellipsis();
}
Loading…
Cancel
Save