jichoi / lms_front star
박민혁 박민혁 09-06
240906 박민혁 회원가입 로그인 대시보드 수정
@7a4b07b0f90c9d15bb42d54f5131c66975cb2518
client/views/Join.vue
--- client/views/Join.vue
+++ client/views/Join.vue
@@ -31,20 +31,41 @@
                   <p class="title" for="username">아이디</p>
                   <input type="text" id="username" v-model="userId" placeholder="아이디를 입력하세요.">
                </div>
-               <p class="title2 flex align-center mb20 help" for="username"><img src="../resources/img/img193_78p.png"
-                     alt=""><em class="green ml10">사용 가능한 아이디입니다.</em></p>
+               <p class="title2 flex align-center mb20 help" for="username" v-if="!isUserIdValid">
+                  <img src="../resources/img/img194_78p.png" alt="">
+                  <em class="gray ml10">영문, 숫자를 조합하여 주세요 (6자리 이상)</em>
+               </p>
+               <p class="title2 flex align-center mb20 help" for="username" v-else>
+                  <img src="../resources/img/img193_78p.png" alt="">
+                  <em class="green ml10">사용 가능한 아이디입니다.</em>
+               </p>
+
                <div class="flex justify-between align-center mb10">
                   <p class="title" for="password">비밀번호</p>
                   <input type="password" id="password" v-model="password" placeholder="비밀번호를 입력하세요.">
                </div>
-               <p class="title2 mb20 flex align-center help" for="username"><img src="../resources/img/img193_78p.png"
-                     alt=""><em class="gray ml10">영문, 숫자, 특수문자 3가지를 조합하여 주세요.(6자리 이상)</em></p>
+               <p class="title2 mb20 flex align-center help" for="password" v-if="!isPasswordValid">
+                  <img src="../resources/img/img194_78p.png" alt="">
+                  <em class="gray ml10">영문, 숫자, 특수문자 3가지를 조합하여 주세요.(6자리 이상)</em>
+               </p>
+               <p class="title2 mb20 flex align-center help" for="password" v-else>
+                  <img src="../resources/img/img193_78p.png" alt="">
+                  <em class="green ml10">비밀번호가 유효합니다.</em>
+               </p>
+
                <div class="flex justify-between align-center mb10">
-                  <p class="title" for="password">비밀번호 확인</p>
-                  <input type="password" id="password" v-model="passwordCheck" placeholder="비밀번호를 입력하세요.">
+                  <p class="title" for="passwordCheck">비밀번호 확인</p>
+                  <input type="password" id="passwordCheck" v-model="passwordCheck" placeholder="비밀번호를 입력하세요.">
                </div>
-               <p class="title2 mb20 flex align-center help" for="username"><img src="../resources/img/img193_78p.png"
-                     alt=""><em class="green ml10">비밀번호가 일치 합니다.</em></p>
+               <p class="title2 mb20 flex align-center help" for="passwordCheck"
+                  v-if="!isPasswordMatched || !isPasswordValid">
+                  <img src="../resources/img/img194_78p.png" alt="">
+                  <em class="gray ml10">비밀번호가 일치하지 않습니다.</em>
+               </p>
+               <p class="title2 mb20 flex align-center help" for="passwordCheck" v-else>
+                  <img src="../resources/img/img193_78p.png" alt="">
+                  <em class="green ml10">비밀번호가 일치합니다.</em>
+               </p>
                <div class="mb30 flex justify-between align-center">
                   <p class="title" for="username">이름</p>
                   <input type="text" id="username" v-model="username" placeholder="이름을 입력하세요.">
@@ -59,17 +80,21 @@
                </div>
                <div class="mb30 flex justify-between align-center">
                   <p class="title" for="username">학교</p>
-                  <div class="search-wrap flex justify-end mb20" style="width: 100%;">
-                     <select name="" id="" class="mr10 data-wrap">
-                        <option value="">학년</option>
-                     </select>
-                     <select name="" id="" class="mr10 data-wrap">
-                        <option value="">반</option>
-                     </select>
-                     <select name="" id="" class="data-wrap">
-                        <option value="">번호</option>
-                     </select>
-
+                  <div class="search-wrap" style="width: 100%;">
+                     <input type="text" placeholder="검색하세요." disabled v-model="userIns">
+                     <button @click="buttonSearch" type="button" title="위원회 검색">
+                        <img src="../resources/img/look_t.png" alt="">
+                     </button>
+                  </div>
+               </div>
+               <div class="mb30 flex justify-between align-center">
+                  <div class="flex justify-between align-center" style="width: 100%;">
+                     <p class="title" for="username"></p>
+                     <input style="width: 12rem;" type="text" id="username" v-model="userGrade" placeholder="학년">
+                     <p class="title2">-</p><input style="width: 14rem;" type="text" id="username" v-model="userClass"
+                        placeholder="반">
+                     <p class="title2">-</p><input style="width: 14rem;" type="text" id="username" v-model="userNumber"
+                        placeholder="번호">
                   </div>
                </div>
                <div class="flex justify-end align-center mb10">
@@ -87,20 +112,41 @@
                   <p class="title" for="username">아이디</p>
                   <input type="text" id="username" v-model="userId" placeholder="아이디를 입력하세요.">
                </div>
