Преглед изворни кода

fix:将任务页面移动到了测试页面中,并将测试页改名为任务

DingXiaoYu пре 3 година
родитељ
комит
e482d98b6b
4 измењених фајлова са 620 додато и 19454 уклоњено
  1. 1 19110
      package-lock.json
  2. 4 4
      src/components/GlobalHeader.vue
  3. 281 280
      src/views/TaskPage/TaskPage.vue
  4. 334 60
      src/views/TestPage/TestPage.vue

Разлика између датотеке није приказан због своје велике величине
+ 1 - 19110
package-lock.json


+ 4 - 4
src/components/GlobalHeader.vue

@@ -6,9 +6,9 @@
       <el-menu-item index="1">
         首页
       </el-menu-item>
-      <el-menu-item v-if="isStudent" index="2">
-        任务
-      </el-menu-item>
+<!--      <el-menu-item v-if="isStudent" index="2">-->
+<!--        任务-->
+<!--      </el-menu-item>-->
       <el-menu-item index="3">
         课程
       </el-menu-item>
@@ -16,7 +16,7 @@
         项目
       </el-menu-item>
       <el-menu-item index="5">
-        测试
+        任务
       </el-menu-item>
       <el-menu-item v-if="isTeacher" index="7">
         管理

+ 281 - 280
src/views/TaskPage/TaskPage.vue

@@ -1,290 +1,291 @@
-<template>
-  <div id="task-page-body">
+//此页面转移至TestPage
+<!--<template>-->
+<!--  <div id="task-page-body">-->
 
-    <el-card>
-      <template #header>
-          <span style="font-weight: bold; font-size: larger">
-            即将到期
-          </span>
-      </template>
-      <div id="task-page-expiring-main">
-        <TestCard v-for="item in expiringTaskList_show" :key="item.id" :testVO="item"/>
-      </div>
-      <el-pagination
-        :page-size="4"
-        :total="expiringTaskList.length"
-        @current-change="handleCurrentChange"
-        layout="total, prev, pager, next"
-        style="width: 200px; margin: 10px auto 0 auto"/>
-    </el-card>
+<!--    <el-card>-->
+<!--      <template #header>-->
+<!--          <span style="font-weight: bold; font-size: larger">-->
+<!--            即将到期-->
+<!--          </span>-->
+<!--      </template>-->
+<!--      <div id="task-page-expiring-main">-->
+<!--        <TestCard v-for="item in expiringTaskList_show" :key="item.id" :testVO="item"/>-->
+<!--      </div>-->
+<!--      <el-pagination-->
+<!--        :page-size="4"-->
+<!--        :total="expiringTaskList.length"-->
+<!--        @current-change="handleCurrentChange"-->
+<!--        layout="total, prev, pager, next"-->
+<!--        style="width: 200px; margin: 10px auto 0 auto"/>-->
+<!--    </el-card>-->
 
-    <el-card>
-      <template #header>
-        <div style="display: flex; justify-content: space-between; align-content: center">
-          <span style="font-weight: bold; font-size: larger;padding-top: 6px">
-            我的任务
-          </span>
-          <el-select placeholder="Select" v-model="selector" filterable clearable>
-            <el-option-group
-              v-for="group in options"
-              :key="group.label"
-              :label="group.label"
-            >
-              <el-option
-                v-for="item in group.options"
-                :key="item.value"
-                :label="item.label"
-                :value="item.value"
-              />
-            </el-option-group>
-          </el-select>
-        </div>
-      </template>
-      <div id="task-page-all-task-main">
-        <div class="task-content">
-          <TestCard v-for="item in myTaskList" :key="item.id" :testVO="item"/>
-        </div>
-        <!--        <el-tabs v-model="activeTaskPaneName">-->
-        <!--          <el-tab-pane label="评测" name="eval">-->
-        <!--            <div class="task-content">-->
-        <!--              <TestCard v-for="item in myEvalExamList" :key="item.id" :testVO="item"/>-->
-        <!--            </div>-->
-        <!--          </el-tab-pane>-->
-        <!--          <el-tab-pane label="代码" name="coder">-->
-        <!--            <div class="task-content">-->
-        <!--              <TestCard v-for="item in myCoderExamList" :key="item.id" :testVO="item"/>-->
-        <!--            </div>-->
-        <!--          </el-tab-pane>-->
-        <!--        </el-tabs>-->
-      </div>
-    </el-card>
+<!--    <el-card>-->
+<!--      <template #header>-->
+<!--        <div style="display: flex; justify-content: space-between; align-content: center">-->
+<!--          <span style="font-weight: bold; font-size: larger;padding-top: 6px">-->
+<!--            我的任务-->
+<!--          </span>-->
+<!--          <el-select placeholder="Select" v-model="selector" filterable clearable>-->
+<!--            <el-option-group-->
+<!--              v-for="group in options"-->
+<!--              :key="group.label"-->
+<!--              :label="group.label"-->
+<!--            >-->
+<!--              <el-option-->
+<!--                v-for="item in group.options"-->
+<!--                :key="item.value"-->
+<!--                :label="item.label"-->
+<!--                :value="item.value"-->
+<!--              />-->
+<!--            </el-option-group>-->
+<!--          </el-select>-->
+<!--        </div>-->
+<!--      </template>-->
+<!--      <div id="task-page-all-task-main">-->
+<!--        <div class="task-content">-->
+<!--          <TestCard v-for="item in myTaskList" :key="item.id" :testVO="item"/>-->
+<!--        </div>-->
+<!--        &lt;!&ndash;        <el-tabs v-model="activeTaskPaneName">&ndash;&gt;-->
+<!--        &lt;!&ndash;          <el-tab-pane label="评测" name="eval">&ndash;&gt;-->
+<!--        &lt;!&ndash;            <div class="task-content">&ndash;&gt;-->
+<!--        &lt;!&ndash;              <TestCard v-for="item in myEvalExamList" :key="item.id" :testVO="item"/>&ndash;&gt;-->
+<!--        &lt;!&ndash;            </div>&ndash;&gt;-->
+<!--        &lt;!&ndash;          </el-tab-pane>&ndash;&gt;-->
+<!--        &lt;!&ndash;          <el-tab-pane label="代码" name="coder">&ndash;&gt;-->
+<!--        &lt;!&ndash;            <div class="task-content">&ndash;&gt;-->
+<!--        &lt;!&ndash;              <TestCard v-for="item in myCoderExamList" :key="item.id" :testVO="item"/>&ndash;&gt;-->
+<!--        &lt;!&ndash;            </div>&ndash;&gt;-->
+<!--        &lt;!&ndash;          </el-tab-pane>&ndash;&gt;-->
+<!--        &lt;!&ndash;        </el-tabs>&ndash;&gt;-->
+<!--      </div>-->
+<!--    </el-card>-->
 
