jichoi / lms_front star
박민혁 박민혁 2024-08-22
240822 박민혁 로그인 기능 추가
@6f4372c63ec9068fe7fe4fd4d25db84af2a89a4d
client/views/Login.vue
--- client/views/Login.vue
+++ client/views/Login.vue
@@ -43,7 +43,7 @@
 
             </button>
          </div>
-        <div class="tab-box" v-show="selectedTab !== 'tab3' && selectedTab !== 'tab4'">
+         <div class="tab-box" v-show="selectedTab !== 'tab3' && selectedTab !== 'tab4'">
             <label class="mr20 title1">
                <input type="radio" v-model="selectedTab" value="tab1" />
                아이디 찾기
@@ -52,7 +52,7 @@
                <input type="radio" v-model="selectedTab" value="tab2" />
                비밀번호 찾기
             </label>
-        </div>
+         </div>
          <!-- 아이디 찾기 -->
          <form @submit.prevent="submitForm" class="find-form mt30" v-if="selectedTab === 'tab1'">
             <div class="mb20 flex justify-between align-center">
@@ -61,10 +61,12 @@
             </div>
             <div class="mb30 flex justify-between align-center">
                <p class="title2" for="username" style="width: 12rem;">전화번호</p>
-               <div class="flex justify-between align-center" style="width: 100%;"><input class="data-wrap" style="width: 12rem;"
-                     type="text" id="username" v-model="username">
-                  <p class="title2">-</p><input class="data-wrap" style="width: 14rem;" type="text" id="username" v-model="username">
-                  <p class="title2">-</p><input class="data-wrap" style="width: 14rem;" type="text" id="username" v-model="username">
+               <div class="flex justify-between align-center" style="width: 100%;"><input class="data-wrap"
+                     style="width: 12rem;" type="text" id="username" v-model="username">
+                  <p class="title2">-</p><input class="data-wrap" style="width: 14rem;" type="text" id="username"
+                     v-model="username">
+                  <p class="title2">-</p><input class="data-wrap" style="width: 14rem;" type="text" id="username"
+                     v-model="username">
                </div>
             </div>
             <div class="flex justify-center ">
@@ -88,10 +90,12 @@
             </div>
             <div class="mb30 flex justify-between align-center">
                <p class="title2" for="username" style="width: 12rem;">전화번호</p>
-               <div class="flex justify-between align-center" style="width: 100%;"><input class="data-wrap" style="width: 12rem;"
-                     type="text" id="username" v-model="username">
-                  <p class="title2">-</p><input class="data-wrap" style="width: 14rem;" type="text" id="username" v-model="username">
-                  <p class="title2">-</p><input class="data-wrap" style="width: 14rem;" type="text" id="username" v-model="username">
+               <div class="flex justify-between align-center" style="width: 100%;"><input class="data-wrap"
+                     style="width: 12rem;" type="text" id="username" v-model="username">
+                  <p class="title2">-</p><input class="data-wrap" style="width: 14rem;" type="text" id="username"
+                     v-model="username">
+                  <p class="title2">-</p><input class="data-wrap" style="width: 14rem;" type="text" id="username"
+                     v-model="username">
                </div>
             </div>
             <div class="flex justify-center ">
@@ -104,7 +108,7 @@
             </div>
          </form>
          <!-- 아이디 찾기 결과 -->
-          <div v-else-if="selectedTab === 'tab3'">
+         <div v-else-if="selectedTab === 'tab3'">
             <div class="flex justify-center mt30">
                <p class="title2">아이디 찾기가 완료 되었습니다.</p>
             </div>
@@ -123,9 +127,9 @@
                   로그인 하기
                </button>
             </div>
-          </div>
+         </div>
          <!-- 비밀번호 찾기 결과 -->
-          <div v-else-if="selectedTab === 'tab4'">
+         <div v-else-if="selectedTab === 'tab4'">
             <div class="flex justify-center mt30">
                <p class="title2">비밀번호 찾기가 완료 되었습니다.</p>
             </div>
@@ -144,7 +148,7 @@
                   로그인 하기
                </button>
             </div>
-          </div>
+         </div>
       </div>
    </div>
 </template>