-               <p class="title2 flex align-center mb20 help" for="username"><img src="../resources/img/img193_78p.png"
-                     alt=""><em class="green ml10">사용 가능한 아이디입니다.</em></p>
+               <p class="title2 flex align-center mb20 help" for="username" v-if="!isUserIdValid">
+                  <img src="../resources/img/img194_78p.png" alt="">
+                  <em class="gray ml10">영문, 숫자를 조합하여 주세요 (6자리 이상)</em>
+               </p>
+               <p class="title2 flex align-center mb20 help" for="username" v-else>
+                  <img src="../resources/img/img193_78p.png" alt="">
+                  <em class="green ml10">사용 가능한 아이디입니다.</em>
+               </p>
+
                <div class="flex justify-between align-center mb10">
                   <p class="title" for="password">비밀번호</p>
                   <input type="password" id="password" v-model="password" placeholder="비밀번호를 입력하세요.">
                </div>
-               <p class="title2 mb20 flex align-center help" for="username"><img src="../resources/img/img193_78p.png"
-                     alt=""><em class="gray ml10">영문, 숫자, 특수문자 3가지를 조합하여 주세요.(6자리 이상)</em></p>
+               <p class="title2 mb20 flex align-center help" for="password" v-if="!isPasswordValid">
+                  <img src="../resources/img/img194_78p.png" alt="">
+                  <em class="gray ml10">영문, 숫자, 특수문자 3가지를 조합하여 주세요.(6자리 이상)</em>
+               </p>
+               <p class="title2 mb20 flex align-center help" for="password" v-else>
+                  <img src="../resources/img/img193_78p.png" alt="">
+                  <em class="green ml10">비밀번호가 유효합니다.</em>
+               </p>
+
                <div class="flex justify-between align-center mb10">
-                  <p class="title" for="password">비밀번호 확인</p>
-                  <input type="password" id="password" v-model="passwordCheck" placeholder="비밀번호를 입력하세요.">
+                  <p class="title" for="passwordCheck">비밀번호 확인</p>
+                  <input type="password" id="passwordCheck" v-model="passwordCheck" placeholder="비밀번호를 입력하세요.">
                </div>
-               <p class="title2 mb20 flex align-center help" for="username"><img src="../resources/img/img193_78p.png"
-                     alt=""><em class="green ml10">비밀번호가 일치 합니다.</em></p>
+               <p class="title2 mb20 flex align-center help" for="passwordCheck"
+                  v-if="!isPasswordMatched || !isPasswordValid">
+                  <img src="../resources/img/img194_78p.png" alt="">
+                  <em class="gray ml10">비밀번호가 일치하지 않습니다.</em>
+               </p>
+               <p class="title2 mb20 flex align-center help" for="passwordCheck" v-else>
+                  <img src="../resources/img/img193_78p.png" alt="">
+                  <em class="green ml10">비밀번호가 일치합니다.</em>
+               </p>
                <div class="mb30 flex justify-between align-center">
                   <p class="title" for="username">이름</p>
                   <input type="text" id="username" v-model="username" placeholder="이름을 입력하세요.">
@@ -116,32 +162,33 @@
                <div class="flex justify-between mb20">
                   <p class="title " for="username"><em class="yellow">학생 정보</em></p>
                   <div class="flex justify-end align-center mb10">
-                     <img src="../resources/img/img192_78p.png" alt="">
+                     <img src="../resources/img/img192_78p.png" alt="" @click="openModal">
                      <p class="title2 ml10" for="password">자녀 추가하기</p>
                   </div>
+               </div>
+               <div v-if="students.length > 0" class="flex justify-between mb20">
+                  <table class="table-wrap">
+                     <thead style="text-align: center; ">
+                        <tr>
+                           <th>자녀 이름</th>
+                           <th>자녀 아이디</th>
+                        </tr>
+                     </thead>
+                     <tbody>
+                        <tr v-for="(student, index) in students">
+                           <td>{{ student.userNm }}</td>
+                           <td>{{ student.loginId }}</td>
+                        </tr>
+                     </tbody>
+                  </table>
                </div>
                <div class="mb30 flex justify-between align-center">
                   <p class="title" for="username">학교</p>
                   <div class="search-wrap" style="width: 100%;">
-                     <input type="text" placeholder="검색하세요.">
+                     <input type="text" placeholder="검색하세요." disabled v-model="userIns">
                      <button @click="buttonSearch" type="button" title="위원회 검색">
                         <img src="../resources/img/look_t.png" alt="">
                      </button>
-                  </div>
-               </div>
-               <div class="mb30 flex justify-between align-center">
-                  <p class="title" for="username">학생 정보</p>
-                  <div class="search-wrap flex justify-end mb20" style="width: 100%;">
-                     <select name="" id="" class="mr10 data-wrap">
-                        <option value="">학년</option>
-                     </select>
-                     <select name="" id="" class="mr10 data-wrap">
-                        <option value="">반</option>
-                     </select>
-                     <select name="" id="" class=" data-wrap">
-                        <option value="">번호</option>
-                     </select>
-
                   </div>
                </div>
                <div class="flex justify-end align-center mb10">
@@ -159,20 +206,41 @@
                   <p class="title" for="username">아이디</p>
                   <input type="text" id="username" v-model="userId" placeholder="아이디를 입력하세요.">
                </div>