-  </div>
-</template>
+<!--  </div>-->
+<!--</template>-->
 
-<script>
-import TestCard from "@/components/TestCard";
+<!--<script>-->
+<!--import TestCard from "@/components/TestCard";-->
 
-const options = [
-  {
-    label: "全部测试",
-    options: [
-      {
-        value: "ALL",
-        label: "全部测试题",
-      },
-      {
-        value: "ALL_NOT_STARTED",
-        label: "全部未开始",
-      },
-      {
-        value: "ALL_RUNNING_IN",
-        label: "全部已参加",
-      },
-      {
-        value: "ALL_RUNNING_NOT",
-        label: "全部未参加",
-      },
-      {
-        value: "ALL_FINISHED",
-        label: "全部已结束",
-      },
-    ]
-  },
-  {
-    label: "评测题",
-    options: [
-      {
-        value: "EVAL_ALL",
-        label: "全部评测题",
-      },
-      {
-        value: "EVAL_NOT_STARTED",
-        label: "未开始评测题",
-      },
-      {
-        value: "EVAL_RUNNING_IN",
-        label: "已参加评测题",
-      },
-      {
-        value: "EVAL_RUNNING_NOT",
-        label: "未参加评测题",
-      },
-      {
-        value: "EVAL_FINISHED",
-        label: "已结束评测题",
-      },
-    ],
-  },
-  {
-    label: "代码题",
-    options: [
-      {
-        value: "CODER_ALL",
-        label: "全部代码题",
-      },
-      {
-        value: "CODER_NOT_STARTED",
-        label: "未开始代码题",
-      },
-      {
-        value: "CODER_RUNNING_IN",
-        label: "已参加代码题",
-      },
-      {
-        value: "CODER_RUNNING_NOT",
-        label: "未参加代码题",
-      },
-      {
-        value: "CODER_FINISHED",
-        label: "已结束代码题",
-      },
-    ],
-  },
-];
-export default {
-  name: "TaskPage",
-  components: {TestCard},
-  data() {
-    return {
-      myEvalExamList: [],
-      myCoderExamList: [],
-      expiringTask_currentPage: 1,
-      activeTaskPaneName: "eval",
-      options: options,
-      selector: "ALL",
-    };
-  },
-  computed: {
-    expiringTaskList_show() {
-      return this.expiringTaskList.slice((this.expiringTask_currentPage - 1) * 4, this.expiringTask_currentPage * 4);
-    },
-    expiringTaskList() {
-      return []
-        .concat(this.myEvalExamList)
-        .concat(this.myCoderExamList)
-        .sort((a, b) => {
-          let a_time = a["endAt"] * 1000 || new Date(a.endTime).getTime();
-          let b_time = b["endAt"] * 1000 || new Date(b.endTime).getTime();
-          return a_time - b_time;
-        })
-        .filter(i => (this.state(i) === "RUNNING_IN" || this.state(i) === "RUNNING_NOT"));
-    },
-    myTaskList() {
-      let out = []
-        .concat(this.myEvalExamList)
-        .concat(this.myCoderExamList)
-        .sort((a, b) => {
-          return this.state(b).charCodeAt(0) - this.state(a).charCodeAt(0);
-        });
-      switch (this.selector) {
-        case "ALL":
-          break;
-        case "ALL_NOT_STARTED":
-          out = out.filter(i => this.state(i) === "NOT_STARTED");
-          break;
-        case "ALL_RUNNING_IN":
-          out = out.filter(i => this.state(i) === "RUNNING_IN");
-          break;
-        case "ALL_RUNNING_NOT":
-          out = out.filter(i => this.state(i) === "RUNNING_NOT");
-          break;
-        case "ALL_FINISHED":
-          out = out.filter(i => this.state(i) === "FINISHED" || this.state(i) === "CLOSED");
-          break;
-        case "EVAL_ALL":
-          out = out.filter(i => i.examId !== undefined);
-          break;
-        case "EVAL_NOT_STARTED":
-          out = out.filter(i => (i.examId !== undefined && this.state(i) === "NOT_STARTED"));
-          break;
-        case "EVAL_RUNNING_IN":
-          out = out.filter(i => (i.examId !== undefined && this.state(i) === "RUNNING_IN"));
-          break;
-        case "EVAL_RUNNING_NOT":
-          out = out.filter(i => (i.examId !== undefined && this.state(i) === "RUNNING_NOT"));
-          break;
-        case "EVAL_FINISHED":
-          out = out.filter(i => (i.examId !== undefined && this.state(i) === "FINISHED"));
-          break;
-        case "CODER_ALL":
-          out = out.filter(i => i.examId === undefined);
-          break;
-        case "CODER_NOT_STARTED":
-          out = out.filter(i => (i.examId === undefined && this.state(i) === "NOT_STARTED"));
-          break;
-        case "CODER_RUNNING_IN":
-          out = out.filter(i => (i.examId === undefined && this.state(i) === "RUNNING_IN"));
-          break;
-        case "CODER_RUNNING_NOT":
-          out = out.filter(i => (i.examId === undefined && this.state(i) === "RUNNING_NOT"));
-          break;
-        case "CODER_FINISHED":
-          out = out.filter(i => (i.examId === undefined && (this.state(i) === "FINISHED" || this.state(i) === "CLOSED")));
-          break;
-      }
-      return out;
-    },
-  },
+<!--const options = [-->
+<!--  {-->
+<!--    label: "全部测试",-->
+<!--    options: [-->
+<!--      {-->
+<!--        value: "ALL",-->
+<!--        label: "全部测试题",-->
+<!--      },-->
+<!--      {-->
+<!--        value: "ALL_NOT_STARTED",-->
+<!--        label: "全部未开始",-->
+<!--      },-->
+<!--      {-->
+<!--        value: "ALL_RUNNING_IN",-->
+<!--        label: "全部已参加",-->
+<!--      },-->
+<!--      {-->
+<!--        value: "ALL_RUNNING_NOT",-->
+<!--        label: "全部未参加",-->
+<!--      },-->
+<!--      {-->
+<!--        value: "ALL_FINISHED",-->
+<!--        label: "全部已结束",-->
+<!--      },-->
+<!--    ]-->
+<!--  },-->
+<!--  {-->
+<!--    label: "评测题",-->
+<!--    options: [-->
+<!--      {-->
+<!--        value: "EVAL_ALL",-->
+<!--        label: "全部评测题",-->
+<!--      },-->
+<!--      {-->
+<!--        value: "EVAL_NOT_STARTED",-->
+<!--        label: "未开始评测题",-->
+<!--      },-->
+<!--      {-->
+<!--        value: "EVAL_RUNNING_IN",-->
+<!--        label: "已参加评测题",-->
+<!--      },-->
+<!--      {-->
+<!--        value: "EVAL_RUNNING_NOT",-->
+<!--        label: "未参加评测题",-->
+<!--      },-->
+<!--      {-->
+<!--        value: "EVAL_FINISHED",-->
+<!--        label: "已结束评测题",-->
+<!--      },-->
+<!--    ],-->
+<!--  },-->
+<!--  {-->
+<!--    label: "代码题",-->
+<!--    options: [-->
+<!--      {-->
+<!--        value: "CODER_ALL",-->
+<!--        label: "全部代码题",-->
+<!--      },-->
+<!--      {-->
+<!--        value: "CODER_NOT_STARTED",-->
+<!--        label: "未开始代码题",-->
+<!--      },-->
+<!--      {-->
+<!--        value: "CODER_RUNNING_IN",-->
+<!--        label: "已参加代码题",-->
+<!--      },-->
+<!--      {-->
+<!--        value: "CODER_RUNNING_NOT",-->
+<!--        label: "未参加代码题",-->
+<!--      },-->
+<!--      {-->
+<!--        value: "CODER_FINISHED",-->
+<!--        label: "已结束代码题",-->
+<!--      },-->
+<!--    ],-->
+<!--  },-->
+<!--];-->
+<!--export default {-->
+<!--  name: "TaskPage",-->
+<!--  components: {TestCard},-->
+<!--  data() {-->
+<!--    return {-->
+<!--      myEvalExamList: [],-->
+<!--      myCoderExamList: [],-->
+<!--      expiringTask_currentPage: 1,-->
+<!--      activeTaskPaneName: "eval",-->
+<!--      options: options,-->
+<!--      selector: "ALL",-->
+<!--    };-->
+<!--  },-->
+<!--  computed: {-->
+<!--    expiringTaskList_show() {-->
+<!--      return this.expiringTaskList.slice((this.expiringTask_currentPage - 1) * 4, this.expiringTask_currentPage * 4);-->
+<!--    },-->
+<!--    expiringTaskList() {-->
+<!--      return []-->
+<!--        .concat(this.myEvalExamList)-->
+<!--        .concat(this.myCoderExamList)-->
+<!--        .sort((a, b) => {-->
+<!--          let a_time = a["endAt"] * 1000 || new Date(a.endTime).getTime();-->
+<!--          let b_time = b["endAt"] * 1000 || new Date(b.endTime).getTime();-->
+<!--          return a_time - b_time;-->
+<!--        })-->
+<!--        .filter(i => (this.state(i) === "RUNNING_IN" || this.state(i) === "RUNNING_NOT"));-->
+<!--    },-->
+<!--    myTaskList() {-->
+<!--      let out = []-->
+<!--        .concat(this.myEvalExamList)-->
+<!--        .concat(this.myCoderExamList)-->
+<!--        .sort((a, b) => {-->
+<!--          return this.state(b).charCodeAt(0) - this.state(a).charCodeAt(0);-->
+<!--        });-->
+<!--      switch (this.selector) {-->
+<!--        case "ALL":-->
+<!--          break;-->
+<!--        case "ALL_NOT_STARTED":-->
+<!--          out = out.filter(i => this.state(i) === "NOT_STARTED");-->
+<!--          break;-->
+<!--        case "ALL_RUNNING_IN":-->
+<!--          out = out.filter(i => this.state(i) === "RUNNING_IN");-->
+<!--          break;-->
+<!--        case "ALL_RUNNING_NOT":-->
+<!--          out = out.filter(i => this.state(i) === "RUNNING_NOT");-->
+<!--          break;-->
+<!--        case "ALL_FINISHED":-->
+<!--          out = out.filter(i => this.state(i) === "FINISHED" || this.state(i) === "CLOSED");-->
+<!--          break;-->
+<!--        case "EVAL_ALL":-->
+<!--          out = out.filter(i => i.examId !== undefined);-->
+<!--          break;-->
+<!--        case "EVAL_NOT_STARTED":-->
+<!--          out = out.filter(i => (i.examId !== undefined && this.state(i) === "NOT_STARTED"));-->
+<!--          break;-->
+<!--        case "EVAL_RUNNING_IN":-->
+<!--          out = out.filter(i => (i.examId !== undefined && this.state(i) === "RUNNING_IN"));-->
+<!--          break;-->
+<!--        case "EVAL_RUNNING_NOT":-->
+<!--          out = out.filter(i => (i.examId !== undefined && this.state(i) === "RUNNING_NOT"));-->
+<!--          break;-->
+<!--        case "EVAL_FINISHED":-->
+<!--          out = out.filter(i => (i.examId !== undefined && this.state(i) === "FINISHED"));-->
+<!--          break;-->
+<!--        case "CODER_ALL":-->
+<!--          out = out.filter(i => i.examId === undefined);-->
+<!--          break;-->
+<!--        case "CODER_NOT_STARTED":-->
+<!--          out = out.filter(i => (i.examId === undefined && this.state(i) === "NOT_STARTED"));-->
+<!--          break;-->
+<!--        case "CODER_RUNNING_IN":-->
+<!--          out = out.filter(i => (i.examId === undefined && this.state(i) === "RUNNING_IN"));-->
+<!--          break;-->
+<!--        case "CODER_RUNNING_NOT":-->
+<!--          out = out.filter(i => (i.examId === undefined && this.state(i) === "RUNNING_NOT"));-->
+<!--          break;-->
+<!--        case "CODER_FINISHED":-->
+<!--          out = out.filter(i => (i.examId === undefined && (this.state(i) === "FINISHED" || this.state(i) === "CLOSED")));-->
+<!--          break;-->
+<!--      }-->
+<!--      return out;-->
+<!--    },-->
+<!--  },-->
 
-  async created() {
-    this.myEvalExamList = (await this.$apis.getStudentEvalExams()).data.data;
-    this.myCoderExamList = (await this.$apis.getStudentCoderExams({})).data.data["res"];
-  },
+<!--  async created() {-->
+<!--    this.myEvalExamList = (await this.$apis.getStudentEvalExams()).data.data;-->
+<!--    this.myCoderExamList = (await this.$apis.getStudentCoderExams({})).data.data["res"];-->
+<!--  },-->
 
-  methods: {
-    handleCurrentChange(index) {
-      this.expiringTask_currentPage = index;
-    },
-    state(testVO) {
-      const now = new Date();
-      if (testVO.examId !== undefined) {
-        if (new Date(testVO.endTime) < now) {
-          return "FINISHED";
-        } else if (new Date(testVO.startTime) > now) {
-          return "NOT_STARTED";
-        } else if (testVO.isJoined) {
-          return "RUNNING_IN";
-        } else {
-          return "RUNNING_NOT";
-        }
-      } else {
-        if (testVO.status === "CLOSED") {
-          return "CLOSED";
-        } else if (testVO.startAt * 1000 > now) {
-          return "NOT_STARTED";
-        } else if (testVO.endAt * 1000 < now) {
-          return "FINISHED";
-        } else if (testVO.joined) {
-          return "RUNNING_IN";
-        } else {
-          return "RUNNING_NOT";
-        }
-      }
-    },
-  },
-};
-</script>
+<!--  methods: {-->
+<!--    handleCurrentChange(index) {-->
+<!--      this.expiringTask_currentPage = index;-->
+<!--    },-->
+<!--    state(testVO) {-->
+<!--      const now = new Date();-->
+<!--      if (testVO.examId !== undefined) {-->
+<!--        if (new Date(testVO.endTime) < now) {-->
+<!--          return "FINISHED";-->
+<!--        } else if (new Date(testVO.startTime) > now) {-->
+<!--          return "NOT_STARTED";-->
+<!--        } else if (testVO.isJoined) {-->
+<!--          return "RUNNING_IN";-->
+<!--        } else {-->
+<!--          return "RUNNING_NOT";-->
+<!--        }-->
+<!--      } else {-->
+<!--        if (testVO.status === "CLOSED") {-->
+<!--          return "CLOSED";-->
+<!--        } else if (testVO.startAt * 1000 > now) {-->
+<!--          return "NOT_STARTED";-->
+<!--        } else if (testVO.endAt * 1000 < now) {-->
+<!--          return "FINISHED";-->
+<!--        } else if (testVO.joined) {-->
+<!--          return "RUNNING_IN";-->
+<!--        } else {-->
+<!--          return "RUNNING_NOT";-->
+<!--        }-->
+<!--      }-->
+<!--    },-->
+<!--  },-->
+<!--};-->
+<!--</script>-->
 
