JudgePreview.vue 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. <template>
  2. <div class="judge-preview" :style="getAreaStyle()">
  3. <SerialNumberPosition v-if="isEnable(data.property.sn_display_mode)" :property="data.property" />
  4. <div class="main">
  5. <ul class="option-list">
  6. <li
  7. v-for="({ content, mark }, i) in data.option_list"
  8. :key="mark"
  9. :style="{ cursor: disabled ? 'not-allowed' : 'pointer' }"
  10. :class="['option-item', { active: isAnswer(mark) }]"
  11. >
  12. <div :class="['option-content', computedIsJudgeRight(mark)]">
  13. <span class="serial-number">{{ convertNumberToLetter(i) }}.</span>
  14. <div class="rich-text" v-html="sanitizeHTML(content)"></div>
  15. </div>
  16. <div class="option-type">
  17. <div
  18. v-for="option_type in incertitudeList"
  19. :key="option_type"
  20. :style="{ cursor: disabled ? 'not-allowed' : 'pointer' }"
  21. :class="[
  22. 'option-type-item',
  23. {
  24. active: isAnswer(mark, option_type),
  25. },
  26. computedIsShowRightAnswer(mark, option_type),
  27. ]"
  28. @click="selectAnswer(mark, option_type)"
  29. >
  30. <SvgIcon
  31. v-if="option_type === option_type_list[0].value"
  32. icon-class="check-mark"
  33. width="17"
  34. height="12"
  35. />
  36. <SvgIcon v-if="option_type === option_type_list[1].value" icon-class="cross" size="12" />
  37. <SvgIcon v-if="option_type === option_type_list[2].value" icon-class="circle" size="16" />
  38. </div>
  39. </div>
  40. </li>
  41. </ul>
  42. </div>
  43. </div>
  44. </template>
  45. <script>
  46. import { getJudgeData, option_type_list, isEnable } from '@/views/book/courseware/data/judge';
  47. import PreviewMixin from '../common/PreviewMixin';
  48. export default {
  49. name: 'JudgePreview',
  50. mixins: [PreviewMixin],
  51. data() {
  52. return {
  53. data: getJudgeData(),
  54. option_type_list,
  55. isEnable,
  56. };
  57. },
  58. computed: {
  59. incertitudeList() {
  60. let _option_type_list = this.data.property.option_type_list;
  61. if (isEnable(this.data.property.is_view_incertitude)) {
  62. return _option_type_list;
  63. }
  64. // 返回不包含第三个元素的新数组
  65. return [..._option_type_list.slice(0, 2), ..._option_type_list.slice(3)];
  66. },
  67. },
  68. methods: {
  69. // 将数字转换为小写字母
  70. convertNumberToLetter(number) {
  71. return String.fromCharCode(97 + number);
  72. },
  73. isAnswer(mark, option_type) {
  74. return this.answer.answer_list.some((li) => li.mark === mark && li.option_type === option_type);
  75. },
  76. // 选择答案
  77. selectAnswer(mark, option_type) {
  78. if (this.disabled) return;
  79. const index = this.answer.answer_list.findIndex((li) => li.mark === mark);
  80. if (index === -1) {
  81. this.answer.answer_list.push({ mark, option_type });
  82. } else {
  83. this.answer.answer_list[index].option_type = option_type;
  84. }
  85. },
  86. // 计算判断题小题题目样式
  87. computedIsJudgeRight(mark) {
  88. if (!this.isJudgingRightWrong) return '';
  89. let selectOption = this.answer.answer_list.find((item) => item.mark === mark); // 查找是否已选中的选项
  90. if (!selectOption) return 'wrong';
  91. return this.data.answer.answer_list.find((item) => item.mark === mark).option_type === selectOption.option_type
  92. ? 'right'
  93. : 'wrong';
  94. },
  95. // 计算是否显示正确答案的样式
  96. computedIsShowRightAnswer(mark, option_type) {
  97. if (!this.isShowRightAnswer) return '';
  98. let selectOption = this.answer.answer_list.find((item) => item.mark === mark); // 查找是否已选中的选项
  99. // 是否是正确的选项类型
  100. let isCorrectType = this.data.answer.answer_list.find((item) => item.mark === mark)?.option_type === option_type;
  101. if (!selectOption) {
  102. return isCorrectType ? 'answer-right' : '';
  103. }
  104. return isCorrectType && !(selectOption.option_type === option_type) ? 'answer-right' : '';
  105. },
  106. },
  107. };
  108. </script>
  109. <style lang="scss" scoped>
  110. @use '@/styles/mixin.scss' as *;
  111. .judge-preview {
  112. @include preview-base;
  113. .option-list {
  114. display: flex;
  115. flex-direction: column;
  116. row-gap: 16px;
  117. .option-item {
  118. display: flex;
  119. column-gap: 16px;
  120. .option-content {
  121. display: flex;
  122. flex: 1;
  123. column-gap: 8px;
  124. align-items: center;
  125. padding: 12px 24px;
  126. background-color: $content-color;
  127. border-radius: 40px;
  128. &.right {
  129. background-color: $right-bc-color;
  130. }
  131. &.wrong {
  132. box-shadow: 0 0 0 1px $error-color;
  133. }
  134. .serial-number {
  135. font-size: 16pt;
  136. color: #000;
  137. }
  138. }
  139. .option-type {
  140. display: flex;
  141. column-gap: 8px;
  142. align-items: center;
  143. &-item {
  144. display: flex;
  145. align-items: center;
  146. justify-content: center;
  147. width: 48px;
  148. height: 48px;
  149. color: #000;
  150. cursor: pointer;
  151. background-color: $content-color;
  152. border-radius: 50%;
  153. &.active {
  154. color: #fff;
  155. background-color: $light-main-color;
  156. }
  157. &.answer-right {
  158. color: $right-color;
  159. border: 1px solid $right-color;
  160. }
  161. }
  162. }
  163. }
  164. }
  165. }
  166. </style>