|
@@ -1,5 +1,5 @@
|
|
|
<template>
|
|
|
- <div class="answer">
|
|
|
+ <div v-loading="loading" class="answer">
|
|
|
<header class="header">
|
|
|
<div class="back round" @click="goBack">
|
|
|
<i class="el-icon-arrow-left"></i>
|
|
@@ -38,8 +38,29 @@
|
|
|
</main>
|
|
|
|
|
|
<footer class="footer">
|
|
|
- <el-popover placement="top-start" trigger="click">
|
|
|
- <div>增加批注</div>
|
|
|
+ <el-popover v-model="isPopover" placement="top-start" trigger="click">
|
|
|
+ <div class="annotations-container">
|
|
|
+ <div class="title">增加批注</div>
|
|
|
+ <div class="score">
|
|
|
+ <span>分数</span>
|
|
|
+ <el-input-number v-model="annotations.score" :min="0" :step="1" />
|
|
|
+ </div>
|
|
|
+ <el-input v-model="annotations.remark" type="textarea" rows="6" resize="none" class="remark" />
|
|
|
+ <div>图片/视频</div>
|
|
|
+
|
|
|
+ <el-upload action="no" accept="audio/*,video/*,image/*" :show-file-list="true" :http-request="upload">
|
|
|
+ <div class="upload">
|
|
|
+ <i class="el-icon-plus avatar-uploader-icon"></i>
|
|
|
+ <span>Upload</span>
|
|
|
+ </div>
|
|
|
+ </el-upload>
|
|
|
+
|
|
|
+ <div class="popover-footer">
|
|
|
+ <el-button @click="isPopover = false">取消</el-button>
|
|
|
+ <el-button type="primary" @click="fillQuestionAnswerRemark">确定</el-button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
<div v-show="isAnnotations" slot="reference" class="annotations"><i class="el-icon-plus"></i>批注</div>
|
|
|
</el-popover>
|
|
|
|
|
@@ -58,10 +79,21 @@
|
|
|
|
|
|
<template v-else>
|
|
|
<el-button round @click="fillQuestionAnswer('pre')">上一题</el-button>
|
|
|
- <el-button v-if="curQuestionIndex === questionList.length - 1" type="primary" round @click="submitAnswer">
|
|
|
+ <el-button
|
|
|
+ v-if="curQuestionIndex === questionList.length - 1 && !isTeacherAnnotations"
|
|
|
+ type="primary"
|
|
|
+ round
|
|
|
+ @click="submitAnswer"
|
|
|
+ >
|
|
|
提交
|
|
|
</el-button>
|
|
|
- <el-button v-else type="primary" round @click="fillQuestionAnswer('next')">下一题</el-button>
|
|
|
+ <el-button
|
|
|
+ v-else-if="curQuestionIndex < questionList.length - 1 || !isTeacherAnnotations"
|
|
|
+ type="primary"
|
|
|
+ round
|
|
|
+ @click="fillQuestionAnswer('next')"
|
|
|
+ >下一题</el-button
|
|
|
+ >
|
|
|
</template>
|
|
|
</div>
|
|
|
</footer>
|
|
@@ -78,8 +110,10 @@ import {
|
|
|
FillQuestionAnswer,
|
|
|
SubmitAnswer,
|
|
|
GetQuestionInfo_AnswerRecord,
|
|
|
+ FillQuestionAnswerRemark,
|
|
|
} from '@/api/exercise';
|
|
|
import { subjectiveQuestionList } from './answer';
|
|
|
+import { fileUpload } from '@/api/app';
|
|
|
|
|
|
import StartQuestion from './components/StartQuestion.vue';
|
|
|
import AnswerReport from './components/AnswerReport.vue';
|
|
@@ -93,13 +127,14 @@ export default {
|
|
|
},
|
|
|
mixins: [PreviewQuestionTypeMixin],
|
|
|
data() {
|
|
|
- const { id, share_record_id } = this.$route.query;
|
|
|
+ const { id, share_record_id, answer_record_id, question_index } = this.$route.query;
|
|
|
|
|
|
return {
|
|
|
exercise_id: id, // 练习题id
|
|
|
share_record_id, // 分享记录id
|
|
|
- answer_record_id: '', // 答题记录id
|
|
|
+ answer_record_id: answer_record_id ?? '', // 答题记录id
|
|
|
secondFormatConversion,
|
|
|
+ isTeacher: this.$store.getters.isTeacher, // 是否是教师
|
|
|
user_answer_record_info: {
|
|
|
correct_answer_show_mode: 1, // 正确答案显示模式
|
|
|
}, // 当前用户的答题记录信息
|
|
@@ -109,6 +144,8 @@ export default {
|
|
|
currentQuestion: {},
|
|
|
// 当前问题索引
|
|
|
curQuestionIndex: -1,
|
|
|
+ question_index: Number(question_index) || -1, // 跳转的问题索引
|
|
|
+ loading: false,
|
|
|
// 倒计时
|
|
|
countDownTimer: null,
|
|
|
answer_mode: 1, // 答题模式
|
|
@@ -117,9 +154,27 @@ export default {
|
|
|
isSubmit: false,
|
|
|
isView: false, // 练习模式下是否查看
|
|
|
curQuestionPage: '', // 当前问题页面
|
|
|
- isAnnotations: false, // 是否显示批注
|
|
|
+ remark: {
|
|
|
+ is_remarked: 'false',
|
|
|
+ }, // 教师批注
|
|
|
+ isPopover: false,
|
|
|
+ annotations: {
|
|
|
+ score: 0,
|
|
|
+ remark: '',
|
|
|
+ file_id_list: [],
|
|
|
+ }, // 批注
|
|
|
};
|
|
|
},
|
|
|
+ computed: {
|
|
|
+ // 是否教师批改
|
|
|
+ isTeacherAnnotations() {
|
|
|
+ return this.question_index >= 0 && this.isTeacher;
|
|
|
+ },
|
|
|
+ // 是否显示批注
|
|
|
+ isAnnotations() {
|
|
|
+ return this.remark.is_remarked === 'true' || this.isTeacherAnnotations;
|
|
|
+ },
|
|
|
+ },
|
|
|
watch: {
|
|
|
curQuestionIndex() {
|
|
|
this.getQuestionInfo();
|
|
@@ -140,6 +195,7 @@ export default {
|
|
|
}
|
|
|
|
|
|
if (this.share_record_id) {
|
|
|
+ this.loading = true;
|
|
|
GetShareRecordInfo({ share_record_id: this.share_record_id }).then(
|
|
|
({ user_answer_record_info, share_record: { exercise_id, answer_mode, answer_time_limit_minute } }) => {
|
|
|
this.user_answer_record_info = user_answer_record_info;
|
|
@@ -147,11 +203,12 @@ export default {
|
|
|
this.getExerciseQuestionIndexList();
|
|
|
this.answer_time_limit_minute = answer_time_limit_minute;
|
|
|
this.time = answer_time_limit_minute * 60;
|
|
|
+ this.loading = false;
|
|
|
// 如果是考试模式,且已经存在答题记录,则直接显示答题报告
|
|
|
- if (this.user_answer_record_info.is_exist_answer_record === 'true' && answer_mode === 2) {
|
|
|
+ if (this.user_answer_record_info.is_exist_answer_record === 'true' && !this.isTeacher) {
|
|
|
this.answer_record_id = this.user_answer_record_info.answer_record_id;
|
|
|
this.answer_mode = answer_mode;
|
|
|
- this.isSubmit = true;
|
|
|
+ if (this.answer_mode === 2) this.isSubmit = true;
|
|
|
}
|
|
|
},
|
|
|
);
|
|
@@ -161,8 +218,11 @@ export default {
|
|
|
GetExerciseQuestionIndexList({ exercise_id: this.exercise_id }).then(({ index_list }) => {
|
|
|
this.questionList = index_list.map((item) => ({
|
|
|
...item,
|
|
|
- isFill: false,
|
|
|
+ isFill: this.isTeacherAnnotations,
|
|
|
}));
|
|
|
+ if (this.question_index >= 0) {
|
|
|
+ this.curQuestionIndex = this.question_index;
|
|
|
+ }
|
|
|
});
|
|
|
},
|
|
|
goBack() {
|
|
@@ -230,11 +290,8 @@ export default {
|
|
|
this.curQuestionIndex = type === 'pre' ? this.curQuestionIndex - 1 : this.curQuestionIndex + 1;
|
|
|
return;
|
|
|
}
|
|
|
- // 如果是主观题或已填写,直接跳转
|
|
|
- if (
|
|
|
- this.questionList[this.curQuestionIndex].isFill ||
|
|
|
- subjectiveQuestionList.includes(this.currentQuestion.type)
|
|
|
- ) {
|
|
|
+ // 如果已填写,直接跳转
|
|
|
+ if (this.questionList[this.curQuestionIndex].isFill) {
|
|
|
if (type === 'pre') return this.preQuestion();
|
|
|
if (type === 'next') return this.nextQuestion();
|
|
|
}
|
|
@@ -246,8 +303,10 @@ export default {
|
|
|
answer: JSON.stringify(answer),
|
|
|
}).then(() => {
|
|
|
this.questionList[this.curQuestionIndex].isFill = true;
|
|
|
- // if (type === 'pre') return this.preQuestion();
|
|
|
- // if (type === 'next') return this.nextQuestion();
|
|
|
+ if (subjectiveQuestionList.includes(this.currentQuestion.type)) {
|
|
|
+ if (type === 'pre') return this.preQuestion();
|
|
|
+ if (type === 'next') return this.nextQuestion();
|
|
|
+ }
|
|
|
// 显示答案
|
|
|
this.$refs.exercise[0].showAnswer(
|
|
|
this.answer_mode === 1,
|
|
@@ -261,11 +320,13 @@ export default {
|
|
|
GetQuestionInfo_AnswerRecord({
|
|
|
answer_record_id: this.answer_record_id,
|
|
|
question_id: this.questionList[this.curQuestionIndex].id,
|
|
|
- }).then(({ user_answer: { is_fill_answer, content } }) => {
|
|
|
+ }).then(({ user_answer: { is_fill_answer, content }, remark }) => {
|
|
|
+ this.remark = remark;
|
|
|
+ console.log(this.remark);
|
|
|
if (is_fill_answer === 'false') return;
|
|
|
- this.$refs.exercise[0].showAnswer(
|
|
|
- this.answer_mode === 1,
|
|
|
- this.user_answer_record_info.correct_answer_show_mode === 1,
|
|
|
+ this.$refs.exercise?.[0].showAnswer(
|
|
|
+ this.answer_mode === 1 && !this.isTeacherAnnotations,
|
|
|
+ this.user_answer_record_info.correct_answer_show_mode === 1 && !this.isTeacherAnnotations,
|
|
|
JSON.parse(content || '{}'),
|
|
|
);
|
|
|
});
|
|
@@ -274,29 +335,56 @@ export default {
|
|
|
submitAnswer() {
|
|
|
if (!this.answer_record_id) return;
|
|
|
|
|
|
- // 如果已经填写过答案,直接提交
|
|
|
- if (this.questionList[this.curQuestionIndex].isFill) {
|
|
|
- SubmitAnswer({ answer_record_id: this.answer_record_id })
|
|
|
- .then(() => {
|
|
|
- this.isSubmit = true;
|
|
|
- })
|
|
|
- .catch(() => {});
|
|
|
- return;
|
|
|
- }
|
|
|
+ this.$confirm('是否确认提交答题?', '提示', {
|
|
|
+ confirmButtonText: '确定',
|
|
|
+ cancelButtonText: '取消',
|
|
|
+ type: 'warning',
|
|
|
+ })
|
|
|
+ .then(() => {
|
|
|
+ clearInterval(this.countDownTimer);
|
|
|
+ // 如果已经填写过答案,直接提交
|
|
|
+ if (this.questionList[this.curQuestionIndex].isFill) {
|
|
|
+ SubmitAnswer({ answer_record_id: this.answer_record_id })
|
|
|
+ .then(() => {
|
|
|
+ this.isSubmit = true;
|
|
|
+ })
|
|
|
+ .catch(() => {});
|
|
|
+ return;
|
|
|
+ }
|
|
|
|
|
|
- this.fillQuestionAnswer('next').then(() => {
|
|
|
- SubmitAnswer({ answer_record_id: this.answer_record_id })
|
|
|
- .then(() => {
|
|
|
- this.isSubmit = true;
|
|
|
- })
|
|
|
- .catch(() => {});
|
|
|
- });
|
|
|
+ this.fillQuestionAnswer('next').then(() => {
|
|
|
+ SubmitAnswer({ answer_record_id: this.answer_record_id })
|
|
|
+ .then(() => {
|
|
|
+ this.isSubmit = true;
|
|
|
+ })
|
|
|
+ .catch(() => {});
|
|
|
+ });
|
|
|
+ })
|
|
|
+ .catch(() => {});
|
|
|
},
|
|
|
selectQuestion(i) {
|
|
|
this.isSubmit = false;
|
|
|
this.isView = true;
|
|
|
this.curQuestionIndex = i;
|
|
|
},
|
|
|
+ upload(file) {
|
|
|
+ fileUpload('Mid', file).then(({ file_info_list }) => {
|
|
|
+ if (file_info_list.length > 0) {
|
|
|
+ const { file_id } = file_info_list[0];
|
|
|
+ this.annotations.file_id_list.push(file_id);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ },
|
|
|
+ fillQuestionAnswerRemark() {
|
|
|
+ FillQuestionAnswerRemark({
|
|
|
+ answer_record_id: this.answer_record_id,
|
|
|
+ question_id: this.questionList[this.curQuestionIndex].id,
|
|
|
+ ...this.annotations,
|
|
|
+ }).then(() => {
|
|
|
+ this.$message.success('批注成功');
|
|
|
+ this.isPopover = false;
|
|
|
+ });
|
|
|
+ },
|
|
|
},
|
|
|
};
|
|
|
</script>
|
|
@@ -366,12 +454,45 @@ export default {
|
|
|
padding: 8px 8px 14px;
|
|
|
font-size: 14px;
|
|
|
|
|
|
- .title {
|
|
|
- color: #000;
|
|
|
- }
|
|
|
+ .annotations-container {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ row-gap: 8px;
|
|
|
+
|
|
|
+ .title {
|
|
|
+ color: #000;
|
|
|
+ }
|
|
|
+
|
|
|
+ .score {
|
|
|
+ display: flex;
|
|
|
+ column-gap: 8px;
|
|
|
+ align-items: center;
|
|
|
|
|
|
- .score {
|
|
|
- color: #999;
|
|
|
+ :first-child {
|
|
|
+ color: #999;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .remark {
|
|
|
+ width: 350px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .upload {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: space-around;
|
|
|
+ width: 80px;
|
|
|
+ height: 80px;
|
|
|
+ padding: 8px;
|
|
|
+ background-color: $fill-color;
|
|
|
+ border: 1px solid $border-color;
|
|
|
+ }
|
|
|
+
|
|
|
+ .popover-footer {
|
|
|
+ display: flex;
|
|
|
+ justify-content: flex-end;
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
</style>
|