MultipleQuestionView.vue 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. <template>
  2. <div v-if="isSyncState && examQuestion.questionType === 'MULTIPLE_CHOICE'" class="question-view">
  3. <question-body :questionBody="question.body" :examQuestion="examQuestion"></question-body>
  4. <div class="ops">
  5. <div class="stu-answer"> {{oldIndexToABCD}}</div>
  6. <div class="score">({{examQuestion.questionScore}}分)</div>
  7. </div>
  8. <div v-for="(option, index) in newQuestionOptions" :key="index" class="option" @click="toggleAnswer(option.oldIndex)">
  9. <div :class="studentAnswer.includes(option.oldIndex) && 'row-selected'">
  10. <input type="checkbox" name="question" value="option.oldIndex" :checked="studentAnswer && studentAnswer.includes(option.oldIndex)" />
  11. <span style="padding: 0 10px;">{{optionName[index]}}: </span>
  12. <span class="question-options" v-if="option.value" v-html="option.value.body"></span>
  13. </div>
  14. </div>
  15. <div class="reset">
  16. <i-button type="warning" size="large" @click="() => answerQuestion(null)">重置答案</i-button>
  17. <span v-if="examShouldShowAnswer()">
  18. &nbsp;&nbsp;&nbsp;<i-button type="info" size="large" @click="showAnswer">显示答案</i-button>
  19. </span>
  20. <div v-if="examShouldShowAnswer() && isShowAnswer">
  21. 正确答案:<div>{{rightAnswerTransform}}</div>
  22. </div>
  23. </div>
  24. </div>
  25. </template>
  26. <script>
  27. import QuestionBody from "./QuestionBody";
  28. import { createNamespacedHelpers } from "vuex";
  29. const { mapMutations, mapGetters } = createNamespacedHelpers(
  30. "examingHomeModule"
  31. );
  32. const optionName = "ABCDEF".split("");
  33. export default {
  34. name: "MultipleQuestionView",
  35. data() {
  36. return {
  37. questionBody: this.question.body,
  38. optionName,
  39. studentAnswer: this.examQuestion.studentAnswer || "",
  40. isShowAnswer: false
  41. };
  42. },
  43. props: {
  44. question: Object,
  45. examQuestion: Object
  46. },
  47. created: function() {
  48. window.addEventListener("keyup", this.keyup);
  49. },
  50. beforeDestroy() {
  51. window.removeEventListener("keyup", this.keyup);
  52. },
  53. beforeUpdate() {
  54. this.answerQuestion(this.studentAnswer);
  55. },
  56. methods: {
  57. ...mapMutations(["updateExamQuestion"]),
  58. ...mapGetters(["examShouldShowAnswer"]),
  59. keyup(e) {
  60. if (
  61. ["BODY", "A", "BUTTON", "DIV"].includes(
  62. document.activeElement.tagName
  63. ) ||
  64. (["INPUT"].includes(document.activeElement.tagName) &&
  65. ["checkbox", "radio"].includes(document.activeElement.type))
  66. ) {
  67. if (
  68. ["KeyA", "KeyB", "KeyC", "KeyD", "KeyE", "KeyF", "KeyG"]
  69. .slice(0, this.question.questionOptionList.length)
  70. .includes(e.code)
  71. ) {
  72. const selectedOldIndex =
  73. "" +
  74. this.newQuestionOptions.find(v => v.name == e.code[3]).oldIndex;
  75. if (this.studentAnswer.includes(selectedOldIndex)) {
  76. this.studentAnswer = this.studentAnswer.replace(
  77. selectedOldIndex,
  78. ""
  79. );
  80. } else {
  81. this.studentAnswer = this.studentAnswer
  82. .concat(selectedOldIndex)
  83. .split("")
  84. .sort()
  85. .join("");
  86. }
  87. }
  88. }
  89. },
  90. toggleAnswer: function(selectedOldIndex) {
  91. if (this.studentAnswer.includes(selectedOldIndex)) {
  92. this.studentAnswer = this.studentAnswer.replace(selectedOldIndex, "");
  93. } else {
  94. this.studentAnswer = this.studentAnswer
  95. .concat(selectedOldIndex)
  96. .split("")
  97. .sort()
  98. .join("");
  99. }
  100. },
  101. async answerQuestion(studentAnswer) {
  102. let realAnswer = studentAnswer;
  103. if (studentAnswer === "") {
  104. realAnswer = null;
  105. }
  106. if (realAnswer !== this.examQuestion.studentAnswer) {
  107. this.updateExamQuestion({
  108. order: this.examQuestion.order,
  109. studentAnswer: realAnswer
  110. });
  111. }
  112. },
  113. showAnswer() {
  114. this.isShowAnswer = !this.isShowAnswer;
  115. }
  116. },
  117. watch: {
  118. examQuestion: function() {
  119. this.studentAnswer = this.examQuestion.studentAnswer || "";
  120. }
  121. },
  122. computed: {
  123. isSyncState() {
  124. return this.examQuestion.order == this.$route.params.order;
  125. },
  126. newQuestionOptions() {
  127. return this.question.questionOptionList.map((v, i) => {
  128. return {
  129. value: this.question.questionOptionList[
  130. this.examQuestion.optionPermutation[i]
  131. ],
  132. oldIndex: "" + this.examQuestion.optionPermutation[i],
  133. name: optionName[i]
  134. };
  135. });
  136. },
  137. oldIndexToABCD() {
  138. return (
  139. this.examQuestion.studentAnswer &&
  140. this.newQuestionOptions
  141. .filter(v => this.examQuestion.studentAnswer.includes(v.oldIndex))
  142. .map(v => v.name)
  143. .join("")
  144. );
  145. },
  146. rightAnswerTransform() {
  147. return (
  148. this.question.rightAnswer &&
  149. this.newQuestionOptions
  150. .filter(v => this.question.rightAnswer.includes(v.oldIndex))
  151. .map(v => v.name)
  152. .join("")
  153. );
  154. }
  155. },
  156. components: {
  157. QuestionBody
  158. }
  159. };
  160. </script>
  161. <style scoped>
  162. .question-view {
  163. display: grid;
  164. grid-row-gap: 10px;
  165. }
  166. .question-body {
  167. font-size: 18px;
  168. margin-bottom: 10px;
  169. }
  170. .ops {
  171. display: flex;
  172. align-items: flex-end;
  173. }
  174. .stu-answer {
  175. width: 100px;
  176. border-bottom: 1px solid black;
  177. text-align: center;
  178. height: 20px;
  179. }
  180. .option {
  181. display: flex;
  182. cursor: pointer;
  183. }
  184. .option:hover {
  185. background-color: aliceblue;
  186. }
  187. .row-selected {
  188. background-color: aliceblue;
  189. width: 100%;
  190. }
  191. .question-options {
  192. text-align: left;
  193. }
  194. </style>