-<style scoped>
-#task-page-body {
-  display: grid;
-  grid-template-columns: 1fr;
-  grid-template-rows: auto auto;
-  grid-gap: 20px;
-  margin: 40px 15vw 80px 15vw;
-}
+<!--<style scoped>-->
+<!--#task-page-body {-->
+<!--  display: grid;-->
+<!--  grid-template-columns: 1fr;-->
+<!--  grid-template-rows: auto auto;-->
+<!--  grid-gap: 20px;-->
+<!--  margin: 40px 15vw 80px 15vw;-->
+<!--}-->
 
-#task-page-expiring-main {
-  display: grid;
-  grid-template-rows: 1fr;
-  grid-template-columns: 1fr 1fr 1fr 1fr;
-  grid-gap: 10px;
-}
+<!--#task-page-expiring-main {-->
+<!--  display: grid;-->
+<!--  grid-template-rows: 1fr;-->
+<!--  grid-template-columns: 1fr 1fr 1fr 1fr;-->
+<!--  grid-gap: 10px;-->
+<!--}-->
 
-.task-content {
-  display: grid;
-  grid-template-columns: 1fr 1fr 1fr 1fr;
-  grid-gap: 10px;
-}
-</style>
+<!--.task-content {-->
+<!--  display: grid;-->
+<!--  grid-template-columns: 1fr 1fr 1fr 1fr;-->
+<!--  grid-gap: 10px;-->
+<!--}-->
+<!--</style>-->

