修改一下 userInfo template
<template>
<div class="container">
<b-card-group deck>
<b-card header="帳號資訊" header-tag="header" class="m-3">
<div role="group" class="m-3">
<label for="account">信箱 (帳號):</label>
<b-form-input
id = "account"
v-model="account"
disabled
trim
></b-form-input>
<b-form-text id="input-live-help" v-if="!emailVerified">
<span>您的帳號尚未認證,點擊</span>
<span class="mail--verified"
v-b-tooltip.hover title="發送認證信"
@click="makeToast('success')"
>
連接
</span>發送認證信
</b-form-text>
<b-form-text id="input-live-help" v-if="emailVerified">
<span style="color: green;">已認證的帳號 !</span>
</b-form-text>
</div>
<div role="group" class="m-3">
<label for="password">密碼:</label>
<b-form-input
id = "password"
v-model="password"
trim
></b-form-input>
</div>
<div role="group" class="m-3">
<label for="backupEmail">信箱 (備援):</label>
<b-form-input
id = "backupEmail"
v-model="backupEmail"
trim
></b-form-input>
</div>
</b-card>
</b-card-group>
<b-card-group deck>
<b-card header="名稱相關" header-tag="header" class="m-3">
<div role="group" class="m-3">
<label for="">暱稱:</label>
<b-form-input
id="displayName"
v-model="displayName"
trim
></b-form-input>
</div>
<div role="group" class="m-3">
<label for="name">英文暱稱:</label>
<b-form-input
id = "name"
v-model="name"
trim
></b-form-input>
</div>
</b-card>
</b-card-group>
<b-card-group deck>
<b-card header="聯絡資訊" header-tag="header" class="m-3">
<div role="group" class="m-3">
<label for="phoneNumber">電話號碼:</label>
<b-form-input
id="phoneNumber"
v-model="phoneNumber"
trim
></b-form-input>
</div>
<div role="group" class="m-3">
<label for="address">住址:</label>
<b-form-input
id = "address"
v-model="address"
trim
></b-form-input>
</div>
</b-card>
</b-card-group>
<b-card-group deck>
<b-card header="簡介" header-tag="header" class="m-3">
<div role="group" class="m-3">
<label for="skills">專長:</label>
<b-form-textarea
id="skills"
v-model="skills"
placeholder="Enter something..."
rows="3"
max-rows="6"
></b-form-textarea>
</div>
<div role="group" class="m-3">
<label for="intro">自我介紹:</label>
<b-form-textarea
id="intro"
v-model="intro"
placeholder="Enter something..."
rows="3"
max-rows="6"
></b-form-textarea>
</div>
</b-card>
</b-card-group>
<b-button @click.native="updateUserInfo" href="#" variant="primary" class="m-3">更新資料</b-button>
</div>
</template>
...
<style lang="scss" scoped>
.mail--verified {
color: #33f;
cursor: pointer;
}
</style>
因為 email 認證的變數是由 firebase.auth().currentUser 裡面的 emailVerified 來負責 (應該沒記錯吧),但是這邊我實測時都會遇到一個問題,如果沒有按照正常程序進到頁面 (從登入開始進來),而是在裡面的頁面重新整理的話,每次一進到頁面就呼叫 F_showUser 時回來的使用者都是 undefined,大概要再等個 1 秒才會真的有使用者出現,我猜想可能因為 Firebase 的狀態還沒有完全更新完,背後後正在重新登入的關係,所以就不能採用一進來呼叫F_showUser 檢查 emailVerified ,而是變成先讀取資料庫,如果 emailVerified 是 false,再執行 refreshVerified,裡面有 F_showUser 的呼叫,這時確認沒問題已經可以檢查到新的使用者和認證狀態了。
所以整個程式的邏輯概念是: 一進來資訊頁時都先在 created 時讀取資料庫,若認證狀態是 false 就會執行 refreshVerified,來確認是否已經認證,若是已認證就直接更新綁定值,執行 appendCurrentValue() 並把雲端抓下來的資料丟進去,更新本地值。
data () {
return {
account: '',
password: '',
backupEmail: '',
displayName: '',
name: '',
phoneNumber: '',
address: '',
skills: '',
intro: '',
photoURL: '',
uid: '',
emailVerified: ''
}
}
created () {
this.F_getManagerInfo(this.$route.params.who).then(manager => {
if (manager.emailVerified === false) this.refreshVerified()
else this.appendCurrentValue(manager)
})
}
下面是所有的 methods:
methods: {
updateUserInfo () {
const info = this.appendCurrentValue({}, 'skip get cloud')
this.F_updateProfile(info)
this.F_updateManagerInfo(this.$route.params.who, info)
},
makeToast (variant = null) {
this.F_sendEmailVerified()
this.$bvToast.toast('我們已發送認證郵件至 ' + this.account + ',請點選信箱連結認證後,再重新整理確認本頁狀態。', {
title: '提示訊息',
variant: variant,
solid: true
})
},
appendCurrentValue (manager, order) {
if (order === 'skip get cloud') {
// 返回更新值
return {
displayName: this.displayName,
name: this.name,
backupEmail: this.backupEmail,
phoneNumber: this.phoneNumber,
address: this.address,
// uid: this.uid,
skills: this.skills,
intro: this.intro
// photoURL: this.photoURL
}
}
// 取得雲端值後丟進來這裡更新綁定值
this.account = manager.account
this.password = manager.password
this.backupEmail = manager.backupEmail
this.displayName = manager.displayName
this.name = manager.name
this.phoneNumber = manager.phoneNumber
this.address = manager.address
this.skills = manager.skills
this.intro = manager.intro
this.emailVerified = manager.emailVerified
// this.uid = manager.uid
// this.photoURL = manager.photoURL
},
refreshVerified () {
(async () => {
let currentUser = null
await this.F_showUser().then(user => {
currentUser = user
})
await this.F_updateManagerInfo(this.$route.params.who, { emailVerified: currentUser.emailVerified })
this.F_getManagerInfo(this.$route.params.who).then(manager => {
this.appendCurrentValue(manager)
})
})()
}
}
這邊等 created 結束後會看見資料被抓下來,並且顯示尚未任認證:
透過設定好的 makeToast ,現在可以去信箱點擊收信,認證連結點下去後 emailVerified 就會變成 true,若是為 true,重新整理後就能夠看見帳號變成已認證的狀態。
Model 大更新,建議對照 userInfo 頁來看用到什麼:
methods: {
async F_showUser (e, msg) {
console.log('觸發了F_showUser')
var user = firebase.auth().currentUser
// var name, email, photoUrl, uid, emailVerified
if (user != null) return user
else return null
},
F_signIn (account, password) {
console.log('觸發了F_signIn')
const self = this
firebase.auth().signInWithEmailAndPassword(account, password).then(function () {
console.log('登入成功')
self.F_showUser().then(user => {
console.log('user::', user)
self.$router.push(`/backend/${user.uid}`)
}).catch(error => {
console.log(error)
})
}).catch(function (error) {
// Handle Errors here.
var errorCode = error.code
var errorMessage = error.message
console.error(errorCode, errorMessage)
})
},
F_signUp (user) {
return firebase.auth().createUserWithEmailAndPassword(user.account, user.password).then(function () {
}).catch(function (error) {
// Handle Errors here.
var errorCode = error.code
var errorMessage = error.message
console.error(errorCode, errorMessage)
})
},
F_signOut () {
console.log('觸發了F_signOut')
const self = this
firebase.auth().signOut().then(function () {
// Sign-out successful.
console.log(self.$route.params)
self.F_updateManagerInfo(self.$route.params.who, { online: false })
self.$router.push('/')
console.log('登出成功')
})
},
F_updateArticle (data) {
console.log('觸發了F_updateArticle')
db.collection('posts').add(data).then(function (res) {
console.log('新增文章成功')
}).catch(res => {
console.log('新增文章失敗')
})
},
F_stateWatcher () {
firebase.auth().onAuthStateChanged(function (user) {
if (user) {
console.log('現在使用者: ', user)
} else {
console.log('logout')
//
}
})
},
F_updateProfile (userInfo) {
console.log('觸發了F_updateProfile')
var user = firebase.auth().currentUser
return user.updateProfile({
displayName: userInfo.displayName
// photoURL: photoURL
})
},
F_checkLogin () {
console.log('觸發了F_checkLogin')
this.F_showUser().then(res => {
console.log(res)
if (res === null) this.$router.push('login')
else this.$router.push(`backend/${res.uid}`)
})
},
F_getCollectionDocsSort (collection, orderBy) {
const docs = []
return db.collection(collection).orderBy(orderBy.where, orderBy.order).get().then(function (querySnapshot) {
querySnapshot.forEach(function (doc) {
const data = doc.data()
data.id = doc.id
docs.push(data)
})
return docs
})
},
F_setManagerData (user) {
db.collection('managers').doc(user.uid).set({
account: user.account,
password: user.password,
displayName: user.displayName,
name: user.name,
backupEmail: user.backupEmail,
phoneNumber: user.phoneNumber,
address: user.address,
uid: user.uid,
emailVerified: false,
online: user.online,
registerTime: user.registerTime
}).catch(function (error) {
console.error('Error writing document: ', error)
})
},
F_getManagerInfo (id) {
var docRef = db.collection('managers').doc(id)
return docRef.get().then(function (doc) {
if (doc.exists) {
return doc.data()
} else {
console.log('No such document!')
}
}).catch(function (error) {
console.log('Error getting document:', error)
})
},
F_updateManagerInfo (id, data) {
var docRef = db.collection('managers').doc(id)
// Set the 'capital' field of the city 'DC'
return docRef.update(data).then(function () {
console.log('Document successfully updated!')
}).catch(function (error) {
// The document probably doesn't exist.
console.error('Error updating document: ', error)
})
},
F_sendEmailVerified () {
var user = firebase.auth().currentUser
user.sendEmailVerification().then(function () {
// Email sent.
}).catch(function (error) {
console.log(error)
})
}
}
這樣註冊流程大概算 OK 了,細部有什麼問題就再說吧,更改密碼和帳號那些太麻煩了,後面通通都給他 disable 好了哈哈。
現在已經做好了寫文章、比較完整的註冊、註冊後的資料填寫、點擊進去文章,那麼下一章我們就來做編輯現有文章吧 ! Firestore 用到現在,不用我說編輯文章應該比較有個底了,大致上的邏輯我們蒐集所有的已 PO 文章,接著藉由他的特有 ID 從資料庫抓下來,更改完後重新上傳,這樣前台就會看到文章已經更新啦!
最後想說有點抱歉的是,畢竟這不是事先準備好的專案,這是很突然的要參加鐵人賽後才開始寫的內容阿,所以請原諒我很多東西變來變去,有點雜亂無章哈哈,有機會的話,明年再考慮看看能不能事先準備再來參加。
沒事也可以逛逛我們其他團隊成員的文章啦 ~~
eien_zheng: 前端小嘍嘍的Golang學習旅程_The journey of learning Golang 系列
PollyPO技術: 前端設計轉前端工程師-JS踩坑雜記 30 天 系列
阿電: 忍住不打牌位,只要30天VueJS帶你上A牌 系列
喬依司: 實作經典 JavaScript 30 系列