提交 b9a48a84 authored 作者: 王鹏飞's avatar 王鹏飞

merge...

...@@ -211,15 +211,30 @@ export default class CourseAction extends BaseACTION { ...@@ -211,15 +211,30 @@ export default class CourseAction extends BaseACTION {
// type: 102 // type: 102
// }) // })
if (cur.course_examination) { if (cur.course_examination) {
let courseExamChildren = []
if (data.exist_examination.length > 1) {
courseExamChildren = data.exist_examination.map((item, index) => {
const map = ['一', '二', '三']
return {
name: `第${map[index]}次考试`,
id: 'course_exam',
offset: index,
sid: sid,
cid: cid,
examId: cur.course_examination,
type: 101
}
})
}
json.tabs1ChapterList.course.push({ json.tabs1ChapterList.course.push({
title: '课程考试', title: '课程考试',
isUp: true, isUp: true,
chapters: [], chapters: courseExamChildren,
id: 'course_exam', id: 'course_exam',
sid: sid, sid: sid,
cid: cid, cid: cid,
examId: cur.course_examination, examId: cur.course_examination,
type: 102 type: 101
}) })
} }
/* 课程考核 考核标准文案读取 */ /* 课程考核 考核标准文案读取 */
......
...@@ -76,7 +76,7 @@ export default class API { ...@@ -76,7 +76,7 @@ export default class API {
// _vIn.$router.push({ // _vIn.$router.push({
// path: '/login/index?rd=' + encodeURIComponent(href.replace(/.*?\/\/.*?\//gi, '/')) // path: '/login/index?rd=' + encodeURIComponent(href.replace(/.*?\/\/.*?\//gi, '/'))
// }) // })
window.location.href = `${webConf.others.loginUrl}'?rd=${encodeURIComponent(window.location.href)}` window.location.href = `${webConf.others.loginUrl}?rd=${encodeURIComponent(window.location.href)}`
} }
} }
......
...@@ -6,7 +6,7 @@ export default class Before { ...@@ -6,7 +6,7 @@ export default class Before {
this.opt = opt || {} this.opt = opt || {}
// 免登录列表 // 免登录列表
this.whiteList = ['login-normal', 'login-code', 'login-forget', 'studentHelp', 'teacherHelp'] this.whiteList = ['login-normal', 'login-code', 'login-forget', 'studentHelp', 'teacherHelp']
this.isMobile = /android|iphone|ipad|ipod/i.test(UA) this.isMobile = /iphone/i.test(UA) || (/android/i.test(UA) && /mobile/i.test(UA))
} }
async update(to, from, next) { async update(to, from, next) {
......
...@@ -10,7 +10,7 @@ export default { ...@@ -10,7 +10,7 @@ export default {
name: 'VEditor', name: 'VEditor',
props: { props: {
value: { type: String }, value: { type: String },
disabled: { type: Boolean, default: null } disabled: { type: Boolean, default: false }
}, },
data() { data() {
return { return {
...@@ -49,16 +49,7 @@ export default { ...@@ -49,16 +49,7 @@ export default {
'/', '/',
{ {
name: 'basicstyles', name: 'basicstyles',
items: [ items: ['Bold', 'Italic', 'Underline', 'Strike', 'Subscript', 'Superscript', '-', 'RemoveFormat']
'Bold',
'Italic',
'Underline',
'Strike',
'Subscript',
'Superscript',
'-',
'RemoveFormat'
]
}, },
{ {
name: 'paragraph', name: 'paragraph',
...@@ -86,14 +77,12 @@ export default { ...@@ -86,14 +77,12 @@ export default {
] ]
} }
if (this.disabled !== null) { // if (this.disabled !== null) {
config.readOnly = this.disabled // console.log(this.disabled)
} // config.readOnly = this.disabled
// }
const editor = (this.ckEditor = CKEDITOR.replace( const editor = (this.ckEditor = CKEDITOR.replace(this.textareaElementId, config))
this.textareaElementId,
config
))
editor.on('instanceReady', () => { editor.on('instanceReady', () => {
const data = this.value const data = this.value
editor.fire('lockSnapshot') editor.fire('lockSnapshot')
...@@ -118,6 +107,7 @@ export default { ...@@ -118,6 +107,7 @@ export default {
editor.fire('unlockSnapshot') editor.fire('unlockSnapshot')
} }
}) })
editor.setReadOnly(this.disabled)
}) })
}, },
bindEvent() { bindEvent() {
......
...@@ -41,7 +41,7 @@ export default { ...@@ -41,7 +41,7 @@ export default {
}, },
filters: { filters: {
showName(name, data) { showName(name, data) {
if (data.type === 5 && data.live) { if ([5, 8].includes(data.type) && data.live) {
return `${name}(${data.live.start_time})` return `${name}(${data.live.start_time})`
} }
return name return name
......
...@@ -10,7 +10,7 @@ export default { ...@@ -10,7 +10,7 @@ export default {
name: 'VEditor', name: 'VEditor',
props: { props: {
value: { type: String }, value: { type: String },
disabled: { type: Boolean, default: null } disabled: { type: Boolean, default: false }
}, },
data() { data() {
return { return {
...@@ -49,16 +49,7 @@ export default { ...@@ -49,16 +49,7 @@ export default {
'/', '/',
{ {
name: 'basicstyles', name: 'basicstyles',
items: [ items: ['Bold', 'Italic', 'Underline', 'Strike', 'Subscript', 'Superscript', '-', 'RemoveFormat']
'Bold',
'Italic',
'Underline',
'Strike',
'Subscript',
'Superscript',
'-',
'RemoveFormat'
]
}, },
{ {
name: 'paragraph', name: 'paragraph',
...@@ -85,14 +76,13 @@ export default { ...@@ -85,14 +76,13 @@ export default {
{ name: 'insert', items: ['Image', 'Table', 'HorizontalRule'] } { name: 'insert', items: ['Image', 'Table', 'HorizontalRule'] }
] ]
} }
if (this.disabled !== null) {
config.readOnly = this.disabled
}
const editor = (this.ckEditor = CKEDITOR.replace( // if (this.disabled !== null) {
this.textareaElementId, // console.log(this.disabled)
config // config.readOnly = this.disabled
)) // }
const editor = (this.ckEditor = CKEDITOR.replace(this.textareaElementId, config))
editor.on('instanceReady', () => { editor.on('instanceReady', () => {
const data = this.value const data = this.value
editor.fire('lockSnapshot') editor.fire('lockSnapshot')
...@@ -117,6 +107,7 @@ export default { ...@@ -117,6 +107,7 @@ export default {
editor.fire('unlockSnapshot') editor.fire('unlockSnapshot')
} }
}) })
editor.setReadOnly(this.disabled)
}) })
}, },
bindEvent() { bindEvent() {
......
...@@ -10,23 +10,18 @@ ...@@ -10,23 +10,18 @@
</template> </template>
</el-upload> </el-upload>
<div class="file-list" v-if="fileList.length"> <div class="file-list" v-if="fileList.length">
<div class="file-list-item" v-for="(fileUrl, index) in fileList" :key="index"> <div class="file-list-item" v-for="(item, index) in fileList" :key="index">
<a :href="fileUrl" target="_blank"> <a :href="item.url" :download="item.name" target="_blank">
<i class="el-icon-document"></i> <i class="el-icon-document"></i>
{{ fileUrl | fileName }} {{ item.name }}
</a> </a>
<div> <div>
<a <a href="javascript:;" @click="handleRemove(index)" style="margin-right: 10px" v-if="!disabled">
href="javascript:;"
@click="handleRemove(index)"
style="margin-right:10px;"
v-if="!disabled"
>
<el-tooltip effect="dark" content="删除"> <el-tooltip effect="dark" content="删除">
<i class="el-icon-delete"></i> <i class="el-icon-delete"></i>
</el-tooltip> </el-tooltip>
</a> </a>
<a :href="fileUrl" :download="fileUrl | fileName" target="_blank"> <a :href="item.url" :download="item.name" target="_blank">
<el-tooltip effect="dark" content="下载"> <el-tooltip effect="dark" content="下载">
<i class="el-icon-download"></i> <i class="el-icon-download"></i>
</el-tooltip> </el-tooltip>
...@@ -55,29 +50,29 @@ export default { ...@@ -55,29 +50,29 @@ export default {
value: { value: {
immediate: true, immediate: true,
handler(value) { handler(value) {
if (value) { if (!value) {
return
}
let fileList = []
if (Array.isArray(value)) { if (Array.isArray(value)) {
this.fileList = value.map(item => { fileList = value.map(item => {
return item.url || item return { name: item.name || item, url: item.url || item }
}) })
} else { } else {
this.fileList = [value] fileList.push({ name: '附件下载', url: value })
}
} }
this.fileList = fileList
} }
} }
}, },
filters: {
fileName(value) {
return value ? value.split('/').pop() : ''
}
},
methods: { methods: {
httpRequest(xhr) { httpRequest(xhr) {
api.uploadFile({ file: xhr.file }).then(response => { api
.uploadFile({ file: xhr.file })
.then(response => {
if (response.success) { if (response.success) {
if (Array.isArray(this.value)) { if (Array.isArray(this.value)) {
this.fileList.push(response.url) this.fileList.push({ name: xhr.file.name, url: response.url })
this.$emit('input', this.fileList) this.$emit('input', this.fileList)
} else { } else {
this.fileList = [response.url] this.fileList = [response.url]
...@@ -85,6 +80,9 @@ export default { ...@@ -85,6 +80,9 @@ export default {
} }
} }
}) })
.catch(error => {
this.$message.error(error.message)
})
}, },
handleRemove(index) { handleRemove(index) {
this.fileList.splice(index, 1) this.fileList.splice(index, 1)
......
...@@ -68,7 +68,7 @@ export default { ...@@ -68,7 +68,7 @@ export default {
const live = this.live const live = this.live
if (this.isLiveEnd && this.hasRecord) { if (this.isLiveEnd && this.hasRecord) {
// 查看回放 // 查看回放
return live.record_url return live.record_url.replace(/^http:|^https:/, '')
} else { } else {
// 直播 // 直播
live.user_name = live.user_name || this.nickName live.user_name = live.user_name || this.nickName
......
...@@ -224,6 +224,7 @@ export default { ...@@ -224,6 +224,7 @@ export default {
// 提交参数 // 提交参数
const params = { answers: JSON.stringify(answers), type: 1 } const params = { answers: JSON.stringify(answers), type: 1 }
// 请求接口 // 请求接口
this.submitLoading = true
this.handleSubmitRequest(params) this.handleSubmitRequest(params)
}, },
// 自动提交 // 自动提交
...@@ -236,7 +237,7 @@ export default { ...@@ -236,7 +237,7 @@ export default {
const params = { answers: JSON.stringify(answers), type: 0 } const params = { answers: JSON.stringify(answers), type: 0 }
// 请求接口 // 请求接口
this.handleSubmitRequest(params) this.handleSubmitRequest(params)
}, 10000) }, 3000)
}, },
// 处理请求接口答案数据 // 处理请求接口答案数据
handleSubmitData() { handleSubmitData() {
...@@ -266,7 +267,6 @@ export default { ...@@ -266,7 +267,6 @@ export default {
}, },
// 请求提交接口 // 请求提交接口
handleSubmitRequest(params) { handleSubmitRequest(params) {
this.submitLoading = true
params.paper_type = 0 params.paper_type = 0
api api
.submitCourseExam(this.sid, this.cid, this.pid, params) .submitCourseExam(this.sid, this.cid, this.pid, params)
......
<template> <template>
<container :title="detail.title" v-loading="loading"> <container :title="exam.title" v-loading="!loaded">
<template v-slot:header-aside v-if="isExamComplete">分数:{{exam.score.total}}</template> <template v-slot:header-aside>
<template v-if="isCompleted">分数:{{ exam.score.total }}</template>
<template v-else>考试时间:{{ status.start_time }} ~ {{ status.terminate_time }}</template>
</template>
<div class="exam"> <div class="exam">
<template v-if="status.examination_status === '00'"> <template v-if="status.examination_status === '00'">
<div class="no-exam">暂无考试</div> <div class="no-exam">暂无考试</div>
</template> </template>
<template v-else-if="isSubmited && !isExamComplete"> <template v-else-if="isSubmited && !isCompleted && !isMultipleExams">
<div class="no-exam">试卷批改中,请耐心等待</div> <div class="no-exam">试卷批改中,请耐心等待</div>
</template> </template>
<template v-else> <template v-else>
<!-- 考试期间,未开始考试 -->
<div class="exam-welcome" v-if="!isStartExam">
<div>考试时间:{{status.start_time}} ~ {{status.terminate_time}}</div>
<el-button
type="primary"
:disabled="!isExamTime"
@click="onStartExam"
>{{startExamButtonText}}</el-button>
</div>
<!-- 考试试题 --> <!-- 考试试题 -->
<div class="exam-form" v-if="isStartExam"> <div class="exam-form" v-if="loaded">
<el-form :disabled="isSubmited"> <el-form :disabled="!canEditable">
<template v-for="items in questions"> <template v-for="items in questions">
<exam-item <exam-item
v-for="(item, index) in items" v-for="(item, index) in items"
...@@ -28,16 +22,27 @@ ...@@ -28,16 +22,27 @@
:type="item.type" :type="item.type"
:data="item" :data="item"
:value="item.formModel" :value="item.formModel"
:disabled="isSubmited" :disabled="!canEditable"
:showResult="isCompleted"
:key="item.id" :key="item.id"
></exam-item> ></exam-item>
</template> </template>
</el-form>
<div class="exam-buttons"> <div class="exam-buttons">
<!-- 允许多次提交 -->
<template v-if="isMultipleExams">
<el-button type="primary" @click="handlePrev" v-if="hasPrev">上一套试卷</el-button>
<el-button type="primary" @click="handleNext" v-if="hasNext">下一套试卷</el-button>
<el-button type="primary" @click="handleNewExam" v-if="hasResubmit">再考一次</el-button>
</template>
<template v-if="!(isSubmited && isMultipleExams)">
<el-tooltip effect="dark" content="提交之后就不能修改了哦" placement="right"> <el-tooltip effect="dark" content="提交之后就不能修改了哦" placement="right">
<el-button type="primary" :loading="submitLoading" @click="onSubmit">{{submitText}}</el-button> <el-button type="primary" :disabled="!canEditable" :loading="submitLoading" @click="onSubmit">{{
submitText
}}</el-button>
</el-tooltip> </el-tooltip>
</template>
</div> </div>
</el-form>
</div> </div>
</template> </template>
</div> </div>
...@@ -75,16 +80,26 @@ export default { ...@@ -75,16 +80,26 @@ export default {
}, },
data() { data() {
return { return {
loading: false, loaded: false,
detail: {}, detail: {},
status: {}, status: {},
questions: [], questions: [],
messageInstance: null, messageInstance: null,
exam: {}, exam: {},
isStartExam: false, // 是否开始考试
autoSubmitTimer: null, // 自动提交定时器 autoSubmitTimer: null, // 自动提交定时器
checkStatusTimer: null, // 考试状态定时器 checkStatusTimer: null, // 考试状态定时器
submitLoading: false submitLoading: false,
isMultipleExams: false, // 是否可以多次考试
maxExams: 3, // 最多考试几次
examCount: this.data.exist_examination.length || 0 // 试卷数量
}
},
watch: {
offset: {
immediate: true,
handler() {
this.init()
}
} }
}, },
computed: { computed: {
...@@ -105,46 +120,95 @@ export default { ...@@ -105,46 +120,95 @@ export default {
// 大于开始时间,小于结束时间 // 大于开始时间,小于结束时间
return this.status.examination_status === '20' return this.status.examination_status === '20'
}, },
// 考试按钮 // 是否提交
startExamButtonText() { isSubmited() {
return this.status.examination_status === '90' ? '考试结束' : '开始考试' return this.exam.type === 1 || this.exam.type === 2
}, },
// 考试完成 // 考试完成
isExamComplete() { isCompleted() {
// 考试完成,批改完成并且公布成绩 // 考试完成,批改完成并且公布成绩
return this.exam.is_published === 1 && this.exam.type === 2 return this.exam.is_published === 1 && this.exam.type === 2
}, },
// 是否提交 // 可以编辑
isSubmited() { canEditable() {
return this.exam.type === 1 || this.exam.type === 2 return !this.isSubmited && this.isExamTime
}, },
// 提交按钮文本 // 提交按钮文本
submitText() { submitText() {
return this.isSubmited ? '已提交' : '提交' return this.isSubmited ? '已提交' : '提交'
},
// 试卷页码
offset() {
const { query } = this.$route
return parseInt(query.offset) || 0
},
// 是否显示上一套试题
hasPrev() {
return !!this.offset
},
// 是否显示下一套试题
hasNext() {
return this.offset < this.examCount - 1
},
// 是否显示再考一次
hasResubmit() {
if (this.examList.length >= this.maxExams) {
return false
}
// 判断状态是否还有未提交的试题
for (const exam of this.examList) {
if (!['1', '2'].includes(exam.status)) {
return false
}
}
return true
// return this.isSubmited && this.isExamTime && this.examCount < this.maxExams
},
// 已存在的试题列表
examList() {
return this.data.exist_examination
} }
}, },
methods: { methods: {
// 开始考试 // 初始化
onStartExam() { async init() {
this.isStartExam = true this.clearTimer()
// 自动提交答题 // 自动获取考试状态
this.autoSubmit() await this.autoCheckExamStatus()
// 获取试题
this.getExam()
},
// 获取考试状态
async getExamStatus() {
await api.getCourseExamStatus(this.sid, this.cid, this.pid).then(response => {
this.status = response
if (this.isSubmited || response.examination_status === '90') {
this.checkStatusTimer && clearInterval(this.checkStatusTimer)
}
})
},
// 自动获取考试状态
async autoCheckExamStatus() {
// 获取试题状态
await this.getExamStatus()
this.checkStatusTimer && clearInterval(this.checkStatusTimer)
this.checkStatusTimer = setInterval(this.getExamStatus, 5000)
}, },
// 获取试题 // 获取试题
getDetail(callback) { getExam() {
this.loading = true this.loaded = false
api api
.getCourseExam(this.sid, this.cid) .getCourseExamResult(this.sid, this.cid, this.pid, { offset: this.offset })
.then(response => { .then(response => {
this.detail = Array.isArray(response) ? null : response this.exam = response
// 设置问题列表数据 this.questions = this.genQuestions(response.sheet)
this.questions = this.detail // 自动提交
? this.genQuestions(this.detail.examination) this.canEditable && this.autoSubmit()
: [] // 更新菜单
callback && callback() this.isMultipleExams && this.$emit('update')
}) })
.finally(() => { .finally(() => {
this.loading = false this.loaded = true
}) })
}, },
// 组装问题数据 // 组装问题数据
...@@ -176,9 +240,7 @@ export default { ...@@ -176,9 +240,7 @@ export default {
type: 3, type: 3,
formModel: { formModel: {
id: item.id, id: item.id,
user_answer: item.user_answer user_answer: item.user_answer ? Base64.decode(item.user_answer.replace(/ /gi, '+')) : '',
? Base64.decode(item.user_answer.replace(/ /gi, '+'))
: '',
attachments: item.attachments || [] attachments: item.attachments || []
} }
} }
...@@ -187,39 +249,7 @@ export default { ...@@ -187,39 +249,7 @@ export default {
return [...radioList, ...checkboxList, ...shortAnswerList] return [...radioList, ...checkboxList, ...shortAnswerList]
}) })
}, },
// 获取考试状态
getExamStatus() {
api.getCourseExamStatus(this.sid, this.cid, this.pid).then(response => {
this.status = response
if (this.isSubmited || response.examination_status === '90') {
this.checkStatusTimer && clearInterval(this.checkStatusTimer)
}
})
},
// 自动获取考试状态
autoCheckExamStatus() {
// 获取试题状态
this.getExamStatus()
this.checkStatusTimer && clearInterval(this.checkStatusTimer)
this.checkStatusTimer = setInterval(() => {
this.getExamStatus()
}, 3000)
},
// 获取考试结果
getExamResult() {
api.getCourseExamResult(this.sid, this.cid, this.pid).then(response => {
// 设置问题列表数据
if (response.code !== 8001) {
this.isStartExam = true
this.exam = response
this.questions = this.genQuestions(response.sheet)
// 自动提交
if (this.isStartExam && !this.isSubmited && !this.isExamComplete) {
this.autoSubmit()
}
}
})
},
// 提交校验 // 提交校验
checkSubmit() { checkSubmit() {
for (let i = 0; i < this.questions.length; i++) { for (let i = 0; i < this.questions.length; i++) {
...@@ -246,6 +276,7 @@ export default { ...@@ -246,6 +276,7 @@ export default {
// 提交参数 // 提交参数
const params = { answers: JSON.stringify(answers), type: 1 } const params = { answers: JSON.stringify(answers), type: 1 }
// 请求接口 // 请求接口
this.submitLoading = true
this.handleSubmitRequest(params) this.handleSubmitRequest(params)
}, },
// 自动提交 // 自动提交
...@@ -258,7 +289,7 @@ export default { ...@@ -258,7 +289,7 @@ export default {
const params = { answers: JSON.stringify(answers), type: 0 } const params = { answers: JSON.stringify(answers), type: 0 }
// 请求接口 // 请求接口
this.handleSubmitRequest(params) this.handleSubmitRequest(params)
}, 10000) }, 3000)
}, },
// 处理请求接口答案数据 // 处理请求接口答案数据
handleSubmitData() { handleSubmitData() {
...@@ -288,7 +319,7 @@ export default { ...@@ -288,7 +319,7 @@ export default {
}, },
// 请求提交接口 // 请求提交接口
handleSubmitRequest(params) { handleSubmitRequest(params) {
this.submitLoading = true params.offset = this.offset
api api
.submitCourseExam(this.sid, this.cid, this.pid, params) .submitCourseExam(this.sid, this.cid, this.pid, params)
.then(response => { .then(response => {
...@@ -299,7 +330,7 @@ export default { ...@@ -299,7 +330,7 @@ export default {
if (response.code === 200) { if (response.code === 200) {
this.$message.success('考试答卷提交成功') this.$message.success('考试答卷提交成功')
this.autoSubmitTimer && clearInterval(this.autoSubmitTimer) this.autoSubmitTimer && clearInterval(this.autoSubmitTimer)
this.getExamResult() this.getExam()
} else { } else {
this.$message.error(response.data.error) this.$message.error(response.data.error)
} }
...@@ -310,20 +341,34 @@ export default { ...@@ -310,20 +341,34 @@ export default {
.finally(() => { .finally(() => {
this.submitLoading = false this.submitLoading = false
}) })
},
// 上一套试卷
handlePrev() {
const offset = this.offset - 1
this.$router.push({ query: { offset } })
},
handleNext() {
const offset = this.offset + 1
this.$router.push({ query: { offset } })
},
handleNewExam() {
this.$router.push({ query: { offset: this.examCount } })
this.examCount++
},
// 清除定时器
clearTimer() {
this.autoSubmitTimer && clearInterval(this.autoSubmitTimer)
this.checkStatusTimer && clearInterval(this.checkStatusTimer)
} }
}, },
beforeMount() { beforeMount() {
// 获取试题 // // 自动获取考试状态
this.getDetail(() => { // this.autoCheckExamStatus()
// 获取考试结果 // // 获取试题
this.getExamResult() // this.getExam()
// 自动获取考试状态
this.autoCheckExamStatus()
})
}, },
destroyed() { destroyed() {
this.autoSubmitTimer && clearInterval(this.autoSubmitTimer) this.clearTimer()
this.checkStatusTimer && clearInterval(this.checkStatusTimer)
} }
} }
</script> </script>
...@@ -333,7 +378,7 @@ export default { ...@@ -333,7 +378,7 @@ export default {
padding: 40px 0; padding: 40px 0;
text-align: center; text-align: center;
.el-button { .el-button {
width: 240px; min-width: 160px;
margin: 40px auto; margin: 40px auto;
} }
} }
......
<template> <template>
<div class="q-item"> <div class="q-item">
<div class="q-item-hd"> <div class="q-item-hd">
<div class="q-item-num">{{index + 1}}.</div> <div class="q-item-num">{{ index + 1 }}.</div>
<div class="q-item-title" v-html="data.content"></div> <div class="q-item-title" v-html="data.content"></div>
<div class="q-item-aside"> <div class="q-item-aside">
<template v-if="typeText">({{typeText}})</template> <template v-if="typeText">({{ typeText }})</template>
<template v-if="data.hasOwnProperty('score')">({{data.score}}分)</template> <template v-if="data.hasOwnProperty('score')">({{ data.score }}分)</template>
</div> </div>
</div> </div>
<div class="q-item-bd"> <div class="q-item-bd">
<!-- 单选 --> <!-- 单选 -->
<el-radio-group v-model="currentValue.user_answer" v-if="type === 1"> <el-radio-group v-model="currentValue.user_answer" v-if="type === 1">
<div class="q-option-item" v-for="item in currentOptions" :key="item.id"> <div class="q-option-item" v-for="item in currentOptions" :key="item.id">
<el-radio :class="genClass(item)" :label="item.id">{{item.abc_option}}</el-radio> <el-radio :class="genClass(item)" :label="item.id">
<div class="q-option-item__answer" v-html="item.abc_option"></div>
</el-radio>
</div> </div>
</el-radio-group> </el-radio-group>
<!-- 多选 --> <!-- 多选 -->
<el-checkbox-group v-model="currentValue.user_answer" v-if="type === 2"> <el-checkbox-group v-model="currentValue.user_answer" v-if="type === 2">
<div class="q-option-item" v-for="item in currentOptions" :key="item.id"> <div class="q-option-item" v-for="item in currentOptions" :key="item.id">
<el-checkbox :class="genClass(item)" :label="item.id">{{item.abc_option}}</el-checkbox> <el-checkbox :class="genClass(item)" :label="item.id">
<div class="q-option-item__answer" v-html="item.abc_option"></div>
</el-checkbox>
</div> </div>
</el-checkbox-group> </el-checkbox-group>
<!-- 简答题 --> <!-- 简答题 -->
...@@ -27,39 +31,34 @@ ...@@ -27,39 +31,34 @@
<v-upload :disabled="disabled" v-model="currentValue.attachments">请上传对应的文件附件:</v-upload> <v-upload :disabled="disabled" v-model="currentValue.attachments">请上传对应的文件附件:</v-upload>
</template> </template>
</div> </div>
<div class="q-item-ft" v-if="disabled"> <div class="q-item-ft" v-if="disabled && showResult">
<template v-if="type === 3"> <template v-if="type === 3">
<p v-if="data.check_comment"> <p v-if="data.check_comment">
<span>评语:</span> <span>评语:</span>
<span>{{data.check_comment}}</span> <span>{{ data.check_comment }}</span>
</p> </p>
</template> </template>
<template v-else> <template v-else>
<div class="result"> <div class="result">
<p> <p>
<span>学生答案:</span> <span>学生答案:</span>
<span :class="isCorrect ? 'is-success' : 'is-error'">{{submitAnswerText}}</span> <span :class="isCorrect ? 'is-success' : 'is-error'">{{ submitAnswerText }}</span>
</p> </p>
<p> <p>
<span>正确答案:</span> <span>正确答案:</span>
<span>{{correctAnswerText}}</span> <span>{{ correctAnswerText }}</span>
</p> </p>
</div> </div>
</template> </template>
<p v-if="data.hasOwnProperty('get_score')"> <p v-if="data.hasOwnProperty('get_score')">
<span>评分:</span> <span>评分:</span>
<span>{{data.get_score}}分</span> <span>{{ data.get_score }}分</span>
</p> </p>
<div class="analyze" v-if="data.analysis"> <div class="analyze" v-if="data.analysis">
<span>解析:</span> <span>解析:</span>
<div class="analyze-main"> <div class="analyze-main">
<span style="color:blue;cursor:pointer;" @click="showAnalyze = !showAnalyze">查看解析</span> <span style="color: blue; cursor: pointer" @click="showAnalyze = !showAnalyze">查看解析</span>
<div <div v-html="data.analysis" v-if="data.analysis" v-show="showAnalyze" class="analyze-content"></div>
v-html="data.analysis"
v-if="data.analysis"
v-show="showAnalyze"
class="analyze-content"
></div>
</div> </div>
</div> </div>
</div> </div>
...@@ -94,7 +93,8 @@ export default { ...@@ -94,7 +93,8 @@ export default {
} }
}, },
// 是否禁用,提交过的是禁用状态 // 是否禁用,提交过的是禁用状态
disabled: { type: Boolean, default: false } disabled: { type: Boolean, default: false },
showResult: { type: Boolean, default: true }
}, },
data() { data() {
return { return {
...@@ -135,16 +135,12 @@ export default { ...@@ -135,16 +135,12 @@ export default {
item.abc_option = `${this.A_Z[index]}. ${item.option}` item.abc_option = `${this.A_Z[index]}. ${item.option}`
// 提交时的选中状态 // 提交时的选中状态
const value = this.value.user_answer || '' const value = this.value.user_answer || ''
item.selected = Array.isArray(value) item.selected = Array.isArray(value) ? value.includes(item.id) : value === item.id
? value.includes(item.id)
: value === item.id
// 处理正确的选中状态 // 处理正确的选中状态
const hasChecked = Object.prototype.hasOwnProperty.call(item, 'checked') const hasChecked = Object.prototype.hasOwnProperty.call(item, 'checked')
const rightAnswer = this.data.right_answer || '' const rightAnswer = this.data.right_answer || ''
if (!hasChecked && rightAnswer) { if (!hasChecked && rightAnswer) {
item.checked = Array.isArray(rightAnswer) item.checked = Array.isArray(rightAnswer) ? rightAnswer.includes(item.id) : rightAnswer === item.id
? rightAnswer.includes(item.id)
: rightAnswer === item.id
} }
return item return item
}) })
...@@ -179,7 +175,7 @@ export default { ...@@ -179,7 +175,7 @@ export default {
methods: { methods: {
// 生成class // 生成class
genClass(item) { genClass(item) {
if (!this.disabled) { if (!this.disabled || !this.showResult) {
return null return null
} }
return { return {
...@@ -232,6 +228,12 @@ export default { ...@@ -232,6 +228,12 @@ export default {
padding-left: 20px; padding-left: 20px;
margin-bottom: 14px; margin-bottom: 14px;
} }
.q-option-item__answer {
display: inline;
::v-deep * {
display: inline;
}
}
.is-success { .is-success {
color: #090; color: #090;
} }
......
<template> <template>
<component <component :is="currentCompoent" :chapter="chapter" :data="data" v-bind="$attrs" v-on="$listeners" v-if="chapter" />
:is="currentCompoent"
:chapter="chapter"
:data="data"
v-bind="$attrs"
v-on="$listeners"
v-if="chapter"
/>
</template> </template>
<script> <script>
......
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
:key="pid" :key="pid"
@pptupdate="handlePPTupdate" @pptupdate="handlePPTupdate"
@change-ppt="handleChangePPT(...arguments, false)" @change-ppt="handleChangePPT(...arguments, false)"
@update="getCourse"
/> />
</div> </div>
</div> </div>
......
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
<!-- <el-button class="rbtn" type="primary" size="medium" icon="el-icon-self-cc-book icon" @click="goCourseAll">{{ $t('pages.learn.course.changeCourse') }}</el-button> --> <!-- <el-button class="rbtn" type="primary" size="medium" icon="el-icon-self-cc-book icon" @click="goCourseAll">{{ $t('pages.learn.course.changeCourse') }}</el-button> -->
</div> </div>
<div class="con-box"> <div class="con-box" v-loading="loading">
<ul class="course-list"> <ul class="course-list">
<template v-for="(item, index) in homeList"> <template v-for="(item, index) in homeList">
<li v-bind:key="index" class="item"> <li v-bind:key="index" class="item">
...@@ -101,7 +101,8 @@ export default { ...@@ -101,7 +101,8 @@ export default {
homeList: [], // 从后台请求 homeList: [], // 从后台请求
param: {}, param: {},
timeInterval: null, timeInterval: null,
newLiveMsg: {} newLiveMsg: {},
loading: false
} }
}, },
mounted () { mounted () {
...@@ -138,12 +139,15 @@ export default { ...@@ -138,12 +139,15 @@ export default {
this.$router.push({ path: `/app/learn/course-detail/${cid}` }) this.$router.push({ path: `/app/learn/course-detail/${cid}` })
}, },
getAjaxList (bool, str) { getAjaxList (bool, str) {
this.loading = true
cAction.Course.getCourseList(bool, this.param).then(json => { cAction.Course.getCourseList(bool, this.param).then(json => {
this.homeList = json this.homeList = json
if (!json.length) { if (!json.length) {
this.$message(str) this.$message(str)
} }
}).catch(e => { this.$message.error(e.message) }).finally(() => {}) }).catch(e => { this.$message.error(e.message) }).finally(() => {
this.loading = false
})
}, },
/** /**
* 分类选择 - 选中某一项 * 分类选择 - 选中某一项
......
...@@ -541,7 +541,7 @@ export default { ...@@ -541,7 +541,7 @@ export default {
window.open(data.live.record_url || data.live.join_url) window.open(data.live.record_url || data.live.join_url)
return return
} }
this.$router.push({ name: 'viewerCourseChapter', params: { cid, id: data.id } }) this.$router.push({ name: 'viewerCourseChapter', params: { cid, id: data.id }, query: { offset: data.offset } })
}, },
/** /**
* 开始学习或继续学习 - 跳转到对应音视频播放页 * 开始学习或继续学习 - 跳转到对应音视频播放页
......
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
<div class="live-item-content"> <div class="live-item-content">
<div class="live-item-content__title">{{ subitem.topic }}</div> <div class="live-item-content__title">{{ subitem.topic }}</div>
<div class="live-item-content__time">{{ subitem.start_time }}</div> <div class="live-item-content__time">{{ subitem.start_time }}</div>
<div class="live-item-content__status">{{ calcTimeText(subitem.start_time, subitem.live_status) }}</div> <div class="live-item-content__status">{{ calcTimeText(subitem) }}</div>
</div> </div>
</div> </div>
</div> </div>
...@@ -178,7 +178,8 @@ export default { ...@@ -178,7 +178,8 @@ export default {
url && window.open(url, '_blank') url && window.open(url, '_blank')
}, },
// 计算日期 // 计算日期
calcTimeText(liveTime, liveStatus) { calcTimeText(data) {
let { start_time: liveTime, live_status: liveStatus } = data
const map = { const map = {
1: this.$t('live.notStarted'), 1: this.$t('live.notStarted'),
2: this.$t('live.liveStreaming'), 2: this.$t('live.liveStreaming'),
...@@ -208,6 +209,9 @@ export default { ...@@ -208,6 +209,9 @@ export default {
}) })
} }
} }
if (liveStatus === 3 && data.enable_record && data.record_url) {
result = this.$t('live.watchReplay')
}
return result return result
} }
}, },
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
<template v-for="(item, index) in msgList"> <template v-for="(item, index) in msgList">
<el-collapse-item v-bind:key="index" :name="index"> <el-collapse-item v-bind:key="index" :name="index">
<template slot="title"> <template slot="title">
<el-badge :is-dot="!item.isShow" class="item">系统通知</el-badge> <el-badge :is-dot="!item.isShow" class="item">{{ item.title || '系统通知' }}</el-badge>
</template> </template>
<div v-html="item.text"></div> <div v-html="item.text"></div>
</el-collapse-item> </el-collapse-item>
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
:total="page.total" :total="page.total"
:hide-on-single-page="true" :hide-on-single-page="true"
@current-change="handleCurrentChange" @current-change="handleCurrentChange"
style="margin:0 auto;padding:40px 0;text-align:center;" style="margin: 0 auto; padding: 40px 0; text-align: center"
></el-pagination> ></el-pagination>
</div> </div>
</div> </div>
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论