+ 334 - 60
src/views/TestPage/TestPage.vue

@@ -21,84 +21,153 @@
             </el-icon>
             <span style="padding-left: 20px">我的测试</span>
           </el-menu-item>
+          <el-menu-item index="3">
+            <el-icon>
+              <DocumentChecked/>
+            </el-icon>
+            <span style="padding-left: 20px">我的任务</span>
+          </el-menu-item>
         </el-menu>
       </el-card>
     </el-col>
     <el-col :span="2"/>
     <el-col :span="18">
-      <el-card>
-        <template #header>
-          <span style="font-weight: bold; font-size: larger">
-            {{ activeName }}
-          </span>
-        </template>
-        <div v-if="this.activeIndex === '1'">
-          <el-tabs v-model="activeTestPaneName" style="width: 100%">
-            <el-tab-pane label="eval测试" name="eval">
-              <div v-for="(item, key) in evalExamList" :key="key">
-                <div v-if="item.length !== 0">
+      <div v-if="this.activeIndex !== '3'">
+        <el-card>
+          <template #header>
+            <span style="font-weight: bold; font-size: larger">
+             {{ activeName }}
+            </span>
+          </template>
+          <div v-if="this.activeIndex === '1'">
+            <el-tabs v-model="activeTestPaneName" style="width: 100%">
+              <el-tab-pane label="eval测试" name="eval">
+                <div v-for="(item, key) in evalExamList" :key="key">
+                  <div v-if="item.length !== 0">
+                    <div>
+                      <el-divider style="margin: 10px 0 20px 0" content-position="left">{{ key }}</el-divider>
+                    </div>
+                    <div class="test-page-main">
+                      <TestCard v-for="exam in item" :key="exam.id" :testVO="exam" :isPublicTest="true"/>
+                    </div>
+                  </div>
+                </div>
+              </el-tab-pane>
+              <el-tab-pane label="coder测试" name="coder">
+                <div v-for="(item, key) in coderExamList" :key="key">
+                  <div v-if="item.length !== 0">
+                    <div>
+                      <el-divider style="margin: 10px 0 20px 0;" content-position="left">{{ key }}</el-divider>
+                    </div>
+                    <div class="test-page-main">
+                      <TestCard v-for="exam in item" :key="exam.id" :testVO="exam"/>
+                    </div>
+                  </div>
+                </div>
+              </el-tab-pane>
+            </el-tabs>
+          </div>
+
+          <div v-if="this.activeIndex === '2' && isStudent">
+            <el-tabs v-model="activeTestPaneName_my" style="width: 100%">
+              <el-tab-pane label="eval测试" name="eval">
+                <div v-for="(item, key) in evalExamList_my" :key="key">
                   <div>
                     <el-divider style="margin: 10px 0 20px 0" content-position="left">{{ key }}</el-divider>
                   </div>
                   <div class="test-page-main">
