Damon 4 lat temu
rodzic
commit
cbe6af78be

+ 1 - 6
src/App.vue

@@ -1,5 +1,5 @@
 <template>
-  <GlobalHeader v-if="this.$route.path!=='/auth'" ref="globalHeader"/>
+  <GlobalHeader v-if="this.$route.path!=='/auth'"/>
   <router-view/>
   <GlobalFooter v-if="this.$route.path!=='/auth'"/>
 </template>
@@ -23,10 +23,5 @@ export default {
       return null;
     };
   },
-  watch:{
-    $route(to, from){
-      this.$refs.globalHeader.fetchMessages();
-    }
-  },
 };
 </script>

+ 7 - 2
src/components/GlobalHeader.vue

@@ -24,7 +24,7 @@
         个人中心
       </el-menu-item>
       <el-menu-item v-if="isTeacher" index="5">
-        教师[临]
+        教师管理
       </el-menu-item>
       <el-menu-item index="6">
         问题[临]
@@ -122,10 +122,15 @@ export default {
   },
 
   watch: {
-    isLogin(newData, oldData) {
+    isLogin(newData) {
       if (newData) {
         this.fetchMessages();
       }
+    },
+    $route() {
+      if (this.isLogin) {
+        this.fetchMessages();
+      }
     }
   },
 

+ 6 - 3
src/router/index.js

@@ -1,6 +1,6 @@
-import {createRouter, createWebHistory} from "vue-router";
+import { createRouter, createWebHistory } from "vue-router";
 import store from "@/store";
-import {ElMessage} from "element-plus";
+import { ElMessage } from "element-plus";
 import PortalPage from "@/views/PortalPage/PortalPage";
 
 const routes = [
@@ -88,7 +88,7 @@ router.beforeEach((to, from, next) => {
       type: "warning",
       duration: 1000,
     });
-    next({name: "Auth", params: {login_to: to.path}});
+    next({ name: "Auth", params: { login_to: to.path } });
   } else {
     if (to.name === "Manage" && !store.getters.isTeacher) {
       ElMessage({
@@ -110,4 +110,7 @@ router.beforeEach((to, from, next) => {
   }
 });
 
+router.afterEach(() => {
+  window.scrollTo(0, 0);
+});
 export default router;

+ 23 - 18
src/views/CoursePage/CourseDetail.vue

@@ -162,7 +162,7 @@
                               :notice-v-o="item" @update="beforeUpdateAnnouncement(item)"
                               @delete="deleteAnnouncement(item, index)"/>
                 </template>
-                <span class="announcement-content">{{ announcementContent(item) }}</span>
+                <div class="announcement-content">{{ announcementContent(item) }}</div>
               </el-collapse-item>
             </el-collapse>
           </div>
@@ -207,7 +207,7 @@
                         {{ comments.mainMessage.createdAt.substring(0, 16).replace("T", " ") }}
                       </el-row>
                       <el-row>
-                        {{ comments.mainMessage.content }}<span @click="handleReplyClick(comments.mainMessage)"
+                        {{ comments.mainMessage.content }}<span @click="handleReplyClick(comments.mainMessage, index)"
                                                                 class="reply-button">回复</span>
                       </el-row>
                     </div>
@@ -267,22 +267,19 @@
         <el-button plain type="danger" @click="beforeFormClose">我再想想</el-button>
       </div>
     </el-dialog>
-    <!--    <el-dialog v-model="announcementDialog"-->
   </div>
 </template>
 
 <script>
 import NoticeItem from "./components/NoticeItem";
 import FileEntry from "./components/FileEntry";
-import {ElMessageBox, ElMessage} from "element-plus";
+import { ElMessageBox, ElMessage } from "element-plus";
 import variables from "@/utils/variables";
 
 export default {
   name: "CourseDetail",
   components: {
-    // eslint-disable-next-line vue/no-unused-components
     NoticeItem,
-    // eslint-disable-next-line vue/no-unused-components
     FileEntry,
   },
   data() {
@@ -330,11 +327,11 @@ export default {
         color: "",
       },
       noticeTypeMap: {
-        announce: {type: "公告", title: "发布公告", color: themeColor.orange},
-        homework: {type: "作业", title: "发布作业", color: themeColor.blue},
-        exam: {type: "考试", title: "发布考试", color: themeColor.red},
+        announce: { type: "公告", title: "发布公告", color: themeColor.orange },
+        homework: { type: "作业", title: "发布作业", color: themeColor.blue },
+        exam: { type: "考试", title: "发布考试", color: themeColor.red },
       },
-      newNoticeInfo: {noticeDescription: "", priority: "1", fileList: []},
+      newNoticeInfo: { noticeDescription: "", priority: "1", fileList: [] },
       postNoticeInfo: {},
       fileEntryList: [{
         id: 1,
@@ -554,7 +551,7 @@ export default {
 
       function createAnnouncement() {
         let announcementVO = {
-          sender: {id: _this.$store.state.user.id,},
+          sender: { id: _this.$store.state.user.id, },
           courseId: _this.courseInfo.id,
           title: _this.announcementForm.title,
           content: _this.announcementForm.content,
@@ -623,7 +620,7 @@ export default {
     readAnnouncement(item) {
       if (!item.read) {
         this.$apis.readAnnouncement(item.id)
-          .then(res => {
+          .then(() => {
             item.read = true;
             this.$refs["noticeItem" + item.id][0].setNoticeInfo(item);
           });
@@ -642,7 +639,7 @@ export default {
         confirmButtonText: "立即选课",
         cancelButtonText: "我再想想",
       })
-        .then(({value}) => {
+        .then(({ value }) => {
           if (value !== this.courseInfo.invitationCode) {
             ElMessage.error("选课码错误");
           } else {
@@ -676,7 +673,7 @@ export default {
               userId: this.$store.state.user.id,
             }
           )
-            .then(res => {
+            .then(() => {
               ElMessage.success("退课成功");
               setTimeout(function () {
                 location.reload();
@@ -734,17 +731,20 @@ export default {
           createdAt: new Date(),
         })
           .then(res => {
-            this.commentTree.push({mainMessage: res.data.data, children: []});
+            const msg = res.data.data;
+            msg.createdAt = this.timestampToTime(msg.createdAt);
+            this.commentTree.push({ mainMessage: msg, children: {} });
             this.commentContent = "";
+            ElMessage.success("发送成功");
           });
       }
     },
     handleReplyClick(target, index) {
       ElMessageBox.prompt("请输入评论内容", "回复", {
-        confirmButtonText: "OK",
-        cancelButtonText: "Cancel",
+        confirmButtonText: "发送",
+        cancelButtonText: "取消",
       })
-        .then(({value}) => {
+        .then(({ value }) => {
           if (value === "") {
             ElMessage.error("无法发表空评论");
           } else {
@@ -761,8 +761,13 @@ export default {
             })
               .then(res => {
                 const msg = res.data.data;
+                msg.createdAt = this.timestampToTime(msg.createdAt);
+                if (msg.targetId === this.commentTree[index].mainMessage.id) {
+                  msg.targetId = null;
+                }
                 this.commentTree[index].children[msg.id] = msg;
                 this.commentContent = "";
+                ElMessage.success("发送成功");
               });
           }
         });

+ 1 - 2
src/views/CoursePage/CoursePage.vue

@@ -37,10 +37,9 @@
         <div v-if="this.activeIndex === '2' && isStudent" class="course-page-main">
           <CourseCard v-for="course in courses_my" :key="course.id" :courseVO="course"/>
         </div>
-        <!--todo-->
         <div v-if="this.activeIndex === '2' && isTeacher">
           教师请前往
-          <span style="cursor: pointer;color: red"
+          <span style="cursor: pointer;color: #409eff"
                 @click="$router.push('/manage')">管理页面</span>
           查看相关课程。
         </div>

+ 1 - 4
src/views/CoursePage/components/NoticeItem.vue

@@ -97,6 +97,7 @@ export default {
 
 <style scoped>
 .notice-item {
+  border-radius: 6px;
   width: 100%;
   display: flex;
   justify-content: space-between;
@@ -147,10 +148,6 @@ export default {
   margin-left: 16px;
 }
 
-.el-button--text {
-  font-weight: 8;
-}
-
 .update-button {
   color: rgb(238, 190, 119);
 }

+ 5 - 1
src/views/CoursePage/style/CourseDetail.css

@@ -82,6 +82,9 @@
     font-size: 14px;
     line-height: 26px;
     color: #333333;
+    padding: 10px 0 10px 20px;
+    border-radius: 10px;
+    background: #f6f6f6;
 }
 
 .title {
@@ -260,12 +263,13 @@
 
 .announcement-content {
     font-size: 16px;
+    padding: 10px 0 0 20px;
 }
 
 .el-timeline-item {
     padding-top: 10px;
     padding-bottom: 10px;
-    border-radius: 10px;
+    border-radius: 6px;
     cursor: pointer;
 }
 

+ 20 - 19
src/views/ManagePage/ManagePage.vue

@@ -47,11 +47,8 @@
             </div>
           </div>
         </template>
-        <div class="course-card-list-container mt-16">
-          <div v-for="(item,index) in myCourseList" :key="index" class="cItem">
-            <CourseCard :ref="'courseCard'+item.id" :courseVO="item" @delete="deleteCourse(item)"
-                        @update="beforeUpdateCourse(item)"></CourseCard>
-          </div>
+        <div class="course-card-list-container">
+          <CourseCard v-for="(item,index) in myCourseList" :key="index" :ref="'courseCard'+item.id" :courseVO="item" @delete="deleteCourse(item)" @update="beforeUpdateCourse(item)"/>
         </div>
       </el-card>
 
@@ -78,7 +75,9 @@
         <el-tabs v-model="activeTestPaneName">
           <el-tab-pane label="评测题" name="eval">
             <div v-for="(item, key) in evalExamList" :key="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>
@@ -86,7 +85,9 @@
           </el-tab-pane>
           <el-tab-pane label="代码题" name="coder">
             <div v-for="(item, key) in coderExamList" :key="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>
@@ -175,9 +176,9 @@
 
 <script>
 import CourseCard from "@/components/CourseCard";
-import {ElMessage, ElMessageBox} from "element-plus";
+import { ElMessage, ElMessageBox } from "element-plus";
 import client from "@/utils/oss";
-import {Back, Document} from "@element-plus/icons-vue";
+import { Back, Document } from "@element-plus/icons-vue";
 import TestCard from "@/components/TestCard";
 
 export default {
@@ -277,19 +278,19 @@ export default {
       myCourseList: [],
       courseType: "all",
       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: [],
       coderExamList: [],
       examType: "all",
       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: "已结束" },
       ],
     };
   },
@@ -311,10 +312,10 @@ export default {
         this.$router.push("portal");
       }
       if (index === "1") {
-        document.getElementById("app").scrollIntoView({behavior: "smooth"});
+        document.getElementById("app").scrollIntoView({ behavior: "smooth" });
       }
       if (index === "2") {
-        document.querySelector("#manage-page-divider").scrollIntoView({behavior: "smooth"});
+        document.querySelector("#manage-page-divider").scrollIntoView({ behavior: "smooth" });
       }
       this.activeIndex = index;
     },

+ 3 - 1
src/views/ManagePage/managePage.css

@@ -20,7 +20,9 @@
 }
 
 .course-card-list-container {
-
+    display: grid;
+    grid-template-columns: 1fr 1fr 1fr 1fr;
+    grid-gap: 10px;
 }
 
 .ml-16 {

+ 41 - 7
src/views/MessagePage/MessagePage.vue

@@ -29,30 +29,46 @@
           <span style="font-weight: bold; font-size: larger">
             {{ title }}
           </span>
+          <span v-if="activeIndex==='2' && myUnReadMessage.length === 0" style="margin-left: 20px">
+            当前显示 {{ (messageDayPeriod + 1) * 3 }} 天内的未读消息,<span @click="handleReadMoreMessage" class="read-more">点击查看更多</span>
+          </span>
         </template>
-        <div v-if="this.activeIndex==='1'" class="message-page-main">
+        <div v-if="activeIndex==='1' && myUnReadAnnouncement.length !== 0" class="message-page-main">
           <MessageCard v-for="i in myUnReadAnnouncement" :key="i.id" :messageVO="i"/>
         </div>
-        <div v-else class="message-page-main">
+        <div v-else-if="activeIndex==='1' && myUnReadAnnouncement.length === 0" style="margin: 100px 0 0 calc(50% - 36px); min-height: 300px">
+          <el-icon :size="72" color="#bfbfbf">
+            <ChatSquare/>
+          </el-icon>
+          <div class="tip">暂无新通知~</div>
+        </div>
+        <div v-else-if="activeIndex==='2' && myUnReadMessage.length !== 0" class="message-page-main">
           <MessageCard v-for="i in myUnReadMessage" :key="i.id" :messageVO="i"/>
         </div>
+        <div v-else-if="activeIndex==='2' && myUnReadMessage.length === 0" style="margin: 100px 0 0 calc(50% - 36px); min-height: 300px">
+          <el-icon :size="72" color="#bfbfbf">
+            <ChatSquare/>
+          </el-icon>
+          <div class="tip">暂无新消息~</div>
+        </div>
       </el-card>
     </el-col>
   </el-row>
 </template>
 
 <script>
-import { Back, Bell, ChatDotRound } from "@element-plus/icons-vue";
+import { Back, Bell, ChatDotRound, ChatSquare } from "@element-plus/icons-vue";
 import MessageCard from "@/views/MessagePage/components/MessageCard";
 
 export default {
   name: "MessagePage",
-  components: { MessageCard, ChatDotRound, Bell, Back },
+  components: { ChatSquare, MessageCard, ChatDotRound, Bell, Back },
   data() {
     return {
       activeIndex: "1",
       myUnReadAnnouncement: [],
       myUnReadMessage: [],
+      messageDayPeriod: 0,
     };
   },
   computed: {
@@ -62,9 +78,7 @@ export default {
   },
   async created() {
     this.myUnReadAnnouncement = (await this.$apis.getUnreadAnnouncements()).data.data;
-    this.myUnReadMessage = (await this.$apis.getUnreadMessages()).data.data;
-    // todo
-    // document.querySelector(".message-page-main").scrollIntoView({ behavior: "smooth" });
+    this.myUnReadMessage = (await this.$apis.getUnreadMessages(this.messageDayPeriod)).data.data;
   },
   methods: {
     handleSelect(index) {
@@ -73,6 +87,10 @@ export default {
         this.$router.push("portal");
       }
     },
+    async handleReadMoreMessage() {
+      this.messageDayPeriod += 1;
+      this.myUnReadMessage = (await this.$apis.getUnreadMessages(this.messageDayPeriod)).data.data;
+    },
   },
 };
 </script>
@@ -88,4 +106,20 @@ export default {
   grid-template-columns: 1fr;
   grid-gap: 10px;
 }
+
+.tip {
+  font-size: small;
+  font-weight: bold;
+  color: #666666;
+}
+
+.read-more {
+  color: #868686;
+  cursor: pointer;
+}
+
+.read-more:hover {
+  text-decoration: underline;
+  color: #409eff;
+}
 </style>

+ 1 - 1
src/views/MessagePage/components/MessageCard.vue

@@ -101,7 +101,7 @@ export default {
 <style scoped>
 .body {
   height: 70px;
-  border: 1px solid #cccccc;
+  border: 1px solid #e8e8e8;
   border-radius: 10px;
   padding: 5px;
 }

+ 16 - 9
src/views/TestPage/TestPage.vue

@@ -35,7 +35,9 @@
           <el-tabs v-model="activeTestPaneName" style="width: 100%">
             <el-tab-pane label="评测题" name="eval">
               <div v-for="(item, key) in evalExamList" :key="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>
@@ -43,7 +45,9 @@
             </el-tab-pane>
             <el-tab-pane label="代码题" name="coder">
               <div v-for="(item, key) in coderExamList" :key="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>
@@ -56,7 +60,9 @@
           <el-tabs v-model="activeTestPaneName_my" style="width: 100%">
             <el-tab-pane label="评测题" name="eval">
               <div v-for="(item, key) in evalExamList_my" :key="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>
@@ -64,7 +70,9 @@
             </el-tab-pane>
             <el-tab-pane label="代码题" name="coder">
               <div v-for="(item, key) in coderExamList_my" :key="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>
@@ -73,10 +81,9 @@
           </el-tabs>
         </div>
 
-        <!--todo-->
         <div v-if="this.activeIndex === '2' && isTeacher">
           教师请前往
-          <span style="cursor: pointer;color: red"
+          <span style="cursor: pointer;color: #409eff"
                 @click="$router.push('/manage')">管理页面</span>
           查看相关测试。
         </div>
@@ -86,12 +93,12 @@
 </template>
 
 <script>
-import {Back, Document, DocumentChecked} from "@element-plus/icons-vue";
+import { Back, Document, DocumentChecked } from "@element-plus/icons-vue";
 import TestCard from "@/components/TestCard";
 
 export default {
   name: "TestPage",
-  components: {TestCard, Back, Document, DocumentChecked,},
+  components: { TestCard, Back, Document, DocumentChecked, },
   data() {
     return {
       activeIndex: "1",
@@ -122,7 +129,7 @@ export default {
     this.$apis.getRecommendEvalExamsGroupByCourse().then(res => {
       this.evalExamList = res.data.data;
     });
-    this.$apis.getRecommendCoderExamsGroupByCourse().then(res=>{
+    this.$apis.getRecommendCoderExamsGroupByCourse().then(res => {
       this.coderExamList = res.data.data;
     });
     if (this.isStudent) {