@@ -170,56 +174,60 @@
       submitForm() {
          console.log('Username:', this.username);
          console.log('Password:', this.password);
-         
+
          const vm = this;
 
          axios({
-                url: "/auth/login.json",
-                method: "post",
-                data: {
-                  loginId: this.username,
-                  password: this.password,
-                },
-            }).then(function (response) {
-               const token = response.headers.get('Authorization');
-               store.dispatch('login', token);
-               vm.branchPage();
-            }).catch(function (error) {
-                console.log(error);
-            });
+            url: "/auth/login.json",
+            method: "post",
+            data: {
+               loginId: this.username,
+               password: this.password,
+            },
+         }).then(function (response) {
+            const token = response.headers.get('Authorization');
+            store.dispatch('login', token);
+            vm.branchPage();
+         }).catch(function (error) {
+            alert("아이디나 비밀번호가 잘못됐습니다 !");
+            console.log(error);
+         });
 
       },
       branchPage() {
          const vm = this;
          const token = localStorage.getItem('token');
          axios.post('/auth/validateToken.json', {}, {
-                headers: {
-                    Authorization: token
-                }
-            }).then(response => {
-                if (response.data.status === 'success') {
-                    const userInfo = response.data.userInfo;
-                    store.commit('setToken', token);
-                    store.commit('setUser', userInfo.usid);
-                    store.commit('setAuthcd', userInfo.author[0].authorCode);
-                    const roles = userInfo.author.map(role => role.authorCode);
+            headers: {
+               Authorization: token
+            }
+         }).then(response => {
+            if (response.data.status === 'success') {
+               const userInfo = response.data.userInfo;
+               store.commit('setToken', token);
+               store.commit('setUser', userInfo.usid);
+               store.commit('setAuthcd', userInfo.author[0].authorCode);
+               const roles = userInfo.author.map(role => role.authorCode);
 
-                    // 학생은 Main_t로 접근할 수 없음
-                    if (roles.includes("STUDENT")) {
-                     vm.goToPage('Dashboard');
-                    }
-                    // 선생님은 Main으로 접근할 수 없음
-                    else if (roles.includes("TEACHER")) {
-                     vm.goToPage('Board');
-                    } 
-                    // 부모님은 Main으로 접근할 수 없음
-                    else if (roles.includes("PARENT")) {
-                     vm.goToPage('Main_p');
-                    } 
-                } 
-            }).catch(error => {
-                console.error(error);
-            });   },
+               // 학생은 Main_t로 접근할 수 없음
+               if (roles.includes("STUDENT")) {
+                  vm.goToPage('Dashboard');
+               }
+               // 선생님은 Main으로 접근할 수 없음
+               else if (roles.includes("TEACHER")) {
+                  vm.goToPage('Board');
+               }
+               // 부모님은 Main으로 접근할 수 없음
+               else if (roles.includes("PARENT")) {
+                  vm.goToPage('Main_p');
+               } else if (roles.includes("ADMIN")) {
+                  vm.goToPage('Dashboard');
+               }
+            }
+         }).catch(error => {
+               console.error(error);
+            });
+      },
       closeModal() {
          this.showModal = false;
       },
