Kaynağa Gözat

删除部分无用依赖;
完成审查 GlobalHeader,AuthPage,PortalPage,MyCourseCard,CourseCard,MyTestCard,TestCard;
feat: TaskPage add selector;

Damon 4 yıl önce
ebeveyn
işleme
de7fd7e8cb

+ 1 - 2
package.json

@@ -26,12 +26,11 @@
     "@vue/compiler-sfc": "^3.0.0",
     "@vue/compiler-sfc": "^3.0.0",
     "babel-eslint": "^10.1.0",
     "babel-eslint": "^10.1.0",
     "eslint": "^6.7.2",
     "eslint": "^6.7.2",
+    "webpack": "^4.x",
     "eslint-plugin-vue": "^7.0.0",
     "eslint-plugin-vue": "^7.0.0",
     "sass": "^1.49.0",
     "sass": "^1.49.0",
     "sass-loader": "^7.3.0",
     "sass-loader": "^7.3.0",
-    "speed-measure-webpack-plugin": "^1.5.0",
     "terser-webpack-plugin": "^4.2.3",
     "terser-webpack-plugin": "^4.2.3",
-    "webpack-bundle-analyzer": "^4.5.0",
     "webpackbar": "^5.0.2"
     "webpackbar": "^5.0.2"
   },
   },
   "eslintConfig": {
   "eslintConfig": {

+ 1 - 3
src/api/mock.js

@@ -451,9 +451,7 @@ const getAllCoderExams = function () {
 };
 };
 
 
 const mockAPIs = {
 const mockAPIs = {
-  getAllEvalExams,
-  getAllCourses,
-  getAllCoderExams,
+
 };
 };
 
 
 export default mockAPIs;
 export default mockAPIs;

+ 0 - 0
src/assets/bilibili_icon.jpg → src/assets/icon-bilibili.jpg


+ 0 - 0
src/assets/zhihu_icon.jpg → src/assets/icon-zhihu.jpg


+ 34 - 28
src/components/CourseCard.vue

@@ -1,8 +1,8 @@
 <template>
 <template>
   <el-card class="course-card" shadow="hover" @click="toCourseInfo">
   <el-card class="course-card" shadow="hover" @click="toCourseInfo">
-    <img :src="imageUrl" alt="" class="image" style="">
+    <img :src="imageUrl" alt="" class="image">
     <el-row>
     <el-row>
-      <el-col :span="16" class="name">{{ courseInfo.name }}</el-col>
+      <el-col :span="16" class="name">{{ title }}</el-col>
       <el-col :span="8" class="status">
       <el-col :span="8" class="status">
         <el-tag v-if="state==='NOT_STARTED'" size="small" type="info">未开始</el-tag>
         <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==='RUNNING'" size="small">进行中</el-tag>
@@ -10,18 +10,17 @@
       </el-col>
       </el-col>
     </el-row>
     </el-row>
     <el-row class="teacher">
     <el-row class="teacher">
-      教师: {{ courseInfo.teacher.name }}
+      教师: {{ teacher }}
     </el-row>
     </el-row>
     <el-row class="semester">
     <el-row class="semester">
-      季度: {{ courseInfo.semester }}
+      季度: {{ semester }}
     </el-row>
     </el-row>
     <el-row class="time">
     <el-row class="time">
-      时间: {{ timestampToTime(courseInfo.startTime) }} 至 {{ timestampToTime(courseInfo.endTime) }}
+      时间: {{ startTime }} 至 {{ endTime }}
     </el-row>
     </el-row>
     <el-row class="description">
     <el-row class="description">
-      {{ courseInfo.description }}
+      {{ description }}
     </el-row>
     </el-row>
-    <el-row></el-row>
     <el-row v-if="isManagePage">
     <el-row v-if="isManagePage">
       <div class="button">
       <div class="button">
         <el-button type="primary" size="small" icon="el-icon-edit" round plain @click.stop="$emit('update')">修改</el-button>
         <el-button type="primary" size="small" icon="el-icon-edit" round plain @click.stop="$emit('update')">修改</el-button>
@@ -32,41 +31,52 @@
 </template>
 </template>
 
 
 <script>
 <script>
-import variables from "@/utils/variables";
-
 export default {
 export default {
   name: "CourseCard",
   name: "CourseCard",
   props: {
   props: {
-    courseVO: {
-      type: Object
-    }
+    courseVO: Object,
   },
   },
   data() {
   data() {
     return {
     return {
-      courseInfo: null,
-      noImgUrl: variables.noImgUrl,
+      noImgUrl: this.$variables.noImgUrl,
     };
     };
   },
   },
   computed: {
   computed: {
-    state: function () {
-      if (new Date(this.courseInfo.endTime) < new Date()) {
+    imageUrl() {
+      return this.courseVO.imageUrl === null ? this.noImgUrl : this.courseVO.imageUrl + "?t=" + Date.now().valueOf();
+    },
+    title() {
+      return this.courseVO.name;
+    },
+    state() {
+      const now = new Date();
+      if (new Date(this.courseVO.endTime) < now) {
         return "FINISHED";
         return "FINISHED";
-      } else if (new Date(this.courseInfo.startTime) > new Date()) {
+      } else if (new Date(this.courseVO.startTime) > now) {
         return "NOT_STARTED";
         return "NOT_STARTED";
       } else {
       } else {
         return "RUNNING";
         return "RUNNING";
       }
       }
     },
     },
-    imageUrl() {
-      return this.courseInfo.imageUrl === null ? this.noImgUrl : this.courseInfo.imageUrl + "?t=" + Date.now().valueOf();
+    teacher() {
+      return this.courseVO.teacher.name || "无教师姓名";
+    },
+    semester() {
+      return this.courseVO.semester || "无季度信息";
+    },
+    startTime() {
+      return this.timestampToTime(this.courseVO.startTime);
+    },
+    endTime() {
+      return this.timestampToTime(this.courseVO.endTime);
+    },
+    description() {
+      return this.courseVO.description || "无课程简介";
     },
     },
     isManagePage() {
     isManagePage() {
-      return this.$route.name === "Manage";
+      return this.$route.name === "Manage" && this.$store.getters.isTeacher;
     },
     },
   },
   },
-  created() {
-    this.courseInfo = this.courseVO;
-  },
   emits: ["delete", "update"],
   emits: ["delete", "update"],
   methods: {
   methods: {
     timestampToTime(timestamp) {
     timestampToTime(timestamp) {
@@ -77,11 +87,7 @@ export default {
       return Y + M + D;
       return Y + M + D;
     },
     },
     toCourseInfo() {
     toCourseInfo() {
-      this.$router.push("/course/" + this.courseInfo.id);
-    },
-    setCourseInfo(item) {
-      this.courseInfo = item;
-      this.$forceUpdate();
+      this.$router.push("/course/" + this.courseVO.id);
     },
     },
   },
   },
 };
 };

+ 2 - 2
src/components/GlobalFooter.vue

@@ -27,10 +27,10 @@
         <div>关注我们</div>
         <div>关注我们</div>
         <div id="global-footer-follow-main">
         <div id="global-footer-follow-main">
           <a href="https://zhuanlan.zhihu.com/c_1220396784981487616" target="_blank">
           <a href="https://zhuanlan.zhihu.com/c_1220396784981487616" target="_blank">
-            <img alt="err" src="@/assets/zhihu_icon.jpg">
+            <img alt="err" src="@/assets/icon-zhihu.jpg">
           </a>
           </a>
           <a href="https://space.bilibili.com/507030405" target="_blank">
           <a href="https://space.bilibili.com/507030405" target="_blank">
-            <img alt="err" src="@/assets/bilibili_icon.jpg">
+            <img alt="err" src="@/assets/icon-bilibili.jpg">
           </a>
           </a>
         </div>
         </div>
       </div>
       </div>

+ 53 - 45
src/components/GlobalHeader.vue

@@ -1,33 +1,53 @@
 <template>
 <template>
   <div id="global-header-body">
   <div id="global-header-body">
     <el-backtop/>
     <el-backtop/>
-    <img id="global-header-logo" alt="err" src="@/assets/seec-logo--full.png" @click="this.$router.push('/portal')">
+    <img id="global-header-logo" alt="err" src="@/assets/seec-logo--full.png" @click="toPortal">
     <el-menu :default-active="activeMenu" mode="horizontal" @select="handleMenuSelect">
     <el-menu :default-active="activeMenu" mode="horizontal" @select="handleMenuSelect">
-      <el-menu-item index="1">首页</el-menu-item>
-      <el-menu-item v-if="isStudent" index="2">任务</el-menu-item>
+      <el-menu-item index="1">
+        首页
+      </el-menu-item>
+      <el-menu-item v-if="isStudent" index="2">
+        任务
+      </el-menu-item>
       <el-submenu index="3">
       <el-submenu index="3">
-        <template #title>{{ quickAccessTitle }}</template>
-        <el-menu-item index="3-1">全部课程</el-menu-item>
-        <el-menu-item index="3-2">全部测试</el-menu-item>
+        <template #title>
+          {{ quickAccessTitle }}
+        </template>
+        <el-menu-item index="3-1">
+          全部课程
+        </el-menu-item>
+        <el-menu-item index="3-2">
+          全部测试
+        </el-menu-item>
       </el-submenu>
       </el-submenu>
-      <el-menu-item index="4">个人中心</el-menu-item>
-      <el-menu-item v-if="isTeacher" index="5">教师[临]</el-menu-item>
-      <el-menu-item index="6">问题[临]</el-menu-item>
+      <el-menu-item index="4">
+        个人中心
+      </el-menu-item>
+      <el-menu-item v-if="isTeacher" index="5">
+        教师[临]
+      </el-menu-item>
+      <el-menu-item index="6">
+        问题[临]
+      </el-menu-item>
     </el-menu>
     </el-menu>
     <div id="global-header-icon">
     <div id="global-header-icon">
-      <div class="global-header-icon-content" @click="toMessageView" style="position: relative">
-        <sup v-if="unreadNum !== '0'" class="reminder">{{ unreadNum }}</sup>
+      <div class="global-header-icon-content" @click="toMessage" style="position: relative">
+        <sup v-if="unreadNum !== '0'" class="reminder">
+          {{ unreadNum }}
+        </sup>
         <svg height="32" viewBox="0 0 1024 1024" width="32" xmlns="http://www.w3.org/2000/svg">
         <svg height="32" viewBox="0 0 1024 1024" width="32" xmlns="http://www.w3.org/2000/svg">
           <path
           <path
             d="M849.6 713.4c8.4-0.4 16.7 1.8 23.8 6.4-28.9-18.5-46.4-50.4-46.3-84.8V436c0-145.9-105.7-267.6-246.9-297.5v-7.2c0-37.1-30.1-67.1-67.2-67.1h-0.1c-37.1 0-67.3 30.1-67.3 67.2v7C304.3 168.4 198.7 290 198.7 436v199.1c0 35.7-18.6 66.9-46.4 84.8 7-4.6 15.4-6.9 23.8-6.4-24.7-0.9-45.5 18.4-46.4 43.1-0.9 24.7 18.4 45.5 43.1 46.4h676.6c24.7 0.1 44.8-20 44.9-44.7 0.1-24.8-19.9-44.9-44.7-44.9zM513 959.8c62 0 112.2-50.2 112.2-111.9H400.7c0 61.7 50.2 111.9 112.3 111.9z"
             d="M849.6 713.4c8.4-0.4 16.7 1.8 23.8 6.4-28.9-18.5-46.4-50.4-46.3-84.8V436c0-145.9-105.7-267.6-246.9-297.5v-7.2c0-37.1-30.1-67.1-67.2-67.1h-0.1c-37.1 0-67.3 30.1-67.3 67.2v7C304.3 168.4 198.7 290 198.7 436v199.1c0 35.7-18.6 66.9-46.4 84.8 7-4.6 15.4-6.9 23.8-6.4-24.7-0.9-45.5 18.4-46.4 43.1-0.9 24.7 18.4 45.5 43.1 46.4h676.6c24.7 0.1 44.8-20 44.9-44.7 0.1-24.8-19.9-44.9-44.7-44.9zM513 959.8c62 0 112.2-50.2 112.2-111.9H400.7c0 61.7 50.2 111.9 112.3 111.9z"
             fill="#E8AA5B"></path>
             fill="#E8AA5B"></path>
         </svg>
         </svg>
       </div>
       </div>
-      <div class="global-header-icon-content" @click="this.$router.push('/home')">
+      <div class="global-header-icon-content" @click="toHome">
         <ElPopover trigger="hover">
         <ElPopover trigger="hover">
           <template #reference>
           <template #reference>
             <div v-if="isLogin" id="info-circle">
             <div v-if="isLogin" id="info-circle">
-              <span>{{ name.substring(0, 1) }}</span>
+              <span>
+                {{ singleName }}
+              </span>
             </div>
             </div>
             <div v-else>
             <div v-else>
               <svg height="32" viewBox="0 0 1025 1024" width="32" xmlns="http://www.w3.org/2000/svg">
               <svg height="32" viewBox="0 0 1025 1024" width="32" xmlns="http://www.w3.org/2000/svg">
@@ -76,7 +96,10 @@ export default {
       return this.$store.state.user.token !== undefined;
       return this.$store.state.user.token !== undefined;
     },
     },
     name() {
     name() {
-      return this.$store.state.user.name;
+      return this.$store.state.user.name || "无名氏";
+    },
+    singleName() {
+      return this.name.substring(0, 1);
     },
     },
     isTeacher() {
     isTeacher() {
       return this.$store.getters.isTeacher;
       return this.$store.getters.isTeacher;
@@ -101,34 +124,31 @@ export default {
   watch: {
   watch: {
     isLogin(newData, oldData) {
     isLogin(newData, oldData) {
       if (newData) {
       if (newData) {
-        this.$apis.getUnreadAnnouncements()
-          .then(res => {
-            this.myUnReadAnnouncements = res.data.data;
-          });
-        this.$apis.getUnreadMessages()
-          .then(res => {
-            this.myUnReadMessages = res.data.data;
-          })
-          .catch();
+        this.fetchMessages();
       }
       }
     }
     }
   },
   },
 
 
-  mounted() {
+  created() {
     if (this.isLogin) {
     if (this.isLogin) {
-      this.$apis.getUnreadAnnouncements()
-        .then(res => {
-          this.myUnReadAnnouncements = res.data.data;
-        });
-      this.$apis.getUnreadMessages()
-        .then(res => {
-          this.myUnReadMessages = res.data.data;
-        })
-        .catch();
+      this.fetchMessages();
     }
     }
   },
   },
 
 
   methods: {
   methods: {
+    toPortal() {
+      this.$router.push("/portal");
+    },
+    toHome() {
+      this.$router.push("/home");
+    },
+    toMessage() {
+      this.$router.push("/message");
+    },
+    async fetchMessages() {
+      this.myUnReadAnnouncements = (await this.$apis.getUnreadAnnouncements()).data.data;
+      this.myUnReadMessages = (await this.$apis.getUnreadMessages()).data.data;
+    },
     handleMenuSelect(key) {
     handleMenuSelect(key) {
       let target = "/portal";
       let target = "/portal";
       this.menuIndex.forEach(i => {
       this.menuIndex.forEach(i => {
@@ -145,18 +165,6 @@ export default {
         this.quickAccessTitle = "快速访问";
         this.quickAccessTitle = "快速访问";
       }
       }
     },
     },
-    toMessageView() {
-      this.$apis.getUnreadAnnouncements()
-        .then(res => {
-          this.myUnReadAnnouncements = res.data.data;
-        });
-      this.$apis.getUnreadMessages()
-        .then(res => {
-          this.myUnReadMessages = res.data.data;
-        })
-        .catch();
-      this.$router.push("/message");
-    },
   },
   },
 };
 };
 </script>
 </script>

+ 56 - 47
src/components/TestCard.vue

@@ -13,46 +13,29 @@
 
 
     <el-row>
     <el-row>
       <el-col :span="16">
       <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 class="title">
+          {{ title }}
         </el-col>
         </el-col>
       </el-col>
       </el-col>
       <el-col :span="8" class="status">
       <el-col :span="8" class="status">
         <el-tag v-if="state==='NOT_STARTED'" size="small" type="info">未开始</el-tag>
         <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==='RUNNING_IN'" size="small" type="success">已参加</el-tag>
+        <el-tag v-else-if="state==='RUNNING_NOT'" size="small">未参加</el-tag>
         <el-tag v-else-if="state==='FINISHED'" size="small" type="danger">已结束</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-tag v-else-if="state==='CLOSED'" size="small" type="info">已关闭</el-tag>
       </el-col>
       </el-col>
     </el-row>
     </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 class="course" v-if="course!==''">
+      {{ course }}
     </el-row>
     </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 class="teacher">
+      {{ teacherName }}
     </el-row>
     </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 class="time">
+      {{ timePeriod }}
     </el-row>
     </el-row>
 
 
     <el-row v-if="type==='eval'" class="comment">
     <el-row v-if="type==='eval'" class="comment">
@@ -62,7 +45,7 @@
 </template>
 </template>
 
 
 <script>
 <script>
-import {ElMessageBox} from "element-plus";
+import { ElMessageBox } from "element-plus";
 
 
 export default {
 export default {
   name: "TestCard",
   name: "TestCard",
@@ -71,12 +54,7 @@ export default {
   },
   },
   data() {
   data() {
     return {
     return {
-      teacher: {
-        type: Object,
-        default: {
-          name: "暂无信息",
-        },
-      },
+      teacher: Object,
     };
     };
   },
   },
   computed: {
   computed: {
@@ -87,38 +65,70 @@ export default {
         return "coder";
         return "coder";
       }
       }
     },
     },
+    title() {
+      if (this.type === "eval") {
+        return this.testVO.examName;
+      } else {
+        return this.testVO.name;
+      }
+    },
+    course() {
+      if (this.type === "eval") {
+        return "";
+      } else {
+        return "所属课程: " + this.testVO.course;
+      }
+    },
+    teacherName() {
+      if (this.type === "eval") {
+        return "教师: " + this.teacher.name;
+      } else {
+        return "教师: " + this.testVO.creator.username;
+      }
+    },
+    timePeriod() {
+      if (this.type === "eval") {
+        return "时间: " + this.testVO.startTime.substring(0, 16) + "至" + this.testVO.endTime.substring(0, 16);
+      } else {
+        return "时间: " + this.timestampToTime(this.testVO.startAt) + "至" + this.timestampToTime(this.testVO.endAt);
+      }
+    },
     state() {
     state() {
+      const now = new Date();
       if (this.type === "eval") {
       if (this.type === "eval") {
-        if (new Date(this.testVO.endTime) < new Date()) {
+        if (new Date(this.testVO.endTime) < now) {
           return "FINISHED";
           return "FINISHED";
-        } else if (new Date(this.testVO.startTime) > new Date()) {
+        } else if (new Date(this.testVO.startTime) > now) {
           return "NOT_STARTED";
           return "NOT_STARTED";
+        } else if (this.testVO.isJoined) {
+          return "RUNNING_IN";
         } else {
         } else {
-          return "RUNNING";
+          return "RUNNING_NOT";
         }
         }
       } else {
       } else {
         if (this.testVO.status === "CLOSED") {
         if (this.testVO.status === "CLOSED") {
           return "CLOSED";
           return "CLOSED";
-        } else if (this.testVO.startAt * 1000 > new Date()) {
+        } else if (this.testVO.startAt * 1000 > now) {
           return "NOT_STARTED";
           return "NOT_STARTED";
-        } else if (this.testVO.endAt * 1000 < new Date()) {
+        } else if (this.testVO.endAt * 1000 < now) {
           return "FINISHED";
           return "FINISHED";
+        } else if (this.testVO.joined) {
+          return "RUNNING_IN";
         } else {
         } else {
-          return "RUNNING";
+          return "RUNNING_NOT";
         }
         }
       }
       }
     },
     },
   },
   },
-  async mounted() {
+  async created() {
     if (this.type === "eval") {
     if (this.type === "eval") {
-      const res = await this.$apis.getUserAPI(this.testVO.course.teacherId);
-      this.teacher = res.data.data;
+      this.teacher = (await this.$apis.getUserAPI(this.testVO.course["teacherId"])).data.data;
     } else {
     } else {
       const res = await this.$apis.getUserAPI(this.testVO.creator.id);
       const res = await this.$apis.getUserAPI(this.testVO.creator.id);
       if (res.data.code === 0) {
       if (res.data.code === 0) {
         this.teacher = res.data.data;
         this.teacher = res.data.data;
       } else {
       } else {
-        this.teacher = {name: this.testVO.creator.username};
+        this.teacher = { name: this.testVO.creator.username };
       }
       }
     }
     }
   },
   },
@@ -201,11 +211,10 @@ export default {
         } else {
         } else {
           this.$router.push(nextURL);
           this.$router.push(nextURL);
         }
         }
-      }).catch();
+      });
     },
     },
   }
   }