-               <p class="title2 flex align-center mb20 help" for="username"><img src="../resources/img/img193_78p.png"
-                     alt=""><em class="green ml10">사용 가능한 아이디입니다.</em></p>
+               <p class="title2 flex align-center mb20 help" for="username" v-if="!isUserIdValid">
+                  <img src="../resources/img/img194_78p.png" alt="">
+                  <em class="gray ml10">영문, 숫자를 조합하여 주세요 (6자리 이상)</em>
+               </p>
+               <p class="title2 flex align-center mb20 help" for="username" v-else>
+                  <img src="../resources/img/img193_78p.png" alt="">
+                  <em class="green ml10">사용 가능한 아이디입니다.</em>
+               </p>
+
                <div class="flex justify-between align-center mb10">
                   <p class="title" for="password">비밀번호</p>
                   <input type="password" id="password" v-model="password" placeholder="비밀번호를 입력하세요.">
                </div>
-               <p class="title2 mb20 flex align-center help" for="username"><img src="../resources/img/img193_78p.png"
-                     alt=""><em class="gray ml10">영문, 숫자, 특수문자 3가지를 조합하여 주세요.(6자리 이상)</em></p>
+               <p class="title2 mb20 flex align-center help" for="password" v-if="!isPasswordValid">
+                  <img src="../resources/img/img194_78p.png" alt="">
+                  <em class="gray ml10">영문, 숫자, 특수문자 3가지를 조합하여 주세요.(6자리 이상)</em>
+               </p>
+               <p class="title2 mb20 flex align-center help" for="password" v-else>
+                  <img src="../resources/img/img193_78p.png" alt="">
+                  <em class="green ml10">비밀번호가 유효합니다.</em>
+               </p>
+
                <div class="flex justify-between align-center mb10">
-                  <p class="title" for="password">비밀번호 확인</p>
-                  <input type="password" id="password" v-model="passwordCheck" placeholder="비밀번호를 입력하세요.">
+                  <p class="title" for="passwordCheck">비밀번호 확인</p>
+                  <input type="password" id="passwordCheck" v-model="passwordCheck" placeholder="비밀번호를 입력하세요.">
                </div>
-               <p class="title2 mb20 flex align-center help" for="username"><img src="../resources/img/img193_78p.png"
-                     alt=""><em class="green ml10">비밀번호가 일치 합니다.</em></p>
+               <p class="title2 mb20 flex align-center help" for="passwordCheck"
+                  v-if="!isPasswordMatched || !isPasswordValid">
+                  <img src="../resources/img/img194_78p.png" alt="">
+                  <em class="gray ml10">비밀번호가 일치하지 않습니다.</em>
+               </p>
+               <p class="title2 mb20 flex align-center help" for="passwordCheck" v-else>
+                  <img src="../resources/img/img193_78p.png" alt="">
+                  <em class="green ml10">비밀번호가 일치합니다.</em>
+               </p>
                <div class="mb30 flex justify-between align-center">
                   <p class="title" for="username">이름</p>
                   <input type="text" id="username" v-model="username" placeholder="이름을 입력하세요.">
@@ -188,26 +256,15 @@
                <div class="mb30 flex justify-between align-center">
                   <p class="title" for="username">학교</p>
                   <div class="search-wrap" style="width: 100%;">
-                     <input type="text" placeholder="검색하세요.">
+                     <input type="text" placeholder="검색하세요." disabled v-model="userIns">
                      <button @click="buttonSearch" type="button" title="위원회 검색">
                         <img src="../resources/img/look_t.png" alt="">
                      </button>
                   </div>
                </div>
                <div class="mb30 flex justify-between align-center">
-                  <p class="title" for="username">학교</p>
-                  <div class="search-wrap flex justify-end mb20" style="width: 100%;">
-                     <select name="" id="" class="mr10 data-wrap">
-                        <option value="">학년</option>
-                     </select>
-                     <select name="" id="" class="mr10 data-wrap">
-                        <option value="">반</option>
-                     </select>
-                     <select name="" id="" class="data-wrap">
-                        <option value="">번호</option>
-                     </select>
-
-                  </div>
+                  <p class="title" for="username">이메일</p>
+                  <input type="text" id="username" v-model="email" placeholder="이메일을 입력하세요.">
                </div>
                <div class="flex justify-end align-center mb10">
                   <input type="checkbox" class="ui-checkbox mr10">
@@ -222,7 +279,7 @@
       </div>
    </div>
    <div v-show="searchOpen" class="popup-wrap">
-      <div class="popup-box ">
+      <div class="popup-box" style="width: 70rem;  margin: 0 auto;">
          <div class="flex justify-between mb30">
             <p class="popup-title">학교 검색</p>
             <button type="button" class="popup-close-btn" @click="closeBtn">
@@ -233,32 +290,113 @@
          <div class="mb30 flex justify-between align-center">
             <p class="title1" for="username" style="width: 12rem;">시/도</p>
             <div class="search-wrap flex justify-end" style="width: 100%;">
-               <select name="" id="" class="mr10 data-wrap">
-                  <option value="">시</option>
-               </select>
-               <select name="" id="" class=" data-wrap">
-                  <option value="">도</option>
+               <input type="text" placeholder="시도명을 정확하게 입력하세요. (EX : 서울특별시, 경기도)" v-model="searchCity">
+            </div>
+         </div>
+         <div class="mb10 flex justify-between align-center">
+            <p class="title1" for="username" style="width: 12rem;">학교급</p>
+            <div class="search-wrap" style="width: 100%;">
+               <select name="" id="" class="mr10 data-wrap" v-model="searchLevel">
+                  <option value="초등학교">초등학교</option>
+                  <option value="중학교">중학교</option>
+                  <option value="고등학교">고등학교</option>
                </select>
             </div>
          </div>
          <div class="mb10 flex justify-between align-center">
             <p class="title1" for="username" style="width: 12rem;">학교명</p>
             <div class="search-wrap" style="width: 100%;">
