Explorar o código

feat: 学生主页修改,添加评论逻辑、评论真实数据样式

ChenYangfan %!s(int64=6) %!d(string=hai) anos
pai
achega
0053ce9437

+ 16 - 0
src/App.vue

@@ -10,6 +10,11 @@ import GlobalMessage from '@/components/GlobalMessage'
 
 export default {
   components: { GlobalMessage },
+  data () {
+    return {
+      userInfo: {}
+    }
+  },
   created () {
     // 在页面加载时读取sessionStorage里的状态信息
     if (sessionStorage.getItem('store')) {
@@ -20,6 +25,17 @@ export default {
     window.addEventListener('beforeunload', () => {
       sessionStorage.setItem('store', JSON.stringify(this.$store.state))
     })
+
+    // getUserInfo().then(res => {
+    //   this.userInfo = res
+    //   this.$router.beforeEach((to, from, next) => {
+    //     if (to.meta.roles && to.meta.roles.includes(this.userInfo.type.toLowerCase())) {
+    //       next()
+    //     } else {
+    //       next({ path: '/login' })
+    //     }
+    //   })
+    // })
   }
 }
 </script>

+ 23 - 14
src/components/CComment.vue

@@ -1,15 +1,29 @@
 <template>
   <div class="comment">
-    <div class="comment-title">评论主题史蒂夫</div>
-    <div class="comment-content">帖子主要内容史蒂夫史蒂夫,将撒东方是否史蒂夫和空间上的恢复健康啊史蒂夫金黄色即可的粉红色</div>
-    <div class="comment-author">作者:陈某某 <span class="role">学生</span></div>
-    <div class="comment-time">2020 年 2 月 3 日</div>
-    <div class="comment-reply">教师回复:是的发送的史蒂夫史蒂夫,发送绝代风华卡史蒂夫是的,规范化建设个地方。</div>
+    <div class="comment-title">主题:{{comment.title}}</div>
+    <div class="comment-content">详情:{{comment.content}}</div>
+    <div class="comment-author">{{createTime}} | 作者:{{comment.userName}} <span class="role">{{role}}</span></div>
+    <div v-if="comment.reply" class="comment-reply">教师回复:{{comment.reply}}</div>
   </div>
 </template>
 
 <script>
-export default {}
+export default {
+  props: ['comment'],
+  computed: {
+    createTime () {
+      return this.$moment(this.comment.createAt).fromNow()
+    },
+    role () {
+      if (this.comment.userType === 'TEACHER') {
+        return '教师'
+      } else if (this.comment.userType === 'STUDENT') {
+        return '学生'
+      }
+      return '身份未知'
+    }
+  }
+}
 </script>
 
 <style lang="scss" scoped>
@@ -17,7 +31,7 @@ export default {}
 
 .comment {
   width: 100%;
-  margin: 32px 0;
+  padding: 16px 0 24px 0;
   font-weight: bold;
 }
 
@@ -28,12 +42,13 @@ export default {}
 .comment-content {
   color: #6a7a8a;
   font-size: 14px;
-  margin-bottom: 12px;
+  margin-bottom: 8px;
 }
 
 .comment-author {
   font-size: 14px;
   color: #7a8a9a;
+  margin-bottom: 4px;
   .role {
     display: inline-block;
     padding: 1px 4px;
@@ -43,12 +58,6 @@ export default {}
   }
 }
 
-.comment-time {
-  color: #8a9aaa;
-  font-size: 14px;
-  margin-bottom: 8px;
-}
-
 .comment-reply {
   font-size: 14px;
   padding: 4px 8px;

+ 1 - 0
src/components/CInput.vue

@@ -35,6 +35,7 @@ export default {
 </script>
 <style lang="scss" scoped>
 @import '~@/style/theme.scss';
+
 input, textarea {
   box-sizing: border-box;
   font-size: 16px;

+ 56 - 9
src/components/DiscussionArea.vue

@@ -1,24 +1,71 @@
 <template>
   <div class="discussion-area">
     <h1 class="title">讨论 & 问答</h1>
-    <discussion-type-bar></discussion-type-bar>
+    <!--    <discussion-type-bar></discussion-type-bar>-->
+    <write-new-comment @comment-submit="handleCommentSubmit" :placeholder="writingAreaPlaceholder"></write-new-comment>
     <div class="discussion-area-content">
-      <c-comment></c-comment>
-      <c-comment></c-comment>
-      <c-comment></c-comment>
-      <c-comment></c-comment>
-      <c-comment></c-comment>
-      <c-comment></c-comment>
+      <div class="sub-title mb-8">本页讨论区</div>
+      <template v-for="comment of comments">
+        <c-comment :key="comment.id" :comment="comment"
+                     :clickHandler="null">
+        </c-comment>
+      </template>
     </div>
   </div>
 </template>
 
 <script>
 import CComment from '@/components/CComment'
-import DiscussionTypeBar from '@/components/DiscussionTypeBar'
+import WriteNewComment from '@/components/WriteNewComment'
+import { mapState } from 'vuex'
+import { createComment, getComments } from '@/server/comment'
 
 export default {
-  components: { DiscussionTypeBar, CComment }
+  components: { WriteNewComment, CComment },
+  data () {
+    return {
+      comments: null
+    }
+  },
+  mounted () {
+    if (!this.userInfo) {
+      this.$setInfoMessage('需要登录本系统才可以浏览课程内容')
+      this.$router.push('login')
+    }
+    this.updateComments()
+  },
+  computed: {
+    ...mapState({
+      userInfo: state => state.main.userInfo,
+      currentPage: state => state.pdf.currentPage,
+      slide: state => state.pdf.slideInfo
+    }),
+    writingAreaPlaceholder () {
+      // if (this.userInfo.type === 'TEACHER') {
+      return '写下针对本页的讨论(标题)'
+      // } else {
+      // }
+    }
+  },
+  methods: {
+    updateComments () {
+      getComments({ slideId: this.slide.id, pageNumber: this.currentPage }).then(res => {
+        this.comments = res.data
+      }).catch(err => {
+        this.$setErrorMessage('获取本页评论区的过程中:' + err.response.data.msg)
+      })
+    },
+    handleCommentSubmit (comment) {
+      createComment({
+        slideId: this.slide.id,
+        pageNumber: this.currentPage,
+        title: comment.title,
+        content: comment.content
+      }).then(res => {
+        this.$setSuccessMessage('您的讨论帖发表成功')
+      })
+    }
+  }
 }
 </script>
 

+ 38 - 0
src/components/WriteNewComment.vue

@@ -0,0 +1,38 @@
+<template>
+  <div class="write-new-comment">
+    <c-input class="mb-12" v-model="title"
+             :placeholder="placeholder || '讨论主题'" maxlength="40"/>
+    <c-input class="mb-12" textarea="true" v-model="content" placeholder="在此填写详细内容"/>
+    <c-button :disabled="!(title && content)" class="secondary full-width mb-24" @click="handleSubmitComment">提交</c-button>
+  </div>
+</template>
+
+<script>
+import CInput from '@/components/CInput'
+import CButton from '@/components/CButton'
+
+export default {
+  props: ['placeholder'],
+  components: { CButton, CInput },
+  data () {
+    return {
+      title: '',
+      content: ''
+    }
+  },
+  methods: {
+    handleSubmitComment () {
+      if (!(this.title && this.content)) {
+        this.$setInfoMessage('主题和内容均需要填写')
+        return
+      }
+
+      this.$emit('comment-submit', { title: this.title, content: this.content })
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+
+</style>

+ 5 - 4
src/router/index.js

@@ -12,27 +12,27 @@ const routes = [{
   path: '/login',
   name: 'login',
   component: () => import('../views/login/Login.vue')
-}, {
-  path: '/api-test',
-  name: 'api-test',
-  component: () => import('../views/api-test/ApiTest.vue')
 }, {
   path: '/register',
   name: 'register',
   component: () => import('../views/register/Register.vue')
 }, {
+  meta: { roles: ['teacher'] },
   path: '/pdf-reader',
   name: 'pdf-reader',
   component: () => import('../views/reader/PdfReader.vue')
 }, {
+  meta: { roles: ['teacher'] },
   path: '/quiz-setting/:slideId',
   name: 'teacher-quiz-setting',
   component: () => import('../views/quiz/TeacherQuizSetting.vue')
 }, {
+  meta: { roles: ['student'] },
   path: '/quiz/:slideId',
   name: 'quiz',
   component: () => import('../views/quiz/QuizView.vue')
 }, {
+  meta: { roles: ['teacher'] },
   path: '/teacher',
   name: 'teacher',
   redirect: '/teacher/explore',
@@ -77,6 +77,7 @@ const routes = [{
     component: () => import('../views/teacher/tabs/TeacherPersonal.vue')
   }]
 }, {
+  meta: { roles: ['student'] },
   path: '/student',
   name: 'student',
   redirect: '/student/explore',

+ 9 - 2
src/store/modules/main.js

@@ -1,8 +1,9 @@
-import { RESET_COURSE, SET_COURSE } from '@/store/types/main-types'
+import { RESET_COURSE, RESET_USER_INFO, SET_COURSE, SET_USER_INFO } from '@/store/types/main-types'
 
 export default {
   state: {
-    courseInfo: {}
+    courseInfo: {},
+    userInfo: {}
   },
 
   mutations: {
@@ -11,6 +12,12 @@ export default {
     },
     [RESET_COURSE] (state) {
       state.courseInfo = {}
+    },
+    [SET_USER_INFO] (state, payload) {
+      state.userInfo = payload.userInfo
+    },
+    [RESET_USER_INFO] (state) {
+      state.userInfo = {}
     }
   }
 }

+ 3 - 0
src/store/types/main-types.js

@@ -1,2 +1,5 @@
 export const SET_COURSE = 'setCourse'
 export const RESET_COURSE = 'resetCourse'
+
+export const SET_USER_INFO = 'setUserInfo'
+export const RESET_USER_INFO = 'resetUserInfo'

+ 0 - 41
src/views/api-test/ApiTest.vue

@@ -1,41 +0,0 @@
-<template>
-  <div class="api-test">
-    <h1 class="title">API 测试界面</h1>
-    <file-uploader class="mb-24" @change="handleFileChange"></file-uploader>
-    文件对象:{{ file }}
-    <div>{{requestResult}}</div>
-  </div>
-</template>
-
-<script>
-import { getUserInfo, loginByEmail } from '@/server/user'
-import FileUploader from '@/components/FileUploader'
-
-export default {
-  components: { FileUploader },
-  data () {
-    return {
-      requestResult: {},
-      file: null
-    }
-  },
-  mounted() {
-    loginByEmail({ email: 'liuqin@nju.edu.cn', password: '123456' }).then(res => {
-      getUserInfo().then(res => {})
-    })
-  },
-  methods: {
-    handleFileChange (file) {
-      this.file = file
-    }
-  }
-}
-</script>
-
-<style lang="scss" scoped>
-.api-test {
-  padding: 40px;
-  max-width: 1000px;
-  margin: 0 auto;
-}
-</style>

+ 2 - 1
src/views/login/Login.vue

@@ -18,6 +18,7 @@ import CInput from '@/components/CInput'
 import CButton from '@/components/CButton'
 import Background from '@/components/Background'
 import { loginByEmail } from '@/server/user'
+import { SET_USER_INFO } from '@/store/types/main-types'
 
 export default {
   components: { CButton, CInput, Background },
@@ -39,7 +40,7 @@ export default {
 
       loginByEmail({ email: this.email, password: this.password }).then(res => {
         this.$setSuccessMessage('欢迎回来,' + res.name)
-        localStorage.setItem('userInfo', JSON.stringify(res))
+        this.$store.commit(SET_USER_INFO, { userInfo: res })
         if (res.type === 'TEACHER' || res.type === 'teacher') {
           this.$router.push({ name: 'teacher' })
         } else {

+ 4 - 0
src/views/student/tabs/StudentDiscussion.vue

@@ -1,6 +1,10 @@
 <template>
   <div class="tab">
     <h1 class="title">讨论区消息通知</h1>
+    <div class="no-content-warning">
+      本页面目前尚未完成 <br>
+      请前往相应课件评论区讨论
+    </div>
   </div>
 </template>
 

+ 4 - 18
src/views/student/tabs/StudentExplore.vue

@@ -1,15 +1,10 @@
 <template>
   <div class="tab complex-tab">
     <div class="left">
-      <h1 class="title">我的主页</h1>
-      <search-bar></search-bar>
-      <!--      <section>-->
-      <!--        <h1 class="sub-title">最近浏览</h1>-->
-      <!--        <slide-card :click-handler="handleSlideCardClick"></slide-card>-->
-      <!--        <br>-->
-      <!--      </section>-->
+      <h1 class="title mb-32">我的主页</h1>
+<!--      <search-bar placeholder="输入关键词搜索课件"  class="mb-24"></search-bar>-->
       <section>
-        <h1 class="sub-title">按课程查找课件</h1>
+        <h1 class="sub-title mb-24">按课程查找课件</h1>
         <div v-if="!courses || courses.length === 0" class="no-content-warning">
           <div class="no-content-warning-tip">
             您还没有加入任何课程
@@ -27,14 +22,13 @@
 </template>
 
 <script>
-import SearchBar from '@/components/SearchBar'
 import CourseCard from '@/components/CourseCard'
 import { studentGetCourses } from '@/server/course'
 import CButton from '@/components/CButton'
 import { SET_COURSE } from '@/store/types/main-types'
 
 export default {
-  components: { CButton, CourseCard, SearchBar },
+  components: { CButton, CourseCard },
   data () {
     return {
       courses: []
@@ -67,12 +61,4 @@ export default {
 
 <style lang="scss" scoped>
 @import "~@/views/shared/tab-common";
-
-.title {
-  margin-bottom: 16px;
-}
-
-.search-bar {
-  margin-bottom: 16px;
-}
 </style>