Damon 4 éve
szülő
commit
dc8aa26ef7

+ 9 - 0
src/api/user.js

@@ -26,6 +26,14 @@ function getUserAPI(data){
   });
 }
 
+function getNameByUsernameAPI(data) {
+  return axios.get(`${prefix}/findNameByUserName`, {
+    params: {
+      username: data,
+    }
+  });
+}
+
 function saveNameAPI(data) {
   return axios.post(`${prefix}/saveName`, data);
 }
@@ -47,6 +55,7 @@ const userAPIs = {
   saveNameAPI,
   saveEmailAPI,
   saveSignatureAPI,
+  getNameByUsernameAPI,
 };
 
 export default userAPIs;

+ 9 - 11
src/components/TestCard.vue

@@ -19,17 +19,16 @@
       </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_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==='RUNNING_IN' && !isPublicTest" size="small" type="success">已参加</el-tag>
+        <el-tag v-else-if="state==='RUNNING_NOT' && !isPublicTest" size="small">未参加</el-tag>
+        <el-tag v-else-if="isPublicTest" 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>
-    <!--    {{testVO}}-->
     <el-row class="course" v-if="course!==''">
       {{ course }}
     </el-row>
-
     <el-row class="teacher">
       {{ teacherName }}
     </el-row>
@@ -52,6 +51,10 @@ export default {
   name: "TestCard",
   props: {
     testVO: Object,
+    isPublicTest: {
+      type: Boolean,
+      default: false,
+    },
   },
   data() {
     return {
@@ -100,7 +103,7 @@ export default {
       if (this.type === "eval") {
         return "教师: " + this.teacher.name;
       } else {
-        return "教师: " + this.testVO.creator.username;
+        return "教师: " + this.teacher;
       }
     },
     timePeriod() {
@@ -141,12 +144,7 @@ export default {
     if (this.type === "eval") {
       this.teacher = (await this.$apis.getUserAPI(this.testVO.course["teacherId"])).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};
-      }
+      this.teacher = (await this.$apis.getNameByUsernameAPI(this.testVO.creator.username)).data.data;
     }
   },
   methods: {

+ 69 - 75
src/views/CoursePage/CourseDetail.vue

@@ -47,7 +47,7 @@
 
       <el-divider v-if="isCreator || isCourseSelected"/>
 
-      <el-card>
+      <el-card v-if="isCreator || isCourseSelected">
 
         <div v-if="isCreator || isCourseSelected" class="course-tabs">
           <el-radio-group v-model="tabName" size="large">
@@ -180,27 +180,54 @@
             ></FileEntry>
           </div>
           <div v-else-if="tabName==='comment'">
-            <el-input v-model="commentContent" placeholder="发表一条友善的评论">
-              <template #append>
-                <el-button type="primary" @click="createComment">发表评论</el-button>
-              </template>
-            </el-input>
+            <el-row>
+              <el-col :span="20">
+                <el-input v-model="commentContent" placeholder="发表一条友善的评论"/>
+              </el-col>
+              <el-col :span="4">
+                <el-button style="width: 100%" type="primary" @click="createComment" plain>发表评论</el-button>
+              </el-col>
+            </el-row>
             <el-divider/>
             <div class="comment">
-              <div v-for="message in commentTree" :key="message.id" class="comment-body">
+              <div v-for="comments in commentTree" :key="comments.id" class="comment-body">
                 <div class="comment-main">
-                  <el-row style="font-weight: bold; margin-bottom: 10px">
-                    <el-col>{{ message.messages[message.mainId].sender.name }}</el-col>
-                    <el-col>{{ message.messages[message.mainId].createdAt.substring(0, 16) }}</el-col>
+                  <el-row>
+                    <div
+                      style="color: white;background: #619dc9;border-radius: 50%;padding: 10px;width: 20px;height: 20px;display: flex;justify-content: center;align-items: center; margin: 10px 10px 0 0">
+                      <span style="color: white; font-weight: bold;font-size: 24px;">{{ comments.mainMessage.sender.name.substring(0, 1) }}</span>
+                    </div>
+                    <div>
+                      <el-row style="font-weight: bold;">
+                        {{ comments.mainMessage.sender.name }}
+                      </el-row>
+                      <el-row style="font-size: small; color: #6d6d6d; margin-bottom: 6px">
+                        {{ comments.mainMessage.createdAt.substring(0, 16).replace("T", " ") }}
+                      </el-row>
+                      <el-row>
+                        {{ comments.mainMessage.content }}
+                      </el-row>
+                    </div>
                   </el-row>
-                  <el-row>{{ message.messages[message.mainId].content }}</el-row>
                 </div>
-                <div v-for="(key,child) in message.messages" :key="'message'+key" class="comment-child">
-                  <el-row v-if="!child.targetType==='COURSE'" style="font-weight: bold; margin-bottom: 10px">
-                    {{ child.sender.name }}
-                  </el-row>
-                  <el-row v-if="!child.targetType==='COURSE'">
-                    @{{ message.messages[child.targetId].sender.name }}:{{ message.messages[child.targetId].content }}
+                <div v-for="child in comments.children" :key="child.id" class="comment-child">
+                  <el-row>
+                    <div
+                      style="color: white;background: #619dc9;border-radius: 50%;padding: 10px;width: 20px;height: 20px;display: flex;justify-content: center;align-items: center; margin: 10px 10px 0 0">
+                      <span style="color: white; font-weight: bold;font-size: 24px;">{{ child.sender.name.substring(0, 1) }}</span>
+                    </div>
+                    <div>
+                      <el-row style="font-weight: bold; margin-bottom: 6px">
+                        {{ child.sender.name }}
+                      </el-row>
+                      <el-row style="font-size: small; color: #6d6d6d; margin-bottom: 6px">
+                        {{ child.createdAt.substring(0, 16).replace("T", " ") }}
+                      </el-row>
+                      <el-row>
+                        <span style="color: black;">{{ child.targetId === null ? "" : `@${comments.children[child.targetId].sender.name}: ` }}</span>{{ child.content }}<span
+                        @click="handleReplyClick(child)" class="reply-button">回复</span>
+                      </el-row>
+                    </div>
                   </el-row>
                 </div>
                 <el-divider/>
@@ -240,7 +267,7 @@
 <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 {
@@ -296,11 +323,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,
@@ -349,7 +376,6 @@ export default {
     },
     imgUrl() {
       return this.courseInfo.imageUrl === null ? this.noImgUrl : this.courseInfo.imageUrl;
-      // + "?t=" + Date.now().valueOf();
     },
     courseTaskList() {
       if (!this.evalExamList || !this.coderExamList) {
@@ -441,8 +467,6 @@ export default {
           }
           window.open("https://coder.seec.seecoder.cn/exam/create/?id_token=" + this.$store.state.user.token);
           break;
-        default:
-          break;
       }
     },
     toTask(task) {
@@ -472,8 +496,6 @@ export default {
               url = type === "eval" ? evalUrl : coderUrl;
             }
             break;
-          default:
-            break;
         }
       } else {
         evalUrl = "https://eval.seec.seecoder.cn/teacher/exam/";
@@ -497,8 +519,7 @@ export default {
         .then(() => {
           this.announcementFormDialog = false;
           this.$refs.announceFormRef.resetFields();
-        })
-        .catch(err => console.log(err));
+        });
     },
     handlePublishAnnouncement() {
       const _this = this;
@@ -515,8 +536,7 @@ export default {
             } else {
               updateAnnouncement();
             }
-          })
-          .catch();
+          });
       } else {
         if (this.announcementForm.id === null) {
           createAnnouncement();
@@ -527,7 +547,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,
@@ -540,8 +560,7 @@ export default {
             _this.announcementFormDialog = false;
             _this.$refs.announceFormRef.resetFields();
             ElMessage.success("新建公告完成");
-          })
-          .catch();
+          });
       }
 
       function updateAnnouncement() {
@@ -562,8 +581,7 @@ export default {
             _this.announcementFormDialog = false;
             _this.$refs.announceFormRef.resetFields();
             ElMessage.success("修改公告完成");
-          })
-          .catch();
+          });
       }
     },
     beforeUpdateAnnouncement(item) {
@@ -585,11 +603,7 @@ export default {
           this.$apis.deleteAnnouncement(item.id)
             .then(() => {
               this.announcementList.splice(index, 1);
-            })
-            .catch();
-        })
-        .catch(action => {
-          console.log(action);
+            });
         });
     },
     announcementContent(item) {
@@ -621,7 +635,7 @@ export default {
         confirmButtonText: "立即选课",
         cancelButtonText: "我再想想",
       })
