ExamingHome.vue 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. <template>
  2. <div v-if="exam && examQuestion()" class="container">
  3. <div class="header">
  4. <RemainTime></RemainTime>
  5. <OverallProgress :exam-question-list="examQuestionList"></OverallProgress>
  6. <QuestionFilters :exam-question-list="examQuestionList"></QuestionFilters>
  7. <Button class="qm-primary-button" @click="submitPaper">交卷</Button>
  8. </div>
  9. <div class="main">
  10. <QuestionView :exam-question="examQuestion()"></QuestionView>
  11. <ArrowNavView :previousQuestionOrder="previousQuestionOrder" :nextQuestionOrder="nextQuestionOrder"></ArrowNavView>
  12. </div>
  13. <div class="side">
  14. <div class="question-nav">
  15. <QuestionNavView :paperStruct="paperStruct" />
  16. </div>
  17. <div class="camera">
  18. <FaceRecognition width="100%" height="100%" :showRecognizeButton="false" />
  19. </div>
  20. </div>
  21. </div>
  22. </template>
  23. <script>
  24. import RemainTime from "./RemainTime.vue";
  25. import OverallProgress from "./OverallProgress.vue";
  26. import QuestionFilters from "./QuestionFilters.vue";
  27. import QuestionView from "./QuestionView.vue";
  28. import ArrowNavView from "./ArrowNavView.vue";
  29. import QuestionNavView from "./QuestionNavView.vue";
  30. import FaceRecognition from "../../../components/FaceRecognition/FaceRecognition";
  31. import { createNamespacedHelpers } from "vuex";
  32. const { mapState, mapMutations } = createNamespacedHelpers("examingHomeModule");
  33. export default {
  34. name: "ExamingHome",
  35. created() {
  36. this.initData();
  37. if (!this.$route.params.order) {
  38. // created can access this.$route?
  39. this.$router.push(this.$route.fullPath + "/order/1");
  40. return;
  41. }
  42. setInterval(() => {
  43. this.toggleSnapNow();
  44. }, 30000);
  45. },
  46. // beforeRouteUpdate(to, from, next) {
  47. // this.updateQuestion(next);
  48. // },
  49. methods: {
  50. ...mapMutations(["updateExamState", "toggleSnapNow"]),
  51. async initData() {
  52. const exam = await this.$http.get(
  53. "/api/ecs_exam_work/exam/" + this.$route.params.examId
  54. );
  55. const paperStruct = await this.$http.get(
  56. "/api/ecs_oe_student/examRecordPaperStruct/getExamRecordPaperStruct?examRecordDataId=" +
  57. this.$route.params.examRecordDataId
  58. );
  59. const examQuestionList = await this.$http.get(
  60. "/api/ecs_oe_student/examQuestion/findExamQuestionList"
  61. );
  62. this.updateExamState({
  63. exam: exam.data,
  64. paperStruct: paperStruct.data,
  65. examQuestionList: examQuestionList.data
  66. });
  67. },
  68. updateQuestion: async function(next) {
  69. // 初始化套题的答案,为回填部分选项做准备
  70. // for (let q of this.examQuestionList) {
  71. // if (q.subQuestionList.length > 0) {
  72. // q.stuAnswer = [];
  73. // for (let sq of q.subQuestionList) {
  74. // q.stuAnswer.push(sq.stuAnswer);
  75. // }
  76. // }
  77. // }
  78. next && next();
  79. if (!this.exam) return;
  80. },
  81. async submitPaper() {
  82. //FIXME: submit precondition
  83. await this.$http.get("/api/ecs_oe_student/examControl/endExam");
  84. this.$router.push("/");
  85. },
  86. examQuestion() {
  87. return (
  88. this.examQuestionList &&
  89. this.examQuestionList.find(
  90. eq => eq.order == this.$route.params.order // number == string
  91. )
  92. );
  93. }
  94. },
  95. computed: {
  96. ...mapState(["exam", "paperStruct", "examQuestionList", "snapNow"]),
  97. previousQuestionOrder: vm => {
  98. if (vm.examQuestion().order > 1) {
  99. return vm.examQuestion().order - 1;
  100. } else {
  101. return null;
  102. }
  103. },
  104. nextQuestionOrder: vm => {
  105. if (vm.examQuestion().order < vm.examQuestionList.length) {
  106. return vm.examQuestion().order + 1;
  107. } else {
  108. return null;
  109. }
  110. }
  111. },
  112. watch: {
  113. $route: function() {
  114. this.examQuestion();
  115. }
  116. },
  117. components: {
  118. RemainTime,
  119. OverallProgress,
  120. QuestionFilters,
  121. QuestionView,
  122. ArrowNavView,
  123. QuestionNavView,
  124. FaceRecognition
  125. }
  126. };
  127. </script>
  128. <style scoped>
  129. .container {
  130. display: grid;
  131. grid-template-areas:
  132. "header header"
  133. "main side";
  134. grid-template-rows: 80px 1fr;
  135. grid-template-columns: 1fr 400px;
  136. height: 100vh;
  137. width: 100vw;
  138. }
  139. .header {
  140. display: grid;
  141. place-items: center;
  142. grid-template-columns: 200px 1fr 300px 100px;
  143. grid-area: header;
  144. height: 80px;
  145. background-color: #f5f5f5;
  146. }
  147. .main {
  148. display: grid;
  149. grid-area: main;
  150. grid-template-rows: 1fr 50px;
  151. }
  152. .side {
  153. display: grid;
  154. grid-area: side;
  155. grid-template-rows: 1fr 300px;
  156. background-color: #f5f5f5;
  157. }
  158. .camera {
  159. align-self: flex-end;
  160. justify-self: flex-end;
  161. }
  162. @media screen and (max-height: 768px) {
  163. .container {
  164. grid-template-rows: 50px 1fr;
  165. }
  166. .header {
  167. height: 50px;
  168. }
  169. .side {
  170. grid-template-rows: 1fr 200px;
  171. }
  172. }
  173. </style>