-               <input type="text" placeholder="검색하세요.">
-               <button @click="buttonSearch" type="button" title="위원회 검색">
+               <input type="text" placeholder="학교명을 입력하세요." v-model="searchSchoolName">
+               <button @click="searchSchool" type="button" title="위원회 검색">
                   <img src="../resources/img/look_t.png" alt="">
                </button>
             </div>
          </div>
-         <p class="title2 mb20 flex align-center help" for="username" style="margin-left: 10rem;"><img
-               src="../resources/img/img194_78p.png" alt=""><em class="gray ml10">학교명을 입력 후 찾기 버튼을 클릭하십시오.</em></p>
+         <div v-if="schools.length > 0" style="max-height: 400px; overflow-y: auto;">
+            <table class="table-wrap">
+               <thead style="text-align: center; ">
+                  <tr>
+                     <th>선택</th>
+                     <th>학교명</th>
+                     <th>학교종류</th>
+                     <th>시도명</th>
+                  </tr>
+               </thead>
+               <tbody>
+                  <tr v-for="(school, index) in schools" :key="school.SD_SCHUL_CODE">
+                     <td>
+                        <input type="radio" name="selectedSchool" :value="school" v-model="selectedSchool">
+                     </td>
+                     <td>{{ school.SCHUL_NM }}</td>
+                     <td>{{ school.SCHUL_KND_SC_NM }}</td>
+                     <td>{{ school.LCTN_SC_NM }}</td>
+                  </tr>
+               </tbody>
+            </table>
+         </div>
+         <p class="title2 mb20 flex align-center help" for="username" style="margin-left: 10rem;"
+            v-if="schools.length === 0">
+            <img src="../resources/img/img194_78p.png" alt="">
+            <em class="gray ml10">학교명을 입력 후 찾기 버튼을 클릭하십시오.</em>
+         </p>
          <div class="flex justify-center ">
-            <button type="button" title="글쓰기" class="new-btn mr10">
+            <button type="button" title="글쓰기" class="new-btn mr10" @click="closeBtn">
                취소
             </button>
-            <button type="button" title="글쓰기" class="new-btn">
-               등록
+            <button type="button" title="글쓰기" class="new-btn" @click="selectSchool">
+               학교선택 / Select School
             </button>
+         </div>
+      </div>
+   </div>
+   <div v-show="showModal" class="popup-wrap">
+      <div class="popup-box" style="width: 70rem;  margin: 0 auto;">
+         <div class="find-form mt30">
+            <div v-if="!searchResult">
+               <div class="mb20 flex justify-between align-center">
+                  <p class="title2" for="username" style="width: 12rem;">자녀 이름</p>
+                  <input class="data-wrap" type="text" id="username" v-model="findUserNm" placeholder="이름을 입력하세요."
+                     style="width: 45rem;">
+               </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"><input class="data-wrap" style="width: 14rem;"
+                        type="text" id="username" v-model="findTel1">
+                     <p class="title2">-</p><input class="data-wrap" style="width: 14rem;" type="text" id="username"
+                        v-model="findTel2">
+                     <p class="title2">-</p><input class="data-wrap" style="width: 14rem;" type="text" id="username"
+                        v-model="findTel3">
+                  </div>
+               </div>
+               <div class="flex justify-center ">
+                  <button type="button" title="글쓰기" class="new-btn mr10" @click="closeModal">
+                     취소
+                  </button>
+                  <button @click="findId" type="button" title="글쓰기" class="new-btn">
+                     찾기
+                  </button>
+               </div>
+            </div>
+            <div v-else>
+               <div class="flex justify-center mt30">
+                  <p class="title2">자녀 찾기가 완료 되었습니다.</p>
+               </div>
+               <table class="table-wrap mt30 mb30">
+                  <tr>
+                     <td class="thead">이름</td>
+                     <td>{{ findUserInfo.userNm }}</td>
+                  </tr>
+                  <tr>
+                     <td class="thead">아이디</td>
+                     <td>{{ findUserInfo.loginId }}</td>
+                  </tr>
+               </table>
+               <div class="flex justify-center ">
+                  <button @click="closeModal" type="button" title="글쓰기" class="new-btn">
+                     추가하기
+                  </button>
+               </div>
+            </div>
          </div>
       </div>
    </div>
@@ -280,10 +418,26 @@
          tel1: '',
          tel2: '',
          tel3: '',
+         findUserNm: '',
+         findTel1: '',
+         findTel2: '',
+         findTel3: '',
+         userGrade: '',
+         userClass: '',
+         userNumber: '',
+         userIns: '',
          email: null,
          selectedTab: 'tab1', // 초기 선택 탭
          showModal: false,
          searchOpen: false,
+         searchCity: '',
+         searchLevel: '초등학교', // 기본값 설정
+         searchSchoolName: '',
+         schools: [],
+         students: [],
+         selectedSchool: null, // 선택된 학교
+         searchResult: false,
+         findUserInfo: {},
       }
    },
    methods: {
@@ -333,7 +487,7 @@
          } else if (vm.selectedTab === 'tab3') {
             auth = 'TEACHER'
          }