-                    <TestCard v-for="exam in item" :key="exam.id" :testVO="exam" :isPublicTest="true"/>
+                    <TestCard v-for="exam in item" :key="exam.id" :testVO="exam"/>
                   </div>
                 </div>
-              </div>
-            </el-tab-pane>
-            <el-tab-pane label="coder测试" name="coder">
-              <div v-for="(item, key) in coderExamList" :key="key">
-                <div v-if="item.length !== 0">
+              </el-tab-pane>
+              <el-tab-pane label="coder测试" name="coder">
+                <div v-for="(item, key) in coderExamList_my" :key="key">
                   <div>
-                    <el-divider style="margin: 10px 0 20px 0;" content-position="left">{{ key }}</el-divider>
+                    <el-divider style="margin: 10px 0 20px 0" content-position="left">{{ key }}</el-divider>
                   </div>
                   <div class="test-page-main">
                     <TestCard v-for="exam in item" :key="exam.id" :testVO="exam"/>
                   </div>
                 </div>
-              </div>
-            </el-tab-pane>
-          </el-tabs>
-        </div>
+              </el-tab-pane>
+            </el-tabs>
+          </div>
 
-        <div v-if="this.activeIndex === '2' && isStudent">
-          <el-tabs v-model="activeTestPaneName_my" style="width: 100%">
-            <el-tab-pane label="eval测试" name="eval">
-              <div v-for="(item, key) in evalExamList_my" :key="key">
-                <div>
-                  <el-divider style="margin: 10px 0 20px 0" content-position="left">{{ key }}</el-divider>
-                </div>
-                <div class="test-page-main">
-                  <TestCard v-for="exam in item" :key="exam.id" :testVO="exam"/>
-                </div>
-              </div>
-            </el-tab-pane>
-            <el-tab-pane label="coder测试" name="coder">
-              <div v-for="(item, key) in coderExamList_my" :key="key">
-                <div>
-                  <el-divider style="margin: 10px 0 20px 0" content-position="left">{{ key }}</el-divider>
-                </div>
-                <div class="test-page-main">
-                  <TestCard v-for="exam in item" :key="exam.id" :testVO="exam"/>
-                </div>
-              </div>
-            </el-tab-pane>
-          </el-tabs>
-        </div>
-
-        <div v-if="this.activeIndex === '2' && isTeacher">
-          教师请前往
-          <span style="cursor: pointer;color: #409eff"
+          <div v-if="this.activeIndex === '2' && isTeacher">
+            教师请前往
+            <span style="cursor: pointer;color: #409eff"
                 @click="$router.push('/manage')">管理页面</span>