@@ -231,8 +239,8 @@
 
       },
       goToPage(page) {
-      this.$router.push({ name: page });
-    },
+         this.$router.push({ name: page });
+      },
 
    },
    components: {
client/views/layout/Header.vue
--- client/views/layout/Header.vue
+++ client/views/layout/Header.vue
@@ -1,6 +1,8 @@
 <template>
   <div class="header flex justify-end">
-    <img src="../../resources/img/setting.png" alt="" />
+    <div class="setting" @click="logout">
+      <img src="../../resources/img/setting.png" alt="" />
+    </div>
     <div class="notice" @click="buttonSearch">
       <img src="../../resources/img/icon2.png" alt="" />
       <p>{{ unCheck }}</p>
@@ -11,38 +13,18 @@
         <div class="flex mb10 justify-between">
           <p class="popup-title">알림</p>
           <button type="button" class="popup-close-btn" @click="closeBtn">
-            <svg-icon
-              type="mdi"
-              :path="mdiWindowClose"
-              class="close-btn"
-            ></svg-icon>
+            <svg-icon type="mdi" :path="mdiWindowClose" class="close-btn"></svg-icon>
           </button>
         </div>
-        <article
-          class="flex justify-between mt20"
-          v-for="(item, index) in dataList"
-          :key="item.id"
-          :class="{ 'selected-row': selectedRow == item.dataList }"
-        >
-          <img
-            style="width: fit-content"
-            src="../../resources/img/img200_13p.png"
-            alt=""
-          />
+        <article class="flex justify-between mt20" v-for="(item, index) in dataList" :key="item.id"
+          :class="{ 'selected-row': selectedRow == item.dataList }">
+          <img style="width: fit-content" src="../../resources/img/img200_13p.png" alt="" />
           <p class="title1 ml20" style="width: 60%">{{ item.bbsTtl }}</p>
-          <button
-            @click="buttonSearch2(item)"
-            type="button"
-            title="글쓰기"
-            class="new-btn"
-          >
+          <button @click="buttonSearch2(item)" type="button" title="글쓰기" class="new-btn">
             자세히 보기
           </button>
         </article>
-        <article
-          class="table-pagination flex justify-center align-center mb20 mt30"
-          style="gap: 10px"
-        >
+        <article class="table-pagination flex justify-center align-center mb20 mt30" style="gap: 10px">
           <button @click="previousPage" :disabled="page === 1">이전</button>
           <button class="selected-btn">{{ page }}</button>
           <button @click="nextPage" :disabled="page === totalPages">
@@ -56,11 +38,7 @@
         <div class="flex mb10 justify-between">
           <p class="popup-title">알림 자세히 보기</p>
           <button type="button" class="popup-close-btn" @click="closeBtn2">
-            <svg-icon
-              type="mdi"
-              :path="mdiWindowClose"
-              class="close-btn"
-            ></svg-icon>
+            <svg-icon type="mdi" :path="mdiWindowClose" class="close-btn"></svg-icon>
           </button>
         </div>
         <div class="board-wrap">
@@ -147,6 +125,20 @@
       this.searchOpen2 = false;
     },
 
+    logout() {
+      const result = confirm('로그아웃 하시겠습니까?')
+      if (result) {
+
+      } else {
+        return;
+      }
+      localStorage.removeItem('token');
+      this.goToPage('login');
+    },
+    goToPage(page) {
+         this.$router.push({ name: page });
+      },
+
     // 공지 조회
     boardList() {
       const vm = this;
client/views/pages/AppRouter.js
--- client/views/pages/AppRouter.js
+++ client/views/pages/AppRouter.js
@@ -96,6 +96,10 @@
 import ExamInsert from "./teacher/ExamInsert.vue";
 import RoadMap from "./teacher/RoadMap.vue";
 
+import store from './AppStore';
+import axios from "axios";
+
+
 const routes = [
     { path: "/login.page", name: "login", component: login },
     { path: "/Join.page", name: "Join", component: Join },
@@ -419,4 +423,62 @@
     routes,
 });
 
+
+AppRouter.beforeEach((to, from, next) => {
+    const publicPages = ['/login.page', '/Join.page'];
+    const authRequired = !publicPages.includes(to.path);
+
+    const isLoggedIn = store.getters.isLoggedIn;
+
+    if (authRequired && !isLoggedIn) {
+        // 토큰이 존재하는지 확인
+        const token = localStorage.getItem('token');
+        if (token) {
+            // 토큰 유효성 검증
+            axios.post('/auth/validateToken.json', {}, {
+                headers: {
+                    Authorization: token
+                }
+            }).then(response => {
+                if (response.data.status === 'success') {
+                    const userInfo = response.data.userInfo;
+                    store.commit('setToken', token);
+                    store.commit('setUser', userInfo.usid);
+                    store.commit('setAuthcd', userInfo.author[0].authorCode);
+                    const roles = userInfo.author.map(role => role.authorCode);
+
+                    // 학생은 Main_t로 접근할 수 없음
+                    if (roles.includes("STUDENT")) {
+                        next('Dashboard.page');
+                    }
+                    // 선생님은 Main으로 접근할 수 없음
+                    else if (roles.includes("TEACHER")) {
+                        next('Board.page');
+                    } else if (roles.includes("PARENT")) {
+                        next('Main_p.page');
+                    } else if (roles.includes("ADMIN")){
+                        next('Dashboard.page');
+                    }
+                } else {
+                    // 유효하지 않은 경우
+                    alert("계정이 로그아웃되었습니다");
+                    localStorage.removeItem('token');
+                    next("login.page");
+                }
+            }).catch(error => {
+                alert("계정이 로그아웃되었습니다");
+
+                console.error('토큰 검증 오류:', error);
+                localStorage.removeItem('token');
+                next("login.page");
+            });
+        } else {
+            next("login.page");
+        }
+    } else {
+        next();
+    }
+});
+
+
 export default AppRouter;
Add a comment
List