-         
+
          axios({
             url: "/auth/insertUser.json",
             method: "post",
@@ -347,7 +501,7 @@
                authcd: auth
             },
          }).then(function (response) {
-            if(response.data.status === 'success'){
+            if (response.data.status === 'success') {
                alert("회원가입에 성공했습니다!")
                vm.goToApp();
             } else {
@@ -355,12 +509,87 @@
             }
          }).catch(function (error) {
          });
-         
+
       },
+      // 학교 찾기
+      searchSchool() {
+         if (!this.searchSchoolName) {
+            alert("학교명을 입력해주세요!");
+            return;
+         }
+
+         axios({
+            url: "https://open.neis.go.kr/hub/schoolInfo",
+            method: "get",
+            params: {
+               KEY: "51f16da8aa344339a49812c23bcedb24", // 인증키를 넣어주세요
+               Type: "json",
+               pIndex: 1,
+               pSize: 100,
+               SCHUL_NM: this.searchSchoolName,
+               LCTN_SC_NM: this.searchCity,
+               SCHUL_KND_SC_NM: this.searchLevel
+            },
+         }).then(response => {
+            const data = response.data.schoolInfo;
+            if (data && data[1] && data[1].row) {
+               this.schools = data[1].row; // 학교 정보를 schools에 저장
+            } else {
+               alert("검색된 학교가 없습니다");
+               this.schools = []; // 결과가 없을 경우 빈 배열로 초기화
+            }
+         }).catch(error => {
+            console.error(error);
+         });
+      },
+      selectSchool() {
+         if (this.selectedSchool) {
+            this.userIns = this.selectedSchool.SCHUL_NM; // 선택된 학교 이름 정보를 userIns에 저장
+            this.closeBtn(); // 팝업 닫기
+         } else {
+            alert("학교를 선택해 주세요.");
+         }
+      },
+      // 자녀 찾기
+      findId() {
+         const vm = this;
+
+         const telno = vm.findTel1 + '-' + vm.findTel2 + '-' + vm.findTel3;
+
+         axios({
+            url: "/auth/findId.json",
+            method: "post",
+            data: {
+               telno: telno,
+               userNm: vm.findUserNm,
+            },
+         }).then(function (response) {
+            vm.findUserInfo = response.data;
+            vm.searchResult = true;
+         }).catch(function (error) {
+            alert("등록되지 않은 자녀입니다!");
+            console.log(error);
+         });
+      },
+
       goToApp() {
          this.$router.push('/Login.page');
       },
+      openModal() {
+         this.showModal = true;
+      },
       closeModal() {
+         if (Object.keys(this.findUserInfo).length > 0) {
+            const isDuplicate = this.students.some(student => student.loginId === this.findUserInfo.loginId);
+
+            if (!isDuplicate) {
+               this.students.push(this.findUserInfo);
+            } else {
+               alert("이미 추가된 학생입니다.");
+            }
+         }
+         this.searchResult = false;
+         this.findUserInfo = null;
          this.showModal = false;
       },
       buttonSearch() {
@@ -371,6 +600,23 @@
 
       },
    },