-          查看相关测试。
-        </div>
+            查看相关测试。
+          </div>
 
-        <div v-if="this.activeIndex === '2' && !isLogin">
-          请先
-          <span style="cursor: pointer;color: #409eff"
+          <div v-if="this.activeIndex === '2' && !isLogin">
+            请先
+            <span style="cursor: pointer;color: #409eff"
                 @click="$router.push('/login')">登录</span>
-        </div>
-      </el-card>
+          </div>
+        </el-card>
+      </div>
+
+      <div v-if="this.activeIndex === '3'">
+        <el-card>
+          <template #header>
+            <span style="font-weight: bold; font-size: larger">
+              即将到期
+            </span>
+          </template>
+          <div id="task-page-expiring-main">
+            <TestCard v-for="item in expiringTaskList_show" :key="item.id" :testVO="item"/>
+          </div>
+          <el-pagination
+              :page-size="4"
+              :total="expiringTaskList.length"
+              @current-change="handleCurrentChange"
+              layout="total, prev, pager, next"
+              style="width: 200px; margin: 10px auto 0 auto"/>
+        </el-card>
+
+        <el-card>
+          <template #header>
+            <div style="display: flex; justify-content: space-between; align-content: center">
+              <span style="font-weight: bold; font-size: larger;padding-top: 6px">
+                我的任务
+              </span>
+              <el-select placeholder="Select" v-model="selector" filterable clearable>
+                <el-option-group
+                    v-for="group in options"
+                    :key="group.label"
+                    :label="group.label"
+                >
+                  <el-option
+                      v-for="item in group.options"
+                      :key="item.value"
+                      :label="item.label"
+                      :value="item.value"
+                  />
+                </el-option-group>
+              </el-select>
+            </div>
+          </template>
+
+          <div id="task-page-all-task-main">
+            <div class="task-content">
+              <TestCard v-for="item in myTaskList" :key="item.id" :testVO="item"/>
+            </div>
+              <!--        <el-tabs v-model="activeTaskPaneName">-->
+              <!--          <el-tab-pane label="评测" name="eval">-->
+              <!--            <div class="task-content">-->
+              <!--              <TestCard v-for="item in myEvalExamList" :key="item.id" :testVO="item"/>-->
+              <!--            </div>-->
+              <!--          </el-tab-pane>-->
+              <!--          <el-tab-pane label="代码" name="coder">-->
+              <!--            <div class="task-content">-->
+              <!--              <TestCard v-for="item in myCoderExamList" :key="item.id" :testVO="item"/>-->
+              <!--            </div>-->
+              <!--          </el-tab-pane>-->
+              <!--        </el-tabs>-->
+          </div>
+        </el-card>
+      </div>
     </el-col>
   </el-row>
 </template>
