|
@@ -5,19 +5,33 @@
|
|
|
<span class="question-number">{{ data.property.question_number }}.</span>
|
|
|
<span v-html="sanitizeHTML(data.stem)"></span>
|
|
|
</div>
|
|
|
- <div v-if="isEnable(data.property.is_enable_description)" class="description">
|
|
|
- <span v-for="(text, i) in descriptionList" :key="i" class="description-item" @click="selectedDescription(text)">
|
|
|
- {{ text }}
|
|
|
- </span>
|
|
|
- </div>
|
|
|
+ <div
|
|
|
+ v-if="isEnable(data.property.is_enable_description)"
|
|
|
+ class="description rich-text"
|
|
|
+ v-html="sanitizeHTML(data.description)"
|
|
|
+ ></div>
|
|
|
|
|
|
<div class="content">
|
|
|
- <div v-for="(item, i) in optionList" :key="i" class="option-list">
|
|
|
+ <div
|
|
|
+ v-for="(item, i) in optionList"
|
|
|
+ :key="i"
|
|
|
+ class="option-list"
|
|
|
+ :style="{ flexDirection: item.type === 'input_student' ? 'row-reverse' : 'row' }"
|
|
|
+ >
|
|
|
<span
|
|
|
class="avatar"
|
|
|
- :style="{ backgroundColor: data.property.role_list?.find(({ mark }) => mark === item.role).color }"
|
|
|
+ :style="{
|
|
|
+ backgroundColor:
|
|
|
+ item.type === 'input_student'
|
|
|
+ ? '#306EFF'
|
|
|
+ : data.property.role_list?.find(({ mark }) => mark === item.role).color,
|
|
|
+ }"
|
|
|
>
|
|
|
- {{ data.property.role_list?.find(({ mark }) => mark === item.role).name }}
|
|
|
+ {{
|
|
|
+ item.type === 'input_student'
|
|
|
+ ? '学生'
|
|
|
+ : data.property.role_list?.find(({ mark }) => mark === item.role).name
|
|
|
+ }}
|
|
|
</span>
|
|
|
|
|
|
<div v-if="item.type === 'text' || item.type === 'input'" class="text-wrapper">
|
|
@@ -31,7 +45,6 @@
|
|
|
:disabled="disabled"
|
|
|
:class="[...computedAnswerClass(item.mark, li.mark, li.content)]"
|
|
|
:style="[{ width: Math.max(80, li.content.length * 16) + 'px' }]"
|
|
|
- @focus="handleInputFocus(i, j)"
|
|
|
/>
|
|
|
<span
|
|
|
v-show="computedAnswerText(item.mark, li.mark, li.content).length > 0"
|
|
@@ -63,6 +76,10 @@
|
|
|
:background-color="data.property.role_list?.find(({ mark }) => mark === item.role).color"
|
|
|
/>
|
|
|
</div>
|
|
|
+
|
|
|
+ <div v-else-if="item.type === 'input_student'">
|
|
|
+ <SoundRecordPreview :wav-blob.sync="item.file_id" :disabled="disabled" type="small" />
|
|
|
+ </div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
@@ -91,11 +108,6 @@ export default {
|
|
|
},
|
|
|
};
|
|
|
},
|
|
|
- computed: {
|
|
|
- descriptionList() {
|
|
|
- return this.data.description.split(/\s+/).filter((item) => item);
|
|
|
- },
|
|
|
- },
|
|
|
watch: {
|
|
|
'data.option_list': {
|
|
|
handler(val) {
|
|
@@ -118,6 +130,14 @@ export default {
|
|
|
handler(val) {
|
|
|
this.answer.answer_list = [];
|
|
|
val.forEach(({ type, content_list, mark, file_id }) => {
|
|
|
+ if (type === 'input_student') {
|
|
|
+ if (file_id.length <= 0) return;
|
|
|
+ this.answer.answer_list.push({
|
|
|
+ audio_file_id: file_id,
|
|
|
+ mark,
|
|
|
+ });
|
|
|
+ return;
|
|
|
+ }
|
|
|
if (type !== 'input') return;
|
|
|
let list = content_list
|
|
|
.map(({ type, mark, content }) => {
|
|
@@ -144,7 +164,7 @@ export default {
|
|
|
this.answer.answer_list.forEach(({ mark, audio_file_id, content_list }) => {
|
|
|
let findOption = this.optionList.find((item) => item.mark === mark);
|
|
|
findOption.file_id = audio_file_id;
|
|
|
- findOption.content_list.forEach((item) => {
|
|
|
+ findOption?.content_list.forEach((item) => {
|
|
|
if (item.type === 'text') return;
|
|
|
let find = content_list.find((li) => li.mark === item.mark);
|
|
|
item.content = find.value;
|
|
@@ -152,54 +172,8 @@ export default {
|
|
|
});
|
|
|
},
|
|
|
},
|
|
|
- created() {
|
|
|
- document.addEventListener('click', this.handleBlur);
|
|
|
- document.addEventListener('keydown', this.handleBlurTab);
|
|
|
- },
|
|
|
- beforeDestroy() {
|
|
|
- document.removeEventListener('click', this.handleBlur);
|
|
|
- document.removeEventListener('keydown', this.handleBlurTab);
|
|
|
- },
|
|
|
methods: {
|
|
|
/**
|
|
|
- * 处理点击失焦
|
|
|
- * @param {MouseEvent} e
|
|
|
- */
|
|
|
- handleBlur(e) {
|
|
|
- if (e.target.tagName === 'INPUT') return;
|
|
|
- this.inputFocus = false;
|
|
|
- },
|
|
|
- /**
|
|
|
- * 处理 tab 键失焦
|
|
|
- * @param {KeyboardEvent} e
|
|
|
- */
|
|
|
- handleBlurTab(e) {
|
|
|
- if (e.key !== 'Tab') return;
|
|
|
- this.inputFocus = false;
|
|
|
- },
|
|
|
- /**
|
|
|
- * 处理输入框聚焦
|
|
|
- * @param {number} i
|
|
|
- * @param {number} j
|
|
|
- */
|
|
|
- handleInputFocus(i, j) {
|
|
|
- this.inputFocus = true;
|
|
|
- this.focusPostion = {
|
|
|
- i,
|
|
|
- j,
|
|
|
- };
|
|
|
- },
|
|
|
- /**
|
|
|
- * 选中描述
|
|
|
- * @param {string} text 描述文本
|
|
|
- */
|
|
|
- selectedDescription(text) {
|
|
|
- if (!this.inputFocus) return;
|
|
|
- const { i, j } = this.focusPostion;
|
|
|
- this.optionList[i].content_list[j].content = text;
|
|
|
- this.inputFocus = false;
|
|
|
- },
|
|
|
- /**
|
|
|
* 计算答题对错选项字体颜色
|
|
|
* @param {string} optionMark 选项标识
|
|
|
* @param {string} mark 选项标识
|
|
@@ -348,21 +322,21 @@ export default {
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- .sound-record-preview {
|
|
|
- padding: 4px;
|
|
|
- background-color: #fff;
|
|
|
- border-radius: 40px;
|
|
|
+ .sound-record-preview {
|
|
|
+ padding: 4px;
|
|
|
+ background-color: #fff;
|
|
|
+ border-radius: 40px;
|
|
|
|
|
|
- :deep .sound-item .sound-item-span {
|
|
|
- color: #1d1d1d;
|
|
|
- background-color: #fff;
|
|
|
- }
|
|
|
+ :deep .sound-item .sound-item-span {
|
|
|
+ color: #1d1d1d;
|
|
|
+ background-color: #fff;
|
|
|
+ }
|
|
|
|
|
|
- :deep .sound-item-luyin .sound-item-span {
|
|
|
- color: #fff;
|
|
|
- background-color: $light-main-color;
|
|
|
- }
|
|
|
+ :deep .sound-item-luyin .sound-item-span {
|
|
|
+ color: #fff;
|
|
|
+ background-color: $light-main-color;
|
|
|
}
|
|
|
}
|
|
|
|