Преглед на файлове

feat: axios 拦截401错误并跳转到主页

ChenYangfan преди 6 години
родител
ревизия
ce09179f32

+ 26 - 4
src/App.vue

@@ -10,15 +10,37 @@
 <script>
 import GlobalMessage from '@/components/Basic/GlobalMessage'
 import SlideUpTransition from '@/animations/SlideUpTransition'
+import { mapState } from 'vuex'
 
 export default {
   components: { GlobalMessage, SlideUpTransition },
-  data () {
-    return {
-      userInfo: {}
-    }
+  computed: {
+    ...mapState({
+      userInfo: state => state.main.userInfo
+    })
   },
   created () {
+    // 拦截 401 - 无登录信息 前往登录界面
+    this.$axios.interceptors.response.use((response) => {
+      return response
+    }, (error) => {
+      if (error.response.status === 401 && this.$route.matched.some(record => record.meta.roles)) {
+        this.$router.push({ name: 'login' })
+        this.$setErrorMessage('请重新登录')
+      } else {
+        return Promise.reject(error)
+      }
+    })
+
+    this.$router.beforeEach((to, from, next) => {
+      if (to.matched.some(record => (record.meta.roles && !record.meta.roles.some(role => role === this.userInfo.type.toLowerCase())))) {
+        this.$setInfoMessage('所前往的页面需要使用' + (this.userInfo.type === 'TEACHER' ? '学生' : '教师') + '身份登录')
+        next({ name: this.userInfo.type === 'TEACHER' ? 'teacher' : 'student' })
+      } else {
+        next()
+      }
+    })
+
     // 在页面加载时读取sessionStorage里的状态信息
     if (sessionStorage.getItem('store')) {
       this.$store.replaceState(Object.assign({}, this.$store.state, JSON.parse(sessionStorage.getItem('store'))))

+ 1 - 1
src/components/Layouts/TabSideComponent.vue

@@ -75,7 +75,7 @@ export default {
   background: transparent;
   box-shadow: 0 0 0 20000px rgba(255,255,255,.5);
   .content {
-    min-height: 350px;
+    min-height: 375px;
   }
 }
 

+ 17 - 3
src/views/login/Login.vue

@@ -1,7 +1,10 @@
 <template>
   <div class="login-view-container">
     <div>
-      <h1 class="title"><span>SEEC</span> 用户登录</h1>
+      <h1 class="title"><span>SEEC</span>用户登录</h1>
+      <router-link :to="{name: userInfo.type === 'TEACHER' ? 'teacher' : 'student'}">
+        <c-button v-if="userInfo.name" block icon="face" theme="green" class="mb-16">已登录用户:{{userInfo.name}}</c-button>
+      </router-link>
       <c-input placeholder="邮箱" type="email" v-model="email"></c-input>
       <section class="tip mb-24">
         <div>关于邮箱的说明:</div>
@@ -23,7 +26,7 @@
 import CInput from '@/components/Basic/CInput'
 import CButton from '@/components/Basic/CButton'
 import Background from '@/components/Layouts/Background'
-import { loginByEmail } from '@/server/user'
+import { getUserInfo, loginByEmail } from '@/server/user'
 import { SET_USER_INFO } from '@/store/types/main-types'
 
 export default {
@@ -31,9 +34,15 @@ export default {
   data () {
     return {
       email: '',
-      password: ''
+      password: '',
+      userInfo: {}
     }
   },
+  mounted () {
+    getUserInfo().then(res => {
+      this.userInfo = res
+    })
+  },
   methods: {
     formChecked () {
       return this.email && this.password
@@ -80,9 +89,14 @@ export default {
 }
 
 .title {
+  color: #6a7a8a;
   span {
     font-family: 'Courier New', 'Courier', monospace;
     font-size: 1.15em;
+    color: #3a4a5a;
+    margin-right: 6px;
+    position: relative;
+    top: 2px;
   }
 }
 

+ 5 - 1
src/views/register/Register.vue

@@ -203,12 +203,16 @@ export default {
 }
 
 .title {
+  color: #6a7a8a;
   span {
     font-family: 'Courier New', 'Courier', monospace;
     font-size: 1.15em;
+    color: #3a4a5a;
+    margin-right: 6px;
+    position: relative;
+    top: 2px;
   }
 }
-
 .sub-title {
   span {
     float: right;

+ 5 - 6
src/views/shared/UserHomeLayout.vue

@@ -32,10 +32,7 @@
         </icon-button>
       </template>
     </div>
-    <div class="exit" @click="handleLogout">
-      <icon-button>exit_to_app</icon-button>
-      退出登录
-    </div>
+    <c-button class="exit" text @click="handleLogout" icon="exit_to_app">注销</c-button>
   </div>
 </template>
 
@@ -43,9 +40,10 @@
 import IconButton from '@/components/Basic/IconButton'
 import { logout } from '@/server/user'
 import SlideInTransition from '@/animations/SlideInSameTransition'
+import CButton from '@/components/Basic/CButton'
 
 export default {
-  components: { IconButton, SlideInTransition },
+  components: { CButton, IconButton, SlideInTransition },
   props: ['tabs', 'role'],
   data () {
     return {
@@ -172,10 +170,11 @@ export default {
 }
 
 .exit {
+  z-index: 4;
   cursor: pointer;
   position: absolute;
   top: 10px;
-  right: 24px;
+  right: 10px;
   display: flex;
   align-items: center;
   color: #6a7a8a;

+ 2 - 2
src/views/shared/tab-common.scss

@@ -1,5 +1,5 @@
 .tab {
-  min-height: 350px;
+  min-height: 375px;
   padding: 40px;
   flex: 1;
   min-width: 340px;
@@ -13,7 +13,7 @@
   min-width: 340px;
   width: 340px;
   align-items: center;
-  min-height: 350px;
+  min-height: 375px;
   max-height: 90vh;
   overflow: auto;
   padding-right: 24px;

+ 1 - 1
src/views/student/tabs/StudentExplore.vue

@@ -13,7 +13,7 @@
         </c-button>
       </tab-actions>
       <section>
-        <h1 class="sub-title mb-24">按课程查找课件</h1>
+        <h1 class="sub-title mb-24">按课程浏览课件</h1>
         <div class="no-content-warning" v-if="courses === null">
           <div class="no-content-warning-tip">加载中...</div>
         </div>