@@ -106,7 +175,83 @@
 <script>
 import {Back, Document, DocumentChecked} from "@element-plus/icons-vue";
 import TestCard from "@/components/TestCard";
-
+const options = [
+  {
+    label: "全部测试",
+    options: [
+      {
+        value: "ALL",
+        label: "全部测试题",
+      },
+      {
+        value: "ALL_NOT_STARTED",
+        label: "全部未开始",
+      },
+      {
+        value: "ALL_RUNNING_IN",
+        label: "全部已参加",
+      },
+      {
+        value: "ALL_RUNNING_NOT",
+        label: "全部未参加",
+      },
+      {
+        value: "ALL_FINISHED",
+        label: "全部已结束",
+      },
+    ]
+  },
+  {
+    label: "评测题",
+    options: [
+      {
+        value: "EVAL_ALL",
+        label: "全部评测题",
+      },
+      {
+        value: "EVAL_NOT_STARTED",
+        label: "未开始评测题",
+      },
+      {
+        value: "EVAL_RUNNING_IN",
+        label: "已参加评测题",
+      },
+      {
+        value: "EVAL_RUNNING_NOT",
+        label: "未参加评测题",
+      },
+      {
+        value: "EVAL_FINISHED",
+        label: "已结束评测题",
+      },
+    ],
+  },
+  {
+    label: "代码题",
+    options: [
+      {
+        value: "CODER_ALL",
+        label: "全部代码题",
+      },
+      {
+        value: "CODER_NOT_STARTED",
+        label: "未开始代码题",
+      },
+      {
+        value: "CODER_RUNNING_IN",
+        label: "已参加代码题",
+      },
+      {
+        value: "CODER_RUNNING_NOT",
+        label: "未参加代码题",
+      },
+      {
+        value: "CODER_FINISHED",
+        label: "已结束代码题",
+      },
+    ],
+  },
+];
 export default {
   name: "TestPage",
   components: {TestCard, Back, Document, DocumentChecked,},
@@ -119,14 +264,22 @@ export default {
       coderExamList_my: [],
       activeTestPaneName: "eval",
       activeTestPaneName_my: "eval",
+      myEvalExamList: [],
+      myCoderExamList: [],
+      expiringTask_currentPage: 1,
+      activeTaskPaneName: "eval",
+      options: options,
+      selector: "ALL",
     };
   },
   computed: {
     activeName() {
       if (this.activeIndex === "1") {
         return "公开测试";
-      } else {
+      } else if (this.activeIndex === "2"){
         return "我的测试";
+      }else{
+        return "我的任务";
       }
     },
     isTeacher() {
@@ -138,8 +291,77 @@ export default {
     isLogin() {
       return this.$store.getters.isLogin;
     },
+    expiringTaskList_show() {
+      return this.expiringTaskList.slice((this.expiringTask_currentPage - 1) * 4, this.expiringTask_currentPage * 4);
+    },
+    expiringTaskList() {
+      return []
+          .concat(this.myEvalExamList)
+          .concat(this.myCoderExamList)
+          .sort((a, b) => {
+            let a_time = a["endAt"] * 1000 || new Date(a.endTime).getTime();
+            let b_time = b["endAt"] * 1000 || new Date(b.endTime).getTime();
+            return a_time - b_time;
+          })
+          .filter(i => (this.state(i) === "RUNNING_IN" || this.state(i) === "RUNNING_NOT"));
+    },
+    myTaskList() {
+      let out = []
+          .concat(this.myEvalExamList)
+          .concat(this.myCoderExamList)
+          .sort((a, b) => {
+            return this.state(b).charCodeAt(0) - this.state(a).charCodeAt(0);
+          });
+      switch (this.selector) {
+        case "ALL":
+          break;
+        case "ALL_NOT_STARTED":
+          out = out.filter(i => this.state(i) === "NOT_STARTED");
+          break;
+        case "ALL_RUNNING_IN":
+          out = out.filter(i => this.state(i) === "RUNNING_IN");
+          break;
+        case "ALL_RUNNING_NOT":
+          out = out.filter(i => this.state(i) === "RUNNING_NOT");
+          break;
+        case "ALL_FINISHED":
+          out = out.filter(i => this.state(i) === "FINISHED" || this.state(i) === "CLOSED");
+          break;
+        case "EVAL_ALL":
+          out = out.filter(i => i.examId !== undefined);
+          break;
+        case "EVAL_NOT_STARTED":
+          out = out.filter(i => (i.examId !== undefined && this.state(i) === "NOT_STARTED"));
+          break;
+        case "EVAL_RUNNING_IN":
+          out = out.filter(i => (i.examId !== undefined && this.state(i) === "RUNNING_IN"));
+          break;
+        case "EVAL_RUNNING_NOT":
+          out = out.filter(i => (i.examId !== undefined && this.state(i) === "RUNNING_NOT"));
+          break;
+        case "EVAL_FINISHED":
+          out = out.filter(i => (i.examId !== undefined && this.state(i) === "FINISHED"));
+          break;
+        case "CODER_ALL":
+          out = out.filter(i => i.examId === undefined);
+          break;
+        case "CODER_NOT_STARTED":
+          out = out.filter(i => (i.examId === undefined && this.state(i) === "NOT_STARTED"));
+          break;
+        case "CODER_RUNNING_IN":
+          out = out.filter(i => (i.examId === undefined && this.state(i) === "RUNNING_IN"));
+          break;
+        case "CODER_RUNNING_NOT":
+          out = out.filter(i => (i.examId === undefined && this.state(i) === "RUNNING_NOT"));
+          break;
+        case "CODER_FINISHED":
+          out = out.filter(i => (i.examId === undefined && (this.state(i) === "FINISHED" || this.state(i) === "CLOSED")));
+          break;
+      }
+      return out;
+    },
   },
-  mounted() {
+  async mounted() {
     this.$apis.getRecommendEvalExamsGroupByCourse().then(res => {
       this.evalExamList = res.data.data;
     });
@@ -156,6 +378,8 @@ export default {
           this.coderExamList_my = res.data.data;
         });
     }
+    this.myEvalExamList = (await this.$apis.getStudentEvalExams()).data.data;
+    this.myCoderExamList = (await this.$apis.getStudentCoderExams({})).data.data["res"];
   },
   methods: {
     handleSelect(index) {
@@ -164,6 +388,35 @@ export default {
       }
       this.activeIndex = index;
     },
+    handleCurrentChange(index) {
+      this.expiringTask_currentPage = index;
+    },
+    state(testVO) {
+      const now = new Date();
+      if (testVO.examId !== undefined) {
+        if (new Date(testVO.endTime) < now) {
+          return "FINISHED";
+        } else if (new Date(testVO.startTime) > now) {
+          return "NOT_STARTED";
+        } else if (testVO.isJoined) {
+          return "RUNNING_IN";
+        } else {
+          return "RUNNING_NOT";
+        }
+      } else {
+        if (testVO.status === "CLOSED") {
+          return "CLOSED";
+        } else if (testVO.startAt * 1000 > now) {
+          return "NOT_STARTED";
+        } else if (testVO.endAt * 1000 < now) {
+          return "FINISHED";
+        } else if (testVO.joined) {
+          return "RUNNING_IN";
+        } else {
+          return "RUNNING_NOT";
+        }
+      }
+    },
   },
 };
 </script>
@@ -184,4 +437,25 @@ export default {
 :deep(.el-divider) {
   margin: 0;
 }
+
+#task-page-body {
+  display: grid;
+  grid-template-columns: 1fr;
+  grid-template-rows: auto auto;
+  grid-gap: 20px;
+  margin: 40px 15vw 80px 15vw;
+}
+
+#task-page-expiring-main {
+  display: grid;
+  grid-template-rows: 1fr;
+  grid-template-columns: 1fr 1fr 1fr 1fr;
+  grid-gap: 10px;
+}
+
+.task-content {
+  display: grid;
+  grid-template-columns: 1fr 1fr 1fr 1fr;
+  grid-gap: 10px;
+}
 </style>

Неке датотеке нису приказане због велике количине промена