하석형 하석형 06-23
250623 하석형 사용자페이지 내정보 SNS 계정 연동 설정
@0dea29aba72ab7c3a1729e06a644df2909ecd321
 
client/resources/api/unified.js (added)
+++ client/resources/api/unified.js
@@ -0,0 +1,26 @@
+import apiClient from "./index";
+
+// 연동된 계정 목록 조회
+export const findAllLink = () => {
+    return apiClient.post(`/mbr/unified/linkedAccounts.json`);
+}
+
+// 계정 연동
+export const linkAccount = params => {
+    return apiClient.post(`/mbr/unified/linkAccount.json`, params);
+}
+
+// 계정 연동 해제
+export const unlinkAccount = params => {
+    return apiClient.post(`/mbr/unified/unlinkAccount.json`, params);
+}
+
+// 계정 재연동
+export const reLinkAccount = params => {
+    return apiClient.post(`/mbr/unified/reLinkAccount.json`, params);
+}
+
+// 기본 프로필 설정
+export const setPrimaryProfile = params => {
+    return apiClient.post(`/mbr/unified/setPrimaryProfile.json`, params);
+}(파일 끝에 줄바꿈 문자 없음)
client/views/component/userInfo/UserInfoView.vue
--- client/views/component/userInfo/UserInfoView.vue
+++ client/views/component/userInfo/UserInfoView.vue
@@ -83,7 +83,7 @@
          
                       <div v-if="showOpt.isSmsAgree"  class="layout">
                         <p class="form-title">문자수신</p>
-                        <p>{{ mbrVO.smsRcptnAgreYn }}</p>
+                        <p>{{ mbrVO.smsRcptnAgreYn === 'Y' ? '수신' : '미수신' }}</p>
                         <!-- <div class="check-area">
                           <div class="form-check">
                             <input
@@ -114,7 +114,7 @@
 
                       <div v-if="showOpt.isEmlAgree"  class="layout">
                         <p class="form-title">이메일수신</p>
-                        <p>{{ mbrVO.emlRcptnAgreYn }}</p>
+                        <p>{{ mbrVO.emlRcptnAgreYn === 'Y' ? '수신' : '미수신' }}</p>
                         <!-- <div class="check-area">
                           <div class="form-check">
                             <input
@@ -236,6 +236,9 @@
     <template v-if="pageRole == 'adm' && pageAuth.delAuthrt == 'Y'" class="gd-1">
       <button class="btn sm red" @click="fnDelete">삭제</button>
     </template>
+    <template v-if="pageRole == 'portal' && pageAuth.delAuthrt == 'Y'" class="gd-1">
+      <button class="btn sm red" @click="fnSelfDelete">회원탈퇴</button>
+    </template>
   </div>
 </template>
 
@@ -245,6 +248,7 @@
   defaultAdminInfoParams,
   defaultUserInfoParams,
 } from "../../../resources/js/defaultUserInfoParams";
+import { mapActions } from "vuex";
 
 // COMPONENT
 import UserAuthorList from "./UserAuthorList.vue";
@@ -315,6 +319,7 @@
           }
         }
         this.mbrVO = response.data.data;
+        this.$emit('mbrVO', this.mbrVO);
         this.changeFormat(); // 휴대폰번호, 전화번호, 이메일 표기변경
       } catch (error) {
         const errorData = error.response.data;
@@ -402,6 +407,35 @@
         }
       }
     },
+
+
+    // 회원탈퇴
+    ...mapActions(["logout"]),
+    async fnSelfDelete() {
+      if (this.mbrVO.sysPvsnYn == 0) {
+        alert("시스템에서 제공하는 정보는 삭제할 수 없습니다.");
+        return;
+      }
+      var isDelete = confirm("정말로 회원탈퇴 하시겠습니까?");
+      if (!isDelete) {
+        return;
+      }
+      // 데이터 세팅
+      let data = this.mbrVO;
+      // 실행
+      try {
+        const response = await mbrDeleteProc(data);
+        alert(response.data["message"]);
+        await this.logout();
+      } catch (error) {
+        const errorData = error.response.data;
+        if (errorData.message != null && errorData.message != "") {
+          alert(error.response.data.message);
+        } else {
+          alert("에러가 발생했습니다.\n관리자에게 문의해주세요.");
+        }
+      }
+    },
   },
 };
 </script>
client/views/pages/user/portal/myPage/myInfo/MyInfoView.vue
--- client/views/pages/user/portal/myPage/myInfo/MyInfoView.vue
+++ client/views/pages/user/portal/myPage/myInfo/MyInfoView.vue
@@ -5,13 +5,34 @@
                 <p>내 정보</p>
             </div>
 
