사람들은 세 가지 부류로 나눌 수 있다. 첫째, 우리를 이용하려는 사람, 즉 원수이다. 둘째, 우리를 이용하려는 동시에 우리에게 이용되어지려는 사람, 즉 친지(親知)이다. 셋째, 우리가 존경하고 또 그를 위해 힘있는 대로 도우려고 하는 사람, 즉 친구이다. -소포클레스
3)register_page.vue(회원가입 페이지)
<template> <v-container> <v-row class="text-center"> <v-col col="12" class="text-center my-5"> <h1 class="display-1">회원가입 페이지</h1> </v-col> </v-row> <v-row> <!-- 반응형에 따라 다르게 너비 조절 --> <v-col class="text-center" cols="8" offset="2" sm="6" offset-sm="3"> <!-- 양식의 입력이 제출되면 페이지를 새로 고침하지 않도록 prevent 사용 --> <form @submit.prevent="fnRegisterUser"> <!-- 필수 입력 사항이 되도록 required 어트리뷰트 적용 --> <v-text-field name="Email" label="이메일" type="email" v-model="sEmail" required ></v-text-field> <v-text-field name="Password" label="비밀번호" type="password" v-model="sPassword" required ></v-text-field> <!-- 비밀번호 확인이 맞는지 검사하도록 rules 어트리뷰트 사용 --> <v-text-field name="ConfirmPassword" label="비밀번호 확인" type="password" v-model="sConfirmPassword" required :rules="[fnCompasrePassword]" ></v-text-field> <!-- 시간 지연 상태이면 버튼을 사라지게 함 --> <v-btn type="submit" v-if="!fnGetLoading" color="orange" dark >회원가입</v-btn> <!-- 시간 지연 상태이면 회전 프로그레스 원 표시 --> <v-progress-circular v-if="fnGetLoading" :size="70" :width="7" color="grey lighten-1" indeterminate ></v-progress-circular> <v-alert type="error" class="mt-3" dismissible v-model="fnAlert">{{fnGetErrMsg}}</v-alert> </form> </v-col> </v-row> </v-container> </template> <script> console.log(" 현재 페이지 : register-page"); export default { name: 'register_page', mounted:function(){ //마운트시 초기화 this.$store.dispatch("setInitLoading"); }, data(){ return{ sEmail:"", //이메일 입력값 임시 저장 sPassword:"", //비밀번호 입력값 임시 저장 sConfirmPassword:"" //비밀번호 입력 확인값 임시 저장 } }, computed:{ //비밀번호와 비밀번호 확인 값이 일치하는지 검사 fnCompasrePassword(){ if(this.sPassword ==this.sConfirmPassword)return true; else return "비밀번호가 일치하지 않습니다.!" }, //오류 메시지 스토어에서 읽어서 반환 fnGetErrMsg(){ //state.sErrorMessage return this.$store.getters.fnGetErrorMessage; }, //시간 지연 상태 스토어에서 읽어서 반환 fnGetLoading(){ return this.$store.getters.fnGetLoading }, fnAlert(){ //오류 메시지 표시 여부 return this.$store.getters.fnGetErrorMessage.length===0?false:true; } }, methods:{ //스토어에 이메일 회원가입 처리 요청 fnRegisterUser(){ if(this.fnCompasrePassword==true){ this.$store.dispatch("fnRegisterUser", { pEmail:this.sEmail, pPassword:this.sPassword }) } } }, //여기서는 다음 warch 를 사용하지 않고 오류 메시지를 처리를 진행봤다.. // watch:{ // //fnGetErrMag() 함수가 오류 메시지를 반환하면 오류 메시지 표시 // fnGetErrMsg(pMsg){ // if(pMsg) this.bAlert=true; // }, // //bAlert값이 false 로 바뀌면 에러 페이지 초기화 // bAlert(pValue){ // if(pValue===false)this.$store.commit("fnSetErrorMessage", ""); // } // } } </script>
4)login_page.vue(로그인 페이지)
<template> <v-container flow> <v-row> <v-col cols="12" class="text-center my-5"> <h1 class="display-1">로그인 페이지</h1> </v-col> </v-row> <v-row> <!-- 반응형에 따라 다르게 너비 조절 --> <v-col class="text-center" cols="8" offset="2" sm="6" offset-sm="3"> <!-- 양식의 입력이 제출 되면 페이지를 다시 로드 하지 않도록 prevent 사용 --> <form @submit.prevent="fnDoLogin"> <!-- 필수 입력사항이 되도록 required 어트리뷰트 적용 --> <v-text-field name="Email" label="이메일" type="email" v-model="sEmail" required> </v-text-field> <v-text-field name="Password" label="비밀번호" type="password" v-model="sPassword" required> </v-text-field> <!-- 시간지연상태인 경우 버튼은 사라지게 함 --> <v-btn type="submit" v-if="!fnGetLoading" color="orange" dark> 로그인 </v-btn> <!-- 시간지연의 경우 회전 프로그레스 원 표시 --> <v-progress-circular v-if="fnGetLoading" indeterminate :width="7" :size="70" color="grey lighten-1"> </v-progress-circular> <!-- 오류 메시지가 있을 경우 표시 --> <v-alert class="mt-3" type="error" dismissible v-model="bAlert"> {{ fnGetErrMsg }} </v-alert> </form> </v-col> </v-row> </v-container> </template> <script> export default { data() { return { bAlert: false, // 오류 메시지 표시 여부 sEmail: '', // 이메일 입력값 임시 저장 sPassword: '' // 비밀번호 입력값 임시 저장 } }, computed: { // 오류메시지 스토어에서 읽어서 반환 fnGetErrMsg() { return this.$store.getters.fnGetErrorMessage; }, // 시간지연상태 스토어에서 읽어서 반환 fnGetLoading() { return this.$store.getters.fnGetLoading; } }, methods: { // 스토어에 이메일 로그인 처리 요청 fnDoLogin() { this.$store.dispatch('fnDoLogin', { pEmail: this.sEmail, pPassword: this.sPassword }) } }, watch: { // fnGetErrMsg 함수가 오류메시지를 반환하면 오류 메시지 표시 fnGetErrMsg(pMsg) { if (pMsg) this.bAlert = true; }, // bAlert 값이 false로 바뀌면 오류메시지 초기화 bAlert(pValue) { if (pValue == false) this.$store.commit('fnSetErrorMessage', ''); } } } </script>
5)error_page.vue(에러페이지)
<template> <v-container> <v-row class="text-center"> <v-col cols="12" class="text-center mt-5"> <h1 class="display-1 my-1">오류가 발생하였습니다!</h1> <p class="body-1">페이지를 찾을 수 없습니다.</p> </v-col> </v-row> </v-container> </template> <script> console.log("현재 페이지 : error-page"); export default { name: 'error_page', data: () => ({ }), } </script>
7. 파이어베이스 호스팅 배포 하기
Vue-Cli 3 을 이용하여 빠르게 PWA( 웹앱 )생성 및 Https 로 파이어 베이스 호스팅 배포 하기
https://macaronics.net/m04/vue/view/2048
2023-04-01 13:55:11
Firebase Function 백엔드 서버 Nodejs 회원 레벨 설정
const functions = require("firebase-functions"); const admin = require('firebase-admin'); const { getAuth } = require('firebase-admin/auth'); const serviceAccount = require("./serviceAccountKey.json"); admin.initializeApp({ credential: admin.credential.cert(serviceAccount) }); //admin.initializeApp(); const db = admin.firestore(); console.log(functions.config().admin.email); // // Create and Deploy Your First Cloud Functions // // https://firebase.google.com/docs/functions/write-firebase-functions // // exports.helloWorld = functions.https.onRequest((request, response) => { // functions.logger.info("Hello logs!", {structuredData: true}); // response.send("Hello from Firebase!"); // }); //exports.createUserLevel = functions.https.onRequest(require('./test')); // exports.createUser = functions.auth.user().onCreate(async (user) => { // let set = {level:2} // if (functions.config().admin.email === user.email && user.emailVerified) set.level = 0; // console.log("레벨 생성 :"); // await getAuth().setCustomUserClaims(user.uid, set).then(() => { // // The new custom claims will propagate to the user's ID token the // // next time a new one is issued. // }); // }); //등록 처리시 exports.createUser = functions.auth.user().onCreate(async (user) => { let customClaims = { admin: false, accessLevel: 1 }; if (user.email && user.email.endsWith('braverokmc79@gmail.com') && user.emailVerified) { //관리자일경우 customClaims = { admin: true, accessLevel: 9 }; } await getAuth().setCustomUserClaims(user.uid, customClaims); }); //firebase store 에 users 정보를 담는 collection 생성 // exports.createUser2 = functions.auth.user().onCreate(async (user) => { // const { uid, email, displayName, emailVerified, photoURL, disabled } = user; // let claims = { level: 2 }; // if (functions.config().admin.email === user.email && user.emailVerified) claims.level = 0; // await getAuth().setCustomUserClaims(uid, claims); // const d = { // uid, email, displayName, emailVerified, photoURL, disabled // } // const r = await db.collection('users').doc(uid).set(d) // return r // }); //const r = await db.collection('users').doc(user.uid).delete(); exports.deleteUser = functions.auth.user().onDelete( (user) => { return db.collection('users').doc(user.email).delete(); });
2022-04-05 13:07:38
mixins.js
import axios from 'axios'; export default { methods: { async $api(url, type, data) { return (await axios({ method: type, url, data }).catch(e => { console.log(e); })).data; }, $base64(file) { return new Promise(resolve => { var a = new FileReader(); a.onload = e => resolve(e.target.result); a.readAsDataURL(file); }); }, $currencyFormat(value, format = '#,###') { if (value == 0 || value == null) return 0; var currency = format.substring(0, 1); if (currency === '$' || currency === '₩') { format = format.substring(1, format.length); } else { currency = ''; } var groupingSeparator = ","; var maxFractionDigits = 0; var decimalSeparator = "."; if (format.indexOf(".") == -1) { groupingSeparator = ","; } else { if (format.indexOf(",") < format.indexOf(".")) { groupingSeparator = ","; decimalSeparator = "."; maxFractionDigits = format.length - format.indexOf(".") - 1; } else { groupingSeparator = "."; decimalSeparator = ","; maxFractionDigits = format.length - format.indexOf(",") - 1; } } var prefix = ""; var d = ""; // v = String(parseFloat(value).toFixed(maxFractionDigits)); var dec = 1; for (var i = 0; i < maxFractionDigits; i++) { dec = dec * 10; } var v = String(Math.round(parseFloat(value) * dec) / dec); if (v.indexOf("-") > -1) { prefix = "-"; v = v.substring(1); } if (maxFractionDigits > 0 && format.substring(format.length - 1, format.length) == '0') { v = String(parseFloat(v).toFixed(maxFractionDigits)); } if (maxFractionDigits > 0 && v.indexOf(".") > -1) { d = v.substring(v.indexOf(".")); d = d.replace(".", decimalSeparator); v = v.substring(0, v.indexOf(".")); } var regExp = /\D/g; v = v.replace(regExp, ""); var r = /(\d+)(\d{3})/; while (r.test(v)) { v = v.replace(r, '$1' + groupingSeparator + '$2'); } return prefix + currency + String(v) + String(d); } } }
2021-12-14 03:18:44
macaronics.net 는 그어떠한 동영상, 이미지, 파일등을 직접적으로 업로드 제공을 하지 않습니다. 페이스북, 트위터 등 각종 SNS 처럼 macaronics.net 는 웹서핑을 통하여 각종 페이지위치등을 하이퍼링크, 다이렉트링크, 직접링크등으로 링크된 페이지 주소만을 수집 저장하여 제공하고 있습니다. 저장된 각각의 주소에 연결된 페이지등은 그 페이지에서 제공하는 "서버, 사이트" 상황에 따라 페이지와 내용이 삭제 중단 될 수 있으며 macaronics.net 과는 어떠한 연관 관련이 없음을 알려드립니다. 또한, 저작권에 관련된 문제있는 글이나 기타 저작권에 관련된 문제가 있는 것은 연락주시면 바로 삭제해 드리겠습니다.
댓글 ( 4)
댓글 남기기