-        .then(({value}) => {
+        .then(({ value }) => {
           if (value !== this.courseInfo.invitationCode) {
             ElMessage.error("选课码错误");
           } else {
@@ -664,58 +678,35 @@ export default {
             .catch(err => {
               ElMessage.error("handleCancelCourse: " + err);
             });
-        })
-        .catch(() => {
         });
     },
     // tab页相关
-    switchTab(tabName) {
+    async switchTab(tabName) {
       switch (tabName) {
         case "task":
           if (this.isTeacher) {
             if (this.courseInfo.evalId !== null) {
-              this.$apis.getTeacherEvalExamsByCourseId(this.courseInfo.evalId)
-                .then(res => {
-                  this.evalExamList = res.data.data;
-                });
+              this.evalExamList = (await this.$apis.getTeacherEvalExamsByCourseId(this.courseInfo.evalId)).data.data;
             }
             if (this.courseInfo.coderId !== null) {
-              this.$apis.getTeacherCoderExamsByCourseId(this.courseInfo.coderId)
-                .then(res => {
-                  this.coderExamList = res.data.data;
-                });
+              this.coderExamList = (await this.$apis.getTeacherCoderExamsByCourseId(this.courseInfo.coderId)).data.data;
             }
           } else if (this.isStudent) {
             if (this.courseInfo.evalId !== null) {
-              this.$apis.getStudentEvalExamsByCourseId(this.courseInfo.evalId)
-                .then(res => {
-                  this.evalExamList = res.data.data;
-                });
+              this.evalExamList = (await this.$apis.getStudentEvalExamsByCourseId(this.courseInfo.evalId)).data.data;
             }
             if (this.courseInfo.coderId !== null) {
-              this.$apis.getStudentCoderExamsByCourseId(this.courseInfo.coderId)
-                .then(res => {
-                  this.coderExamList = res.data.data;
-                });
+              this.coderExamList = (await this.$apis.getStudentCoderExamsByCourseId(this.courseInfo.coderId)).data.data;
             }
           }
           break;
         case "notice":
-          this.$apis.getAnnouncementsByCourseId(this.$route.params.id)
-            .then(res => {
-              this.announcementList = res.data.data;
-            });
+          this.announcementList = (await this.$apis.getAnnouncementsByCourseId(this.$route.params.id)).data.data;
           break;
         case "courseware":
           break;
         case "comment":
-          this.$apis.getCommentsByCourseId(this.$route.params.id)
-            .then(res => {
-              this.commentTree = res.data.data;
-            })
-            .catch();
-          break;
-        default:
+          this.commentTree = (await this.$apis.getCommentsByCourseId(this.$route.params.id)).data.data;
           break;
       }
     },
@@ -736,12 +727,15 @@ export default {
           createdAt: new Date(),
         })
           .then(res => {
-            this.commentTree.push({mainMessage: res.data.data, children: []});
+            console.log(res);
+            this.commentTree.push({ mainMessage: res.data.data, children: [] });
             this.commentContent = "";
-          })
-          .catch();
+          });
       }
     },
