Browse Source

考试界面,头部信息

Michael Wang 6 years ago
parent
commit
5d410535d4

+ 15 - 1
http-test/online-exam.http

@@ -7,7 +7,7 @@ Content-Type: application/json;charset=UTF-8
 "accountType":"STUDENT_CODE"}
 
 
-@token = 0290ade4db874d388339aa236e7b676a
+@token = 807870010c1a4e20bdd627ab68f62ecd
 @key = U_S_109_53286
 
 ###
@@ -33,3 +33,17 @@ GET https://ecs-dev.qmth.com.cn:8878/api/ecs_core/org/logo?domain=ecs-dev.qmth.c
 ###
 GET https://ecs-dev.qmth.com.cn:8878/api/ecs_core/org/getRootOrgByCode?code=ecs-dev.qmth.com.cn
 
+### 开始考试
+GET https://ecs-dev.qmth.com.cn:8878/api/exam_control/start?stu_exam_info_id=194505112781
+token: {{token}}
+key: {{key}}
+
+### 结束考试(交卷)
+GET https://ecs-dev.qmth.com.cn:8878/api/exam_control/submit
+token: {{token}}
+key: {{key}}
+
+### heartbeat
+GET https://ecs-dev.qmth.com.cn:8878/api/exam_control/heartbeat
+token: {{token}}
+key: {{key}}

+ 72 - 0
src/features/OnlineExam/Examing/ExamingHome.vue

@@ -0,0 +1,72 @@
+<template>
+  <div class="container">
+    <div class="header">
+      <RemainTime></RemainTime>
+      <OverallProgress :exam-question-list="examQuestionList"></OverallProgress>
+      <QuestionFilters :exam-question-list="examQuestionList"></QuestionFilters>
+      <Button class="qm-primary-button">交卷</Button>
+    </div>
+    <div class="main">
+      main
+    </div>
+    <div class="side">
+      <div class="question-nav">
+        question nav
+      </div>
+      <div class="camera">
+        camera
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import RemainTime from "./RemainTime.vue";
+import OverallProgress from "./OverallProgress.vue";
+import QuestionFilters from "./QuestionFilters.vue";
+
+export default {
+  data() {
+    return {
+      exam: null,
+      paperStruct: null,
+      examQuestionList: []
+    };
+  },
+  async mounted() {
+    const exam = await this.$http.get(
+      "/api/ecs_exam_work/exam/" + this.$route.params.examId
+    );
+    this.exam = exam.data;
+
+    const paperStruct = await this.$http.get(
+      "/api/exam_question/paper_struct/?exam_record_id=" +
+        this.$route.query.examRecordId
+    );
+    this.paperStruct = paperStruct.data;
+
+    const examQuestionList = await this.$http.get(
+      "/api/exam_question/?exam_record_id=" + this.$route.query.examRecordId
+    );
+    this.examQuestionList = examQuestionList.data;
+  },
+  components: {
+    RemainTime,
+    OverallProgress,
+    QuestionFilters
+  }
+};
+</script>
+
+<style scoped>
+.header {
+  /* display: flex;
+  flex-direction: row; */
+  display: grid;
+  place-items: center;
+  grid-template-columns: 200px 1fr 300px 100px;
+
+  height: 80px;
+}
+</style>
+

+ 30 - 0
src/features/OnlineExam/Examing/OverallProgress.vue

@@ -0,0 +1,30 @@
+<template>
+  <div class="remain-time">进度 {{progress}}</div>
+</template>
+
+<script>
+export default {
+  name: "OverallProgress",
+  data() {
+    return {};
+  },
+  props: {
+    examQuestionList: Array
+  },
+  async mounted() {},
+  computed: {
+    progress: function() {
+      return `${this.examQuestionList.filter(q => q.stuAnswer).length} / ${
+        this.examQuestionList.length
+      }`;
+    }
+  }
+};
+</script>
+
+<style scoped>
+.remain-time {
+  justify-self: flex-start;
+}
+</style>
+

+ 43 - 0
src/features/OnlineExam/Examing/QuestionFilters.vue

@@ -0,0 +1,43 @@
+<template>
+  <div class="q-filters">
+    <div class="remain-time">全部 {{all}}</div>
+    <div class="remain-time">已答 {{answered}}</div>
+    <div class="remain-time">标记 {{signed}}</div>
+    <div class="remain-time">未答 {{unanswered}}</div>
+  </div>
+</template>
+
+<script>
+export default {
+  name: "QuestionFilters",
+  data() {
+    return {};
+  },
+  props: {
+    examQuestionList: Array
+  },
+  async mounted() {},
+  computed: {
+    all: function() {
+      return this.examQuestionList.length;
+    },
+    answered: function() {
+      return this.examQuestionList.filter(q => q.stuAnswer).length;
+    },
+    signed: function() {
+      return this.examQuestionList.filter(q => q.isSign).length;
+    },
+    unanswered: function() {
+      return this.examQuestionList.filter(q => !q.stuAnswer).length;
+    }
+  }
+};
+</script>
+
+<style scoped>
+.q-filters {
+  display: grid;
+  grid-template-columns: 1fr 1fr 1fr 1fr;
+}
+</style>
+

