JudgePreview.vue 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. <!-- eslint-disable vue/no-v-html -->
  2. <template>
  3. <div class="judge-preview">
  4. <div class="stem">
  5. <span class="question-number">{{ data.property.question_number }}.</span>
  6. <span v-html="sanitizeHTML(data.stem)"></span>
  7. </div>
  8. <AudioPlay
  9. v-if="isEnable(data.property.is_enable_listening) && data.file_id_list.length > 0"
  10. :file-id="data.file_id_list[0]"
  11. />
  12. <ul class="option-list">
  13. <li
  14. v-for="({ content, mark }, i) in data.option_list"
  15. :key="mark"
  16. :class="['option-item', { active: isAnswer(mark) }]"
  17. >
  18. <div class="option-content">
  19. <span class="serial-number">{{ computedQuestionNumber(i, data.option_number_show_mode) }}</span>
  20. <div v-html="sanitizeHTML(content)"></div>
  21. </div>
  22. <div class="option-type">
  23. <div
  24. v-for="option_type in data.property.option_type_list"
  25. :key="option_type"
  26. :class="[
  27. 'option-type-item',
  28. {
  29. active: isAnswer(mark, option_type),
  30. },
  31. ]"
  32. @click="selectAnswer(mark, option_type)"
  33. >
  34. <SvgIcon v-if="option_type === option_type_list[0].value" icon-class="check-mark" width="17" height="12" />
  35. <SvgIcon v-if="option_type === option_type_list[1].value" icon-class="cross" size="12" />
  36. <SvgIcon v-if="option_type === option_type_list[2].value" icon-class="circle" size="20" />
  37. </div>
  38. </div>
  39. </li>
  40. </ul>
  41. </div>
  42. </template>
  43. <script>
  44. import { option_type_list } from '@/views/exercise_questions/data/judge';
  45. import { computedQuestionNumber } from '@/views/exercise_questions/data/common';
  46. import PreviewMixin from './components/PreviewMixin';
  47. export default {
  48. name: 'JudgePreview',
  49. mixins: [PreviewMixin],
  50. data() {
  51. return {
  52. computedQuestionNumber,
  53. option_type_list,
  54. };
  55. },
  56. methods: {
  57. isAnswer(mark, option_type) {
  58. return this.answer.answer_list.some((li) => li.mark === mark && li.option_type === option_type);
  59. },
  60. selectAnswer(mark, option_type) {
  61. const index = this.answer.answer_list.findIndex((li) => li.mark === mark);
  62. if (index === -1) {
  63. this.answer.answer_list.push({ mark, option_type });
  64. } else {
  65. this.answer.answer_list[index].option_type = option_type;
  66. }
  67. },
  68. },
  69. };
  70. </script>
  71. <style lang="scss" scoped>
  72. @use '@/styles/mixin.scss' as *;
  73. .judge-preview {
  74. @include preview;
  75. .option-list {
  76. display: flex;
  77. flex-direction: column;
  78. row-gap: 16px;
  79. .option-item {
  80. display: flex;
  81. column-gap: 16px;
  82. .option-content {
  83. display: flex;
  84. flex: 1;
  85. column-gap: 24px;
  86. align-items: center;
  87. padding: 12px 24px;
  88. background-color: $content-color;
  89. border-radius: 40px;
  90. .serial-number {
  91. color: #000;
  92. }
  93. }
  94. .option-type {
  95. display: flex;
  96. column-gap: 8px;
  97. align-items: center;
  98. &-item {
  99. display: flex;
  100. align-items: center;
  101. justify-content: center;
  102. width: 48px;
  103. height: 48px;
  104. color: #000;
  105. cursor: pointer;
  106. background-color: $content-color;
  107. border-radius: 50%;
  108. &.active {
  109. color: #fff;
  110. background-color: $light-main-color;
  111. }
  112. }
  113. }
  114. }
  115. }
  116. }
  117. </style>