+    handleReplyClick(target) {
+      alert(target);
+    },
   },
 };
 </script>

+ 4 - 4
src/views/CoursePage/CoursePage.vue

@@ -11,13 +11,13 @@
         </el-menu-item>
         <el-menu-item index="1">
           <el-icon>
-            <Document/>
+            <Folder/>
           </el-icon>
           <span style="padding-left: 20px">全部课程</span>
         </el-menu-item>
         <el-menu-item index="2">
           <el-icon>
-            <DocumentChecked/>
+            <FolderChecked/>
           </el-icon>
           <span style="padding-left: 20px">我的课程</span>
         </el-menu-item>
@@ -50,12 +50,12 @@
 </template>
 
 <script>
-import { Back, Document, DocumentChecked } from "@element-plus/icons-vue";
+import { Back, Folder, FolderChecked } from "@element-plus/icons-vue";
 import CourseCard from "@/components/CourseCard";
 
 export default {
   name: "CoursePage",
-  components: { Back, CourseCard, Document, DocumentChecked },
+  components: { FolderChecked, Folder, Back, CourseCard },
   data() {
     return {
       activeIndex: "1",

+ 12 - 7
src/views/CoursePage/style/CourseDetail.css

@@ -179,7 +179,6 @@
 
 }
 
-
 .new-notice-btn {
     display: flex;
     justify-content: center;
@@ -242,16 +241,21 @@
     margin: 30px 0 0 30px;
 }
 
-.comment-body {
-
+.comment-child {
+    padding: 20px 0 0 30px;
 }
 
-.comment-main {
-
+.reply-button {
+    padding: 2px;
+    border-radius: 4px;
+    margin-left: 20px;
+    font-size: small;
+    cursor: pointer;
+    color: #808080;
 }
 
-.comment-child {
-    padding: 20px 0 0 20px;
+.reply-button:hover {
+    background: #a5d1ff;
 }
 
 .announcement-content {
@@ -261,6 +265,7 @@
 .el-timeline-item {
     padding-top: 10px;
     padding-bottom: 10px;
+    padding-left: 200px;
     cursor: pointer;
 }
 

+ 32 - 11
src/views/PortalPage/PortalPage.vue

@@ -65,9 +65,15 @@
           <ElButton plain round type="primary" @click="toCourse">查看全部课程</ElButton>
         </div>
         <el-divider class="portal-card-divider"/>
-        <div class="portal-card-content">
+        <div class="portal-card-content" v-if="showExampleCourseList.length !== 0">
           <CourseCard v-for="item in showExampleCourseList" :key="item.id" :courseVO="item"/>
         </div>
+        <div v-else :style="{marginTop: (this.courseRowHeight / 2 - 100) + 'px'}" style="margin-left: calc(50% - 36px)">
+          <el-icon :size="72" color="#bfbfbf">
+            <FolderOpened/>
+          </el-icon>
+          <div class="tip">暂无数据~</div>
+        </div>
       </el-card>
     </div>
 
@@ -127,15 +133,27 @@
           <ElButton plain round type="primary" @click="toTest">查看全部测试</ElButton>
         </div>
         <el-divider class="portal-card-divider"/>
-        <el-tabs v-model="activeTestPaneName" @tab-click="changeTestPane" style="min-height: 300px;">
+        <el-tabs v-model="activeTestPaneName" @tab-click="changeTestPane" style="min-height: 400px;">
           <el-tab-pane label="评测题" name="eval">
-            <div class="portal-card-content">
-              <TestCard v-for="item in showExampleEvalTestList" :key="item.id" :testVO="item"/>
+            <div class="portal-card-content" v-if="showExampleEvalTestList.length !== 0">
+              <TestCard v-for="item in showExampleEvalTestList" :key="item.id" :testVO="item" :isPublicTest="true"/>
+            </div>
+            <div v-else style="margin: 100px 0 0 calc(50% - 36px);">
+              <el-icon :size="72" color="#bfbfbf">
+                <FolderOpened/>
+              </el-icon>
+              <div class="tip">暂无数据~</div>
             </div>
           </el-tab-pane>
           <el-tab-pane label="代码题" name="coder">
-            <div class="portal-card-content">
-              <TestCard v-for="item in showExampleCoderTestList" :key="item.id" :testVO="item"/>
+            <div class="portal-card-content" v-if="showExampleCoderTestList.length !== 0">
+              <TestCard v-for="item in showExampleCoderTestList" :key="item.id" :testVO="item" :isPublicTest="true"/>
+            </div>
+            <div v-else style="margin: 100px 0 0 calc(50% - 36px);">
+              <el-icon :size="72" color="#bfbfbf">
+                <FolderOpened/>
+              </el-icon>
+              <div class="tip">暂无数据~</div>
             </div>
           </el-tab-pane>
         </el-tabs>
@@ -149,13 +167,14 @@ import CarouselCard from "@/views/PortalPage/components/CarouselCard";
 import CourseCard from "@/components/CourseCard";
 import MyCourseCard from "@/views/PortalPage/components/MyCourseCard";
 import MyTestCard from "@/views/PortalPage/components/MyTestCard";
-import { Lock, SetUp, ShoppingCart } from "@element-plus/icons-vue";
+import { FolderOpened, Lock, SetUp, ShoppingCart } from "@element-plus/icons-vue";
 import TestCard from "@/components/TestCard";
 
 export default {
   //数据
   name: "PortalPage",
   components: {
+    FolderOpened,
     TestCard,
     SetUp,
     ShoppingCart,
@@ -222,13 +241,13 @@ export default {
     const that = this;
 
     this.exampleCourseList = (await this.$apis.getExampleCourses()).data.data;
-    this.exampleEvalTestList = (await this.$apis.getRecommendEvalExams()).data.data.filter(i => this.state(i) === "RUNNING");
-    this.exampleCoderTestList = (await this.$apis.getRecommendCoderExams({})).data.data.filter(i => this.state(i) === "RUNNING");
+    this.exampleEvalTestList = (await this.$apis.getRecommendEvalExams()).data.data;
+    this.exampleCoderTestList = (await this.$apis.getRecommendCoderExams({})).data.data;
 
     if (this.isLogin && this.isStudent) {
       this.myCourseList = (await this.$apis.getStudentCourses()).data.data;
       this.myEvalExamList = (await this.$apis.getStudentEvalExams()).data.data.filter(i => this.state(i) === "RUNNING");
-      this.myCoderExamList = (await this.$apis.getStudentCoderExams({})).data.data.res;
+      this.myCoderExamList = (await this.$apis.getStudentCoderExams({})).data.data.res.filter(i => this.state(i) === "RUNNING");
     }
 
     await this.$nextTick(() => that.handleResize());
@@ -255,7 +274,9 @@ export default {
         this.courseRowHeight = 640;
         this.isExpanding = true;
       }
-      this.testRowHeight = Math.max(this.$refs.portalTestCardBodyMain.$el.clientHeight, 300);
+      if (this.$refs.portalTestCardBodyMain) {
+        this.testRowHeight = Math.max(this.$refs.portalTestCardBodyMain.$el.clientHeight, 300);
+      }
     },
     changeTestPane() {
       const that = this;

+ 3 - 8
src/views/PortalPage/components/MyTestCard.vue

@@ -50,7 +50,7 @@ export default {
   },
   data() {
     return {
-      teacher: Object,
+      teacher: "Loading...",
     };
   },
   computed: {
@@ -79,7 +79,7 @@ export default {
       if (this.type === "eval") {
         return "教师: " + this.teacher.name;
       } else {
-        return "教师: " + this.testVO.creator.username;
+        return "教师: " + this.teacher;
       }
     },
     timePeriod() {
@@ -120,12 +120,7 @@ export default {
     if (this.type === "eval") {
       this.teacher = (await this.$apis.getUserAPI(this.testVO.creatorId)).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 };
-      }
+      this.teacher = (await this.$apis.getNameByUsernameAPI(this.testVO.creator.username)).data.data;
     }
   },
   methods: {

+ 0 - 1
src/views/TestPage/TestPage.vue

@@ -12,7 +12,6 @@
         <el-menu-item index="1">
           <el-icon>
             <Document/>
-            <!--            todo 图标更改,数据要改-->
           </el-icon>
           <span style="padding-left: 20px">公开测试</span>
         </el-menu-item>