-}
-;
+};
 </script>
 </script>
 
 
 <style scoped>
 <style scoped>

+ 3 - 2
src/global/register-element.js

@@ -37,7 +37,7 @@ import {
   ElMenuItem,
   ElMenuItem,
   ElSubmenu, ElCollapse, ElCollapseItem,
   ElSubmenu, ElCollapse, ElCollapseItem,
   ElSwitch,
   ElSwitch,
-  ElBadge,
+  ElBadge, ElOptionGroup,
 } from "element-plus";
 } from "element-plus";
 
 
 // NOTE 使用到的组件列表,请确保 import 和 component 的一致性
 // NOTE 使用到的组件列表,请确保 import 和 component 的一致性
@@ -82,7 +82,8 @@ const components = [
   ElCollapse,
   ElCollapse,
   ElCollapseItem,
   ElCollapseItem,
   ElSwitch,
   ElSwitch,
-  ElBadge
+  ElBadge,
+  ElOptionGroup,
 ];
 ];
 
 
 export default function (app) {
 export default function (app) {

+ 3 - 8
src/main.js

@@ -4,16 +4,10 @@ import App from "./App.vue";
 import router from "./router";
 import router from "./router";
 import store from "./store";
 import store from "./store";
 import api from "@/api";
 import api from "@/api";
-import { ElMessage, ElLoading } from "element-plus";
+import { ElMessage } from "element-plus";
+import variables from "@/utils/variables";
 
 
 const app = createApp(App).use(store).use(router).use(globalComponentRegister);
 const app = createApp(App).use(store).use(router).use(globalComponentRegister);
-app.use(ElLoading);
-app.directive("title", {
-  inserted: function (el) {
-    document.title = el.dataset.title;
-  },
-});
-
 app.directive("teacher-permission", {
 app.directive("teacher-permission", {
   mounted(el, binding) {
   mounted(el, binding) {
     if (binding.value.role !== "TEACHER") {
     if (binding.value.role !== "TEACHER") {
@@ -32,4 +26,5 @@ app.directive("student-permission", {
 app.config.productionTip = false;
 app.config.productionTip = false;
 app.config.globalProperties.$apis = api;
 app.config.globalProperties.$apis = api;
 app.config.globalProperties.$message = ElMessage;
 app.config.globalProperties.$message = ElMessage;
+app.config.globalProperties.$variables = variables;
 app.mount("#app");
 app.mount("#app");

+ 7 - 2
src/views/AuthPage/AuthPage.vue

@@ -1,5 +1,5 @@
 <template>
 <template>
-  <img id="auth-img" alt="err" src="@/assets/seec-logo--horizontal.png" @click="this.$router.push('/portal')">
+  <img id="auth-img" alt="err" src="@/assets/seec-logo--horizontal.png" @click="toPortal">
   <div id="auth-card">
   <div id="auth-card">
     <AuthCard/>
     <AuthCard/>
   </div>
   </div>
@@ -10,7 +10,12 @@ import AuthCard from "@/views/AuthPage/components/AuthCard";
 
 
 export default {
 export default {
   name: "AuthPage",
   name: "AuthPage",
-  components: { AuthCard }
+  components: { AuthCard },
+  methods: {
+    toPortal() {
+      this.$router.push("/portal");
+    }
+  },
 };
 };
 </script>
 </script>
 
 

+ 5 - 5
src/views/AuthPage/components/SlideVerifier.vue

@@ -84,11 +84,11 @@ export default {
   },
   },
   mounted() {
   mounted() {
     this.init();
     this.init();
-    window.onresize = () => {
-      debounce(() => {
-        this.init();
-      }, 120);
-    };
+    // window.onresize = () => {
+    //   debounce(() => {
+    //     this.init();
+    //   }, 120);
+    // };
   },
   },
   methods: {
   methods: {
     /**
     /**

+ 15 - 15
src/views/ManagePage/ManagePage.vue

@@ -1,7 +1,7 @@
 <template>
 <template>
   <el-row id="manage-page-body">
   <el-row id="manage-page-body">
     <el-col :span="3">
     <el-col :span="3">
-      <el-menu background-color="#f8f9fb" default-active="1" style="position: fixed; width: 180px;"
+      <el-menu background-color="#f8f9fb" default-active="1" style="width: 180px; z-index: -1;"
                @select="handleSelect">
                @select="handleSelect">
         <el-menu-item index="0">
         <el-menu-item index="0">
           <el-icon>
           <el-icon>
@@ -165,9 +165,9 @@
 
 
 <script>
 <script>
 import CourseCard from "@/components/CourseCard";
 import CourseCard from "@/components/CourseCard";
-import {ElMessage, ElMessageBox} from "element-plus";
+import { ElMessage, ElMessageBox } from "element-plus";
 import client from "@/utils/oss";
 import client from "@/utils/oss";
-import {Back, Document} from "@element-plus/icons-vue";
+import { Back, Document } from "@element-plus/icons-vue";
 import CoderCard from "@/components/CoderCard";
 import CoderCard from "@/components/CoderCard";
 import EvalCard from "@/components/EvalCard";
 import EvalCard from "@/components/EvalCard";
 
 
@@ -269,19 +269,19 @@ export default {
       myCourseList: [],
       myCourseList: [],
       courseType: "all",
       courseType: "all",
       courseTypeOptions: [
       courseTypeOptions: [
-        {value: "all", label: "全部课程"},
-        {value: "pending", label: "未开始"},
-        {value: "start", label: "正在进行"},
-        {value: "end", label: "已结束"},
+        { value: "all", label: "全部课程" },
+        { value: "pending", label: "未开始" },
+        { value: "start", label: "正在进行" },
+        { value: "end", label: "已结束" },
       ],
       ],
       evalExamList: [],
       evalExamList: [],
       coderExamList: [],
       coderExamList: [],
       examType: "all",
       examType: "all",
       examTypeOptions: [
       examTypeOptions: [
-        {value: "all", label: "全部测试"},
-        {value: "pending", label: "未开始"},
-        {value: "start", label: "正在进行"},
-        {value: "end", label: "已结束"},
+        { value: "all", label: "全部测试" },
+        { value: "pending", label: "未开始" },
+        { value: "start", label: "正在进行" },
+        { value: "end", label: "已结束" },
       ],
       ],
     };
     };
   },
   },
@@ -290,7 +290,7 @@ export default {
     this.$apis.getTeacherCourses().then(res => {
     this.$apis.getTeacherCourses().then(res => {
       this.myCourseList = res.data.data;
       this.myCourseList = res.data.data;
     });
     });
-    this.$apis.getTeacherEvalExams({state: 0}).then(res => {
+    this.$apis.getTeacherEvalExams({ state: 0 }).then(res => {
       this.evalExamList = res.data.data.examVOList;
       this.evalExamList = res.data.data.examVOList;
     });
     });
     this.$apis.getTeacherCoderExams({}).then(res => {
     this.$apis.getTeacherCoderExams({}).then(res => {
@@ -303,10 +303,10 @@ export default {
         this.$router.push("portal");
         this.$router.push("portal");
       }
       }
       if (index === "1") {
       if (index === "1") {
-        document.getElementById("app").scrollIntoView({behavior: "smooth"});
+        document.getElementById("app").scrollIntoView({ behavior: "smooth" });
       }
       }
       if (index === "2") {
       if (index === "2") {
-        document.querySelector("#manage-page-divider").scrollIntoView({behavior: "smooth"});
+        document.querySelector("#manage-page-divider").scrollIntoView({ behavior: "smooth" });
       }
       }
       this.activeIndex = index;
       this.activeIndex = index;
     },
     },
@@ -387,7 +387,7 @@ export default {
                   _this.myCourseList[i] = res.data.data;
                   _this.myCourseList[i] = res.data.data;
                 }
                 }
               }
               }
-              _this.$refs["courseCard" + _this.form.id][0].setCourseInfo(res.data.data);
+              _this.$refs["courseCard" + _this.form.id][0].$props.courseVO = res.data.data;
               _this.dialogVisible = false;
               _this.dialogVisible = false;
               _this.$refs.formRef.resetFields();
               _this.$refs.formRef.resetFields();
               _this.form.courseTime = [null, null];
               _this.form.courseTime = [null, null];

+ 6 - 0
src/views/PortalPage/PortalPage.css

@@ -49,4 +49,10 @@
     display: grid;
     display: grid;
     grid-template-columns: 1fr 1fr 1fr;
     grid-template-columns: 1fr 1fr 1fr;
     grid-gap: 20px;
     grid-gap: 20px;
+}
+
+.tip {
+    font-size: small;
+    font-weight: bold;
+    color: #666666;
 }
 }

+ 65 - 61
src/views/PortalPage/PortalPage.vue

@@ -14,11 +14,11 @@
           <div v-if="!isLogin"
           <div v-if="!isLogin"
                :style="{height: (this.courseRowHeight - 63) + 'px', marginTop: (this.courseRowHeight / 2 - 100) + 'px'}"
                :style="{height: (this.courseRowHeight - 63) + 'px', marginTop: (this.courseRowHeight / 2 - 100) + 'px'}"
                class="portal-card-main" style="cursor: pointer"
                class="portal-card-main" style="cursor: pointer"
-               @click="this.$router.push('/auth')">
+               @click="toAuth">
             <el-icon :size="72" color="#bfbfbf">
             <el-icon :size="72" color="#bfbfbf">
               <Lock/>
               <Lock/>
             </el-icon>
             </el-icon>
-            <div style="font-size: small; font-weight: bold; color: #666666">登录以查看</div>
+            <div class="tip">登录以查看</div>
           </div>
           </div>
 
 
           <div v-if="isLogin && isStudent && myCourseList.length!==0"
           <div v-if="isLogin && isStudent && myCourseList.length!==0"
@@ -32,21 +32,21 @@
           <div v-if="isLogin && isStudent && myCourseList.length===0"
           <div v-if="isLogin && isStudent && myCourseList.length===0"
                :style="{height: (this.courseRowHeight - 63) + 'px', marginTop: (this.courseRowHeight / 2 - 100) + 'px'}"
                :style="{height: (this.courseRowHeight - 63) + 'px', marginTop: (this.courseRowHeight / 2 - 100) + 'px'}"
                class="portal-card-main" style="cursor: pointer"
                class="portal-card-main" style="cursor: pointer"
-               @click="this.$router.push('/course')">
+               @click="toCourse">
             <el-icon :size="72" color="#bfbfbf">
             <el-icon :size="72" color="#bfbfbf">
               <ShoppingCart/>
               <ShoppingCart/>
             </el-icon>
             </el-icon>
-            <div style="font-size: small; font-weight: bold; color: #666666">去选择课程</div>
+            <div class="tip">去选择课程</div>
           </div>
           </div>
 
 
           <div v-show="isLogin && isTeacher"
           <div v-show="isLogin && isTeacher"
                :style="{height: (this.courseRowHeight - 63) + 'px', marginTop: (this.courseRowHeight / 2 - 100) + 'px'}"
                :style="{height: (this.courseRowHeight - 63) + 'px', marginTop: (this.courseRowHeight / 2 - 100) + 'px'}"
                class="portal-card-main" style="cursor: pointer"
                class="portal-card-main" style="cursor: pointer"
-               @click="this.$router.push('/manage')">
+               @click="toManage">
             <el-icon :size="72" color="#bfbfbf">
             <el-icon :size="72" color="#bfbfbf">
               <SetUp/>
               <SetUp/>
             </el-icon>
             </el-icon>
-            <div style="font-size: small; font-weight: bold; color: #666666">去管理课程</div>
+            <div class="tip">去管理课程</div>
           </div>
           </div>
         </div>
         </div>
       </el-card>
       </el-card>
@@ -56,17 +56,17 @@
       <el-card id="portal-course-card-main" :style="{height: this.courseRowHeight + 'px'}">
       <el-card id="portal-course-card-main" :style="{height: this.courseRowHeight + 'px'}">
         <div class="portal-card-title">
         <div class="portal-card-title">
           <div class="portal-card-title-main">精选课程</div>
           <div class="portal-card-title-main">精选课程</div>
-          <el-pagination v-if="isExpanding && courseList.length > 6"
+          <el-pagination v-if="isExpanding && exampleCourseList.length > 6"
                          :page-size="6"
                          :page-size="6"
-                         :total="courseList.length"
+                         :total="exampleCourseList.length"
                          @current-change="handleCourseCurrentChange"
                          @current-change="handleCourseCurrentChange"
                          layout="prev, pager, next"
                          layout="prev, pager, next"
                          style="width: 200px; margin: 0 auto 0 auto"/>
                          style="width: 200px; margin: 0 auto 0 auto"/>
-          <ElButton plain round type="primary" @click="this.$router.push('/course')">查看全部课程</ElButton>
+          <ElButton plain round type="primary" @click="toCourse">查看全部课程</ElButton>
         </div>
         </div>
         <el-divider class="portal-card-divider"/>
         <el-divider class="portal-card-divider"/>
         <div class="portal-card-content">
         <div class="portal-card-content">
-          <CourseCard v-for="item in showCourseList" :key="item.id" :courseVO="item"/>
+          <CourseCard v-for="item in showExampleCourseList" :key="item.id" :courseVO="item"/>
         </div>
         </div>
       </el-card>
       </el-card>
     </div>
     </div>
@@ -81,11 +81,11 @@
           <div v-if="!isLogin"
           <div v-if="!isLogin"
                :style="{height: (this.testRowHeight - 63) + 'px', marginTop: (this.testRowHeight / 2 - 100) + 'px'}"
                :style="{height: (this.testRowHeight - 63) + 'px', marginTop: (this.testRowHeight / 2 - 100) + 'px'}"
                class="portal-card-main" style="cursor: pointer"
                class="portal-card-main" style="cursor: pointer"
-               @click="this.$router.push('/auth')">
+               @click="toAuth">
             <el-icon :size="72" color="#bfbfbf">
             <el-icon :size="72" color="#bfbfbf">
               <Lock/>
               <Lock/>
             </el-icon>
             </el-icon>
-            <div style="font-size: small; font-weight: bold; color: #666666">登录以查看</div>
+            <div class="tip">登录以查看</div>
           </div>
           </div>
 
 
           <div v-if="isLogin && isStudent && myTestList!==null && myTestList.length!==0"
           <div v-if="isLogin && isStudent && myTestList!==null && myTestList.length!==0"
@@ -99,21 +99,21 @@
           <div v-if="isLogin && isStudent && myTestList!==null && myTestList.length===0"
           <div v-if="isLogin && isStudent && myTestList!==null && myTestList.length===0"
                :style="{height: (this.testRowHeight - 63) + 'px', marginTop: (this.testRowHeight / 2 - 100) + 'px'}"
                :style="{height: (this.testRowHeight - 63) + 'px', marginTop: (this.testRowHeight / 2 - 100) + 'px'}"
                class="portal-card-main" style="cursor: pointer"
                class="portal-card-main" style="cursor: pointer"
-               @click="this.$router.push('/test')">
+               @click="toTest">
             <el-icon :size="72" color="#bfbfbf">
             <el-icon :size="72" color="#bfbfbf">
               <ShoppingCart/>
               <ShoppingCart/>
             </el-icon>
             </el-icon>
-            <div style="font-size: small; font-weight: bold; color: #666666">去参加测试</div>
+            <div class="tip">去参加测试</div>
           </div>
           </div>
 
 
           <div v-show="isLogin && isTeacher"
           <div v-show="isLogin && isTeacher"
                :style="{height: (this.testRowHeight - 63) + 'px', marginTop: (this.testRowHeight / 2 - 100) + 'px'}"
                :style="{height: (this.testRowHeight - 63) + 'px', marginTop: (this.testRowHeight / 2 - 100) + 'px'}"
                class="portal-card-main" style="cursor: pointer"
                class="portal-card-main" style="cursor: pointer"
-               @click="this.$router.push('/manage')">
+               @click="toManage">
             <el-icon :size="72" color="#bfbfbf">
             <el-icon :size="72" color="#bfbfbf">
               <SetUp/>
               <SetUp/>
             </el-icon>
             </el-icon>
-            <div style="font-size: small; font-weight: bold; color: #666666">去管理测试</div>
+            <div class="tip">去管理测试</div>
           </div>
           </div>
         </div>
         </div>
 
 
@@ -124,24 +124,23 @@
       <el-card id="portal-test-card-main" ref="portalTestCardBodyMain">
       <el-card id="portal-test-card-main" ref="portalTestCardBodyMain">
         <div class="portal-card-title">
         <div class="portal-card-title">
           <div class="portal-card-title-main">智能测试</div>
           <div class="portal-card-title-main">智能测试</div>
-          <ElButton plain round type="primary" @click="this.$router.push('/test')">查看全部测试</ElButton>
+          <ElButton plain round type="primary" @click="toTest">查看全部测试</ElButton>
         </div>
         </div>
         <el-divider class="portal-card-divider"/>
         <el-divider class="portal-card-divider"/>
         <el-tabs v-model="activeTestPaneName" @tab-click="changeTestPane">
         <el-tabs v-model="activeTestPaneName" @tab-click="changeTestPane">
           <el-tab-pane label="评测题" name="eval">
           <el-tab-pane label="评测题" name="eval">
             <div class="portal-card-content">
             <div class="portal-card-content">
-              <TestCard v-for="item in evalExamList" :key="item.id" :testVO="item"/>
+              <TestCard v-for="item in showExampleEvalTestList" :key="item.id" :testVO="item"/>
             </div>
             </div>
           </el-tab-pane>
           </el-tab-pane>
           <el-tab-pane label="代码题" name="coder">
           <el-tab-pane label="代码题" name="coder">
             <div class="portal-card-content">
             <div class="portal-card-content">
-              <TestCard v-for="item in coderExamList" :key="item.id" :testVO="item"/>
+              <TestCard v-for="item in showExampleCoderTestList" :key="item.id" :testVO="item"/>
             </div>
             </div>
           </el-tab-pane>
           </el-tab-pane>
         </el-tabs>
         </el-tabs>
       </el-card>
       </el-card>
     </div>
     </div>
-
   </div>
   </div>
 </template>
 </template>
 
 
@@ -150,7 +149,7 @@ import CarouselCard from "@/views/PortalPage/components/CarouselCard";
 import CourseCard from "@/components/CourseCard";
 import CourseCard from "@/components/CourseCard";
 import MyCourseCard from "@/views/PortalPage/components/MyCourseCard";
 import MyCourseCard from "@/views/PortalPage/components/MyCourseCard";
 import MyTestCard from "@/views/PortalPage/components/MyTestCard";
 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";
 import TestCard from "@/components/TestCard";
 
 
 export default {
 export default {
@@ -170,10 +169,10 @@ export default {
     return {
     return {
       isExpanding: false,
       isExpanding: false,
       activeTestPaneName: "eval",
       activeTestPaneName: "eval",
-      evalExamList: [],
-      courseList: [],
+      exampleEvalTestList: [],
+      exampleCourseList: [],
       showCourseList_current: 1,
       showCourseList_current: 1,
-      coderExamList: [],
+      exampleCoderTestList: [],
       myCourseList: [],
       myCourseList: [],
       myEvalExamList: [],
       myEvalExamList: [],
       myCoderExamList: [],
       myCoderExamList: [],
@@ -192,14 +191,24 @@ export default {
       return this.$store.getters.isStudent;
       return this.$store.getters.isStudent;
     },
     },
     myTestList() {
     myTestList() {
-      if (!this.myEvalExamList || !this.myCoderExamList) {
-        return [];
-      } else {
-        return [].concat(this.myEvalExamList).concat(this.myCoderExamList);
-      }
+      return []
+        .concat(this.myEvalExamList)
+        .concat(this.myCoderExamList)
+        .sort((a, b) => {
+          let a_time = a.startAt * 1000 || new Date(a.startTime).getTime();
+          let b_time = b.startAt * 1000 || new Date(b.startTime).getTime();
+          return a_time - b_time;
+        });
+      ;
+    },
+    showExampleCourseList() {
+      return this.exampleCourseList.slice((this.showCourseList_current - 1) * 6, this.showCourseList_current * 6);
+    },
+    showExampleCoderTestList() {
+      return this.exampleCoderTestList.filter(i => this.state(i) === "RUNNING").slice(0, 6);
     },
     },
-    showCourseList() {
-      return this.courseList.slice((this.showCourseList_current - 1) * 6, this.showCourseList_current * 6);
+    showExampleEvalTestList() {
+      return this.exampleEvalTestList.filter(i => this.state(i) === "RUNNING").slice(0, 6);
     },
     },
   },
   },
 
 
@@ -213,39 +222,35 @@ export default {
   async mounted() {
   async mounted() {
     const that = this;
     const that = this;
 
 
-    this.courseList = (await this.$apis.getExampleCourses()).data.data;
-    this.evalExamList = (await this.$apis.getExampleEvalExams()).data.data.filter(i => {
-      return this.state(i) === "RUNNING";
-    }).slice(0, 6);
-    this.coderExamList = (await this.$apis.getExampleCoderExams()).data.data.res.filter(i => {
-      return this.state(i) === "RUNNING";
-    }).slice(0, 6);
+    this.exampleCourseList = (await this.$apis.getExampleCourses()).data.data;
+    this.exampleEvalTestList = (await this.$apis.getExampleEvalExams()).data.data;
+    this.exampleCoderTestList = (await this.$apis.getExampleCoderExams({})).data.data.res.filter(i => this.state(i) === "RUNNING");
 
 
     if (this.isLogin && this.isStudent) {
     if (this.isLogin && this.isStudent) {
-      this.$apis.getStudentCourses().then(res => {
-        this.myCourseList = res.data.data;
-        that.handleResize();
-      });
-      this.$apis.getStudentEvalExams({state: 0}).then(res => {
-        this.myEvalExamList = res.data.data.examVOList;
-        that.handleResize();
-      });
-      this.$apis.getStudentCoderExams({}).then(res => {
-        this.myCoderExamList = res.data.data.res;
-        that.handleResize();
-      });
+      this.myCourseList = (await this.$apis.getStudentCourses()).data.data;
+      this.myEvalExamList = (await this.$apis.getStudentEvalExams({ state: 0 })).data.data["examVOList"];
+      this.myCoderExamList = (await this.$apis.getStudentCoderExams({})).data.data["res"];
     }
     }
 
 
-    await this.$nextTick(() => {
-      that.handleResize();
-    });
+    await this.$nextTick(() => that.handleResize());
   },
   },
 
 
   //其他函数
   //其他函数
   methods: {
   methods: {
+    toAuth() {
+      this.$router.push("/auth");
+    },
+    toCourse() {
+      this.$router.push("/course");
+    },
+    toManage() {
+      this.$router.push("/manage");
+    },
+    toTest() {
+      this.$router.push("/test");
+    },
     handleResize() {
     handleResize() {
       if (this.$route.path !== "/portal") return;
       if (this.$route.path !== "/portal") return;
-      // todo @DQJ 可能还得优化
       let scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop;
       let scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop;
       if (scrollTop > 100) {
       if (scrollTop > 100) {
         this.courseRowHeight = 640;
         this.courseRowHeight = 640;
@@ -255,15 +260,14 @@ export default {
     },
     },
     changeTestPane() {
     changeTestPane() {
       const that = this;
       const that = this;
-      this.$nextTick(() => {
-        that.handleResize();
-      });
+      this.$nextTick(() => that.handleResize());
     },
     },
     state(testVO) {
     state(testVO) {
+      const now = new Date();
       if (testVO.examId) {
       if (testVO.examId) {
-        if (new Date(testVO.endTime) < new Date()) {
+        if (new Date(testVO.endTime) < now) {
           return "FINISHED";
           return "FINISHED";
-        } else if (new Date(testVO.startTime) > new Date()) {
+        } else if (new Date(testVO.startTime) > now) {
           return "NOT_STARTED";
           return "NOT_STARTED";
         } else {
         } else {
           return "RUNNING";
           return "RUNNING";
@@ -271,9 +275,9 @@ export default {
       } else {
       } else {
         if (testVO.status === "CLOSED") {
         if (testVO.status === "CLOSED") {
           return "CLOSED";
           return "CLOSED";
-        } else if (testVO.startAt * 1000 > new Date()) {
+        } else if (testVO.startAt * 1000 > now) {
           return "NOT_STARTED";
           return "NOT_STARTED";
-        } else if (testVO.endAt * 1000 < new Date()) {
+        } else if (testVO.endAt * 1000 < now) {
           return "FINISHED";
           return "FINISHED";
         } else {
         } else {
           return "RUNNING";
           return "RUNNING";

+ 23 - 25
src/views/PortalPage/components/MyCourseCard.vue

@@ -1,59 +1,57 @@
 <template>
 <template>
-  <el-card class="body" shadow="hover" @click="toCourseInfo">
+  <el-card class="body" shadow="hover" @click="this.$router.push('/course/' + this.courseVO.id)">
     <el-row>
     <el-row>
       <el-col :span="6">
       <el-col :span="6">
         <img :src="imageUrl" alt="err" class="course-img">
         <img :src="imageUrl" alt="err" class="course-img">
       </el-col>
       </el-col>
-
       <el-col :span="2"/>
       <el-col :span="2"/>
-
       <el-col :span="16">
       <el-col :span="16">
-
         <el-row>
         <el-row>
-          <el-col :span="18" class="title">{{ courseVO.name }}</el-col>
+          <el-col :span="18" class="title">{{ title }}</el-col>
           <el-col :span="4">
           <el-col :span="4">
             <el-tag v-if="state==='NOT_STARTED'" size="small" type="info">未开始</el-tag>
             <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==='RUNNING'" size="small">进行中</el-tag>
             <el-tag v-else-if="state==='OVER'" size="small" type="danger">已结束</el-tag>
             <el-tag v-else-if="state==='OVER'" size="small" type="danger">已结束</el-tag>
           </el-col>
           </el-col>
         </el-row>
         </el-row>
-
-        <el-row style="position: absolute; bottom: 0">
+        <el-row class="info">
           <el-col>
           <el-col>
-            <el-row class="teacher">教师: {{ courseVO.teacher.name }}</el-row>
-            <el-row class="time">开课时间: {{ courseTime }}</el-row>
+            <el-row class="teacher">教师: {{ teacher }}</el-row>
+            <el-row class="time">开课时间: {{ startTime }}</el-row>
           </el-col>
           </el-col>
         </el-row>
         </el-row>
-
       </el-col>
       </el-col>
     </el-row>
     </el-row>
   </el-card>
   </el-card>
 </template>
 </template>
 
 
 <script>
 <script>
-import variables from "@/utils/variables";
-
 export default {
 export default {
   name: "MyCourseCard",
   name: "MyCourseCard",
   props: {
   props: {
-    courseVO: {
-      type: Object
-    }
+    courseVO: Object,
   },
   },
   computed: {
   computed: {
-    state: function () {
-      if (new Date(this.courseVO.endTime) < new Date()) {
+    title() {
+      return this.courseVO.name || "无课程名称";
+    },
+    state() {
+      const now = new Date();
+      if (new Date(this.courseVO.endTime) < now) {
         return "OVER";
         return "OVER";
-      } else if (new Date(this.courseVO.startTime) > new Date()) {
+      } else if (new Date(this.courseVO.startTime) > now) {
         return "NOT_STARTED";
         return "NOT_STARTED";
       } else {
       } else {
         return "RUNNING";
         return "RUNNING";
       }
       }
     },
     },
+    teacher() {
+      return this.courseVO.teacher.name || "无教师名称";
+    },
     imageUrl() {
     imageUrl() {
-      return this.courseVO.imageUrl === null ? variables.noImgUrl : this.courseVO.imageUrl;
+      return this.courseVO.imageUrl === null ? this.$variables.noImgUrl : this.courseVO.imageUrl;
     },
     },
-    courseTime() {
+    startTime() {
       const date = new Date(this.courseVO.startTime);
       const date = new Date(this.courseVO.startTime);
       const Y = date.getFullYear() + "-";
       const Y = date.getFullYear() + "-";
       const M = (date.getMonth() + 1 < 10 ? "0" + (date.getMonth() + 1) : date.getMonth() + 1) + "-";
       const M = (date.getMonth() + 1 < 10 ? "0" + (date.getMonth() + 1) : date.getMonth() + 1) + "-";
@@ -61,11 +59,6 @@ export default {
       return Y + M + D;
       return Y + M + D;
     },
     },
   },
   },
-  methods: {
-    toCourseInfo() {
-      this.$router.push("/course/" + this.courseVO.id);
-    },
-  },
 };
 };
 </script>
 </script>
 
 
@@ -97,6 +90,11 @@ export default {
   margin-bottom: 10px;
   margin-bottom: 10px;
 }
 }
 
 
+.info {
+  position: absolute;
+  bottom: 0;
+}
+
 .teacher {
 .teacher {
   font-size: 12px;
   font-size: 12px;
   color: #999999;
   color: #999999;

+ 56 - 48
src/views/PortalPage/components/MyTestCard.vue

@@ -2,7 +2,7 @@
   <el-card class="body" shadow="hover" @click="toTestInfo">
   <el-card class="body" shadow="hover" @click="toTestInfo">
 
 
     <div :style="{borderBottom: type==='eval' ? '30px solid #f5b86e' : '30px solid #8dc9e2'}"
     <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;">
+         style="float: right; width: 0; height: 0; position: absolute;right: 0;bottom: -1px;border-left: 30px solid transparent;">
       <div v-if="type==='eval'" style="padding: 0 4px 0 4px; position: absolute; right: 0; bottom: -30px; color: white">
       <div v-if="type==='eval'" style="padding: 0 4px 0 4px; position: absolute; right: 0; bottom: -30px; color: white">
         E
         E
       </div>
       </div>
@@ -13,54 +13,35 @@
 
 
     <el-row>
     <el-row>
       <el-col :span="20">
       <el-col :span="20">
-        <el-col v-if="type==='eval'" class="title">
-          {{ testVO.examName }}
-        </el-col>
-        <el-col v-else class="title">
-          {{ testVO.name }}
+        <el-col class="title">
+          {{ title }}
         </el-col>
         </el-col>
       </el-col>
       </el-col>
-      <el-col :span="4" style="text-align: center;">
+      <el-col :span="4">
         <el-tag v-if="state==='NOT_STARTED'" size="small" type="info">未开始</el-tag>
         <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==='RUNNING_IN'" size="small" type="success">已参加</el-tag>
+        <el-tag v-else-if="state==='RUNNING_NOT'" size="small">未参加</el-tag>
         <el-tag v-else-if="state==='FINISHED'" size="small" type="danger">已结束</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-tag v-else-if="state==='CLOSED'" size="small" type="info">已关闭</el-tag>
       </el-col>
       </el-col>
     </el-row>
     </el-row>
 
 
-    <el-row>
-      <el-col v-if="type==='eval'" class="course">
-
-      </el-col>
-      <el-col v-else class="course">
-        所属课程: {{ testVO.course }}
-      </el-col>
+    <el-row class="course" v-if="course!==''">
+      {{ course }}
     </el-row>
     </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 class="teacher">
+      {{ teacherName }}
     </el-row>
     </el-row>
 
 
-    <el-row>
-      <el-col v-if="type==='eval'" class="test-period">
-        时间: {{ testVO.startTime.substring(0, 16) }} 至 {{ testVO.endTime.substring(0, 16) }}
-      </el-col>
-      <el-col v-else class="test-period">
-        {{ timestampToTime(testVO.startAt) }} 至 {{ timestampToTime(testVO.endAt) }}
-      </el-col>
+    <el-row class="test-period">
+      {{ timePeriod }}
     </el-row>
     </el-row>
-
-
   </el-card>
   </el-card>
 </template>
 </template>
 
 
 <script>
 <script>
-import {ElMessageBox} from "element-plus";
+import { ElMessageBox } from "element-plus";
 
 
 export default {
 export default {
   name: "MyTestCard",
   name: "MyTestCard",
@@ -69,12 +50,7 @@ export default {
   },
   },
   data() {
   data() {
     return {
     return {
-      teacher: {
-        type: Object,
-        default: {
-          name: "暂无信息",
-        },
-      },
+      teacher: Object,
     };
     };
   },
   },
   computed: {
   computed: {
@@ -85,38 +61,70 @@ export default {
         return "coder";
         return "coder";
       }
       }
     },
     },
+    title() {
+      if (this.type === "eval") {
+        return this.testVO.examName;
+      } else {
+        return this.testVO.name;
+      }
+    },
+    course() {
+      if (this.type === "eval") {
+        return "";
+      } else {
+        return "所属课程: " + this.testVO.course;
+      }
+    },
+    teacherName() {
+      if (this.type === "eval") {
+        return "教师: " + this.teacher.name;
+      } else {
+        return "教师: " + this.testVO.creator.username;
+      }
+    },
+    timePeriod() {
+      if (this.type === "eval") {
+        return "时间: " + this.testVO.startTime.substring(0, 16) + "至" + this.testVO.endTime.substring(0, 16);
+      } else {
+        return "时间: " + this.timestampToTime(this.testVO.startAt) + "至" + this.timestampToTime(this.testVO.endAt);
+      }
+    },
     state() {
     state() {
+      const now = new Date();
       if (this.type === "eval") {
       if (this.type === "eval") {
-        if (new Date(this.testVO.endTime) < new Date()) {
+        if (new Date(this.testVO.endTime) < now) {
           return "FINISHED";
           return "FINISHED";
-        } else if (new Date(this.testVO.startTime) > new Date()) {
+        } else if (new Date(this.testVO.startTime) > now) {
           return "NOT_STARTED";
           return "NOT_STARTED";
+        } else if (this.testVO.isJoined) {
+          return "RUNNING_IN";
         } else {
         } else {
-          return "RUNNING";
+          return "RUNNING_NOT";
         }
         }
       } else {
       } else {
         if (this.testVO.status === "CLOSED") {
         if (this.testVO.status === "CLOSED") {
           return "CLOSED";
           return "CLOSED";
-        } else if (this.testVO.startAt * 1000 > new Date()) {
+        } else if (this.testVO.startAt * 1000 > now) {
           return "NOT_STARTED";
           return "NOT_STARTED";
-        } else if (this.testVO.endAt * 1000 < new Date()) {
+        } else if (this.testVO.endAt * 1000 < now) {
           return "FINISHED";
           return "FINISHED";
+        } else if (this.testVO.joined) {
+          return "RUNNING_IN";
         } else {
         } else {
-          return "RUNNING";
+          return "RUNNING_NOT";
         }
         }
       }
       }
     },
     },
   },
   },
-  async mounted() {
+  async created() {
     if (this.type === "eval") {
     if (this.type === "eval") {
-      const res = await this.$apis.getUserAPI(this.testVO.creatorId);
-      this.teacher = res.data.data;
+      this.teacher = (await this.$apis.getUserAPI(this.testVO.creatorId)).data.data;
     } else {
     } else {
       const res = await this.$apis.getUserAPI(this.testVO.creator.id);
       const res = await this.$apis.getUserAPI(this.testVO.creator.id);
       if (res.data.code === 0) {
       if (res.data.code === 0) {
         this.teacher = res.data.data;
         this.teacher = res.data.data;
       } else {
       } else {
-        this.teacher = {name: this.testVO.creator.username};
+        this.teacher = { name: this.testVO.creator.username };
       }
       }
     }
     }
   },
   },

+ 190 - 40
src/views/TaskPage/TaskPage.vue

@@ -15,28 +15,47 @@
         :total="expiringTaskList.length"
         :total="expiringTaskList.length"
         @current-change="handleCurrentChange"
         @current-change="handleCurrentChange"
         layout="total, prev, pager, next"
         layout="total, prev, pager, next"
-        style="width: 200px; margin: 0 auto 0 auto"/>
+        style="width: 200px; margin: 10px auto 0 auto"/>
     </el-card>
     </el-card>
 
 
     <el-card>
     <el-card>
       <template #header>
       <template #header>
-          <span style="font-weight: bold; font-size: larger">
+        <div style="display: flex; justify-content: space-between; align-content: center">
+          <span style="font-weight: bold; font-size: larger;padding-top: 6px">
             我的任务
             我的任务
           </span>
           </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>
       </template>
       <div id="task-page-all-task-main">
       <div id="task-page-all-task-main">
-        <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 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>
       </div>
     </el-card>
     </el-card>
 
 
@@ -46,6 +65,83 @@
 <script>
 <script>
 import TestCard from "@/components/TestCard";
 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 {
 export default {
   name: "TaskPage",
   name: "TaskPage",
   components: { TestCard },
   components: { TestCard },
@@ -55,6 +151,8 @@ export default {
       myCoderExamList: [],
       myCoderExamList: [],
       expiringTask_currentPage: 1,
       expiringTask_currentPage: 1,
       activeTaskPaneName: "eval",
       activeTaskPaneName: "eval",
+      options: options,
+      selector: "ALL",
     };
     };
   },
   },
   computed: {
   computed: {
@@ -62,28 +160,75 @@ export default {
       return this.expiringTaskList.slice((this.expiringTask_currentPage - 1) * 4, this.expiringTask_currentPage * 4);
       return this.expiringTaskList.slice((this.expiringTask_currentPage - 1) * 4, this.expiringTask_currentPage * 4);
     },
     },
     expiringTaskList() {
     expiringTaskList() {
-      if (!this.myEvalExamList || !this.myCoderExamList) {
-        return [];
-      } else {
-        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 => {
-            return this.state(i) === "RUNNING";
-          });
+      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);
+      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 mounted() {
-    this.myEvalExamList = (await this.$apis.getAllEvalExams()).data.data["examVOList"];
-
-    this.$apis.getStudentCoderExams({}).then(res => {
-      this.myCoderExamList = res.data.data.res;
-    });
+  async created() {
+    this.myEvalExamList = (await this.$apis.getStudentEvalExams({ state: 0 })).data.data["examVOList"];
+    this.myCoderExamList = (await this.$apis.getStudentCoderExams({})).data.data["res"];
+    // this.myEvalExamList = (await this.$apis.getAllEvalExams()).data.data["examVOList"];
+    // this.myCoderExamList = (await this.$apis.getExampleCoderExams({})).data.data["res"];
   },
   },
 
 
   methods: {
   methods: {
@@ -91,23 +236,28 @@ export default {
       this.expiringTask_currentPage = index;
       this.expiringTask_currentPage = index;
     },
     },
     state(testVO) {
     state(testVO) {
-      if (testVO.examId) {
-        if (new Date(testVO.endTime) < new Date()) {
+      const now = new Date();
+      if (testVO.examId !== undefined) {
+        if (new Date(testVO.endTime) < now) {
           return "FINISHED";
           return "FINISHED";
-        } else if (new Date(testVO.startTime) > new Date()) {
+        } else if (new Date(testVO.startTime) > now) {
           return "NOT_STARTED";
           return "NOT_STARTED";
+        } else if (testVO.isJoined) {
+          return "RUNNING_IN";
         } else {
         } else {
-          return "RUNNING";
+          return "RUNNING_NOT";
         }
         }
       } else {
       } else {
         if (testVO.status === "CLOSED") {
         if (testVO.status === "CLOSED") {
           return "CLOSED";
           return "CLOSED";
-        } else if (testVO.startAt * 1000 > new Date()) {
+        } else if (testVO.startAt * 1000 > now) {
           return "NOT_STARTED";
           return "NOT_STARTED";
-        } else if (testVO.endAt * 1000 < new Date()) {
+        } else if (testVO.endAt * 1000 < now) {
           return "FINISHED";
           return "FINISHED";
+        } else if (testVO.joined) {
+          return "RUNNING_IN";
         } else {
         } else {
-          return "RUNNING";
+          return "RUNNING_NOT";
         }
         }
       }
       }
     },
     },

+ 2 - 8
vue.config.js

@@ -1,7 +1,4 @@
-// const { BundleAnalyzerPlugin } = require("webpack-bundle-analyzer");
-const SpeedMeasurePlugin = require("speed-measure-webpack-plugin");
 const WebpackBar = require("webpackbar");
 const WebpackBar = require("webpackbar");
-const smp = new SpeedMeasurePlugin();
 
 
 module.exports = {
 module.exports = {
   productionSourceMap: false,
   productionSourceMap: false,
@@ -22,14 +19,12 @@ module.exports = {
       },
       },
     },
     },
   },
   },
-  configureWebpack: smp.wrap({
+  configureWebpack: {
     devServer: {
     devServer: {
       proxy: {
       proxy: {
         "/api": {
         "/api": {
           // target: "https://p-server.seec.seecoder.cn/api",
           // target: "https://p-server.seec.seecoder.cn/api",
           target: "http://localhost:8080/api",
           target: "http://localhost:8080/api",
-          // secure: false,
-          // changeOrigin: true,
           pathRewrite: {
           pathRewrite: {
             "^/api": ""
             "^/api": ""
           }
           }
@@ -40,7 +35,6 @@ module.exports = {
     plugins: process.env.NODE_ENV === "development" ?
     plugins: process.env.NODE_ENV === "development" ?
       [
       [
         new WebpackBar(),
         new WebpackBar(),
-        // new BundleAnalyzerPlugin(),
       ] : []
       ] : []
-  }),
+  },
 };
 };

Dosya farkı çok büyük olduğundan ihmal edildi
+ 220 - 209
yarn.lock


Bu fark içinde çok fazla dosya değişikliği olduğu için bazı dosyalar gösterilmiyor