+ 25 - 0
src/features/OnlineExam/Examing/RemainTime.vue

@@ -0,0 +1,25 @@
+<template>
+  <div class="remain-time">剩余时间 {{remainTimeFormatted}}</div>
+</template>
+
+<script>
+import moment from "moment";
+
+export default {
+  name: "RemainTime",
+  data() {
+    return {
+      remainTime: null
+    };
+  },
+  async mounted() {
+    const res = await this.$http.get("/api/exam_control/heartbeat");
+    this.remainTime = res.data.leftTime;
+  },
+  computed: {
+    remainTimeFormatted: function() {
+      return moment.utc(this.remainTime).format("HH:mm:ss");
+    }
+  }
+};
+</script>

+ 13 - 2
src/features/OnlineExam/OnlineExamOverview.vue

@@ -10,9 +10,9 @@
       <!-- data-ui-sref="exam.start({examRecordId: startInfo.id,stuExamInfoId:stateParams.stuExamInfoId,examMins:startInfo.paperMins,examId:examInfo.id,faceVerifyMinute:startInfo.faceVerifyMinute})" -->
 
       <a class="qm-primary-button" v-show="remainTime > 110" disabled style="display: inline-block; width: 100%;">
-        强制阅读(倒计时:{{remainTime}})</a>
+        强制阅读(倒计时:{{remainTimeFormatted}})</a>
       <a class="qm-primary-button" v-show="remainTime < 110" style="display: inline-block; width: 100%;">
-        开始答题(倒计时:{{remainTime}})</a>
+        开始答题(倒计时:{{remainTimeFormatted}})</a>
     </div>
 
     <div class="exam-detail">
@@ -41,6 +41,8 @@
 </template>
 
 <script>
+import moment from "moment";
+
 export default {
   data() {
     return {
@@ -53,6 +55,10 @@ export default {
   async mounted() {
     this.intervalId = setInterval(() => {
       this.remainTime = --this.remainTime;
+      if (remainTime === 0) {
+        this.$router.push("/online-exam/exam/:id/");
+        window.clearInterval(this.intervalId);
+      }
     }, 1000);
     const exam = await this.$http.get(
       "/api/ecs_exam_work/exam/" + this.$route.params.examId
@@ -144,6 +150,11 @@ export default {
   },
   beforeDestroy() {
     clearInterval(this.intervalId);
+  },
+  computed: {
+    remainTimeFormatted: function() {
+      return moment.utc(this.remainTime).format("hh:mm:ss");
+    }
   }
 };
 </script>

+ 6 - 0
src/router.js

@@ -4,6 +4,7 @@ import Router from "vue-router";
 import NotFoundComponent from "./views/NotFoundComponent.vue";
 import OnlineExamHome from "./features/OnlineExam/OnlineExamHome.vue";
 import OnlineExamOverview from "./features/OnlineExam/OnlineExamOverview.vue";
+import ExamingHome from "./features/OnlineExam/Examing/ExamingHome.vue";
 import OfflineExamHome from "./features/OfflineExam/OfflineExamHome.vue";
 import OnlinePracticeHome from "./features/OnlinePractice/OnlinePracticeHome.vue";
 import Login from "./features/Login/Login.vue";
@@ -33,6 +34,11 @@ let router = new Router({
       name: "OnlineExamOverview",
       component: OnlineExamOverview
     },
+    {
+      path: "/online-exam/exam/:examId/",
+      name: "OnlineExamingHome",
+      component: ExamingHome
+    },
     {
       path: "/online-practice",
       name: "OnlinePracticeHome",

+ 2 - 2
src/styles/global.css

@@ -54,7 +54,7 @@
   color: #ffffff;
   background-color: #13bb8a;
   border-radius: 6px;
-  padding: 0 50px;
+  padding: 0 30px;
   line-height: 36px;
   overflow: hidden;
 }
@@ -70,7 +70,7 @@
   color: #999999;
   background-color: #ffffff;
   border-radius: 6px;
-  padding: 0 50px;
+  padding: 0 30px;
   line-height: 36px;
   overflow: hidden;
 }