+   computed: {
+      isUserIdValid() {
+         // 사용자 아이디 유효성 검사 (예: 6자 이상, 영어와 숫자)
+         const regex = /^[a-zA-Z0-9]{6,}$/;
+         return regex.test(this.userId);
+      },
+      isPasswordValid() {
+         // 비밀번호 유효성 검사 (예: 6자 이상, 영문, 숫자, 특수문자 포함)
+         const regex = /^(?=.*[a-zA-Z])(?=.*[0-9])(?=.*[!@#$%^&*])[A-Za-z\d!@#$%^&*]{6,}$/;
+         return regex.test(this.password);
+      },
+      isPasswordMatched() {
+         // 비밀번호 확인 일치 여부
+         return this.password === this.passwordCheck;
+      }
+   },
+
    components: {
       SvgIcon
    },
client/views/Login.vue
--- client/views/Login.vue
+++ client/views/Login.vue
@@ -9,7 +9,7 @@
                <img src="../resources/img/icon1.png" alt="" class="mr20">
                <h2> 로그인 하기</h2>
             </div>
-            <form @submit.prevent="submitForm" class="login-form ">
+            <div class="login-form ">
                <div class="mb30">
                   <p class="mb15 title" for="username">아이디</p>
                   <input type="text" id="username" v-model="username" placeholder="아이디를 입력하세요.">
@@ -18,7 +18,7 @@
                   <p class="mb15 title" for="password">비밀번호</p>
                   <input type="password" id="password" v-model="password" placeholder="비밀번호를 입력하세요.">
                </div>
-               <button class="login-btn mt50" type="submit" @click="goToApp"><img src="../resources/img/button.png"
+               <button class="login-btn mt50" type="submit" @click="submitForm"><img src="../resources/img/button.png"
                      alt="">
                   <p>로그인</p>
                </button>
@@ -30,12 +30,12 @@
                      <p class="underline title2" @click="goToPage('Join')">회원가입</p>
                   </button>
                </div>
-            </form>
+            </div>
          </div>
       </div>
    </div>
    <div v-show="searchOpen" class="popup-wrap">
-      <div class="popup-box ">
+      <div class="popup-box" style="width: 70rem;  margin: 0 auto;">
          <div class="flex justify-end mb10">
             <!-- <p class="popup-title">학교 검색</p> -->
             <button type="button" class="popup-close-btn" @click="closeBtn">
@@ -50,19 +50,19 @@
             </label>
             <label class="mr20 title1">
                <input type="radio" v-model="selectedTab" value="tab2" />
-               비밀번호 찾기
+               비밀번호 변경
             </label>
          </div>
          <!-- 아이디 찾기 -->
          <div class="find-form mt30" v-if="selectedTab === 'tab1'">
             <div class="mb20 flex justify-between align-center">
                <p class="title2" for="username" style="width: 12rem;">이름</p>
-               <input class="data-wrap" type="text" id="username" v-model="findUserNm" placeholder="이름을 입력하세요.">
+               <input class="data-wrap" type="text" id="username" v-model="findUserNm" placeholder="이름을 입력하세요."  style="width: 45rem;" >
             </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="findTel1">
+               <div class="flex justify-between align-center"><input class="data-wrap"
+                     style="width: 14rem;" type="text" id="username" v-model="findTel1">
                   <p class="title2">-</p><input class="data-wrap" style="width: 14rem;" type="text" id="username"
                      v-model="findTel2">
                   <p class="title2">-</p><input class="data-wrap" style="width: 14rem;" type="text" id="username"
@@ -78,21 +78,19 @@
                </button>
             </div>
          </div>
-         <!-- 비밀번호 찾기 -->
+         <!-- 비밀번호 변경 -->
          <div class="find-form mt30" v-else-if="selectedTab === 'tab2'">
             <div class="mb20 flex justify-between align-center">
                <p class="title2" for="username" style="width: 12rem;">아이디</p>
-               <input class="data-wrap" type="text" id="username" v-model="changeUserNm" placeholder="아이디를 입력하세요.">
+               <input class="data-wrap" type="text" id="username" v-model="changeLoginId" placeholder="아이디를 입력하세요." style="width: 45rem;" >
             </div>
             <div class="mb20 flex justify-between align-center">
-               <p class="title2" for="username" style="width: 12rem;">변경할 비밀번호</p>
-               <input class="data-wrap" type="text" id="username" v-model="changeUserPw" placeholder="변경할 비밀번호를 입력하세요.">
+               <p class="title2" for="username" style="width: 14rem;">변경할 비밀번호</p>
+               <input class="data-wrap" type="password" id="username" v-model="changeUserPw" placeholder="변경할 비밀번호를 입력하세요." style="width: 45rem;" >
             </div>
-            <p class="title2 mb20 flex align-center help" for="username"><img src="../resources/img/img193_78p.png"
-                     alt=""><em class="gray ml10">영문, 숫자, 특수문자 3가지를 조합하여 주세요.(6자리 이상)</em></p>
             <div class="mb20 flex justify-between align-center">
                <p class="title2" for="username" style="width: 12rem;">비밀번호 확인</p>
-               <input class="data-wrap" type="text" id="username" v-model="changeUserPwCheck" placeholder="변경할 비밀번호를 입력하세요.">
+               <input class="data-wrap" type="password" id="username" v-model="changeUserPwCheck" placeholder="변경할 비밀번호를 입력하세요." style="width: 45rem;" >
             </div>
             <div class="flex justify-center ">
                <button type="button" title="글쓰기" class="new-btn mr10" @click="closeBtn">
@@ -164,6 +162,9 @@
          findTel2: '',
          findTel3: '',
          findUserInfo : {},
+         changeLoginId:'',
+         changeUserPw: '',
+         changeUserPwCheck: '',
       }
    },
    methods: {
@@ -264,7 +265,53 @@
          });
       },
 
