Bladeren bron

Merge branch 'master' of https://gogs.interscope.i234.me/mo0647/influence

DESKTOP-T61HUSC\user 5 maanden geleden
bovenliggende
commit
89d0a25281
11 gewijzigde bestanden met toevoegingen van 534 en 144 verwijderingen
  1. 1 0
      .env
  2. 2 1
      .env.development
  3. BIN
      assets/img/inf_bg.png
  4. BIN
      assets/img/ven_bg.png
  5. 128 0
      assets/scss/main.scss
  6. 12 1
      components/common/header.vue
  7. 2 3
      middleware/auth.global.js
  8. 1 1
      nuxt.config.ts
  9. 202 52
      pages/auth/join.vue
  10. 3 2
      pages/auth/popupClose.vue
  11. 183 84
      pages/index.vue

+ 1 - 0
.env

@@ -2,6 +2,7 @@
 VITE_APP_BASE_URL="/"
 VITE_APP_API_URL="https://shopdeli.mycafe24.com"
 VITE_APP_API_PORT=8080
+VITE_APP_API_DOMAIN="https://shopdeli.mycafe24.com"
 VITE_APP_DEBUG_LEVEL=trace
 VITE_APP_MODE=prod
 VITE_APP_KAKAO_APP_KEY=""

+ 2 - 1
.env.development

@@ -1,7 +1,8 @@
 #import.meta.env로 호출 가능
 VITE_APP_BASE_URL="/"
-VITE_APP_API_URL="https://shopdeli.mycafe24.com"
+VITE_APP_API_URL="http://localhost:3000"
 VITE_APP_API_PORT=8080
+VITE_APP_API_DOMAIN="https://shopdeli.mycafe24.com"
 VITE_APP_DEBUG_LEVEL=trace
 VITE_APP_MODE=development
 VITE_APP_KAKAO_APP_KEY=""

BIN
assets/img/inf_bg.png


BIN
assets/img/ven_bg.png


+ 128 - 0
assets/scss/main.scss

