Ver código fonte

refactor: EvalCard & CoderCard merge into TestCard

Damon 4 anos atrás
pai
commit
6425ed75bf
3 arquivos alterados com 238 adições e 15 exclusões
  1. 0 7
      src/api/mock.js
  2. 231 0
      src/components/TestCard.vue
  3. 7 8
      src/views/PortalPage/PortalPage.vue

+ 0 - 7
src/api/mock.js

@@ -1,9 +1,3 @@
-import { axios } from "@/requests/axios.config";
-
-function example() {
-  return axios.get("/example");
-}
-
 const getAllEvalExams = function () {
   return {
     data: {
@@ -457,7 +451,6 @@ const getAllCoderExams = function () {
 };
 
 const mockAPIs = {
-  example,
   getAllEvalExams,
   getAllCourses,
   getAllCoderExams,

+ 231 - 0
src/components/TestCard.vue

@@ -0,0 +1,231 @@
+<template>
+  <el-card class="test" shadow="hover" @click="toTestInfo">
+
+    <div :style="{borderBottom: type==='eval' ? '30px solid #f5b86e' : '30px solid #8dc9e2'}"
+         style="float: right; width: 0; height: 0; position: absolute;right: 0;bottom: 0;border-left: 30px solid transparent;">
+      <div v-if="type==='eval'" style="padding: 0 4px 0 4px; position: absolute; right: 0; bottom: -30px; color: white">
+        E
+      </div>
+      <div v-else style="padding: 0 3px 0 3px; position: absolute; right: 0; bottom: -30px; color: white">
+        C
+      </div>
+    </div>
+
+    <el-row>
+      <el-col :span="16">
+        <el-col v-if="type==='eval'" class="title">
+          {{ testVO.examName }}
+        </el-col>
+        <el-col v-else class="title">
+          {{ testVO.name }}
+        </el-col>
+      </el-col>
+      <el-col :span="8" class="status">
+        <el-tag v-if="state==='NOT_STARTED'" size="small" type="info">未开始</el-tag>
+        <el-tag v-else-if="state==='RUNNING'" size="small">进行中</el-tag>
+        <el-tag v-else-if="state==='FINISHED'" size="small" type="danger">已结束</el-tag>
+        <el-tag v-else-if="state==='CLOSED'" size="small" type="info">已关闭</el-tag>
+      </el-col>
+    </el-row>
+
+    <el-row>
+      <el-col v-if="type==='eval'" class="course">
+        所属课程: eval course
+      </el-col>
+      <el-col v-else class="course">
+        所属课程: {{ testVO.course }}
+      </el-col>
+    </el-row>
+
+    <el-row>
+      <el-col v-if="type==='eval'" class="teacher">
+        教师: {{ teacher.name }}
+      </el-col>
+      <el-col v-else class="teacher">
+        教师: {{ testVO.creator.username }}
+      </el-col>
+    </el-row>
+
+    <el-row>
+      <el-col v-if="type==='eval'" class="time">
+        时间: {{ testVO.startTime.substring(0, 16) }} 至 {{ testVO.endTime.substring(0, 16) }}
+      </el-col>
+      <el-col v-else class="time">
+        {{ timestampToTime(testVO.startAt) }} 至 {{ timestampToTime(testVO.endAt) }}
+      </el-col>
+    </el-row>
+
+    <el-row v-if="type==='eval'" class="comment">
+      {{ testVO.comment }}
+    </el-row>
+  </el-card>
+</template>
+
+<script>
+import { ElMessageBox } from "element-plus";
+
+export default {
+  name: "TestCard",
+  props: {
+    testVO: Object,
+  },
+  data() {
+    return {
+      teacher: {
+        type: Object,
+        default: {
+          name: "暂无信息",
+        },
+      },
+    };
+  },
+  computed: {
+    type() {
+      if (this.testVO.examId) {
+        return "eval";
+      } else {
+        return "coder";
+      }
+    },
+    state() {
+      if (this.type === "eval") {
+        if (new Date(this.testVO.endTime) < new Date()) {
+          return "FINISHED";
+        } else if (new Date(this.testVO.startTime) > new Date()) {
+          return "NOT_STARTED";
+        } else {
+          return "RUNNING";
+        }
+      } else {
+        if (this.testVO.status === "CLOSED") {
+          return "CLOSED";
+        } else if (this.testVO.startAt * 1000 > new Date()) {
+          return "NOT_STARTED";
+        } else if (this.testVO.endAt * 1000 < new Date()) {
+          return "FINISHED";
+        } else {
+          return "RUNNING";
+        }
+      }
+    },
+  },
+  async mounted() {
+    if (this.type === "eval") {
+      const res = await this.$apis.getUserAPI(this.testVO.creatorId);
+      this.teacher = res.data.data;
+    } else {
+      const res = await this.$apis.getUserAPI(this.testVO.creator.id);
+      if (res.data.code === 0) {
+        this.teacher = res.data.data;
+      } else {
+        this.teacher = { name: this.testVO.creator.username };
+      }
+    }
+  },
+  methods: {
+    timestampToTime(timestamp) {
+      const date = new Date(timestamp * 1000);
+      const Y = date.getFullYear() + "-";
+      const M = (date.getMonth() + 1 < 10 ? "0" + (date.getMonth() + 1) : date.getMonth() + 1) + "-";
+      const D = (date.getDate() < 10 ? "0" + date.getDate() : date.getDate()) + " ";
+      const h = (date.getHours() < 10 ? "0" + date.getHours() : date.getHours()) + ":";
+      const m = (date.getMinutes() < 10 ? "0" + date.getMinutes() : date.getMinutes());
+      return Y + M + D + h + m;
+    },
+    toTestInfo() {
+      let messageBoxContent = "";
+      let messageBoxTitle = "";
+      let confirmButtonText = "";
+      let cancelButtonText = "让我想想";
+      let nextURL = "";
+
+      if (this.type === "eval") {
+        if (this.testVO.isJoined) {
+          messageBoxTitle = "Eval";
+          nextURL = "https://eval.seec.seecoder.cn?id_token=" + this.$store.state.user.token;
+          window.open(this.nextURL);
+          return;
+        } else {
+          // todo: eval系统暂时应该不存在参加了评测但是isJoined字段为false的情况。
+        }
+      } else {
+        messageBoxTitle = "Coder";
+        if (this.testVO.joined) {
+          nextURL = "https://coder.seec.seecoder.cn/exam/" + this.testVO.id + "?id_token=" + this.$store.state.user.token;
+          window.open(nextURL);
+          return;
+        } else {
+          messageBoxContent = "尚未参加该测试,是否立即参加?";
+          confirmButtonText = "立即参加";
+          nextURL = "https://coder.seec.seecoder.cn/exam?id_token=" + this.$store.state.user.token;
+        }
+      }
+
+      ElMessageBox.confirm(messageBoxContent, messageBoxTitle, {
+        distinguishCancelAndClose: true,
+        confirmButtonText,
+        cancelButtonText,
+      }).then(() => {
+        if (nextURL.startsWith("http")) {
+          window.open(nextURL);
+        } else {
+          this.$router.push(nextURL);
+        }
+      });
+    },
+  }
+};
+</script>
+
+<style scoped>
+.test {
+  min-height: 180px;
+  border-radius: 8px;
+  height: calc(100% - 14px);
+  position: relative;
+  border: 1px solid #cccccc;
+}
+
+.test:hover {
+  cursor: pointer;
+  border: 1px solid #aaaaaa;
+}
+
+.title {
+  font-weight: bold;
+  font-size: medium;
+}
+
+.status {
+  text-align: right;
+}
+
+.course {
+  font-size: 10px;
+  margin-top: 4px;
+  color: #999999;
+}
+
+.teacher {
+  font-size: 10px;
+  margin-top: 10px;
+  color: #999999;
+}
+
+.time {
+  margin-top: 4px;
+  font-size: 10px;
+  margin-bottom: 16px;
+  color: #999999;
+}
+
+.comment {
+  background-color: #f6f6f6;
+  color: #777777;
+  margin-top: 10px;
+  border-radius: 8px;
+  padding: 10px;
+  font-size: 10px;
+  margin-bottom: 16px;
+}
+</style>

+ 7 - 8
src/views/PortalPage/PortalPage.vue

@@ -124,12 +124,12 @@
         <el-tabs v-model="activeTestPaneName" @tab-click="changeTestPane">
           <el-tab-pane label="评测题" name="eval">
             <div class="portal-card-content">
-              <EvalCard v-for="item in evalExamList" :key="item.id" :examVO="item"></EvalCard>
+              <TestCard v-for="item in evalExamList" :key="item.id" :testVO="item"/>
             </div>
           </el-tab-pane>
           <el-tab-pane label="代码题" name="coder">
             <div class="portal-card-content">
-              <CoderCard v-for="item in coderExamList" :key="item.id" :coderVO="item"/>
+              <TestCard v-for="item in coderExamList" :key="item.id" :testVO="item"/>
             </div>
           </el-tab-pane>
         </el-tabs>
@@ -142,24 +142,22 @@
 <script>
 import CarouselCard from "@/views/PortalPage/components/CarouselCard";
 import CourseCard from "@/components/CourseCard";
-import EvalCard from "@/components/EvalCard";
-import CoderCard from "@/components/CoderCard";
 import MyCourseCard from "@/views/PortalPage/components/MyCourseCard";
 import MyTestCard from "@/views/PortalPage/components/MyTestCard";
-import {Lock, SetUp, ShoppingCart} from "@element-plus/icons-vue";
+import { Lock, SetUp, ShoppingCart } from "@element-plus/icons-vue";
+import TestCard from "@/components/TestCard";
 
 export default {
   //数据
   name: "PortalPage",
   components: {
+    TestCard,
     SetUp,
     ShoppingCart,
     Lock,
     MyTestCard,
-    CoderCard,
     CourseCard,
     CarouselCard,
-    EvalCard,
     MyCourseCard
   },
   data() {
@@ -212,6 +210,7 @@ export default {
     this.evalExamList = (await this.$apis.getExampleEvalExams()).data.data;
     // todo ERROR: 缺少 token 就无法请求
     // this.coderExamList = (await this.$apis.getAllCoderExams()).data.data;
+    this.coderExamList = this.$apis.getAllCoderExams().data.data.res;
 
     if (this.isLogin && this.isStudent) {
       this.$apis.getStudentCourses(this.$store.state.user.id).then(res => {
@@ -219,7 +218,7 @@ export default {
         this.myCourseLoading = false;
         that.handleResize();
       });
-      this.$apis.getStudentEvalExams({state: 0}).then(res => {
+      this.$apis.getStudentEvalExams({ state: 0 }).then(res => {
         this.myEvalExamList = res.data.data.examVOList;
         this.myTestLoading = false;
         that.handleResize();