-      // 비밀번호 확인하기
+      // 비밀번호 재설정하기
+      changePw() {
+         const vm = this;
+
+         const passwordPattern = /^(?=.*[a-zA-Z])(?=.*\d)(?=.*[!@#$%^&*])[A-Za-z\d!@#$%^&*]{6,}$/;
+
+         if (!vm.changeLoginId) {
+            alert("아이디가 비어 있습니다!");
+            return;
+         }
+
+         if (!vm.changeUserPw) {
+            alert("비밀번호가 비어 있습니다!");
+            return;
+         }
+
+         if (vm.changeUserPw !== vm.changeUserPwCheck) {
+            alert("비밀번호가 일치하지 않습니다.");
+            return;
+         }
+
+         if (!passwordPattern.test(vm.changeUserPw)) {
+            alert("비밀번호는 영문, 숫자, 특수문자를 조합하여 6자리 이상이어야 합니다.");
+            return;
+         }
+
+
+         axios({
+            url: "/auth/resetPassword.json",
+            method: "post",
+            data: {
+               loginId: vm.changeLoginId,
+               newPassword: vm.changeUserPw,
+            },
+         }).then(function (response) {
+            if (response.data.status === 'success') {
+               alert("비밀번호 변경에 성공했습니다!")
+               vm.selectedTab = 'tab4';
+            } else {
+               alter(response.data.message);
+            }
+
+         }).catch(function (error) {
+            alert("비밀번호 변경에 오류가 발생했습니다!");
+            console.log(error);
+         });
+      },
 
       closeModal() {
          this.showModal = false;
client/views/pages/main/Dashboard.vue
--- client/views/pages/main/Dashboard.vue
+++ client/views/pages/main/Dashboard.vue
@@ -1,11 +1,14 @@
 <template>
-  <p class="title1" v-if="state === 'finish'">
+  <p class="title1" v-if="state === 'finish'" style="position: absolute; top: 50%; transform: translate(0, -50%);">
     오늘 공부를 다했어요! 너무 고생했어요!
   </p>
-  <p class="title1" v-else-if="state === 'notRegistered'">
-    지금은 학습 루트가 등록이 안됐어요! 학습 일정에서 학습루트를 등록해볼까요?
-  </p>
-  <p class="title1" v-else-if="state === 'noProblem'">
+  <div class="title1" v-else-if="state === 'notRegistered'" style="position: absolute; top: 50%; transform: translate(0, -50%);">
+    <div>
+      <h3>지금은 학습 루트가 등록이 안됐어요! 학습 일정에서 학습루트를 등록해볼까요?</h3>
+    <button type="button" title="바로가기" class="yellow-btn" @click="goToPage2('MyPlan2')">바로가기</button>
+    </div>
+  </div>
+  <p class="title1" v-else-if="state === 'noProblem'" style="position: absolute; top: 50%; transform: translate(0, -50%);">
     교재에 등록된 문제가 없습니다.
   </p>
   <div v-else class="main">
@@ -26,12 +29,12 @@
             </div>
             <button class="popTxt" v-for="(item, index) in items" :key="index" @click="toggleImage(index)" data-num="1">
               <img :src="labeledItems[0].label.length >= 4
-                  ? item.imgSrc3
-                  : item.imgSrc1
+                ? item.imgSrc3
+                : item.imgSrc1
                 " :style="{ display: !rabbitCompl[1] ? 'block' : 'none' }" />
               <img :src="labeledItems[0].label.length >= 4
-                  ? item.imgSrc4
-                  : item.imgSrc2
+                ? item.imgSrc4
+                : item.imgSrc2
                 " :style="{ display: rabbitCompl[1] ? 'block' : 'none' }" />
             </button>
             <p>{{ labeledItems[0].label }}</p>
@@ -43,12 +46,12 @@
             </div>
             <button class="popTxt" v-for="(item, index) in items" :key="index" @click="toggleImage(index)" data-num="2">
               <img :src="labeledItems[1].label.length >= 4
-                  ? item.imgSrc3
-                  : item.imgSrc1
+                ? item.imgSrc3
+                : item.imgSrc1
                 " :style="{ display: !rabbitCompl[2] ? 'block' : 'none' }" />
               <img :src="labeledItems[1].label.length >= 4
-                  ? item.imgSrc4
-                  : item.imgSrc2
+                ? item.imgSrc4
+                : item.imgSrc2
                 " :style="{ display: rabbitCompl[2] ? 'block' : 'none' }" />
             </button>
             <p>{{ labeledItems[1].label }}</p>
@@ -62,12 +65,12 @@
             </div>
             <button class="popTxt" v-for="(item, index) in items" :key="index" @click="toggleImage(index)" data-num="7">
               <img :src="labeledItems[6].label.length >= 4
-                  ? item.imgSrc3
-                  : item.imgSrc1
+                ? item.imgSrc3
+                : item.imgSrc1
                 " :style="{ display: !rabbitCompl[7] ? 'block' : 'none' }" />
               <img :src="labeledItems[6].label.length >= 4
-                  ? item.imgSrc4
-                  : item.imgSrc2
+                ? item.imgSrc4
+                : item.imgSrc2
                 " :style="{ display: rabbitCompl[7] ? 'block' : 'none' }" />
             </button>
             <p>{{ labeledItems[6].label }}</p>
@@ -79,12 +82,12 @@
             </div>
             <button class="popTxt" v-for="(item, index) in items" :key="index" @click="toggleImage(index)" data-num="6">
               <img :src="labeledItems[5].label.length >= 4
-                  ? item.imgSrc3
-                  : item.imgSrc1
+                ? item.imgSrc3
+                : item.imgSrc1
                 " :style="{ display: !rabbitCompl[6] ? 'block' : 'none' }" />
               <img :src="labeledItems[5].label.length >= 4
-                  ? item.imgSrc4
-                  : item.imgSrc2
+                ? item.imgSrc4
+                : item.imgSrc2
                 " :style="{ display: rabbitCompl[6] ? 'block' : 'none' }" />
             </button>
             <p>{{ labeledItems[5].label }}</p>
@@ -96,12 +99,12 @@
             </div>
             <button class="popTxt" v-for="(item, index) in items" :key="index" @click="toggleImage(index)" data-num="5">
               <img :src="labeledItems[4].label.length >= 4
-                  ? item.imgSrc3
-                  : item.imgSrc1
+                ? item.imgSrc3
+                : item.imgSrc1
                 " :style="{ display: !rabbitCompl[5] ? 'block' : 'none' }" />
               <img :src="labeledItems[4].label.length >= 4
-                  ? item.imgSrc4
-                  : item.imgSrc2
+                ? item.imgSrc4
+                : item.imgSrc2
                 " :style="{ display: rabbitCompl[5] ? 'block' : 'none' }" />
             </button>
             <p>{{ labeledItems[4].label }}</p>
@@ -113,12 +116,12 @@
             </div>
             <button class="popTxt" v-for="(item, index) in items" :key="index" @click="toggleImage(index)" data-num="4">
               <img :src="labeledItems[3].label.length >= 4
-                  ? item.imgSrc3
-                  : item.imgSrc1
+                ? item.imgSrc3
+                : item.imgSrc1
                 " :style="{ display: !rabbitCompl[4] ? 'block' : 'none' }" />
               <img :src="labeledItems[3].label.length >= 4
-                  ? item.imgSrc4
-                  : item.imgSrc2
+                ? item.imgSrc4
+                : item.imgSrc2
                 " :style="{ display: rabbitCompl[4] ? 'block' : 'none' }" />
             </button>
             <p>{{ labeledItems[3].label }}</p>
@@ -130,12 +133,12 @@
             </div>
             <button class="popTxt" v-for="(item, index) in items" :key="index" @click="toggleImage(index)" data-num="3">
               <img :src="labeledItems[2].label.length >= 4
-                  ? item.imgSrc3
-                  : item.imgSrc1
+                ? item.imgSrc3
+                : item.imgSrc1
                 " :style="{ display: !rabbitCompl[3] ? 'block' : 'none' }" />
               <img :src="labeledItems[2].label.length >= 4
-                  ? item.imgSrc4
-                  : item.imgSrc2
+                ? item.imgSrc4
+                : item.imgSrc2
                 " :style="{ display: rabbitCompl[3] ? 'block' : 'none' }" />
             </button>
             <p>{{ labeledItems[2].label }}</p>
@@ -151,12 +154,12 @@
             </div>
             <button class="popTxt" v-for="(item, index) in items" :key="index" @click="toggleImage(index)" data-num="8">
               <img :src="labeledItems[7].label.length >= 4
-                  ? item.imgSrc3
-                  : item.imgSrc1
+                ? item.imgSrc3
+                : item.imgSrc1
                 " :style="{ display: !rabbitCompl[8] ? 'block' : 'none' }" />
               <img :src="labeledItems[7].label.length >= 4
-                  ? item.imgSrc4
-                  : item.imgSrc2
+                ? item.imgSrc4
+                : item.imgSrc2
                 " :style="{ display: rabbitCompl[8] ? 'block' : 'none' }" />
             </button>
             <p class="long">{{ labeledItems[7].label }}</p>
@@ -168,12 +171,12 @@
             </div>
             <button class="popTxt" v-for="(item, index) in items" :key="index" @click="toggleImage(index)" data-num="9">
               <img :src="labeledItems[8].label.length >= 4
-                  ? item.imgSrc3
-                  : item.imgSrc1
+                ? item.imgSrc3
+                : item.imgSrc1
                 " :style="{ display: !rabbitCompl[9] ? 'block' : 'none' }" />
               <img :src="labeledItems[8].label.length >= 4
-                  ? item.imgSrc4
-                  : item.imgSrc2
+                ? item.imgSrc4
+                : item.imgSrc2
                 " :style="{ display: rabbitCompl[9] ? 'block' : 'none' }" />
             </button>
             <p>{{ labeledItems[8].label }}</p>
@@ -186,12 +189,12 @@
             <button class="popTxt" v-for="(item, index) in items" :key="index" @click="toggleImage(index)"
               data-num="10">
               <img :src="labeledItems[9].label.length >= 4
-                  ? item.imgSrc3
-                  : item.imgSrc1
+                ? item.imgSrc3
+                : item.imgSrc1
                 " :style="{ display: !rabbitCompl[10] ? 'block' : 'none' }" />
               <img :src="labeledItems[9].label.length >= 4
-                  ? item.imgSrc4
-                  : item.imgSrc2
+                ? item.imgSrc4
+                : item.imgSrc2
                 " :style="{ display: rabbitCompl[10] ? 'block' : 'none' }" />
             </button>
             <p>{{ labeledItems[9].label }}</p>
@@ -207,12 +210,12 @@
             <button class="popTxt" v-for="(item, index) in items" :key="index"
               @click="toggleImageAndShowPopup(index, '11')" data-num="11">
               <img :src="labeledItems[10].label.length >= 4
-                  ? item.imgSrc3
-                  : item.imgSrc1
+                ? item.imgSrc3
+                : item.imgSrc1
                 " :style="{ display: !rabbitCompl[11] ? 'block' : 'none' }" />
               <img :src="labeledItems[10].label.length >= 4
-                  ? item.imgSrc4
-                  : item.imgSrc2
+                ? item.imgSrc4
+                : item.imgSrc2
                 " :style="{ display: rabbitCompl[11] ? 'block' : 'none' }" />
             </button>
             <p class="long">{{ labeledItems[10].label }}</p>
@@ -430,6 +433,7 @@
 
       if (!book_id || !unit_id) {
         console.error("book_id 또는 unit_id가 설정되지 않았습니다.");
+        this.state = "notRegistered";
         return;
       }
       this.fetchImage(unit_id);
@@ -667,6 +671,14 @@
       // this.$router.push({ name: page, query: { unit_id, book_id } });
       this.$router.push({ name: page });
     },
+    goToPage2(page, unit_id) {
+      this.$router.push({
+        name: page, query: {
+          unit_id: unit_id,
+        },
+      });
+    },
+
     storeLearningId(labeledItems) {
       this.$store.dispatch("updateLearningData", labeledItems);
       this.$store.dispatch("updateLearningId", labeledItems.learning_id); // 단어장에 사용중..
Add a comment
List