-            <UserInfoView :pageId="pageId" />
+            <UserInfoView :pageId="pageId" @child-mbrVO="mbrVO = $event"/>
+            <div>
+                <p>SNS 계정 연동 설정</p>
+            </div>
+            <div>
+                <div v-for="link in linkList" :key="link.id" class="sns-link-item">
+                    <div v-if="linkList.length > 1 && link.lgnOffrType !== 'S'">
+                        <div class="sns-link-info">
+                            <span>{{ convertOffrType(link.lgnOffrType) }}</span>
+                            <!-- <span>{{ link.snsEml }}</span> -->
+                        </div>
+                        <div class="switch-container">
+                            <label class="switch">
+                                <input type="checkbox" v-model="link.linkVtlzYn" @change="toggleLink(link)">
+                                <span class="slider"></span>
+                            </label>
+                            <p>{{ link.linkVtlzYn ? '연동' : '해제' }}</p>
+                        </div>
+                    </div>
+                </div>
+            </div>
         </div>
     </div>
 </template>
 
 <script>
 import pageAuthMixin from "../../../../../../views/common/pageAuthMixin.js";
+import { findAllLink, unlinkAccount, reLinkAccount, setPrimaryProfile } from "../../../../../../resources/api/unified.js";
 // COMPONENETS
 import UserInfoView from "../../../../../component/userInfo/UserInfoView.vue";
 
@@ -23,7 +44,121 @@
     data() {
         return {
             pageId: this.$store.state.mbrId, // 페이지 아이디
+
+            linkList: [], // 연동된 계정 목록
+            mbrVO: {},
         };
     },
+    created() {
+        this.findAllLink(); // 연동된 계정 목록 조회
+    },
+    methods: {
+        // 연동된 계정 목록 조회
+        async findAllLink() {
+            try {
+                const res = await findAllLink();
+                if (res.status == 200) {
+                    this.linkList = res.data.data;
+                }
+            } catch (error) {
+                const errorData = error.response?.data;
+                if (errorData?.message != null && errorData?.message != "") {
+                    alert(error.response.data.message);
+                } else {
+                    alert("에러가 발생했습니다.\n관리자에게 문의해주세요.");
+                }
+            }
+        },
+
+        // 연동 버튼 클릭
+        async toggleLink(link) {
+            const checked = link.linkVtlzYn;
+            if (!confirm(checked ? "연동을 설정하시겠습니까?" : "연동을 해제하시겠습니까?")) {
+                link.linkVtlzYn = !checked; // 체크박스 상태 되돌리기
+                return;
+            }
+
+            const proc = checked ? reLinkAccount : unlinkAccount;
+            try {
+                const res = await proc({ lgnOffrType: link.lgnOffrType });
+                if (res.status == 200) {
+                    alert(res.data.message);
+                }
+            } catch (error) {
+                const errorData = error.response?.data;
+                if (errorData?.message != null && errorData?.message != "") {
+                    alert(error.response.data.message);
+                } else {
+                    alert("에러가 발생했습니다.\n관리자에게 문의해주세요.");
+                }
+            }
+        },
+
+        // SNS 계정 타입 변환
+        convertOffrType(code) {
+            switch (code) {
+                case 'G': return '구글';
+                case 'K': return '카카오';
+                case 'N': return '네이버';
+                case 'S': return '시스템';
+                default: return '기타';
+            }
+        }
+    },
 };
-</script>
(파일 끝에 줄바꿈 문자 없음)
+</script>
+
+<style scoped>
+.switch-container {
+    display: flex;
+    align-items: center;
+    gap: 10px;
+    font-family: Arial, sans-serif;
+}
+
+.switch {
+    position: relative;
+    display: inline-block;
+    width: 50px;
+    height: 28px;
+}
+
+.switch input {
+    opacity: 0;
+    width: 0;
+    height: 0;
+}
+
+.slider {
+    position: absolute;
+    cursor: pointer;
+    background-color: #ccc;
+    transition: 0.4s;
+    border-radius: 34px;
+    top: 0;
+    left: 0;
+    right: 0;
+    bottom: 0;
+}
+
+.slider:before {
+    position: absolute;
+    content: "";
+    height: 20px;
+    width: 20px;
+    left: 4px;
+    bottom: 4px;
+    background-color: white;
+    transition: 0.4s;
+    border-radius: 50%;
+}
+
+/* Checked 상태일 때 */
+input:checked+.slider {
+    background-color: #4caf50;
+}
+
+input:checked+.slider:before {
+    transform: translateX(22px);
+}
+</style>
(파일 끝에 줄바꿈 문자 없음)
Add a comment
List