| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359 |
- <template>
- <div class="login-wrap">
- <!-- header -->
- <div class="login--header">
- <div class="login--header--l">
- <div class="logo">
- <!-- prettier-ignore -->
- SHOPDELI
- </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">
- <!-- prettier-ignore -->
- SHOPDELI
- </span>
- <!-- <p>We Make Scalable Mobility Life</p> -->
- </div>
- </div>
- <div class="login-r">
- <div class="tit-login">
- <strong>로그인</strong>
- </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>
- <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>
- <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="short--login--wrap">
- <v-btn class="btn--google" @click="onGoogleLogin"></v-btn>
- <v-btn class="btn--kakao"></v-btn>
- <v-btn class="btn--naver"></v-btn>
- </div>
- </div>
- </div>
- <!-- footer -->
- <div class="login-footer">
- <div class="login--footer--l">
- <p>COPYRIGHT@2025 SHOPDELI INC. ALL RIGHTS RESERVED.</p>
- <p>마포구 합정동</p>
- </div>
- </div>
- </div>
- </template>
- <script setup>
- /************************
- * import
- ************************/
- //import PrivacyPop from "@/components/login/privacyPop.vue";
- //import AgrNPop from "@/components/terms/agreeNListPop.vue";
- import apiUrl from "@/composables/useApi";
- import QRCode from "qrcode";
- import { useI18n } from "vue-i18n";
- /************************
- * layout setting
- ************************/
- definePageMeta({
- layout: "loginlayout",
- });
- /************************
- * plugins inject
- ************************/
- const { $dayjs, $log, $eventBus, $toast, $userAgent } = useNuxtApp();
- const useStore = useDetailStore();
- /************************
- * data & created
- ************************/
- // 현재 입력 중인 필드를 설정하는 함수
- const setInputField = (name) => {
- fnValidCheck(name);
- };
- const pageId = "login";
- const i18n = useI18n();
- // 다국어
- let listObj = ref({
- langTypeList: {},
- });
- // 로그인 정보
- const loginForm = ref({
- userId: "",
- passwd: "",
- otpNum: "",
- username: "",
- authType: "GOOGLE",
- userAgent: "",
- validCheck: {
- input: {
- userId: true,
- passwd: true,
- },
- otp: {
- otpNum: true,
- },
- inputErrorCheck: true,
- inputValidTxt: "",
- otpValidTxt: "",
- loginValidCheck: false,
- btnTxt: "",
- btnTxtType: "",
- },
- });
- // 구글 OTP 1차 팝업
- const authPop1 = ref({
- popYn: false,
- certifyYN: false,
- userId: "",
- passwd: "",
- otpNum: "",
- validOtpKey: true,
- validOtpTxt: "",
- btnTxt: "",
- btnTxtType: "",
- applyBtn: false,
- succOtpYn: false,
- businessName: "",
- agreeChk1: false,
- agreeChk2: false,
- validCheck: {
- userId: true,
- passwd: true,
- },
- validTxt: "",
- errorCheck: false,
- });
- // 구글 OTP 2차 팝업
- const authPop2 = ref({
- popYn: false,
- otpNum: "",
- validOtpKey: true,
- validOtpTxt: "",
- errorCheck: false,
- });
- // 아이디 찾기
- const findId = ref({
- popYn: false,
- //tenantName: '',
- email: "",
- otpNum: "",
- validCheck: {
- input: {
- //tenantName: true,
- email: true,
- },
- otp: {
- otpNum: true,
- },
- inputErrorCheck: true,
- inputValidTxt: "",
- otpValidTxt: "",
- findIdValidCheck: false,
- },
- btnTxt: "",
- });
- // 비밀번호 초기화
- const resetPw = ref({
- popYn: false,
- userId: "",
- email: "",
- otpNum: "",
- validCheck: {
- input: {
- userId: true,
- email: true,
- },
- otp: {
- otpNum: true,
- },
- inputErrorCheck: true,
- inputValidTxt: "",
- otpValidTxt: "",
- resetPwValidCheck: false,
- },
- btnTxt: "",
- });
- // 초기 패스워드 변경
- const initPw = ref({
- popYn: false,
- passwd: "",
- passwd2: "",
- validCheck: {
- passwd: true,
- passwd2: true,
- },
- passwdCheck: false,
- errorTxt: "",
- });
- const selectPlaceholder = ref("");
- const initAuthPop1 = ref({});
- const initAuthPop2 = ref({});
- const initFindId = ref({});
- const initResetPw = ref({});
- const initInitPw = ref({});
- const googleOtpQrCode = ref("");
- const googleOtpSecretKey = ref("");
- const loginInfo = ref({});
- const checkbox = ref(false);
- const langType = ref("");
- const toggleVisibility = () => {
- visible.value = !visible.value;
- };
- const visible = ref(false);
- const isAgrNPop = ref(false);
- const isShowAgrNPop = ref(false);
- let saveId = localStorage.getItem("saveId");
- if (saveId) {
- checkbox.value = true;
- loginForm.value.userId = saveId;
- }
- // 개인정보처리방침 이용약관 팝업
- //const privacyPop = ref(false);
- const privacyDetail = ref({
- kr: {
- title: "",
- contents: "",
- },
- en: {
- title: "",
- contents: "",
- },
- });
- const systemInfo = ref({
- mode: "",
- });
- const loginAction = (__ID, __PASS) => {
- let _req = {
- id: __ID,
- password: __PASS,
- };
- useAxios()
- .post("/roulette/login", _req)
- .then((res) => {
- if (res.data) {
- useAuthStore().setAuth(res.data);
- useAuthStore().setAccessToken(res.data.accessToken);
- useAuthStore().setRefreshToken(res.data.refreshToken);
- localStorage.setItem("tempAccess", __ID);
- useUtil.setPageMove("/view/item");
- useStore.menuInfo.menuIndex = "0";
- useStore.menuInfo.menuId = "menu01";
- useStore.menuInfo.pageRtName = "제품 관리";
- useStore.menuInfo.pageStatus = null;
- }
- })
- .catch((error) => {
- if (error.response) {
- console.log("status:", error.response.status, "data:", error.response.data);
- // 안전하게 errCode, message 접근
- const errData = error.response.data || {};
- const errCode = errData.errCode || errData.errorCode || errData.code || "";
- const errMsg = errData.message || "알 수 없는 오류가 발생했습니다.";
- console.log("errCode:", errCode, "message:", errMsg);
- } else {
- console.log("error:", error.message, error.code);
- }
- if (error.response?.status) {
- fnLoginSet(error.response.data.messages.message);
- }
- $log.debug("[login][fnIdPwCheck][error]");
- })
- .finally(() => {
- $log.debug("[login][fnIdPwCheck][finished]");
- });
- };
- // onMounted
- onMounted(() => {
- const handler = (event) => {
- if (event.origin !== "https://shopdeli.mycafe24.com") return;
- if (event.data?.accessToken) {
- useAuthStore().setAuth(event.data);
- useAuthStore().setAccessToken(event.data.accessToken);
- useAuthStore().setRefreshToken(event.data.refreshToken);
- localStorage.setItem("tempAccess", event.data.user?.ID);
- useUtil.setPageMove("/view/event/evtList");
- useStore.menuInfo.menuIndex = "0";
- useStore.menuInfo.menuId = "menu02";
- useStore.menuInfo.pageRtName = "이벤트 관리";
- useStore.menuInfo.pageStatus = null;
- }
- };
- window.addEventListener("message", handler);
- onBeforeUnmount(() => window.removeEventListener("message", handler));
- });
- watchEffect(() => {
- // 감시하고자 하는 데이터를 해당 블럭내에서 사용하면 호출된다.
- // getLang.value를 감시하는 상태
- fnGetEnumCode(useLangStore().getLang);
- });
- $eventBus.off("SET_SUCCESS_POPUP");
- $eventBus.on("SET_SUCCESS_POPUP", () => {
- // 안내 팝업 확인 클릭 팝업 초기화처리
- fnOtpPopClose("findId");
- fnOtpPopClose("resetPw");
- });
- $eventBus.off("PASSWD_CHANGE");
- $eventBus.on("PASSWD_CHANGE", () => {
- fnPasswdChange();
- });
- $eventBus.off("INIT_PASSWORD");
- $eventBus.on("INIT_PASSWORD", () => {
- initPw.value.popYn = true;
- });
- $eventBus.off("SET_LOGIN");
- $eventBus.on("SET_LOGIN", () => {
- fnLogin();
- });
- /************************
- * Methods
- ************************/
- // created
- loginForm.value.btnTxtType = "S";
- authPop1.value.btnTxtType = "S";
- loginForm.value.btnTxt = i18n.t("login.authNumSend");
- authPop1.value.btnTxt = i18n.t("common.sendAuthNumber");
- findId.value.btnTxt = i18n.t("common.sendAuthNumber");
- resetPw.value.btnTxt = i18n.t("common.sendAuthNumber");
- initAuthPop1.value = _cloneDeep(authPop1.value);
- initAuthPop2.value = _cloneDeep(authPop2.value);
- initFindId.value = _cloneDeep(findId.value);
- initResetPw.value = _cloneDeep(resetPw.value);
- initInitPw.value = _cloneDeep(initPw.value);
- /**
- * @SCRIPT
- * 다국어 기능 | 한글 영문 변경 이벤트
- */
- function fnLangChange() {
- useLangStore().setLang(langType.value);
- }
- function fnGetEnumCode(lang) {
- lang = useUtil.nvl(lang, "kr");
- langType.value = lang;
- let objEnum = useEnumCode.getEnumCode(lang);
- listObj.value.langTypeList = objEnum.langType;
- i18n.locale.value = lang;
- }
- /**
- * @SCRIPT
- * 라디오버튼 변경 이벤트 (버튼별 문구)
- */
- function fnChangeAuth() {
- if (loginForm.value.authType === "GOOGLE") {
- selectPlaceholder.value = i18n.t("login.googleOTPNum");
- } else if (loginForm.value.authType === "EMAIL") {
- selectPlaceholder.value = i18n.t("login.emailAuthNum");
- } else {
- selectPlaceholder.value = i18n.t("login.smsAuthNum");
- }
- loginForm.value.btnTxt = i18n.t("login.authNumSend");
- loginForm.value.btnTxtType = "S";
- if (!loginForm.value.validCheck.otp.otpNum) {
- fnValidCheck("main_otpNum");
- }
- }
- /**
- * @SCRIPT
- * 구글OTP 인증 버튼 클릭 이벤트
- * @param {*} type
- */
- function fnAuthCheck(type) {
- let issuer = ""; // 회사명
- let account = ""; // 아이디
- let otpUrl = ""; // 큐알코드 생성 URL
- let _req = {
- username: authPop1.value.userId,
- password: btoa(authPop1.value.passwd),
- mfaType: "SMS",
- otpNum: authPop1.value.otpNum,
- };
- if (type === "optApply1") {
- fnValidCheck("createOtp_userId");
- fnValidCheck("createOtp_passwd");
- if (authPop1.value.errorCheck) {
- fnAuth("POPUP");
- }
- } else if (type === "optApply2") {
- //OTP 인증 팝업2
- useAxios()
- .post(apiUrl.googleSecretKey, _req)
- .then((res) => {
- googleOtpSecretKey.value = res.data.data.secretKey;
- // 시크릿 키를 이용한 큐알코드 생성
- issuer = "[P5G]" + authPop1.value.businessName;
- account = authPop1.value.userId;
- otpUrl =
- "otpauth://totp/" +
- encodeURIComponent(issuer + ":" + account).replace(/\+/g, "%20") +
- "?secret=" +
- encodeURIComponent(googleOtpSecretKey.value).replace(/\+/g, "%20") +
- "&issuer=" +
- encodeURIComponent(issuer).replace(/\+/g, "%20");
- fnCreateQrCode(otpUrl);
- $toast.success("인증처리가 완료되었습니다.");
- authPop1.value.applyBtn = false;
- authPop1.value.agreeChk1 = true;
- authPop1.value.succOtpYn = true;
- $log.debug("[login][fnAuthCheck][success]");
- })
- .catch((error) => {
- $log.debug("[login][fnAuthCheck][error]");
- let errorData = error.response.data;
- errorData.type = "fnAuthCheck";
- fnLoginFail(errorData);
- })
- .finally(() => {
- $log.debug("[login][fnAuthCheck][finished]");
- });
- } else if (type === "optApply2Yn") {
- authPop1.value.popYn = false;
- authPop2.value.popYn = true;
- } else if (type === "findId") {
- //fnValidCheck('findId_tenantName')
- fnValidCheck("findId_email");
- if (findId.value.validCheck.inputErrorCheck) {
- fnIdPwCheck(type);
- }
- } else if (type === "resetPw") {
- fnValidCheck("resetPw_userId");
- fnValidCheck("resetPw_email");
- if (resetPw.value.validCheck.inputErrorCheck) {
- fnIdPwCheck(type);
- }
- } else if (type === "createOtp_otpNum") {
- // 구글OTP등록화면에서 인증번호 받기
- fnAuthSend(authPop1.value.btnTxtType, "createOtp_otpNum");
- } else {
- fnValidCheck("main_userId");
- fnValidCheck("main_passwd");
- if (loginForm.value.validCheck.inputErrorCheck) {
- fnAuth(type);
- }
- }
- }
- /**
- * @SCRIPT
- * 큐알코드 생성
- * @param {*} otpUrl
- */
- async function fnCreateQrCode(otpUrl) {
- googleOtpQrCode.value = await QRCode.toDataURL(otpUrl);
- }
- /**
- * @SCRIPT
- * 로그인 실패관련 토스트 & confirm 처리
- */
- function fnLoginFail(dataObj) {
- let errorMessage = "";
- let type = dataObj.type;
- if (dataObj.code === "2001" || dataObj.code === "2002") {
- let valieTxt = "";
- if (!useUtil.isNull(dataObj.reason)) {
- if (dataObj.reason < "4") {
- valieTxt += i18n.t("login.valid.isNullPw");
- } else {
- // 4회 이상 비밀번호 실패
- fnLoginFailConfirm(dataObj);
- }
- } else {
- valieTxt += i18n.t("login.valid.isNullId");
- }
- console.log("비밀번호 초기화 팝업:::" + resetPw.value.popYn);
- console.log("아이디찾기 팝업:::" + findId.value.popYn);
- console.log("OTP생성 팝업:::" + authPop1.value.popYn);
- if (resetPw.value.popYn) {
- resetPw.value.validCheck.inputErrorCheck = false;
- resetPw.value.validCheck.inputValidTxt = valieTxt;
- } else if (findId.value.popYn) {
- findId.value.validCheck.inputErrorCheck = false;
- findId.value.validCheck.inputValidTxt = valieTxt;
- } else if (authPop1.value.popYn) {
- authPop1.value.errorCheck = false;
- authPop1.value.validTxt = valieTxt;
- } else {
- loginForm.value.validCheck.inputErrorCheck = false;
- loginForm.value.validCheck.inputValidTxt = valieTxt;
- }
- } else if (dataObj.code === "2003") {
- let otpTxt = "";
- if (loginForm.value.authType === "GOOGLE") {
- otpTxt += i18n.t("login.valid.isNullOtp");
- } else if (loginForm.value.authType === "EMAIL") {
- otpTxt += i18n.t("login.valid.isNullEmail");
- } else {
- otpTxt += i18n.t("login.valid.isNullSms");
- }
- if (resetPw.value.popYn) {
- resetPw.value.validCheck.otp.otpNum = false;
- resetPw.value.validCheck.otpValidTxt = i18n.t("login.valid.isNullEmail");
- } else if (findId.value.popYn) {
- findId.value.validCheck.otp.otpNum = false;
- findId.value.validCheck.otpValidTxt = i18n.t("login.valid.isNullEmail");
- } else if (authPop1.value.popYn) {
- authPop1.value.validOtpKey = false;
- authPop1.value.validOtpTxt = i18n.t("login.valid.isNullSms");
- } else {
- loginForm.value.validCheck.otp.otpNum = false;
- loginForm.value.validCheck.otpValidTxt = otpTxt;
- }
- } else if (
- dataObj.code === "2004" ||
- dataObj.code === "2005" ||
- dataObj.code === "2006" ||
- dataObj.code === "2007" ||
- dataObj.code === "2010"
- ) {
- // 2004: 접속허용IP아님 , 2005: 사업자 접속불가 상태, 2006: 사업자 계약 만료, 2007: 접속 계정 수 초과, 2010: 계정 잠김 (비밀번호 틀림 N 회) 5회 이상 비밀번호 실패
- fnLoginFailConfirm(dataObj);
- }
- if (!useUtil.isNull(errorMessage)) {
- // 토스트 함수 (success, info, error, warn, dark)
- if (type === "findId" || type === "resetPw")
- errorMessage += i18n.t("login.failMessage.2001");
- else errorMessage += i18n.t("login.valid.isNull");
- nextTick().then(() => {
- $toast.error(errorMessage);
- });
- }
- }
- /**
- * @SCRIPT
- * 로그인 실패관련 토스트 & confirm 처리
- */
- function fnLoginFailConfirm(dataObj) {
- let confirmMessage = "";
- if (dataObj.code === "2002") confirmMessage = i18n.t("login.failMessage.2002");
- else if (dataObj.code === "2004") confirmMessage = i18n.t("login.failMessage.2004");
- else if (dataObj.code === "2005") confirmMessage = i18n.t("login.failMessage.2005");
- else if (dataObj.code === "2006") confirmMessage = i18n.t("login.failMessage.2006");
- else if (dataObj.code === "2007") confirmMessage = i18n.t("login.failMessage.2007");
- else if (dataObj.code === "2010") confirmMessage = i18n.t("login.failMessage.2010");
- let param = {
- id: pageId,
- title: i18n.t("common.popTitle"),
- content: confirmMessage,
- yes: {
- text: i18n.t("common.confirm"),
- isProc: true,
- event: "",
- param: {},
- },
- };
- $eventBus.emit("OPEN_CONFIRM_POP_UP", param);
- }
- /**
- * @SCRIPT
- * 아이디 저장 체크 이벤트
- */
- function fnSaveId() {
- if (checkbox.value) {
- // 체크 시 저장
- localStorage.setItem("saveId", loginForm.value.userId);
- } else {
- // 미체크 시 삭제
- localStorage.removeItem("saveId");
- }
- }
- /**
- * @API
- * 아이디 찾기에서 사업자명 & 이메일 주소 체크 API
- * 비밀번호 초기화에서 사용자계정 & 이메일 주소 체크 API
- */
- function fnIdPwCheck(type) {
- let _req = {};
- if (type === "findId") {
- //_req.tenantName = findId.value.tenantName,
- _req.email = findId.value.email;
- } else {
- (_req.accountId = resetPw.value.userId), (_req.email = resetPw.value.email);
- }
- useAxios()
- .post(apiUrl.findCheck, _req)
- .then((res) => {
- if (type === "findId") {
- findId.value.btnTxt = i18n.t("common.sendReAuthNumber");
- } else {
- resetPw.value.btnTxt = i18n.t("common.sendReAuthNumber");
- }
- $toast.success(i18n.t("login.sendEmail"));
- $log.debug("[login][fnIdPwCheck][success]");
- })
- .catch((error) => {
- let errorData = error.response.data;
- errorData.type = type;
- fnLoginFail(errorData);
- $log.debug("[login][fnIdPwCheck][error]");
- })
- .finally(() => {
- $log.debug("[login][fnIdPwCheck][finished]");
- });
- }
- /**
- * @API
- * 가입된 아이디 비밀번호 체크 API
- */
- function fnAuth(type) {
- let _req = {};
- if (type === "POPUP") {
- _req.username = authPop1.value.userId;
- _req.password = btoa(authPop1.value.passwd);
- } else {
- _req.username = loginForm.value.userId;
- _req.password = btoa(loginForm.value.passwd);
- }
- // 아이디&비밀번호 validation체크 정상일 경우 아이디 비밀번호를 체크 하는 API를 진행한다.
- useAxios()
- .post(apiUrl.idPwCheck, _req)
- .then((res) => {
- if (type === "GOOGLE") {
- fnLogin();
- } else if (type === "POPUP") {
- // if(useUtil.isNull(res.data.data.tenantName)) {
- // authPop1.value.businessName = ''
- // } else {
- // authPop1.value.businessName = res.data.data.tenantName
- // }
- // 아이디 비밀번호 입력 영역 비활성화
- authPop1.value.certifyYN = true;
- //authPop1.value.agreeChk1 = true
- } else {
- // 아이디&비밀번호가 존재하여 이메일 발송을 진행합니다.
- fnAuthSend(loginForm.value.btnTxtType, "loginForm");
- }
- $log.debug("[login][fnAuth][success]");
- })
- .catch((error) => {
- let errorData = error.response.data;
- errorData.type = type;
- fnLoginFail(errorData);
- $log.debug("[login][fnAuth][error]");
- })
- .finally(() => {
- $log.debug("[login][fnAuth][finished]");
- });
- }
- /**
- * @API
- * 가입된 아이디 비밀번호 체크가 정상 일 경우 인증번호 발송
- * 이메일(EMAIL) & 문자(SMS)
- */
- function fnAuthSend(type, form) {
- let _req = {};
- if (form === "loginForm") {
- (_req.username = loginForm.value.userId),
- (_req.password = btoa(loginForm.value.passwd)),
- (_req.mfaType = loginForm.value.authType);
- } else {
- (_req.username = authPop1.value.userId),
- (_req.password = btoa(authPop1.value.passwd)),
- (_req.mfaType = "SMS");
- }
- useAxios()
- .post(apiUrl.otpSend, _req)
- .then((res) => {
- if (form === "loginForm") {
- loginForm.value.btnTxt = i18n.t("login.authNumReSend");
- loginForm.value.btnTxtType = "R";
- } else {
- authPop1.value.btnTxt = i18n.t("login.authNumReSend");
- authPop1.value.btnTxtType = "R";
- }
- if (type === "S") {
- if (form === "loginForm") {
- if (loginForm.value.authType === "EMAIL") {
- $toast.success(i18n.t("login.sendEmail"));
- } else {
- $toast.success(i18n.t("login.sendSms"));
- }
- } else {
- $toast.success(i18n.t("login.sendSms"));
- }
- } else {
- if (form === "loginForm") {
- if (loginForm.value.authType === "EMAIL") {
- $toast.success(i18n.t("login.sendReEmail"));
- } else {
- $toast.success(i18n.t("login.sendReSms"));
- }
- } else {
- $toast.success(i18n.t("login.sendReSms"));
- }
- }
- $log.debug("[login][fnAuthSend][success]");
- })
- .catch((error) => {
- $log.debug("[login][fnAuthSend][error]");
- // 에러 메시지 체크 팝업으로 변경
- let param = {
- id: pageId,
- title: i18n.t("common.popTitle"),
- content: i18n.t("login.sendFail"),
- yes: {
- text: i18n.t("common.confirm"),
- isProc: true,
- event: "",
- param: {},
- },
- };
- $eventBus.emit("OPEN_CONFIRM_POP_UP", param);
- // let errorMessage = i18n.t('login.sendFail')
- // errorMessage += error.response.data.message
- // $toast.error(errorMessage)
- })
- .finally(() => {
- $log.debug("[login][fnAuthSend][finished]");
- });
- }
- const fnLoginSet = (__MSG) => {
- let param = {
- id: pageId,
- title: "로그인",
- content: __MSG,
- yes: {
- text: "확인",
- isProc: true,
- event: "FN_LOGIN",
- param: "",
- },
- no: {
- text: "취소",
- isProc: false,
- },
- };
- $eventBus.emit("OPEN_CONFIRM_POP_UP", param);
- };
- // 구글 로그인 버튼 클릭 시 호출
- function onGoogleLogin() {
- const clientId =
- "373780605211-diojebh7mug45urv9rnqdil6n0b1ogge.apps.googleusercontent.com"; // 실제 클라이언트 ID로 교체
- const redirectUri = "https://shopdeli.mycafe24.com/auth/callback"; // 실제 리디렉션 URI로 교체
- const scope = "openid email profile";
- const responseType = "code"; // 또는 'code' (백엔드 연동 시)
- const state = Math.random().toString(36).substring(2);
- const googleAuthUrl = `https://accounts.google.com/o/oauth2/v2/auth?client_id=${clientId}&redirect_uri=${encodeURIComponent(
- redirectUri
- )}&response_type=${responseType}&scope=${encodeURIComponent(scope)}&state=${state}`;
- 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(
- googleAuthUrl,
- "googleLogin",
- `width=${width},height=${height},left=${left},top=${top},resizable=yes,scrollbars=yes`
- );
- }
- /**
- * @API
- * 최종 로그인 버튼 클릭 시 API
- */
- function fnLogin(__USERID, __USERPASS) {
- // 파라미터 전달 값 [아이디, 비밀번호, otpNum, 브라우저정보]
- //userId: loginForm.value.userId,
- // let _req = {
- // username: loginForm.value.userId,
- // password: btoa(loginForm.value.passwd),
- // };
- localStorage.setItem("tempAccess", __USERID);
- if (__USERID == "admin" && __USERPASS == "1234") {
- useUtil.setPageMove("/view/media/newsList");
- } else {
- fnLoginSet("비밀번호가 맞지 않습니다. 확인해주세요.");
- }
- // useAxios()
- // .post(apiUrl.otpCheck, _req)
- // .then((res) => {
- // loginInfo.value = res.data.data;
- // useAuthStore().setAccessToken(loginInfo.value.accessToken);
- // useAuthStore().setRefreshToken(loginInfo.value.refreshToken);
- // // OTP key체크 성공 후 개인정보에 대한 API를 호출 한다.
- // fnServiceModeCheck();
- // $log.debug("[login][fnLogin][success]");
- // })
- // .catch((error) => {
- // $log.debug("[login][fnLogin][error]");
- // let errorData = error.response.data;
- // errorData.type = "fnLogin";
- // fnLoginFail(errorData);
- // })
- // .finally(() => {
- // $log.debug("[login][fnLogin][finished]");
- // });
- }
- /**
- * @API
- * 최종 로그인 전 점검공지에 대한 정보를 가져온다.
- */
- function fnServiceModeCheck() {
- useAxios()
- .get(useApi.getServiceMode)
- .then((res) => {
- $log.debug("[login][fnServiceModeCheck][success]");
- let data = res.data.data;
- systemInfo.value.mode = data.mode;
- fnMyInfo();
- })
- .catch((error) => {
- $log.debug("[login][fnServiceModeCheck][error]");
- useErrorHandler().fnSetCommErrorHandle(error);
- })
- .finally(() => {
- $log.debug("[login][fnServiceModeCheck][finished]");
- });
- }
- /**
- * @API
- * 최종 로그인 버튼 클릭 후 성공 시 토큰값을 통해 개인정보 API 호출
- */
- function fnMyInfo() {
- useAxios()
- .get(apiUrl.myInfo)
- .then((res) => {
- let dataObj = {};
- dataObj = res.data.data;
- dataObj.accessToken = useAuthStore().getAccessToken;
- dataObj.refreshToken = useAuthStore().getRefreshToken;
- useAuthStore().setServiceMode(systemInfo.value.mode);
- useAuthStore().setAuth(dataObj);
- // 아이디 저장 여부 체크
- fnSaveId();
- let accountValue = useAuthStore().getAccountRole.charAt(0).toUpperCase();
- // 첫화면 redirect_page URL로 설정
- // 초기 비밀번호 사용
- if (useAuthStore().getFirstLoginYn === "Y") {
- // 최초로그인
- initPw.value.popYn = true;
- } else if (useAuthStore().getPwExpiredYN === "Y") {
- // 비밀번호 3개월 만료
- let param = {
- id: pageId,
- title: i18n.t("common.popTitle"),
- content: i18n.t("login.failMessage.2009"),
- yes: {
- text: i18n.t("common.confirm"),
- isProc: true,
- event: "INIT_PASSWORD", // 확인 클릭 시 비밀번호 변경 팝업 활성화
- param: {},
- },
- no: {
- text: i18n.t("common.skip"),
- isProc: true,
- event: "SET_LOGIN", // 건너뛰기 클릭 시 로그인 처리
- param: {},
- },
- };
- $eventBus.emit("OPEN_CONFIRM_POP_UP", param);
- } else if (useAuthStore().getTermsArgYN === "N") {
- // 필수약관동의여부
- isShowAgrNPop.value = true;
- nextTick().then(() => {
- isAgrNPop.value = true;
- });
- } else {
- if (systemInfo.value.mode === "INACTIVE") {
- // 점검모드일 경우 점검모드 페이지로 이동
- if (accountValue === "S") {
- useUtil.setPageMove("/view/home/dashboard");
- } else {
- useUtil.setPageMove("/view/home/serviceMode");
- }
- } else {
- if (accountValue === "A" || accountValue === "S") {
- useUtil.setPageMove("/view/home/dashboard");
- } else {
- useUtil.setPageMove("/view/home/tenantDashboard");
- }
- }
- }
- $log.debug("[login][fnMyInfo][success]");
- })
- .catch((error) => {
- $log.debug("[login][fnMyInfo][error]");
- useErrorHandler().fnSetCommErrorHandle(error);
- })
- .finally(() => {
- $log.debug("[login][fnMyInfo][finished]");
- });
- }
- /**
- * @API
- * 최초 비밀번호 변경 API 호출
- */
- function fnPasswdChange() {
- let _req = {
- newPassword: btoa(initPw.value.passwd2),
- };
- useAxios()
- .post(apiUrl.myInfoUpdate, _req)
- .then((res) => {
- localStorage.removeItem("authStore");
- // 세션 초기화 및 로그인 화면 이동
- useUtil.setPageMove("/");
- $log.debug("[login][fnPasswdChange][success]");
- })
- .catch((error) => {
- $log.debug("[login][fnPasswdChange][error]");
- let errorData = error.response.data;
- errorData.type = "fnPasswdChange";
- fnLoginFail(errorData);
- })
- .finally(() => {
- $log.debug("[login][fnPasswdChange][finished]");
- });
- }
- /**
- * @API
- * 로그인 FOOTER 약관 조회 API
- */
- function fnPrivacy(type) {
- let _req = {
- termsType: useUtil.nvl(type, null),
- };
- useAxios()
- .get(apiUrl.loginTerms, { params: _req })
- .then((res) => {
- let dataObj = res.data.data;
- privacyDetail.value.kr.title = dataObj.termsTitle;
- privacyDetail.value.kr.contents = dataObj.termsCont;
- privacyDetail.value.en.title = dataObj.termsTitleEn;
- privacyDetail.value.en.contents = dataObj.termsContEn;
- privacyPop.value = true;
- })
- .catch((error) => {
- $log.debug("[login][fnPrivacy][error]");
- useErrorHandler().fnSetCommErrorHandle(error, fnPrivacy);
- })
- .finally(() => {
- $log.debug("[login][fnPrivacy][finished]");
- });
- }
- /**
- * @SCRIPT
- * 아이디 & 비밀번호 & otp 값의 유효성 검사 체크 및 로그인 버튼 활성화 이벤트
- */
- function fnValidCheck(input) {
- if (_includes(input, "main_")) {
- let commonValidCheck = {
- inputCheck: false,
- otpCheck: false,
- };
- if (input === "main_userId") {
- if (
- useUtil.isNull(loginForm.value.userId) ||
- !/^[a-zA-Z0-9._-]{1,20}$/.test(loginForm.value.userId)
- ) {
- loginForm.value.validCheck.input.userId = false;
- loginForm.value.validCheck.inputValidTxt = i18n.t("login.valid.isNull");
- } else {
- loginForm.value.validCheck.input.userId = true;
- if (!useUtil.isNull(loginForm.value.passwd)) {
- fnValidCheck("main_passwd");
- }
- }
- } else if (input === "main_passwd") {
- if (
- useUtil.isNull(loginForm.value.passwd) ||
- !/^(?=.*[a-zA-Z])(?=.*[!@#$%^*+=-])(?=.*[0-9]).{8,30}$/i.test(
- loginForm.value.passwd
- )
- ) {
- //if(useUtil.isNull(loginForm.value.passwd)) {
- loginForm.value.validCheck.input.passwd = false;
- loginForm.value.validCheck.inputValidTxt = i18n.t("login.valid.isNull");
- } else {
- loginForm.value.validCheck.input.passwd = true;
- }
- } else if (input === "main_otpNum") {
- loginForm.value.otpNum = useValid.p5gNumCheck(loginForm.value.otpNum, "otp");
- if (
- useUtil.isNull(loginForm.value.otpNum) ||
- loginForm.value.otpNum.length <= 5
- ) {
- loginForm.value.validCheck.otp.otpNum = false;
- if (loginForm.value.authType === "GOOGLE") {
- loginForm.value.validCheck.otpValidTxt = i18n.t("login.valid.isNullOtp");
- } else if (loginForm.value.authType === "EMAIL") {
- loginForm.value.validCheck.otpValidTxt = i18n.t("login.valid.isNullEmail");
- } else {
- loginForm.value.validCheck.otpValidTxt = i18n.t("login.valid.isNullSms");
- }
- } else {
- loginForm.value.validCheck.otp.otpNum = true;
- }
- }
- loginForm.value.validCheck.inputErrorCheck = _every(
- loginForm.value.validCheck.input,
- (value) => value === true
- );
- // 전체 항목에 대한 validation이 정상일 경우 login버튼 활성화
- if (
- !useUtil.isNull(loginForm.value.userId) &&
- !useUtil.isNull(loginForm.value.passwd) &&
- !useUtil.isNull(loginForm.value.otpNum)
- ) {
- commonValidCheck.inputCheck = _every(
- loginForm.value.validCheck.input,
- (value) => value === true
- );
- commonValidCheck.otpCheck = _every(
- loginForm.value.validCheck.otp,
- (value) => value === true
- );
- }
- loginForm.value.validCheck.loginValidCheck = _every(
- commonValidCheck,
- (value) => value === true
- );
- } else if (_includes(input, "createOtp_")) {
- if (input === "createOtp_userId") {
- if (
- useUtil.isNull(authPop1.value.userId) ||
- !/^[a-zA-Z0-9._-]{1,20}$/.test(authPop1.value.userId)
- ) {
- authPop1.value.validCheck.userId = false;
- authPop1.value.validTxt = i18n.t("login.valid.isNull");
- } else {
- authPop1.value.validCheck.userId = true;
- if (!useUtil.isNull(authPop1.value.passwd)) {
- fnValidCheck("createOtp_passwd");
- }
- }
- } else if (input === "createOtp_passwd") {
- if (
- useUtil.isNull(authPop1.value.passwd) ||
- !/^(?=.*[a-zA-Z])(?=.*[!@#$%^*+=-])(?=.*[0-9]).{8,30}$/i.test(
- authPop1.value.passwd
- )
- ) {
- //if(useUtil.isNull(authPop1.value.passwd)) {
- authPop1.value.validCheck.passwd = false;
- authPop1.value.validTxt = i18n.t("login.valid.isNull");
- } else {
- authPop1.value.validCheck.passwd = true;
- }
- } else if (input === "createOtp_otpNum1") {
- authPop1.value.otpNum = useValid.p5gNumCheck(authPop1.value.otpNum, "otp");
- if (useUtil.isNull(authPop1.value.otpNum) || authPop1.value.otpNum.length <= 5) {
- authPop1.value.validOtpKey = false;
- authPop1.value.errorCheck = false;
- authPop1.value.validOtpTxt = i18n.t("login.valid.isNullSms");
- } else {
- authPop1.value.validOtpKey = true;
- authPop1.value.errorCheck = true;
- authPop1.value.applyBtn = true;
- }
- } else if (input === "createOtp_otpNum") {
- authPop2.value.otpNum = useValid.p5gNumCheck(authPop2.value.otpNum, "otp");
- if (useUtil.isNull(authPop2.value.otpNum) || authPop2.value.otpNum.length <= 5) {
- authPop2.value.validOtpKey = false;
- authPop2.value.errorCheck = false;
- if (loginForm.value.authType === "GOOGLE") {
- authPop2.value.validOtpTxt = i18n.t("login.valid.isNullOtp");
- } else if (loginForm.value.authType === "EMAIL") {
- authPop2.value.validOtpTxt = i18n.t("login.valid.isNullEmail");
- } else {
- authPop2.value.validOtpTxt = i18n.t("login.valid.isNullSms");
- }
- } else {
- authPop2.value.validOtpKey = true;
- authPop2.value.errorCheck = true;
- }
- }
- authPop1.value.errorCheck = _every(
- authPop1.value.validCheck,
- (value) => value === true
- );
- } else if (_includes(input, "findId_")) {
- let validAllCheck = {
- inputCheck: false,
- otpCheck: false,
- };
- // if(input === 'findId_tenantName') {
- // if(useUtil.isNull(findId.value.tenantName)) {
- // findId.value.validCheck.input.tenantName = false
- // findId.value.validCheck.inputValidTxt = i18n.t('login.findId.valid.isNullTenantName')
- // } else {
- // findId.value.validCheck.input.tenantName = true
- // if(!useUtil.isNull(findId.value.email)) {
- // fnValidCheck('findId_email')
- // }
- // }
- // } else
- if (input === "findId_email") {
- if (useUtil.isNull(findId.value.email)) {
- findId.value.validCheck.input.email = false;
- findId.value.validCheck.inputValidTxt = i18n.t(
- "login.findId.valid.isNullEmail"
- );
- } else if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(findId.value.email)) {
- findId.value.validCheck.input.email = false;
- findId.value.validCheck.inputValidTxt = i18n.t(
- "login.findId.valid.isTypeEmail"
- );
- } else {
- findId.value.validCheck.input.email = true;
- }
- } else if (input === "findId_otpNum") {
- findId.value.otpNum = useValid.p5gNumCheck(findId.value.otpNum, "otp");
- if (useUtil.isNull(findId.value.otpNum) || findId.value.otpNum.length <= 5) {
- findId.value.validCheck.otp.otpNum = false;
- findId.value.validCheck.otpValidTxt = i18n.t("login.findId.valid.isNullOtp");
- } else {
- findId.value.validCheck.otp.otpNum = true;
- }
- }
- // tenantName & email validation check
- findId.value.validCheck.inputErrorCheck = _every(
- findId.value.validCheck.input,
- (value) => value === true
- );
- //!useUtil.isNull(findId.value.tenantName) &&
- if (!useUtil.isNull(findId.value.email) && !useUtil.isNull(findId.value.otpNum)) {
- validAllCheck.inputCheck = findId.value.validCheck.inputErrorCheck;
- validAllCheck.otpCheck = findId.value.validCheck.otp.otpNum;
- }
- findId.value.validCheck.findIdValidCheck = _every(
- validAllCheck,
- (value) => value === true
- );
- } else if (_includes(input, "resetPw_")) {
- let validAllCheck = {
- inputCheck: false,
- otpCheck: false,
- };
- if (input === "resetPw_userId") {
- if (useUtil.isNull(resetPw.value.userId)) {
- resetPw.value.validCheck.input.userId = false;
- resetPw.value.validCheck.inputValidTxt = i18n.t(
- "login.resetPasswd.valid.isNullUserId"
- );
- } else {
- resetPw.value.validCheck.input.userId = true;
- if (!useUtil.isNull(resetPw.value.email)) {
- fnValidCheck("resetPw_email");
- }
- }
- } else if (input === "resetPw_email") {
- if (useUtil.isNull(resetPw.value.email)) {
- resetPw.value.validCheck.input.email = false;
- resetPw.value.validCheck.inputValidTxt = i18n.t(
- "login.resetPasswd.valid.isNullEmail"
- );
- } else if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(resetPw.value.email)) {
- resetPw.value.validCheck.input.email = false;
- resetPw.value.validCheck.inputValidTxt = i18n.t(
- "login.resetPasswd.valid.isTypeEmail"
- );
- } else {
- resetPw.value.validCheck.input.email = true;
- }
- } else if (input === "resetPw_otpNum") {
- resetPw.value.otpNum = useValid.p5gNumCheck(resetPw.value.otpNum, "otp");
- if (useUtil.isNull(resetPw.value.otpNum) || resetPw.value.otpNum.length <= 5) {
- resetPw.value.validCheck.otp.otpNum = false;
- resetPw.value.validCheck.otpValidTxt = i18n.t(
- "login.resetPasswd.valid.isNullOtp"
- );
- } else {
- resetPw.value.validCheck.otp.otpNum = true;
- }
- }
- // tenantName & email validation check
- resetPw.value.validCheck.inputErrorCheck = _every(
- resetPw.value.validCheck.input,
- (value) => value === true
- );
- if (
- !useUtil.isNull(resetPw.value.userId) &&
- !useUtil.isNull(resetPw.value.email) &&
- !useUtil.isNull(resetPw.value.otpNum)
- ) {
- validAllCheck.inputCheck = resetPw.value.validCheck.inputErrorCheck;
- validAllCheck.otpCheck = resetPw.value.validCheck.otp.otpNum;
- }
- resetPw.value.validCheck.resetPwValidCheck = _every(
- validAllCheck,
- (value) => value === true
- );
- } else {
- if (input === "initPw_passwd") {
- let digits1 = useAuthStore().getAuth.phoneNumber.replace(/\D/g, "");
- let digits2 = initPw.value.passwd.replace(/\D/g, "");
- let lastEightDigits1 = digits1.slice(-8);
- let lastEightDigits2 = digits2.slice(-8);
- if (useUtil.isNull(initPw.value.passwd)) {
- initPw.value.validCheck.passwd = false;
- initPw.value.errorTxt = i18n.t("login.valid.isNullNewPassword");
- } else if (_includes(initPw.value.passwd, useAuthStore().getAuth.accountId)) {
- // 아이디는 비밀번호로 사용할 수 없습니다.
- initPw.value.validCheck.passwd = false;
- initPw.value.errorTxt = i18n.t(
- "common.header.myInfoUpdateModal.valid.includeId"
- );
- } else if (lastEightDigits1 === lastEightDigits2) {
- // 연락처와 유사한 비밀번호는 사용할 수 없습니다.
- initPw.value.validCheck.passwd = false;
- initPw.value.errorTxt = i18n.t(
- "common.header.myInfoUpdateModal.valid.includePhone"
- );
- } else if (/(.)\1{2,}/.test(initPw.value.passwd)) {
- // 3자리 이상 연속 숫자, 문자는 사용 불가합니다.
- initPw.value.validCheck.passwd = false;
- initPw.value.errorTxt = i18n.t(
- "common.header.myInfoUpdateModal.valid.continuousUse"
- );
- } else if (
- !/^(?=.*[a-zA-Z])(?=.*[!@#$%^*+=-])(?=.*[0-9]).{8,30}$/i.test(
- initPw.value.passwd
- )
- ) {
- // 비밀번호는 문자,숫자,특수문자 조합 8~30자리로입력
- initPw.value.validCheck.passwd = false;
- initPw.value.errorTxt = i18n.t(
- "common.header.myInfoUpdateModal.valid.validPassword"
- );
- } else {
- initPw.value.validCheck.passwd = true;
- if (!useUtil.isNull(initPw.value.passwd2)) {
- fnValidCheck("initPw_passwd2");
- }
- }
- } else {
- if (initPw.value.passwd != initPw.value.passwd2) {
- // 신규비밀번호가 일치 하지 않습니다.
- initPw.value.validCheck.passwd2 = false;
- initPw.value.errorTxt = i18n.t(
- "common.header.myInfoUpdateModal.valid.missmatchPassword"
- );
- } else {
- initPw.value.validCheck.passwd2 = true;
- }
- }
- if (!useUtil.isNull(initPw.value.passwd) && !useUtil.isNull(initPw.value.passwd2)) {
- initPw.value.passwdCheck = _every(
- initPw.value.validCheck,
- (value) => value === true
- );
- }
- }
- }
- </script>
|