@@ -452,3 +452,131 @@ html {
 .fts--14{
   font-size:14px!important;
 }
+
+
+.agree--box{
+  gap:20px;
+}
+
+.login--gate{
+  width:100%;
+  height:100%;
+  position: fixed;
+  top:0px;
+  left:0px;
+  z-index: 9999999;
+  > div{
+    .btn--contents{
+      display: flex;
+      flex-direction: column;
+      position: relative;
+      z-index: 2;      
+      > h2{
+        color:#fff;
+        font-size:40px;
+        font-weight: 900;
+        text-transform: uppercase;
+        text-shadow:2px 2px 2px rgba(0,0,0,0.4) ;
+      }
+      .loc--btn{
+        margin-top:25px;
+        border-radius: 50px;
+        border:1px solid #fff;
+        background: rgba(255,255,255,.5);
+        color:#000;
+        font-weight: 900;
+        box-shadow: none;
+      }
+    }
+  }
+  .inf--gate{
+    width:50%;
+    height: 100%;
+    background: #6fbac3;
+    position: absolute;
+    left:0px;
+    top:0px;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    transition: all 0.7s cubic-bezier(0.25, 0.8, 0.25, 1);
+    
+    &.actv{
+      width:60%;
+      z-index: 9;
+
+      .btn--contents{
+        h2{
+          font-size:80px;
+        }
+      }
+      &:after{
+        width:80px;
+        height:80px;
+        top:20px;
+        left:20px;
+        transform: translate(0,0);
+      }
+    }
+    &:after{
+      content:'';
+      display: block;
+      width:60%;
+      height:60%;
+      background: url(../img/inf_bg.png) no-repeat center;
+      background-size: contain;
+      position: absolute;
+      top:50%;
+      left:50%;
+      transform: translate(-50%,-50%);
+      opacity: .3;      
+      z-index: 1;
+      transition: all 0.7s cubic-bezier(0.25, 0.8, 0.25, 1);
+    }
+  }
+  .ven--gate{
+    width:50%;
+    height:100%;
+    background: #ec7360;
+    position: absolute;
+    right:0px;
+    
+    top:0px;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    transition: all 0.7s cubic-bezier(0.25, 0.8, 0.25, 1);
+    &.actv{
+      width:60%;
+      z-index: 9;
+      .btn--contents{
+        h2{
+          font-size:80px;
+        }
+      }
+      &:after{
+        width:80px;
+        height:80px;
+        top:20px;
+        right:20px;
+        left:auto;
+        transform: translate(0,0);
+      }
+    }
+    &:after{
+      content:'';
+      display: block;
+      width:60%;
+      height:45%;
+      background: url(../img/ven_bg.png) no-repeat center;
+      background-size: contain;
+      position: absolute;
+      top:50%;
+      left:50%;
+      transform: translate(-50%,-50%);
+      opacity: .3;      
+      z-index: 1;
+      transition: all 0.7s cubic-bezier(0.25, 0.8, 0.25, 1);
+    }
+  }
+}

+ 12 - 1
components/common/header.vue

@@ -122,10 +122,20 @@
     let _req = {
       SEQ: useStoreAuth.getSnsTempData.user.SEQ,
       GOOGLE_REFRESH_TOKEN: useStoreAuth.getSnsTempData.user.GOOGLE_REFRESH_TOKEN,
+      KAKAO_REFRESH_TOKEN: useStoreAuth.getSnsTempData.user.KAKAO_REFRESH_TOKEN,
+      NAVER_REFRESH_TOKEN: useStoreAuth.getSnsTempData.user.NAVER_REFRESH_TOKEN,
     };
 
+    let _uri = useStoreAuth.getSnsTempData.user.GOOGLE_REFRESH_TOKEN
+      ? "/auth/withdrawal"
+      : useStoreAuth.getSnsTempData.user.KAKAO_REFRESH_TOKEN
+      ? "/auth/kakaowithdrawal"
+      : useStoreAuth.getSnsTempData.user.NAVER_REFRESH_TOKEN
+      ? "/auth/naverwithdrawal"
+      : "/auth/withdrawal";
+
     useAxios()
-      .post("/auth/withdrawal", _req)
+      .post(_uri, _req)
       .then((res) => {
         localStorage.removeItem("tempAccess");
         useStore.getSnsTempData = "";
@@ -158,6 +168,7 @@
 |    라이프사이클 : onMounted
 ************************************************************************/
   onMounted(() => {
+    console.log(useStoreAuth.getSnsTempData.user);
     userId.value = localStorage.getItem("tempAccess");
     userName.value = JSON.parse(localStorage.getItem("authStore"))?.auth.name;
     userCompanyName.value = JSON.parse(

+ 2 - 3
middleware/auth.global.js

@@ -6,8 +6,7 @@ export default defineNuxtRouteMiddleware(async (to, from) => {
   const tokenPassPages = [
     '/', 
     '/roulette',    
-    '/auth/popupClose',    
-    '/auth/join'
+    '/auth'    
   ]
   //let accountValue = useAuthStore().getAccountRole.charAt(0).toUpperCase()
 
@@ -22,7 +21,7 @@ export default defineNuxtRouteMiddleware(async (to, from) => {
   }
 
   // 2. 토큰 체크 (모든 페이지)
-  if (!tokenPassPages.includes(to.path)) {
+  if (!tokenPassPages.includes(to.path) && !tokenPassPages.some(path => path !== '/' && to.path.startsWith(path + '/'))) {
     const accessToken = useAuthStore().getAccessToken
     if (!accessToken || accessToken === '' || typeof accessToken !== 'string') {
       $log.error('[ 페이지 접근 불가] 인증되지 않은 사용자입니다.')

+ 1 - 1
nuxt.config.ts

@@ -24,7 +24,7 @@ export default defineNuxtConfig({
   },  
   devtools: { enabled: false },
   devServer : {
-    host: '0.0.0.0'
+    //host: '0.0.0.0'
   },
   build: {
     transpile: ['vuetify'],   

+ 202 - 52
pages/auth/join.vue

@@ -14,17 +14,18 @@
     <div class="login-box type--join">
       <div class="login-r">
         <h2 class="mk--title">{{ titleh }}</h2>
-        <div class="join--type">
+        <!-- <div class="join--type">
           <v-radio-group v-model="form.formValue0" row inline class="custom-radio type2">
-            <v-radio value="Y" label="인플루언"></v-radio>
+            <v-radio value="Y" label="인플루언"></v-radio>
             <v-radio value="N" label="벤더"></v-radio>
           </v-radio-group>
-        </div>
+        </div> -->
         <div class="tit-login">
           <strong>회원가입</strong>
           <span><i>*</i>필수입력 항목</span>
         </div>
-        <div class="login-input-wrap">
+
+        <div v-show="form.formValue0 === 'Y'" class="login-input-wrap">
           <div class="txt-field-box">
             <v-text-field
               :disabled="useStore.getSnsTempData?.ID ? true : false"
@@ -150,10 +151,126 @@
             ></v-textarea>
           </div>
         </div>
-        {{ useStore.getSnsTempData }}
+
+        <div v-show="form.formValue0 === 'N'" class="login-input-wrap">
+          <div class="txt-field-box">
+            <v-text-field
+              v-model="formVendor.formValue1"
+              placeholder="아이디를 입력해주세요"
+              class="custom-input"
+            ></v-text-field>
+          </div>
+
+          <div class="txt-field-box">
+            <v-text-field
+              v-model="formVendor.formValue2"
+              :type="visible ? 'text' : 'password'"
+              placeholder="패스워드를 입력해주세요."
+              class="custom-input"
+              id="password"
+            ></v-text-field>
+            <i
+              class="ico-eye"
+              @click.stop="toggleVisibility"
+              :class="visible ? 'eye-on' : 'eye-off'"
+            ></i>
+            <i class="ico"></i>
+          </div>
+
+          <div class="txt-field-box">
+            <v-text-field
+              v-model="formVendor.formValue3"
+              :type="visible ? 'text' : 'password'"
+              placeholder="패스워드 확인"
+              class="custom-input"
+            ></v-text-field>
+            <i
+              class="ico-eye"
+              @click.stop="toggleVisibility"
+              :class="visible ? 'eye-on' : 'eye-off'"
+            ></i>
+            <i class="ico"></i>
+          </div>
+
+          <div class="txt-field-box">
+            <v-text-field
+              v-model="formVendor.formValue4"
+              :maxlength="20"
+              :counter="20"
+              placeholder="회사명"
+              class="custom-input"
+            ></v-text-field>
+          </div>
+
+          <div class="txt-field-box">
+            <v-text-field
+              v-model="formVendor.formValue5"
+              :maxlength="20"
+              :counter="20"
+              placeholder="담당자 명"
+              class="custom-input"
+            ></v-text-field>
+          </div>
+
+          <div class="txt-field-box phone">
+            <v-text-field
+              placeholder=""
+              class="custom-input"
+              v-model="formVendor.formValue8"
+            ></v-text-field>
+            -
+            <v-text-field
+              placeholder="1234"
+              class="custom-input"
+              v-model="formVendor.formValue9"
+            ></v-text-field>
+            -
+            <v-text-field
+              placeholder="5678"
+              class="custom-input"
+              v-model="formVendor.formValue10"
+            ></v-text-field>
+          </div>
+
+          <div class="txt-field-box email">
+            <v-text-field
+              v-model="formVendor.formValue12"
+              class="custom-input"
+              placeholder=""
+            ></v-text-field>
+            <span v-if="formVendor.formValue11 != 'direct'">@</span>
+            <v-select
+              v-model="formVendor.formValue11"
+              :items="formVendor.formValueItems11"
+              item-title="text"
+              item-value="value"
+              class="custom-select"
+            ></v-select>
+          </div>
+
+          <div class="mt-5 d-flex agree--box">
+            <v-checkbox class="custom-check type2" v-model="formVendor.formValue13">
+              <template v-slot:label>개인정보약관동의</template>
+            </v-checkbox>
+            <v-checkbox class="custom-check type2" v-model="formVendor.formValue14">
+              <template v-slot:label>제3자 정보동의</template>
+            </v-checkbox>
+          </div>
+        </div>
 
         <div class="login-btn-wrap">
-          <v-btn class="custom-btn btn-blue" @click.stop="joinMember">회원가입</v-btn>
+          <v-btn
+            v-show="form.formValue0 === 'Y'"
+            class="custom-btn btn-blue"
+            @click.stop="joinMember('influence')"
+            >회원가입</v-btn
+          >
+          <v-btn
+            v-show="form.formValue0 === 'N'"
+            class="custom-btn btn-blue"
+            @click.stop="joinMember('vendor')"
+            >회원가입</v-btn
+          >
         </div>
       </div>
     </div>
@@ -184,8 +301,9 @@
   /************************
    *    전역
    ************************/
-  const titleh = ref("인플루언");
+  const titleh = ref("인플루언");
   const useStore = useAuthStore();
+  const randomString = ref("");
 
   //인플루언서 폼
   const form = ref({
@@ -251,66 +369,92 @@
 
   //밴더 폼
   const formVendor = ref({
-    formValue0: "N",
+    formValue0: "",
     formValue1: "", // 아이디
     formValue2: "", // 패스워드
     formValue3: "", // 패스워드 확인
     formValue4: "", // 닉네임
     formValue5: "", // 이름
     formValue6: "소셜채널 선택", // 소셜 채널
+    formValue7: "", // 소셜 ID 또는 주소
+    formValue8: "010", // 휴대폰1
+    formValue9: "", // 휴대폰2
+    formValue10: "", // 휴대폰3
+    formValue11: "email", // 이메일1
+    formValueItems11: [
+      {
+        text: "이메일 선택",
+        value: "email",
+      },
+      {
+        text: "직접입력",
+        value: "direct",
+      },
+      {
+        text: "naver.com",
+        value: "naver",
+      },
+      {
+        text: "gmail.com",
+        value: "gmail",
+      },
+      {
+        text: "daum.net",
+        value: "daum",
+      },
+    ], // 이메일 아이템
+    formValue12: "",
+    formValue13: "", // 개인정보약관동의
+    formValue14: "", // 제3자 정보동의
   });
 
   /************************
    *    함수
    ************************/
 
-  const joinMember = () => {
-    /*
-      제출내용 :
-      1. 인플루언서
-        일반회원 인경우
-        - 아이디
-        - 패스워드
-        - 패스워드 확인
-        - 닉네임
-        - 이름
-        - 소셜 채널
-        - 소셜 ID 또는 주소
-        - 휴대폰 번호
-        - 이메일
-        - 자기소개
-
-
-      2. 소셜계정일경우
-        - 아이디 : 자동입력
-        - 패스워드 : 비번은 미입력
-        - 패스워드 확인 : 비번은 미입력
-        - 닉네임
-        - 이름 : 자동입력
-        - 소셜 채널
-        - 소셜 ID 또는 주소
-        - 휴대폰 번호
-        - 이메일 : 자동입력
-        - 자기소개
-    */
+  const generateRandomAlphanumeric = (length) => {
+    const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
+    let result = "";
+    const charsLength = chars.length;
+    for (let i = 0; i < length; i++) {
+      result += chars.charAt(Math.floor(Math.random() * charsLength));
+    }
+    return result;
+  };
 
-    // 여기에 폼 제출 로직을 추가하세요.
-    let _req = {
-      ID: form.value.formValue1,
-      PASSWORD: form.value.formValue2,
-      NAME: form.value.formValue5,
-      NICK_NAME: form.value.formValue4 || "", //닉네임 없으면 빈문자
-      PHONE: `${form.value.formValue8}-${form.value.formValue9}-${form.value.formValue10}`,
-      EMAIL: form.value.formValue12,
-      SNS_TYPE: form.value.formValue6,
-      SNS_LINK_ID: form.value.formValue7,
-      ADD_INFO1: form.value.formValue13,
-      GOOGLE_REFRESH_TOKEN: useStore.getSnsTempData?.GOOGLE_REFRESH_TOKEN || "",
-      TYPE: useStore.getSnsTempData ? "1" : "0", // SNS 가입일경우 1, 일반회원 가입일경우 0
-    };
+  const joinMember = (id_type) => {
+    let _req = "";
+    let _api = "";
+    if (id_type === "influence") {
+      _api = "/auth/joinmember";
+      _req = {
+        ID: form.value.formValue1,
+        PASSWORD: form.value.formValue2,
+        NAME: form.value.formValue5,
+        NICK_NAME: form.value.formValue4 || "", //닉네임 없으면 빈문자
+        PHONE: `${form.value.formValue8}-${form.value.formValue9}-${form.value.formValue10}`,
+        EMAIL: form.value.formValue12,
+        SNS_TYPE: form.value.formValue6,
+        SNS_LINK_ID: form.value.formValue7,
+        ADD_INFO1: form.value.formValue13,
+        GOOGLE_REFRESH_TOKEN: useStore.getSnsTempData?.GOOGLE_REFRESH_TOKEN || "",
+        TYPE: useStore.getSnsTempData ? "1" : "0", // SNS 가입일경우 1, 일반회원 가입일경우 0
+      };
+    } else {
+      _api = "/auth/joinvendor";
+      _req = {
+        ID: formVendor.value.formValue1,
+        PASSWORD: formVendor.value.formValue3,
+        COMPANY_NAME: formVendor.value.formValue4,
+        COMPANY_NUMBER: (randomString.value = generateRandomAlphanumeric(100)),
+        NAME: formVendor.value.formValue5,
+        HP: `${formVendor.value.formValue8}-${formVendor.value.formValue9}-${formVendor.value.formValue10}`,
+        EMAIL: formVendor.value.formValue12,
+      };
+    }
 
     useAxios()
-      .post("/auth/joinmember", _req)
+      .post(_api, _req)
       .then((res) => {
         if (_req.TYPE === "1") {
           // SNS 가입일 경우
@@ -343,6 +487,12 @@
    *    마운트
    ************************/
   onMounted(() => {
+    const route = useRoute();
+    const typeParam = route.query.type;
+    typeParam === "influence"
+      ? (form.value.formValue0 = "Y")
+      : (form.value.formValue0 = "N");
+
     if (useStore.getSnsTempData?.EMAIL) {
       form.value.formValue12 = useStore.getSnsTempData.EMAIL;
       form.value.formValue11 = "direct"; // 이메일 직접입력으로 설정

+ 3 - 2
pages/auth/popupClose.vue

@@ -6,6 +6,7 @@
     const accessToken = q.get("accessToken");
     const refreshToken = q.get("refreshToken");
     const user = q.get("user") ? JSON.parse(decodeURIComponent(q.get("user"))) : null;
+    const targetOrigin = import.meta.env.VITE_APP_BASE_URL;
 
     // If joinType is 'influencer', you can handle it here if needed
     if (user.JOIN === "1") {
@@ -13,7 +14,7 @@
         {
           user,
         },
-        "http://0.0.0.0:3000"
+        targetOrigin
       );
 
       window.close();
@@ -24,7 +25,7 @@
           refreshToken,
           user,
         },
-        "http://0.0.0.0:3000"
+        targetOrigin
       );
 
       window.close();

+ 183 - 84
pages/index.vue

@@ -1,95 +1,114 @@
 <template>
   <div class="login-wrap">
-    <!-- header -->
-    <div class="login--header">
-      <div class="login--header--l">
-        <div class="logo">
-          <!-- prettier-ignore  -->
-          SHOPDELI
+    <div class="login--gate" v-show="loginVisible == 'Y'">
+      <div class="inf--gate" :class="gate1 ? 'actv' : ''">
+        <div class="btn--contents" @mouseenter.stop="[(gate1 = !gate1), (gate2 = false)]">
+          <h2>influence</h2>
+          <v-btn class="loc--btn" @click.stop="location('influence')"
+            >Discover more ></v-btn
+          >
+        </div>
+      </div>
+      <div class="ven--gate" :class="gate2 ? 'actv' : ''">
+        <div class="btn--contents" @mouseenter.stop="[(gate2 = !gate2), (gate1 = false)]">
+          <h2>vendor</h2>
+          <v-btn class="loc--btn" @click.stop="location('vendor')">Discover more ></v-btn>
         </div>
       </div>
-      <div class="login--header--r"></div>
     </div>
-    <!-- login -->
-    <div class="login-box">
-      <div class="login-l">
-        <div class="login-l-center">
-          <span class="logo">
+
+    <div class="login--cock" v-show="loginVisible == 'N'">
+      <!-- header -->
+      <div class="login--header">
+        <div class="login--header--l">
+          <div class="logo">
             <!-- prettier-ignore  -->
             SHOPDELI
-          </span>
-          <!-- <p>We Make Scalable Mobility Life</p> -->
+          </div>
         </div>
+        <div class="login--header--r"></div>
       </div>
-      <div class="login-r">
-        <div class="tit-login">
-          <strong>로그인</strong>
+      <!-- login -->
+      <div class="login-box">
+        <div class="login-l">
+          <div class="login-l-center">
+            <span class="logo">
+              <!-- prettier-ignore  -->
+              SHOPDELI
+            </span>
+            <!-- <p>We Make Scalable Mobility Life</p> -->
+          </div>
         </div>
-        <div class="login-input-wrap">
-          <div
-            class="txt-field-box"
-            :class="!loginForm.validCheck.input.userId ? 'error' : ''"
-          >
-            <v-text-field
-              v-model="loginForm.userId"
-              placeholder="아이디를 입력해주세요"
-              class="custom-input"
-              @keyup.enter="loginAction(loginForm.userId, loginForm.passwd)"
-              @input="setInputField('main_userId')"
-            ></v-text-field>
-            <i class="ico"></i>
+        <div class="login-r">
+          <div class="tit-login">
+            <strong>로그인</strong>
           </div>
-          <div
-            class="txt-field-box"
-            :class="!loginForm.validCheck.input.passwd ? 'error' : ''"
-          >
-            <v-text-field
-              v-model="loginForm.passwd"
-              :type="visible ? 'text' : 'password'"
-              placeholder="비밀번호를 입력해주세요"
-              class="custom-input"
-              id="password"
-              @keyup.enter="loginAction(loginForm.userId, loginForm.passwd)"
-              @input="setInputField('main_passwd')"
-            ></v-text-field>
-            <i
-              class="ico-eye"
-              @click.stop="toggleVisibility"
-              :class="visible ? 'eye-on' : 'eye-off'"
-            ></i>
-            <i class="ico"></i>
+          <div class="login-input-wrap">
+            <div
+              class="txt-field-box"
+              :class="!loginForm.validCheck.input.userId ? 'error' : ''"
+            >
+              <v-text-field
+                v-model="loginForm.userId"
+                placeholder="아이디를 입력해주세요"
+                class="custom-input"
+                @keyup.enter="loginAction(loginForm.userId, loginForm.passwd)"
+                @input="setInputField('main_userId')"
+              ></v-text-field>
+              <i class="ico"></i>
+            </div>
+            <div
+              class="txt-field-box"
+              :class="!loginForm.validCheck.input.passwd ? 'error' : ''"
+            >
+              <v-text-field
+                v-model="loginForm.passwd"
+                :type="visible ? 'text' : 'password'"
+                placeholder="비밀번호를 입력해주세요"
+                class="custom-input"
+                id="password"
+                @keyup.enter="loginAction(loginForm.userId, loginForm.passwd)"
+                @input="setInputField('main_passwd')"
+              ></v-text-field>
+              <i
+                class="ico-eye"
+                @click.stop="toggleVisibility"
+                :class="visible ? 'eye-on' : 'eye-off'"
+              ></i>
+              <i class="ico"></i>
+            </div>
+            <!-- <p class="error-txt" v-if="!loginForm.validCheck.inputErrorCheck">
+              {{ loginForm.validCheck.passwd }}
+            </p> -->
           </div>
-          <!-- <p class="error-txt" v-if="!loginForm.validCheck.inputErrorCheck">
-            {{ loginForm.validCheck.passwd }}
-          </p> -->
-        </div>
 
-        <div class="login-btn-wrap">
-          <v-btn
-            class="custom-btn btn-blue"
-            @keyup.enter="loginAction(loginForm.userId, loginForm.passwd)"
-            @click="loginAction(loginForm.userId, loginForm.passwd)"
-            >로그인</v-btn
-          >
-        </div>
-        <div class="join--btn--wrap">
-          <v-btn class="custom-btn text--btn">아이디 찾기</v-btn>
-          <v-btn class="custom-btn text--btn">비밀번호 찾기</v-btn>
-          <v-btn class="custom-btn text--btn" @click="location('join')">회원가입</v-btn>
-        </div>
-        <div class="short--login--wrap">
-          <v-btn class="btn--google" @click.stop="onGoogleLogin"></v-btn>
-          <v-btn class="btn--kakao" @click.stop="onKakaoLogin"></v-btn>
-          <v-btn class="btn--naver"></v-btn>
+          <div class="login-btn-wrap">
+            <v-btn
+              class="custom-btn btn-blue"
+              @keyup.enter="loginAction(loginForm.userId, loginForm.passwd)"
+              @click="loginAction(loginForm.userId, loginForm.passwd)"
+              >로그인</v-btn
+            >
+          </div>
+          <div class="join--btn--wrap">
+            <v-btn class="custom-btn text--btn">아이디 찾기</v-btn>
+            <v-btn class="custom-btn text--btn">비밀번호 찾기</v-btn>
+            <v-btn class="custom-btn text--btn" @click="location('join')">회원가입</v-btn>
+          </div>
+          <div class="short--login--wrap" v-if="loginForm.loginType == 'influence'">
+            <v-btn class="btn--google" @click.stop="onGoogleLogin"></v-btn>
+            <v-btn class="btn--kakao" @click.stop="onKakaoLogin"></v-btn>
+            <v-btn class="btn--naver" @click.stop="onNaverLogin"></v-btn>
+          </div>
         </div>
       </div>
-    </div>
 
-    <!-- footer -->
-    <div class="login-footer">
-      <div class="login--footer--l">
-        <p>COPYRIGHT@2025 SHOPDELI INC. ALL RIGHTS RESERVED.</p>
-        <p>마포구 합정동</p>
+      <!-- footer -->
+      <div class="login-footer">
+        <div class="login--footer--l">
+          <p>COPYRIGHT@2025 SHOPDELI INC. ALL RIGHTS RESERVED.</p>
+          <p>마포구 합정동</p>
+        </div>
       </div>
     </div>
   </div>
@@ -118,14 +137,20 @@
   const { $dayjs, $log, $eventBus, $toast, $userAgent } = useNuxtApp();
 
   const useStore = useDetailStore();
+  const route = useRoute();
   /************************
    *    data & created
    ************************/
+
   // 현재 입력 중인 필드를 설정하는 함수
   const setInputField = (name) => {
     fnValidCheck(name);
   };
   const pageId = "login";
+  const gate1 = ref(false);
+  const gate2 = ref(false);
+  const loginVisible = ref("N");
+
   const i18n = useI18n();
   // 다국어
   let listObj = ref({
@@ -139,6 +164,7 @@
     username: "",
     authType: "GOOGLE",
     userAgent: "",
+    loginType: "",
     validCheck: {
       input: {
         userId: true,
@@ -327,7 +353,7 @@
   const location = (__id) => {
     switch (__id) {
       case "join":
-        useUtil.setPageMove("/auth/join");
+        useUtil.setPageMove("/auth/join?type=" + loginForm.value.loginType);
         break;
       case "findId":
         findId.value.popYn = true;
@@ -335,6 +361,14 @@
       case "resetPw":
         resetPw.value.popYn = true;
         break;
+      case "influence":
+        useUtil.setPageMove("/?type=influence");
+        loginVisible.value = "N";
+        break;
+      case "vendor":
+        useUtil.setPageMove("/?type=vendor");
+        loginVisible.value = "N";
+        break;
       default:
         break;
     }
@@ -342,13 +376,26 @@
 
   // onMounted
   onMounted(() => {
+    //로그인페이지 접근시 파라미터 체크하여 인플루언서, 밴더 구분
+    const typeParam = route.query.type;
+    if (typeParam == "influence") {
+      loginForm.value.loginType = "influence";
+    } else if (typeParam == "vendor") {
+      loginForm.value.loginType = "vendor";
+    } else {
+      loginVisible.value = "Y";
+    }
+
     //구글 인증 프로세스
     function handleMessage(event) {
+      const appBaseUrl = import.meta.env.VITE_APP_BASE_URL;
       // 개발환경이면 아래처럼 확인
-      if (
-        event.origin === "http://0.0.0.0:3000" || //배포시 도메인 변경
-        event.origin === "http://localhost:3000" //배포시 도메인 변경
-      ) {
+      const allowedOrigins = [
+        "http://0.0.0.0:3000",
+        "http://localhost:3000",
+        appBaseUrl,
+      ].filter(Boolean);
+      if (allowedOrigins.includes(event.origin)) {
         const { accessToken, refreshToken, user } = event.data;
 
         if (user?.JOIN === "1") {
@@ -369,7 +416,7 @@
           useAuthStore().setTempData(result);
           useAuthStore().setAccessToken(accessToken);
           useAuthStore().setRefreshToken(refreshToken);
-          localStorage.setItem("tempAccess", result.user.NICK_NAME);
+          localStorage.setItem("tempAccess", result.user);
           useUtil.setPageMove("/view/item");
           useStore.menuInfo.menuIndex = "0";
           useStore.menuInfo.menuId = "menu02";
@@ -382,6 +429,21 @@
     onBeforeUnmount(() => window.removeEventListener("message", handleMessage));
   });
 
+  watch(
+    () => route.query.type,
+    (newType) => {
+      if (newType === "influence" || newType === "vendor") {
+        loginForm.value.loginType = newType;
+        loginVisible.value = "N"; // 로그인 폼 보이기
+      } else {
+        loginVisible.value = "Y"; // 게이트 페이지 보이기
+      }
+    },
+    {
+      immediate: true, // 컴포넌트가 마운트될 때 즉시 실행
+    }
+  );
+
   watchEffect(() => {
     // 감시하고자 하는 데이터를 해당 블럭내에서 사용하면 호출된다.
     // getLang.value를 감시하는 상태
@@ -434,9 +496,11 @@
 
   // 구글 로그인 인증 시퀀스
   function onGoogleLogin() {
+    const appBaseUrl = import.meta.env.VITE_APP_API_DOMAIN;
     const clientId =
       "373780605211-diojebh7mug45urv9rnqdil6n0b1ogge.apps.googleusercontent.com"; // 실제 클라이언트 ID로 교체
-    const redirectUri = "https://shopdeli.mycafe24.com/auth/callback"; // 실제 리디렉션 URI로 교체
+    //const redirectUri = "https://shopdeli.mycafe24.com/auth/callback"; // 실제 리디렉션 URI로 교체
+    const redirectUri = `${appBaseUrl}/auth/callback`;
     const scope = "openid email profile";
     const responseType = "code"; // 또는 'code' (백엔드 연동 시)
     const state = Math.random().toString(36).substring(2);
@@ -476,7 +540,8 @@
 
   //카카오 인증 시퀀스
   function onKakaoLogin() {
-    const kakaoAuthUrl = "https://shopdeli.mycafe24.com/auth/kakaoLogin"; // 실제 리디렉션 URI로 교체
+    const appBaseUrl = import.meta.env.VITE_APP_API_DOMAIN;
+    const kakaoAuthUrl = `${appBaseUrl}/auth/kakaoLogin`; // 실제 리디렉션 URI로 교체
 
     const width = 500;
     const height = 600;
@@ -507,6 +572,40 @@
     );
   }
 
+  //네이버 인증 시퀀스
+  function onNaverLogin() {
+    const appBaseUrl = import.meta.env.VITE_APP_BASE_URL;
+    const naverAuthUrl = `${appBaseUrl}/auth/naverLogin`; // 실제 리디렉션 URI로 교체
+
+    const width = 500;
+    const height = 600;
+    const dualScreenLeft =
+      window.screenLeft !== undefined ? window.screenLeft : window.screenX;
+    const dualScreenTop =
+      window.screenTop !== undefined ? window.screenTop : window.screenY;
+
+    const currentWidth = window.innerWidth
+      ? window.innerWidth
+      : document.documentElement.clientWidth
+      ? document.documentElement.clientWidth
+      : screen.width;
+
+    const currentHeight = window.innerHeight
+      ? window.innerHeight
+      : document.documentElement.clientHeight
+      ? document.documentElement.clientHeight
+      : screen.height;
+
+    const left = dualScreenLeft + (currentWidth - width) / 2;
+    const top = dualScreenTop + (currentHeight - height) / 2;
+
+    window.open(
+      naverAuthUrl,
+      "naverLogin",
+      `width=${width},height=${height},left=${left},top=${top},resizable=yes,scrollbars=yes`
+    );
+  }
+
   /**
    * @API
    * 최종 로그인 버튼 클릭 시 API