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

新增作业互评

上级 cf3099ae
......@@ -27,8 +27,8 @@
<!-- <script src="//view.csslcloud.net/js/sdk/3.1.0/liveSDK.js" type="text/javascript"></script> -->
<!-- 日志采集 -->
<script src="https://zws-imgs-pub.ezijing.com/static/plugin/mqtt_msg.godzyx-1.0.3.js"></script>
<script src="https://zws-imgs-pub.ezijing.com/static/plugin/error.godzyx-1.0.3.js"></script>
<!-- <script src="https://zws-imgs-pub.ezijing.com/static/plugin/mqtt_msg.godzyx-1.0.3.js"></script>
<script src="https://zws-imgs-pub.ezijing.com/static/plugin/error.godzyx-1.0.3.js"></script> -->
<!-- Matomo -->
<script type="text/javascript">
......
......@@ -8,9 +8,7 @@ const httpRequest = new BaseAPI(webConf)
* @param {string} courseId 课程ID
*/
export function getCourse(semesterId, courseId) {
return httpRequest.get(
`/api/lms/v2/education/courses/${semesterId}/${courseId}`
)
return httpRequest.get(`/api/lms/v2/education/courses/${semesterId}/${courseId}`)
}
/**
......@@ -44,10 +42,7 @@ export function getChapterVideoAliyun(vid) {
* @param {Object} params
*/
export function getChapterVideoProgress(semesterId, resourseId, params) {
return httpRequest.get(
`/api/lms/v2/education/video/${semesterId}/${resourseId}/device`,
params
)
return httpRequest.get(`/api/lms/v2/education/video/${semesterId}/${resourseId}/device`, params)
}
/**
......@@ -65,9 +60,7 @@ export function updateChapterVideoProgress(params) {
* @param {string} resourseId 章节的资源ID
*/
export function getChapterHomework(semesterId, courseId, resourseId) {
return httpRequest.get(
`/api/lms/v2/education/homeworks/${semesterId}/${courseId}/${resourseId}`
)
return httpRequest.get(`/api/lms/v2/education/homeworks/${semesterId}/${courseId}/${resourseId}`)
}
/**
......@@ -77,9 +70,7 @@ export function getChapterHomework(semesterId, courseId, resourseId) {
* @param {string} chapterId 章节ID
*/
export function getChapterHomeworkDeadline(semesterId, courseId, chapterId) {
return httpRequest.get(
`/api/lms/v2/education/homeworks/${semesterId}/${courseId}/${chapterId}/deadline`
)
return httpRequest.get(`/api/lms/v2/education/homeworks/${semesterId}/${courseId}/${chapterId}/deadline`)
}
/**
......@@ -106,9 +97,7 @@ export function uploadFile(data) {
* @param {string} courseId 课程ID
*/
export function getCourseWork(semesterId, courseId) {
return httpRequest.get(
`/api/lms/v2/education/courses/${semesterId}/${courseId}/essay`
)
return httpRequest.get(`/api/lms/v2/education/courses/${semesterId}/${courseId}/essay`)
}
/**
......@@ -117,11 +106,9 @@ export function getCourseWork(semesterId, courseId) {
* @param {string} courseId 课程ID
*/
export function updateCourseWork(semesterId, courseId, data) {
return httpRequest.post(
`/api/lms/v2/education/courses/${semesterId}/${courseId}/essay`,
data,
{ headers: { 'Content-Type': 'multipart/form-data' } }
)
return httpRequest.post(`/api/lms/v2/education/courses/${semesterId}/${courseId}/essay`, data, {
headers: { 'Content-Type': 'multipart/form-data' }
})
}
/**
......@@ -130,9 +117,7 @@ export function updateCourseWork(semesterId, courseId, data) {
* @param {string} courseId 课程ID
*/
export function getCourseExam(semesterId, courseId) {
return httpRequest.get(
`/api/lms/v2/education/${semesterId}/${courseId}/examination`
)
return httpRequest.get(`/api/lms/v2/education/${semesterId}/${courseId}/examination`)
}
/**
......@@ -142,9 +127,7 @@ export function getCourseExam(semesterId, courseId) {
* @param {string} examId 试题ID
*/
export function getCourseExamStatus(semesterId, courseId, examId) {
return httpRequest.get(
`/api/lms/v2/education/${semesterId}/${courseId}/examination/${examId}/status`
)
return httpRequest.get(`/api/lms/v2/education/${semesterId}/${courseId}/examination/${examId}/status`)
}
/**
......@@ -154,11 +137,9 @@ export function getCourseExamStatus(semesterId, courseId, examId) {
* @param {string} examId 试题ID
*/
export function submitCourseExam(semesterId, courseId, examId, data) {
return httpRequest.post(
`/api/lms/v2/education/${semesterId}/${courseId}/examination/${examId}/sheet`,
data,
{ headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }
)
return httpRequest.post(`/api/lms/v2/education/${semesterId}/${courseId}/examination/${examId}/sheet`, data, {
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
})
}
/**
......@@ -168,8 +149,33 @@ export function submitCourseExam(semesterId, courseId, examId, data) {
* @param {string} examId 试题ID
*/
export function getCourseExamResult(semesterId, courseId, examId, params) {
return httpRequest.get(
`/api/lms/v2/education/${semesterId}/${courseId}/examination/${examId}/sheet`,
params
)
return httpRequest.get(`/api/lms/v2/education/${semesterId}/${courseId}/examination/${examId}/sheet`, params)
}
/**
* 获取课后评论作业
* @param {string} semesterId 学期ID
* @param {string} courseId 课程ID
* @param {string} chapterId 章节ID
*/
export function getChapterHomeworkOther(semesterId, courseId, chapterId, params) {
return httpRequest.get(`/api/lms/v2/education/homeworks/other/${semesterId}/${courseId}/${chapterId}`, params)
}
/**
* 获取课后课业回答
* @param {string} semesterId 学期ID
* @param {string} courseId 课程ID
* @param {string} chapterId 章节ID
*/
export function getChapterHomeworkOtherAll(semesterId, courseId, chapterId, params) {
return httpRequest.get(`/api/lms/v2/education/homeworks/otherall/${semesterId}/${courseId}/${chapterId}`, params)
}
/**
* 获取课程考试结果
* @param {string} examId 试题ID
*/
export function addChapterHomeworkComment(examId, params) {
return httpRequest.post(`/api/lms/v2/education/homeworks/comment/${examId}`, params)
}
<template>
<div class="upload">
<el-upload action :disabled="disabled" :show-file-list="false" :http-request="httpRequest">
<el-upload action :disabled="disabled" :show-file-list="false" :http-request="httpRequest" v-bind="$attrs">
<slot></slot>
<el-button type="text" icon="el-icon-upload">{{ $t('viewerWork.clickUpload') }}</el-button>
<template v-slot:tip>
......
<template>
<container :title="chapter.name" v-loading="loading">
<div class="exam-form">
<el-form :disabled="disabled || !isWorkTime">
<exam-item
v-for="(item, index) in questions"
:index="index"
:type="item.question_type"
:data="item"
:value="item.formModel"
:disabled="disabled || !isWorkTime"
:key="item.id"
></exam-item>
</el-form>
</div>
<p style="color: red" v-if="deadline">{{ $t('viewerWork.deadline', { deadline }) }}</p>
<!-- 驳回状态 -->
<template v-if="detail && detail.status === 1">
<div class="work-bottom">
<div class="info">
<div class="paper-check">
<h4>{{ $t('viewerWork.rejectTips') }}</h4>
<div class="paper-check-item">
<b>{{ $t('viewerWork.rejectTime') }}</b>
{{ detail.checker_time }}
</div>
<div class="paper-check-item">
<b>{{ $t('viewerWork.rejectContent') }}</b>
<div class="edit_html" v-html="detail.check_comments"></div>
</div>
</div>
</div>
</div>
<div class="buttons">
<el-button type="primary" @click="onReEdit" :disabled="!isWorkTime">{{ $t('viewerWork.reEdit') }}</el-button>
<div>
<container :title="chapter.name" v-loading="loading">
<div class="exam-form">
<template v-for="(item, index) in questions">
<el-form :disabled="disabled || !isWorkTime" :key="item.id" ref="form" :model="item.formModel" :rules="rules">
<el-form-item prop="user_answer">
<exam-item
:index="index"
:type="item.question_type"
:data="item"
:value="item.formModel"
:disabled="disabled || !isWorkTime"
:hasUpload="hasUpload"
></exam-item>
</el-form-item>
</el-form>
</template>
</div>
</template>
<!-- 正常状态 -->
<template v-else>
<div class="work-bottom" v-if="detail">
<div class="info">
<template v-if="isRevised">
<p style="color: red" v-if="deadline">{{ $t('viewerWork.deadline', { date: deadline }) }}</p>
<!-- 驳回状态 -->
<template v-if="detail && detail.status === 1">
<div class="work-bottom">
<div class="info">
<div class="paper-check">
<p>{{ $t('viewerWork.correctionTime') }}{{ detail.checker_time }}</p>
<div class="paper-check-item" v-if="hasScore">
<b>{{ $t('viewerWork.score') }}</b>
{{ detail.score }}
<h4>{{ $t('viewerWork.rejectTips') }}</h4>
<div class="paper-check-item">
<b>{{ $t('viewerWork.rejectTime') }}</b>
{{ detail.checker_time }}
</div>
<div class="paper-check-item">
<b>{{ $t('viewerWork.comments') }}</b>
<b>{{ $t('viewerWork.rejectContent') }}</b>
<div class="edit_html" v-html="detail.check_comments"></div>
</div>
</div>
</template>
<template v-else-if="detail.created_time">
<p class="help">{{ $t('viewerWork.submitted', { time: detail.created_time }) }}</p>
<template v-if="detail.updated_time && detail.updated_time !== detail.created_time">
<p class="help">{{ $t('viewerWork.submitDateTime') }} {{ detail.updated_time }}</p>
</div>
</div>
<div class="buttons">
<el-button type="primary" @click="onReEdit" :disabled="!isWorkTime">{{ $t('viewerWork.reEdit') }}</el-button>
</div>
</template>
<!-- 正常状态 -->
<template v-else>
<div class="work-bottom" v-if="detail">
<div class="info">
<template v-if="isRevised">
<div class="paper-check">
<p>{{ $t('viewerWork.correctionTime') }}{{ detail.checker_time }}</p>
<div class="paper-check-item" v-if="hasScore">
<b>{{ $t('viewerWork.score') }}</b>
{{ detail.score }}
</div>
<div class="paper-check-item">
<b>{{ $t('viewerWork.comments') }}</b>
<div class="edit_html" v-html="detail.check_comments"></div>
</div>
</div>
</template>
<template v-else-if="detail.created_time">
<p class="help">{{ $t('viewerWork.submitted', { time: detail.created_time }) }}</p>
<template v-if="detail.updated_time && detail.updated_time !== detail.created_time">
<p class="help">{{ $t('viewerWork.submitDateTime') }} {{ detail.updated_time }}</p>
</template>
</template>
</template>
</div>
</div>
</div>
<div class="buttons">
<el-tooltip :content="$t('viewerWork.workSubmitButtonTips')" placement="right">
<el-button type="primary" :disabled="disabled || !isWorkTime" :loading="submitLoading" @click="onSubmit">{{
submitText
}}</el-button>
</el-tooltip>
</div>
</template>
</container>
<div class="buttons">
<el-tooltip :content="$t('viewerWork.workSubmitButtonTips')" placement="right">
<el-button type="primary" :disabled="disabled || !isWorkTime" :loading="submitLoading" @click="onSubmit">{{
submitText
}}</el-button>
</el-tooltip>
<span v-if="hasComment">{{ $t('viewerWork.commentTips') }}</span>
</div>
</template>
</container>
<chapter-work-comment :endDate="commentEndDate" v-if="showComment" />
</div>
</template>
<script>
......@@ -77,13 +84,14 @@ import Base64 from 'Base64'
// componets
import Container from '../common/container.vue'
import ExamItem from './examItem.vue'
import ChapterWorkComment from './chapterWorkComment.vue'
// api
import * as api from '../../api'
// 章节作业
export default {
name: 'ChapterWork',
components: { Container, ExamItem },
components: { Container, ExamItem, ChapterWorkComment },
props: {
// 当前选中的
chapter: {
......@@ -109,7 +117,17 @@ export default {
messageInstance: null,
deadline: '', // 截止时间
disabled: false,
submitLoading: false
submitLoading: false,
hasUpload: true, // 是否可以上传
isAnonymous: false, // 是否匿名
hasComment: false, // 是否评论
commentEndDate: '',
rules: {
user_answer: [
{ required: true, message: '请输入', trigger: 'change' },
{ max: 1000, message: '最多输入1000个字符', trigger: 'change' }
]
}
}
},
watch: {
......@@ -160,6 +178,13 @@ export default {
hasScore() {
// allow_score 1 显示 2隐藏
return this.detail.allow_score !== 2
},
// 显示作业评论
showComment() {
return true
// const currentTime = new Date().getTime()
// const endTime = +new Date(this.deadline)
// return this.hasComment && currentTime > endTime
}
},
methods: {
......@@ -167,6 +192,10 @@ export default {
getDeadline() {
api.getChapterHomeworkDeadline(this.sid, this.cid, this.pid).then(response => {
this.deadline = response.dead_line
this.hasUpload = !!response.pdf
this.isAnonymous = !!response.anonymous
this.hasComment = !!response.comment
this.commentEndDate = response.comment_end
})
},
// 获取详情
......@@ -236,14 +265,16 @@ export default {
},
// 提交校验
checkSubmit() {
const questions = this.questions
for (let i = 0; i < questions.length; i++) {
const value = questions[i].formModel.user_answer
if (Array.isArray(value) ? !value.length : !value) {
return false
}
let result = true
for (let i = 0; i < this.questions.length; i++) {
this.$refs.form[i].validate(valid => {
if (!valid) {
result = valid
return result
}
})
}
return true
return result
},
// 提交
onSubmit() {
......
<template>
<div class="chatper-work-answer-item">
<div class="chapter-work-answer-item-hd" v-if="data.personal_name">{{ data.personal_name }}:</div>
<div class="chapter-work-answer-item-bd">
<div class="item" v-for="item in workList" :key="item.question_id">
<div v-html="decode(item.descreption)"></div>
<a :href="item.file_url" target="_blank" class="file" v-if="item.file_url">
<i class="el-icon-document"></i>
{{ $t('viewerWork.downloadName') }}
</a>
</div>
</div>
<slot />
</div>
</template>
<script>
import Base64 from 'Base64'
export default {
props: {
data: { type: Object, default: () => ({}) }
},
data() {
return {}
},
computed: {
// 作业列表
workList() {
return this.data.work_contents ? JSON.parse(this.data.work_contents) : []
}
},
methods: {
decode(value) {
return value ? Base64.decode(value) : ''
}
}
}
</script>
<style lang="scss">
.chatper-work-answer-item {
border-bottom: 1px solid #c9c9c97a;
margin-bottom: 20px;
.item + .item {
border-top: 1px dashed #c9c9c97a;
}
.file {
display: inline-block;
margin-bottom: 10px;
text-decoration: none;
color: #333;
&:hover {
color: #b49441;
}
}
}
</style>
<template>
<container :title="$t('viewerWork.submittedAssignments')">
<chapter-work-answer-item v-for="item in list" :data="item" :key="item.id" />
<el-pagination
background
layout="prev, pager, next"
:current-page.sync="page.currentPage"
:page-size="page.limit"
:total="page.total"
:hide-on-single-page="true"
@current-change="handleCurrentChange"
style="margin: 0 auto; padding: 40px 0; text-align: center"
></el-pagination>
</container>
</template>
<script>
// api
import * as api from '../../api'
// componets
import Container from '../common/container.vue'
import chapterWorkAnswerItem from './chapterWorkAnswerItem.vue'
export default {
components: { Container, chapterWorkAnswerItem },
data() {
return {
list: [],
page: {
offset: 0,
total: 0,
currentPage: 1,
limit: 10
}
}
},
computed: {
// 学期ID
sid() {
return this.$route.params.sid
},
// 课程ID
cid() {
return this.$route.params.cid
},
// 当前页面的ID
pid() {
return this.$route.params.id
}
},
methods: {
getList() {
const params = { offset: this.page.offset, limit: this.page.limit }
api.getChapterHomeworkOtherAll(this.sid, this.cid, this.pid, params).then(response => {
this.list = response.data
this.page.total = parseInt(response.count)
})
},
handleCurrentChange() {
this.page.offset = (this.page.currentPage - 1) * this.page.limit
this.getList()
}
},
beforeMount() {
this.getList()
}
}
</script>
<style lang="scss" scoped>
.more {
text-align: center;
padding-top: 40px;
}
</style>
<template>
<container :title="$t('viewerWork.commentTitle')">
<chapter-work-comment-item v-for="item in list" :data="item" :key="item.id" v-bind="$attrs" @update="getList" />
<div class="more">
<router-link :to="`${$route.path}/answers`" target="_blank">
<el-button round>{{ $t('viewerWork.answerMoreButtonText') }}</el-button>
</router-link>
</div>
</container>
</template>
<script>
// api
import * as api from '../../api'
// componets
import Container from '../common/container.vue'
import ChapterWorkCommentItem from './chapterWorkCommentItem.vue'
export default {
components: { Container, ChapterWorkCommentItem },
data() {
return {
list: []
}
},
computed: {
// 学期ID
sid() {
return this.$route.params.sid
},
// 课程ID
cid() {
return this.$route.params.cid
},
// 当前页面的ID
pid() {
return this.$route.params.id
}
},
methods: {
getList() {
api.getChapterHomeworkOther(this.sid, this.cid, this.pid).then(response => {
this.list = response
})
}
},
beforeMount() {
this.getList()
}
}
</script>
<style lang="scss" scoped>
.more {
text-align: center;
padding-top: 40px;
}
</style>
<template>
<chapter-work-answer-item :data="data" :key="data.id">
<el-form :model="ruleForm" :rules="rules" :hide-required-asterisk="true" label-position="top" ref="ruleForm">
<el-form-item :label="$t('viewerWork.commentMyTitle')" prop="comment">
<v-editor v-model="ruleForm.comment" :disabled="disabled"></v-editor>
</el-form-item>
<el-form-item>
<div class="button">
<el-button type="primary" :disabled="disabled" @click="handleSubmit">{{
$t('viewerWork.commentSubmitText')
}}</el-button>
<p>{{ $t('viewerWork.commentSubmitTips', { date: endDate }) }}</p>
</div>
</el-form-item>
</el-form>
</chapter-work-answer-item>
</template>
<script>
// api
import * as api from '../../api'
// componets
import ChapterWorkAnswerItem from './chapterWorkAnswerItem.vue'
import VEditor from '@/components/ckeditor'
export default {
props: { endDate: { type: String }, data: { type: Object, default: () => ({}) } },
components: { ChapterWorkAnswerItem, VEditor },
data() {
return {
ruleForm: { comment: this.data.comment },
rules: {
comment: [
{ required: true, message: '请输入评价内容', trigger: 'blur' },
{ max: 1000, message: '最多输入1000个字符', trigger: 'blur' }
]
}
}
},
computed: {
isSubmitTime() {
// 大于开始时间,小于结束时间
const endTime = +new Date(this.endDate)
const currentTime = new Date().getTime()
return currentTime < endTime
},
// 是否禁用
disabled() {
return !this.isSubmitTime
// return false
}
},
methods: {
// 提交评价
handleSubmit() {
this.$refs.ruleForm.validate().then(this.handleSubmitReqeuest)
},
handleSubmitReqeuest() {
api.addChapterHomeworkComment(this.data.id, this.ruleForm).then(response => {
this.$message({ type: 'success', message: response.message })
this.$emit('update')
})
}
}
}
</script>
<style lang="scss" scoped>
.button {
display: flex;
align-items: center;
p {
padding-left: 20px;
}
}
</style>
<template>
<div></div>
</template>
<script>
export default {
data() {
return {}
}
}
</script>
......@@ -28,7 +28,7 @@
<!-- 简答题 -->
<template v-if="type === 3">
<v-editor v-model="currentValue.user_answer" :disabled="disabled"></v-editor>
<v-upload :disabled="disabled" v-model="currentValue.attachments"
<v-upload :disabled="disabled" v-model="currentValue.attachments" accept=".pdf" v-if="hasUpload"
>{{ $t('viewerWork.workUrl.label') }}</v-upload
>
</template>
......@@ -98,7 +98,8 @@ export default {
},
// 是否禁用,提交过的是禁用状态
disabled: { type: Boolean, default: false },
showResult: { type: Boolean, default: true }
showResult: { type: Boolean, default: true },
hasUpload: { type: Boolean, default: true }
},
data() {
return {
......
......@@ -239,13 +239,13 @@ export default {
display: flex;
justify-content: space-between;
align-items: center;
padding: 40px 0;
padding: 20px 0 40px;
// text-align: center;
}
.course-viewer-content-hd__title {
position: relative;
display: inline-block;
margin: 0 0 0 20px;
margin: 0;
padding: 0 0 5px;
font-size: 20px;
border-bottom: 3px solid #707070;
......
......@@ -41,7 +41,7 @@ export default {
anotherSubmitText: 'Take another test',
correctRate: 'Correct rate',
revisedButtonText: 'Corrected',
deadline: 'Please submit before the deadline {date}',
deadline: 'Deadline: {date} Modifications can be made any time before deadline.',
rejectTips: 'The assignment is rejected, click the "re-edit" button to re-edit the content and submit again',
rejectTime: 'Rejection time',
rejectContent: 'Rejection instructions',
......@@ -59,17 +59,24 @@ export default {
workStep3: 'Submit before the deadline',
workTheme: { label: 'Theme', placeholder: 'Theme', rule: 'Please enter Theme' },
workDescription: { label: 'Text', placeholder: 'Text', rule: 'Please enter the text' },
workUrl: { label: 'Please upload the corresponding file attachment', rule: 'Please upload attachment' },
workUrl: { label: 'Upload Attachment', rule: 'Please upload attachment' },
studentAnswer: 'Student answer',
correctAnswer: 'Correct answer',
analyze: 'Parsing',
viewResolution: 'View resolution',
singleChoice: 'Single Choice',
multipleChoice: 'Multiple Choice',
clickUpload: 'Click upload',
clickUpload: 'Click here to upload',
delete: 'Delete',
download: 'Download',
downloadName: 'Download attachment'
downloadName: 'Download attachment',
commentTips: 'Please continue to finish comment assignments after the deadline.',
commentTitle: 'Comment on Other Student Assignments',
commentMyTitle: 'My Comment',
commentSubmitText: 'Submit Comment ',
commentSubmitTips: 'Deadline: {date} Modifications can be made any time before deadline.',
answerMoreButtonText: 'Check other students assignments',
submittedAssignments: 'Submitted Assignments'
},
viewerExam: {},
viewerRead: {
......
......@@ -34,14 +34,14 @@ export default {
examSubmitButtonTips: '提交之后就不能修改了哦',
examStartButtonText: '开始考试',
examEndButtonText: '考试结束',
examSubmitError: '还有题目未做,不能提交',
examSubmitError: '请检查输入内容是否正确',
examSubmitSuccess: '提交成功',
prevPapers: '上一套试卷',
nextPapers: '下一套试卷',
anotherSubmitText: '再考一次',
correctRate: '正确率',
revisedButtonText: '已批改',
deadline: '请于截止日期 {date} 前提交',
deadline: '提交作业截止时间为: {date} ,截止时间前均可修改。',
rejectTips: '作业被驳回,点击“重新编辑”按钮重新编辑内容再次提交',
rejectTime: '驳回时间',
rejectContent: '驳回说明',
......@@ -68,7 +68,14 @@ export default {
clickUpload: '点击上传',
delete: '删除',
download: '下载',
downloadName: '附件下载'
downloadName: '附件下载',
commentTips: '作业提交截止后,请继续完成评论作业。',
commentTitle: '评论同学作业',
commentSubmitTips: '提交评论截止时间为:{date},截止时间前均可修改。',
commentMyTitle: '我的评论',
commentSubmitText: '提交评价',
answerMoreButtonText: '去看其他同学作业',
submittedAssignments: '同学提交的作业'
},
viewerRead: {
download: '下载',
......
......@@ -9,5 +9,9 @@ export default [
component: () => import('./components/layout.vue')
}
]
},
{
path: '/viewer/:sid/:cid/:id/answers',
component: () => import('./components/work/chapterWorkAnswerList.vue')
}
]
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论