|
|
@@ -63,8 +63,13 @@
|
|
|
<!-- 选择题:我的作答 + 选项;解答题:已上传图片,可删除 -->
|
|
|
<div class="dock_answer">
|
|
|
<span class="dock_label">我的作答:</span>
|
|
|
- <span v-if="isSingle" class="dock_sub_no">(1)</span>
|
|
|
- <el-checkbox-group v-if="isSingle" class="choice_radio" v-model="answers[currentQuestion.id]"
|
|
|
+ <!-- <span v-if="isSingle" class="dock_sub_no">(1)</span> -->
|
|
|
+ <el-radio-group v-if="isJudge" class="choice_radio" v-model="answers[currentQuestion.id]"
|
|
|
+ @change="persistState">
|
|
|
+ <el-radio label="T">对</el-radio>
|
|
|
+ <el-radio label="F">错</el-radio>
|
|
|
+ </el-radio-group>
|
|
|
+ <el-checkbox-group v-else-if="isSingle" class="choice_radio" v-model="answers[currentQuestion.id]"
|
|
|
@change="persistState">
|
|
|
<el-checkbox v-for="opt in currentQuestion.options" :key="opt.key" :label="opt.key">
|
|
|
{{ opt.key }}
|
|
|
@@ -139,18 +144,20 @@ function buildOptions(item) {
|
|
|
}
|
|
|
|
|
|
function mapQuestion(item, index) {
|
|
|
- const choice = isChoiceQuestion(item);
|
|
|
+ const judge = Number(item.isJudge) === 1;
|
|
|
+ const choice = judge || isChoiceQuestion(item);
|
|
|
const id = item.homeWorkStuQuesId || item.questionId || index;
|
|
|
return {
|
|
|
id,
|
|
|
questionId: item.questionId,
|
|
|
homeWorkStuQuesId: item.homeWorkStuQuesId,
|
|
|
+ isJudge: judge,
|
|
|
type: choice ? 'single' : 'photo',
|
|
|
- typeName: item.questionTypeName || (choice ? '客观题' : '主观题'),
|
|
|
- groupName: item.questionTypeName || (choice ? '客观题' : '主观题'),
|
|
|
+ typeName: item.questionTypeName || (judge ? '判断题' : (choice ? '客观题' : '主观题')),
|
|
|
+ groupName: item.questionTypeName || (judge ? '判断题' : (choice ? '客观题' : '主观题')),
|
|
|
difficulty: item.difficultyName || '',
|
|
|
stem: item.questionContent || '',
|
|
|
- options: choice ? buildOptions(item) : [],
|
|
|
+ options: judge ? [] : (choice ? buildOptions(item) : []),
|
|
|
writeAnswer: item.writeAnswer || '',
|
|
|
writeUrls: Array.isArray(item.writeUrls) ? item.writeUrls : [],
|
|
|
submitEndTime: item.submitEndTime || '',
|
|
|
@@ -193,13 +200,14 @@ export default {
|
|
|
const name = (this.homework && this.homework.subjectName) || '';
|
|
|
return this.$global.getSubjectsName(name, null, 'color');
|
|
|
},
|
|
|
- // 按题型分组,供左侧序号导航使用
|
|
|
+ // 按接口返回的 questionTypeName 分组,有几种题型就显示几组
|
|
|
questionGroups() {
|
|
|
const groups = [];
|
|
|
this.questions.forEach((item, index) => {
|
|
|
- let group = groups.find(g => g.type === item.type);
|
|
|
+ const name = item.groupName || item.typeName || '其他';
|
|
|
+ let group = groups.find(g => g.name === name);
|
|
|
if (!group) {
|
|
|
- group = { type: item.type, name: item.groupName, list: [] };
|
|
|
+ group = { type: name, name, list: [] };
|
|
|
groups.push(group);
|
|
|
}
|
|
|
group.list.push({ ...item, index });
|
|
|
@@ -212,10 +220,14 @@ export default {
|
|
|
if (!item) return null;
|
|
|
return { ...item, index: this.currentIndex };
|
|
|
},
|
|
|
- // 当前题是否为选择题
|
|
|
+ // 当前题是否为选择题(含判断题)
|
|
|
isSingle() {
|
|
|
return !!(this.currentQuestion && this.currentQuestion.type === 'single');
|
|
|
},
|
|
|
+ // isJudge 为 1 时是判断题,只显示对 / 错
|
|
|
+ isJudge() {
|
|
|
+ return !!(this.currentQuestion && this.currentQuestion.isJudge);
|
|
|
+ },
|
|
|
hasOptionText() {
|
|
|
const options = (this.currentQuestion && this.currentQuestion.options) || [];
|
|
|
return options.some(opt => opt.text);
|
|
|
@@ -315,9 +327,13 @@ export default {
|
|
|
return null;
|
|
|
},
|
|
|
applyDetail(res) {
|
|
|
- const list = Array.isArray(res && res.data) ? res.data : [];
|
|
|
+ const detail = this.pickDetail(res);
|
|
|
+ const list = detail.questionDetails;
|
|
|
+ this.mergeHomework(detail);
|
|
|
this.questions = list.map(mapQuestion);
|
|
|
- const endTime = (this.questions[0] && this.questions[0].submitEndTime) || this.homework.endTime;
|
|
|
+ const endTime = detail.submitEndTime
|
|
|
+ || (this.questions[0] && this.questions[0].submitEndTime)
|
|
|
+ || (this.homework && this.homework.endTime);
|
|
|
if (endTime && this.homework) this.homework.endTime = endTime;
|
|
|
this.fillAnswers();
|
|
|
if (this.currentIndex < 0 || this.currentIndex >= this.questions.length) {
|
|
|
@@ -325,6 +341,33 @@ export default {
|
|
|
}
|
|
|
this.persistState();
|
|
|
},
|
|
|
+ // 详情 data 为作业对象,题目在 questionDetails;兼容旧的题目数组
|
|
|
+ pickDetail(res) {
|
|
|
+ const data = res && res.data;
|
|
|
+ if (Array.isArray(data)) return { questionDetails: data };
|
|
|
+ if (data && typeof data === 'object') {
|
|
|
+ return {
|
|
|
+ ...data,
|
|
|
+ questionDetails: Array.isArray(data.questionDetails) ? data.questionDetails : [],
|
|
|
+ };
|
|
|
+ }
|
|
|
+ return { questionDetails: [] };
|
|
|
+ },
|
|
|
+ // 用详情里的作业信息补齐头部:名称、教师、科目、截止时间
|
|
|
+ mergeHomework(detail) {
|
|
|
+ const current = this.homework || {};
|
|
|
+ this.homework = {
|
|
|
+ ...current,
|
|
|
+ homeWorkId: detail.homeWorkId != null ? detail.homeWorkId : current.homeWorkId,
|
|
|
+ homeWorkStuId: detail.homeWorkStuId != null ? detail.homeWorkStuId : current.homeWorkStuId,
|
|
|
+ homeworkName: detail.homeWorkName || current.homeworkName || '',
|
|
|
+ teacherName: detail.createUserName || current.teacherName || '',
|
|
|
+ subjectName: detail.courseName || current.subjectName || '',
|
|
|
+ courseCode: detail.courseCode != null ? detail.courseCode : current.courseCode,
|
|
|
+ endTime: detail.submitEndTime || current.endTime || '',
|
|
|
+ questionNum: detail.questionNumber != null ? detail.questionNumber : current.questionNum,
|
|
|
+ };
|
|
|
+ },
|
|
|
fillAnswers() {
|
|
|
const savedAnswers = this.savedAnswers || {};
|
|
|
const answers = {};
|
|
|
@@ -333,6 +376,8 @@ export default {
|
|
|
const hasSaved = savedAnswers[item.id] != null || savedAnswers[String(item.id)] != null;
|
|
|
if (item.type === 'photo') {
|
|
|
answers[item.id] = hasSaved && Array.isArray(saved) ? saved : item.writeUrls.slice();
|
|
|
+ } else if (item.isJudge) {
|
|
|
+ answers[item.id] = this.normalizeJudgeAnswer(hasSaved ? saved : item.writeAnswer);
|
|
|
} else {
|
|
|
// 选择题多选,答案统一为选项 key 数组;兼容历史字符串缓存与接口回显
|
|
|
answers[item.id] = this.normalizeChoiceAnswer(hasSaved ? saved : item.writeAnswer, item.options);
|
|
|
@@ -340,6 +385,13 @@ export default {
|
|
|
});
|
|
|
this.answers = answers;
|
|
|
},
|
|
|
+ // 判断题回显:T 为对,F 为错
|
|
|
+ normalizeJudgeAnswer(value) {
|
|
|
+ const text = String(value == null ? '' : value).trim();
|
|
|
+ if (text === 'T' || text === 't' || text === '对' || text.toLowerCase() === 'true') return 'T';
|
|
|
+ if (text === 'F' || text === 'f' || text === '错' || text.toLowerCase() === 'false') return 'F';
|
|
|
+ return '';
|
|
|
+ },
|
|
|
// 把接口/缓存里的答案归一化为合法选项 key 数组,兼容 "A,C"、"AC"、"A|C"、["A"] 等格式
|
|
|
normalizeChoiceAnswer(value, options) {
|
|
|
const validKeys = (options || []).map(opt => opt.key);
|
|
|
@@ -521,16 +573,20 @@ export default {
|
|
|
if (this.uploading) this.$message.warning('图片正在上传,请稍候');
|
|
|
return Promise.resolve(false);
|
|
|
}
|
|
|
- const isChoice = question.type === 'single';
|
|
|
+ const isJudge = !!question.isJudge;
|
|
|
+ const isChoice = question.type === 'single' && !isJudge;
|
|
|
+ const judgeValue = this.answers[question.id];
|
|
|
const payload = {
|
|
|
homeWorkId: this.homework && this.homework.homeWorkId,
|
|
|
homeWorkStuId: this.homework && this.homework.homeWorkStuId,
|
|
|
homeWorkStuQuesId: question.homeWorkStuQuesId,
|
|
|
questionId: question.questionId,
|
|
|
commitFlag,
|
|
|
- // 选择题多选,以英文逗号拼接所选选项;拍照题提交图片地址
|
|
|
- writeAnswer: isChoice ? (this.answers[question.id] || []).join(',') : '',
|
|
|
- writeUrls: isChoice ? [] : (this.answers[question.id] || []),
|
|
|
+ // 判断题传 T / F;选择题多选以英文逗号拼接;拍照题提交图片地址
|
|
|
+ writeAnswer: isJudge
|
|
|
+ ? (judgeValue === 'T' || judgeValue === 'F' ? judgeValue : '')
|
|
|
+ : (isChoice ? (this.answers[question.id] || []).join(',') : ''),
|
|
|
+ writeUrls: isJudge || isChoice ? [] : (this.answers[question.id] || []),
|
|
|
};
|
|
|
this.saving = true;
|
|
|
return this.$api.teachingHomework.commitHomeWorkWriteAnswer(payload).then(res => {
|
|
|
@@ -925,6 +981,40 @@ export default {
|
|
|
color: #333;
|
|
|
line-height: 20px;
|
|
|
}
|
|
|
+
|
|
|
+ :deep(.el-radio) {
|
|
|
+ margin-right: 0 !important;
|
|
|
+ height: 20px;
|
|
|
+ display: inline-flex !important;
|
|
|
+ align-items: center;
|
|
|
+ }
|
|
|
+
|
|
|
+ :deep(.el-radio__input) {
|
|
|
+ display: inline-flex;
|
|
|
+ align-items: center;
|
|
|
+ height: 16px;
|
|
|
+ line-height: 16px;
|
|
|
+ }
|
|
|
+
|
|
|
+ :deep(.el-radio__inner) {
|
|
|
+ width: 16px;
|
|
|
+ height: 16px;
|
|
|
+ border: 1px solid #DCDFE6;
|
|
|
+ background: #fff;
|
|
|
+ }
|
|
|
+
|
|
|
+ :deep(.el-radio__input.is-checked .el-radio__inner) {
|
|
|
+ background-color: #2E64FA;
|
|
|
+ border-color: #2E64FA;
|
|
|
+ }
|
|
|
+
|
|
|
+ :deep(.el-radio__input.is-checked + .el-radio__label),
|
|
|
+ :deep(.el-radio__label) {
|
|
|
+ padding-left: 8px;
|
|
|
+ font-size: 14px;
|
|
|
+ color: #333;
|
|
|
+ line-height: 20px;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
.photo_list {
|